PR 10437
[deliverable/binutils-gdb.git] / gas / config / tc-cris.c
index 5e8d4bd6e89d95539fb27896799f11826081030c..e4e3bcc01bdf27f955dfda155d8aee9b84406253 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-cris.c -- Assembler code for the CRIS CPU core.
 /* tc-cris.c -- Assembler code for the CRIS CPU core.
-   Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2009
+   Free Software Foundation, Inc.
 
    Contributed by Axis Communications AB, Lund, Sweden.
    Originally written for GAS 1.38.1 by Mikael Asker.
 
    Contributed by Axis Communications AB, Lund, Sweden.
    Originally written for GAS 1.38.1 by Mikael Asker.
@@ -9,7 +10,7 @@
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    any later version.
 
    GAS is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the
-   Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.  */
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include <stdio.h>
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
@@ -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.  */
 
 /* 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.  */
 
 /* 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.  */
@@ -120,52 +120,45 @@ enum cris_archs
   arch_cris_any_v0_v10, arch_crisv32, arch_cris_common_v10_v32
 };
 
   arch_cris_any_v0_v10, arch_crisv32, arch_cris_common_v10_v32
 };
 
-static enum cris_archs cris_arch_from_string PARAMS ((char **));
-static int cris_insn_ver_valid_for_arch PARAMS ((enum cris_insn_version_usage,
-                                                enum cris_archs));
-
-static void cris_process_instruction PARAMS ((char *,
-                                             struct cris_instruction *,
-                                             struct cris_prefix *));
-static int get_bwd_size_modifier PARAMS ((char **, int *));
-static int get_bw_size_modifier PARAMS ((char **, int *));
-static int get_gen_reg PARAMS ((char **, int *));
-static int get_spec_reg PARAMS ((char **,
-                                const struct cris_spec_reg **));
-static int get_sup_reg PARAMS ((char **, int *));
-static int get_autoinc_prefix_or_indir_op PARAMS ((char **,
-                                                  struct cris_prefix *,
-                                                  int *, int *, int *,
-                                                  expressionS *));
-static int get_3op_or_dip_prefix_op PARAMS ((char **,
-                                            struct cris_prefix *));
-static int cris_get_expression PARAMS ((char **, expressionS *));
-static int get_flags PARAMS ((char **, int *));
-static void gen_bdap PARAMS ((int, expressionS *));
-static int branch_disp PARAMS ((int));
-static void gen_cond_branch_32 PARAMS ((char *, char *, fragS *,
-                                       symbolS *, symbolS *, long int));
-static void cris_number_to_imm PARAMS ((char *, long, int, fixS *, segT));
-static void cris_create_short_jump PARAMS ((char *, addressT, addressT,
-                                           fragS *, symbolS *));
-static void s_syntax PARAMS ((int));
-static void s_cris_file PARAMS ((int));
-static void s_cris_loc PARAMS ((int));
-static void s_cris_arch PARAMS ((int));
+static enum cris_archs cris_arch_from_string (char **);
+static int cris_insn_ver_valid_for_arch (enum cris_insn_version_usage,
+                                        enum cris_archs);
+
+static void cris_process_instruction (char *, struct cris_instruction *,
+                                     struct cris_prefix *);
+static int get_bwd_size_modifier (char **, int *);
+static int get_bw_size_modifier (char **, int *);
+static int get_gen_reg (char **, int *);
+static int get_spec_reg (char **, const struct cris_spec_reg **);
+static int get_sup_reg (char **, int *);
+static int get_autoinc_prefix_or_indir_op (char **, struct cris_prefix *,
+                                          int *, int *, int *,
+                                          expressionS *);
+static int get_3op_or_dip_prefix_op (char **, struct cris_prefix *);
+static int cris_get_expression (char **, expressionS *);
+static int get_flags (char **, int *);
+static void gen_bdap (int, expressionS *);
+static int branch_disp (int);
+static void gen_cond_branch_32 (char *, char *, fragS *, symbolS *, symbolS *,
+                               long int);
+static void cris_number_to_imm (char *, long, int, fixS *, segT);
+static void s_syntax (int);
+static void s_cris_file (int);
+static void s_cris_loc (int);
+static void s_cris_arch (int);
+static void s_cris_dtpoff (int);
 
 /* Get ":GOT", ":GOTOFF", ":PLT" etc. suffixes.  */
 
 /* Get ":GOT", ":GOTOFF", ":PLT" etc. suffixes.  */
-static void cris_get_pic_suffix PARAMS ((char **,
-                                        bfd_reloc_code_real_type *,
-                                        expressionS *));
-static unsigned int cris_get_pic_reloc_size
-  PARAMS ((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.  */
 
 /* All the .syntax functions.  */
-static void cris_force_reg_prefix PARAMS ((void));
-static void cris_relax_reg_prefix PARAMS ((void));
-static void cris_sym_leading_underscore PARAMS ((void));
-static void cris_sym_no_leading_underscore PARAMS ((void));
-static char *cris_insn_first_word_frag PARAMS ((void));
+static void cris_force_reg_prefix (void);
+static void cris_relax_reg_prefix (void);
+static void cris_sym_leading_underscore (void);
+static void cris_sym_no_leading_underscore (void);
+static char *cris_insn_first_word_frag (void);
 
 /* Handle to the opcode hash table.  */
 static struct hash_control *op_hash = NULL;
 
 /* Handle to the opcode hash table.  */
 static struct hash_control *op_hash = NULL;
@@ -189,6 +182,9 @@ static bfd_boolean symbols_have_leading_underscore
 /* Whether or not we allow PIC, and expand to PIC-friendly constructs.  */
 static bfd_boolean pic = FALSE;
 
 /* 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
 /* If we're configured for "cris", default to allow all v0..v10
    instructions and register names.  */
 #ifndef DEFAULT_CRIS_ARCH
@@ -201,6 +197,7 @@ static enum cris_archs cris_arch = XCONCAT2 (arch_,DEFAULT_CRIS_ARCH);
 const pseudo_typeS md_pseudo_table[] =
 {
   {"dword", cons, 4},
 const pseudo_typeS md_pseudo_table[] =
 {
   {"dword", cons, 4},
+  {"dtpoffd", s_cris_dtpoff, 4},
   {"syntax", s_syntax, 0},
   {"file", s_cris_file, 0},
   {"loc", s_cris_loc, 0},
   {"syntax", s_syntax, 0},
   {"file", s_cris_file, 0},
   {"loc", s_cris_loc, 0},
@@ -273,6 +270,7 @@ const char FLT_CHARS[] = "";
 #define STATE_COND_BRANCH_COMMON    (5)
 #define STATE_ABS_BRANCH_V32       (6)
 #define STATE_LAPC                 (7)
 #define STATE_COND_BRANCH_COMMON    (5)
 #define STATE_ABS_BRANCH_V32       (6)
 #define STATE_LAPC                 (7)
+#define STATE_COND_BRANCH_PIC       (8)
 
 #define STATE_LENGTH_MASK          (3)
 #define STATE_BYTE                 (0)
 
 #define STATE_LENGTH_MASK          (3)
 #define STATE_BYTE                 (0)
@@ -396,6 +394,18 @@ const relax_typeS md_cris_relax_table[] =
   {0,        0,         4, 0},
 
   /* Unused (7, 3).  */
   {0,        0,         4, 0},
 
   /* Unused (7, 3).  */
+  {1,        1,         0,  0},
+
+  /* PIC for pre-v32: Bcc o (8, 0).  */
+  {BRANCH_BF, BRANCH_BB, 0,  ENCODE_RELAX (STATE_COND_BRANCH_PIC, 1)},
+
+  /* Bcc [PC+] (8, 1).  */
+  {BRANCH_WF, BRANCH_WB, 2,  ENCODE_RELAX (STATE_COND_BRANCH_PIC, 2)},
+
+  /* 32-bit expansion, PIC (8, 2).  */
+  {0,        0,         12, 0},
+
+  /* Unused (8, 3).  */
   {1,        1,         0,  0}
 };
 
   {1,        1,         0,  0}
 };
 
@@ -438,8 +448,10 @@ const char *md_shortopts = "hHN";
 
 int md_short_jump_size = 6;
 
 
 int md_short_jump_size = 6;
 
-/* The v32 version has a delay-slot, hence two bytes longer.  */
+/* The v32 version has a delay-slot, hence two bytes longer.
+   The pre-v32 PIC version uses a prefixed insn.  */
 #define cris_any_v0_v10_long_jump_size 6
 #define cris_any_v0_v10_long_jump_size 6
+#define cris_any_v0_v10_long_jump_size_pic 8
 #define crisv32_long_jump_size 8
 
 int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size);
 #define crisv32_long_jump_size 8
 
 int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size);
@@ -449,7 +461,7 @@ int md_long_jump_size = XCONCAT2 (DEFAULT_CRIS_ARCH,_long_jump_size);
    that, the output format must remain fixed.  */
 
 const char *
    that, the output format must remain fixed.  */
 
 const char *
-cris_target_format ()
+cris_target_format (void)
 {
   switch (OUTPUT_FLAVOR)
     {
 {
   switch (OUTPUT_FLAVOR)
     {
@@ -471,7 +483,7 @@ cris_target_format ()
    cris_arch.  */
 
 unsigned int
    cris_arch.  */
 
 unsigned int
-cris_mach ()
+cris_mach (void)
 {
   unsigned int retval = 0;
 
 {
   unsigned int retval = 0;
 
@@ -505,10 +517,8 @@ cris_mach ()
    The offset can be 8, 16 or 32 bits long.  */
 
 long
    The offset can be 8, 16 or 32 bits long.  */
 
 long
-cris_relax_frag (seg, fragP, stretch)
-     segT seg ATTRIBUTE_UNUSED;
-     fragS *fragP;
-     long stretch ATTRIBUTE_UNUSED;
+cris_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP,
+                long stretch ATTRIBUTE_UNUSED)
 {
   long growth;
   offsetT aim = 0;
 {
   long growth;
   offsetT aim = 0;
@@ -524,6 +534,7 @@ cris_relax_frag (seg, fragP, stretch)
      because of the different reasons that they aren't relaxable.  */
   switch (fragP->fr_subtype)
     {
      because of the different reasons that they aren't relaxable.  */
   switch (fragP->fr_subtype)
     {
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_DWORD):
@@ -612,10 +623,7 @@ cris_relax_frag (seg, fragP, stretch)
    fr_var starts with a value.  */
 
 int
    fr_var starts with a value.  */
 
 int
-md_estimate_size_before_relax (fragP, segment_type)
-     fragS *fragP;
-     /* The segment is either N_DATA or N_TEXT.  */
-     segT segment_type;
+md_estimate_size_before_relax (fragS *fragP, segT segment_type)
 {
   int old_fr_fix;
   symbolS *symbolP = fragP->fr_symbol;
 {
   int old_fr_fix;
   symbolS *symbolP = fragP->fr_symbol;
@@ -644,6 +652,7 @@ md_estimate_size_before_relax (fragP, segment_type)
       HANDLE_RELAXABLE (STATE_COND_BRANCH);
       HANDLE_RELAXABLE (STATE_COND_BRANCH_V32);
       HANDLE_RELAXABLE (STATE_COND_BRANCH_COMMON);
       HANDLE_RELAXABLE (STATE_COND_BRANCH);
       HANDLE_RELAXABLE (STATE_COND_BRANCH_V32);
       HANDLE_RELAXABLE (STATE_COND_BRANCH_COMMON);
+      HANDLE_RELAXABLE (STATE_COND_BRANCH_PIC);
       HANDLE_RELAXABLE (STATE_ABS_BRANCH_V32);
 
     case ENCODE_RELAX (STATE_LAPC, STATE_UNDF):
       HANDLE_RELAXABLE (STATE_ABS_BRANCH_V32);
 
     case ENCODE_RELAX (STATE_LAPC, STATE_UNDF):
@@ -751,6 +760,9 @@ md_estimate_size_before_relax (fragP, segment_type)
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_DWORD):
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE):
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD):
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
@@ -792,10 +804,8 @@ md_estimate_size_before_relax (fragP, segment_type)
    The caller will turn the frag into a ".space 0".  */
 
 void
    The caller will turn the frag into a ".space 0".  */
 
 void
-md_convert_frag (abfd, sec, fragP)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     segT sec ATTRIBUTE_UNUSED;
-     fragS *fragP;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
+                fragS *fragP)
 {
   /* Pointer to first byte in variable-sized part of the frag.  */
   char *var_partp;
 {
   /* Pointer to first byte in variable-sized part of the frag.  */
   char *var_partp;
@@ -837,6 +847,7 @@ md_convert_frag (abfd, sec, fragP)
   switch (fragP->fr_subtype)
     {
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
   switch (fragP->fr_subtype)
     {
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_BYTE):
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_BYTE):
     case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_BYTE):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_BYTE):
     case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_BYTE):
@@ -845,6 +856,7 @@ md_convert_frag (abfd, sec, fragP)
       break;
 
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
       break;
 
     case ENCODE_RELAX (STATE_COND_BRANCH, STATE_WORD):
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_WORD):
     case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_WORD):
     case ENCODE_RELAX (STATE_COND_BRANCH_COMMON, STATE_WORD):
     case ENCODE_RELAX (STATE_ABS_BRANCH_V32, STATE_WORD):
@@ -872,6 +884,14 @@ md_convert_frag (abfd, sec, fragP)
       var_part_size = 2 + 2 + 4 + 2;
       break;
 
       var_part_size = 2 + 2 + 4 + 2;
       break;
 
+    case ENCODE_RELAX (STATE_COND_BRANCH_PIC, STATE_DWORD):
+      gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP,
+                         fragP->fr_symbol, (symbolS *) NULL,
+                         fragP->fr_offset);
+      /* Twelve bytes added: a branch, nop and a pic-branch-32.  */
+      var_part_size = 2 + 2 + 4 + 2 + 2;
+      break;
+
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
       gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP,
                          fragP->fr_symbol, (symbolS *) NULL,
     case ENCODE_RELAX (STATE_COND_BRANCH_V32, STATE_DWORD):
       gen_cond_branch_32 (fragP->fr_opcode, var_partp, fragP,
                          fragP->fr_symbol, (symbolS *) NULL,
@@ -975,7 +995,7 @@ md_convert_frag (abfd, sec, fragP)
       break;
 
     case ENCODE_RELAX (STATE_MUL, STATE_BYTE):
       break;
 
     case ENCODE_RELAX (STATE_MUL, STATE_BYTE):
-      /* This is the only time we check position and aligmnent of the
+      /* This is the only time we check position and alignment of the
         placement-tracking frag.  */
       if (sec->alignment_power < 2)
        as_bad_where (fragP->fr_file, fragP->fr_line,
         placement-tracking frag.  */
       if (sec->alignment_power < 2)
        as_bad_where (fragP->fr_file, fragP->fr_line,
@@ -1001,37 +1021,42 @@ md_convert_frag (abfd, sec, fragP)
 }
 
 /* Generate a short jump around a secondary jump table.
 }
 
 /* Generate a short jump around a secondary jump table.
-   Used by md_create_long_jump.
+   Also called from md_create_long_jump, when sufficient.  */
 
 
-   This used to be md_create_short_jump, but is now called from
-   md_create_long_jump instead, when sufficient, since the sizes of the
-   jumps are the same for pre-v32.  */
-
-static void
-cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol)
-     char *storep;
-     addressT from_addr;
-     addressT to_addr;
-     fragS *fragP ATTRIBUTE_UNUSED;
-     symbolS *to_symbol ATTRIBUTE_UNUSED;
+void
+md_create_short_jump (char *storep, addressT from_addr, addressT to_addr,
+                       fragS *fragP ATTRIBUTE_UNUSED,
+                       symbolS *to_symbol ATTRIBUTE_UNUSED)
 {
   long int distance;
 
   /* See md_create_long_jump about the comment on the "+ 2".  */
   long int max_minimal_minus_distance;
   long int max_minimal_plus_distance;
 {
   long int distance;
 
   /* See md_create_long_jump about the comment on the "+ 2".  */
   long int max_minimal_minus_distance;
   long int max_minimal_plus_distance;
+  long int max_minus_distance;
+  long int max_plus_distance;
   int nop_opcode;
 
   if (cris_arch == arch_crisv32)
     {
       max_minimal_minus_distance = BRANCH_BB_V32 + 2;
       max_minimal_plus_distance = BRANCH_BF_V32 + 2;
   int nop_opcode;
 
   if (cris_arch == arch_crisv32)
     {
       max_minimal_minus_distance = BRANCH_BB_V32 + 2;
       max_minimal_plus_distance = BRANCH_BF_V32 + 2;
+      max_minus_distance = BRANCH_WB_V32 + 2;
+      max_plus_distance = BRANCH_WF_V32 + 2;
       nop_opcode = NOP_OPCODE_V32;
     }
       nop_opcode = NOP_OPCODE_V32;
     }
+  else if (cris_arch == arch_cris_common_v10_v32)
+    /* Bail out for compatibility mode.  (It seems it can be implemented,
+       perhaps with a 10-byte sequence: "move.d NNNN,$pc/$acr", "jump
+       $acr", "nop"; but doesn't seem worth it at the moment.)  */
+    as_fatal (_("Out-of-range .word offset handling\
+ is not implemented for .arch common_v10_v32"));
   else
     {
       max_minimal_minus_distance = BRANCH_BB + 2;
       max_minimal_plus_distance = BRANCH_BF + 2;
   else
     {
       max_minimal_minus_distance = BRANCH_BB + 2;
       max_minimal_plus_distance = BRANCH_BF + 2;
+      max_minus_distance = BRANCH_WB + 2;
+      max_plus_distance = BRANCH_WF + 2;
       nop_opcode = NOP_OPCODE;
     }
 
       nop_opcode = NOP_OPCODE;
     }
 
@@ -1051,7 +1076,8 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol)
         a nop to keep disassembly sane.  */
       md_number_to_chars (storep + 4, nop_opcode, 2);
     }
         a nop to keep disassembly sane.  */
       md_number_to_chars (storep + 4, nop_opcode, 2);
     }
-  else
+  else if (max_minus_distance <= distance
+          && distance <= max_plus_distance)
     {
       /* Make it a "long" short jump: "BA (PC+)".  */
       md_number_to_chars (storep, BA_PC_INCR_OPCODE, 2);
     {
       /* Make it a "long" short jump: "BA (PC+)".  */
       md_number_to_chars (storep, BA_PC_INCR_OPCODE, 2);
@@ -1066,6 +1092,9 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol)
       /* A nop for the delay slot.  */
       md_number_to_chars (storep + 4, nop_opcode, 2);
     }
       /* A nop for the delay slot.  */
       md_number_to_chars (storep + 4, nop_opcode, 2);
     }
+  else
+    as_bad_where (fragP->fr_file, fragP->fr_line,
+                 _(".word case-table handling failed: table too large"));
 }
 
 /* Generate a long jump in a secondary jump table.
 }
 
 /* Generate a long jump in a secondary jump table.
@@ -1078,12 +1107,8 @@ cris_create_short_jump (storep, from_addr, to_addr, fragP, to_symbol)
    to_symbol  Destination symbol.  */
 
 void
    to_symbol  Destination symbol.  */
 
 void
-md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol)
-     char *storep;
-     addressT from_addr;
-     addressT to_addr;
-     fragS *fragP;
-     symbolS *to_symbol;
+md_create_long_jump (char *storep, addressT from_addr, addressT to_addr,
+                    fragS *fragP, symbolS *to_symbol)
 {
   long int distance;
 
 {
   long int distance;
 
@@ -1096,29 +1121,23 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol)
   long int max_short_plus_distance
     = cris_arch != arch_crisv32 ? BRANCH_WF + 3 : BRANCH_WF_V32 + 3;
 
   long int max_short_plus_distance
     = cris_arch != arch_crisv32 ? BRANCH_WF + 3 : BRANCH_WF_V32 + 3;
 
-  /* Bail out for compatibility mode.  (It seems it can be implemented,
-     perhaps with a 10-byte sequence: "move.d NNNN,$pc/$acr", "jump
-     $acr", "nop"; but doesn't seem worth it at the moment.)  */
-  if (cris_arch == arch_cris_common_v10_v32)
-    as_fatal (_("Out-of-range .word offset handling\
- is not implemented for .arch common_v10_v32"));
-
   distance = to_addr - from_addr;
 
   if (max_short_minus_distance <= distance
       && distance <= max_short_plus_distance)
     /* Then make it a "short" long jump.  */
   distance = to_addr - from_addr;
 
   if (max_short_minus_distance <= distance
       && distance <= max_short_plus_distance)
     /* Then make it a "short" long jump.  */
-    cris_create_short_jump (storep, from_addr, to_addr, fragP,
+    md_create_short_jump (storep, from_addr, to_addr, fragP,
                            to_symbol);
   else
     {
       /* We have a "long" long jump: "JUMP [PC+]".  If CRISv32, always
                            to_symbol);
   else
     {
       /* We have a "long" long jump: "JUMP [PC+]".  If CRISv32, always
-        make it a BA.  Else make it an "ADD [PC+],PC" if we're supposed
+        make it a BA.  Else make it an "MOVE [PC=PC+N],P0" if we're supposed
         to emit PIC code.  */
       md_number_to_chars (storep,
                          cris_arch == arch_crisv32
                          ? BA_DWORD_OPCODE
         to emit PIC code.  */
       md_number_to_chars (storep,
                          cris_arch == arch_crisv32
                          ? BA_DWORD_OPCODE
-                         : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE),
+                         : (pic ? MOVE_PC_INCR_OPCODE_PREFIX
+                            : JUMP_PC_INCR_OPCODE),
                          2);
 
       /* Follow with a ".DWORD to_addr", PC-relative for PIC.  */
                          2);
 
       /* Follow with a ".DWORD to_addr", PC-relative for PIC.  */
@@ -1131,6 +1150,9 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol)
       /* Follow it with a "NOP" for CRISv32.  */
       if (cris_arch == arch_crisv32)
        md_number_to_chars (storep + 6, NOP_OPCODE_V32, 2);
       /* Follow it with a "NOP" for CRISv32.  */
       if (cris_arch == arch_crisv32)
        md_number_to_chars (storep + 6, NOP_OPCODE_V32, 2);
+      else if (pic)
+       /* ...and the rest of the move-opcode for pre-v32 PIC.  */
+       md_number_to_chars (storep + 6, MOVE_PC_INCR_OPCODE_SUFFIX, 2);
     }
 }
 
     }
 }
 
@@ -1138,7 +1160,7 @@ md_create_long_jump (storep, from_addr, to_addr, fragP, to_symbol)
    start of the insn for debug-format use.  */
 
 static char *
    start of the insn for debug-format use.  */
 
 static char *
-cris_insn_first_word_frag ()
+cris_insn_first_word_frag (void)
 {
   char *insnp = frag_more (2);
 
 {
   char *insnp = frag_more (2);
 
@@ -1157,7 +1179,7 @@ cris_insn_first_word_frag ()
 /* Port-specific assembler initialization.  */
 
 void
 /* Port-specific assembler initialization.  */
 
 void
-md_begin ()
+md_begin (void)
 {
   const char *hashret = NULL;
   int i = 0;
 {
   const char *hashret = NULL;
   int i = 0;
@@ -1195,7 +1217,8 @@ md_begin ()
          continue;
        }
 
          continue;
        }
 
-      hashret = hash_insert (op_hash, name, (PTR) &cris_opcodes[i]);
+      /* Need to cast to get rid of "const".  FIXME: Fix hash_insert instead.  */
+      hashret = hash_insert (op_hash, name, (void *) &cris_opcodes[i]);
 
       if (hashret != NULL && *hashret != '\0')
        as_fatal (_("Can't hash `%s': %s\n"), cris_opcodes[i].name,
 
       if (hashret != NULL && *hashret != '\0')
        as_fatal (_("Can't hash `%s': %s\n"), cris_opcodes[i].name,
@@ -1216,8 +1239,7 @@ md_begin ()
 /* Assemble a source line.  */
 
 void
 /* Assemble a source line.  */
 
 void
-md_assemble (str)
-     char *str;
+md_assemble (char *str)
 {
   struct cris_instruction output_instruction;
   struct cris_prefix prefix;
 {
   struct cris_instruction output_instruction;
   struct cris_prefix prefix;
@@ -1239,7 +1261,7 @@ md_assemble (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:
       /* 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)
        {
         relocation.  */
       if (prefix.reloc == BFD_RELOC_NONE)
        {
@@ -1256,13 +1278,13 @@ md_assemble (str)
       md_number_to_chars (opcodep, (long) prefix.opcode, 2);
 
       /* Having a specified reloc only happens for DIP and for BDAP with
       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
         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,
 
          p = frag_more (relocsize);
          fix_new_exp (frag_now, (p - frag_now->fr_literal), relocsize,
@@ -1341,11 +1363,12 @@ md_assemble (str)
             That case is handled by md_estimate_size_before_relax.  */
          length_code = to_seg == now_seg ? STATE_BYTE : STATE_UNDF;
 
             That case is handled by md_estimate_size_before_relax.  */
          length_code = to_seg == now_seg ? STATE_BYTE : STATE_UNDF;
 
-         /* Make room for max twelve bytes of variable length for v32 mode,
-            ten for v10 and older.  */
+         /* Make room for max twelve bytes of variable length for v32 mode
+            or PIC, ten for v10 and older.  */
          frag_var (rs_machine_dependent,
                    (cris_arch == arch_crisv32
          frag_var (rs_machine_dependent,
                    (cris_arch == arch_crisv32
-                    || cris_arch == arch_cris_common_v10_v32) ? 12 : 10, 0,
+                    || cris_arch == arch_cris_common_v10_v32
+                    || pic) ? 12 : 10, 0,
                    ENCODE_RELAX (cris_arch == arch_crisv32
                                  ? (output_instruction.opcode
                                     == BA_QUICK_OPCODE
                    ENCODE_RELAX (cris_arch == arch_crisv32
                                  ? (output_instruction.opcode
                                     == BA_QUICK_OPCODE
@@ -1353,7 +1376,8 @@ md_assemble (str)
                                     : STATE_COND_BRANCH_V32)
                                  : (cris_arch == arch_cris_common_v10_v32
                                     ? STATE_COND_BRANCH_COMMON
                                     : STATE_COND_BRANCH_V32)
                                  : (cris_arch == arch_cris_common_v10_v32
                                     ? STATE_COND_BRANCH_COMMON
-                                    : STATE_COND_BRANCH),
+                                    : (pic ? STATE_COND_BRANCH_PIC
+                                       : STATE_COND_BRANCH)),
                                  length_code),
                    sym, addvalue, opcodep);
        }
                                  length_code),
                    sym, addvalue, opcodep);
        }
@@ -1364,7 +1388,8 @@ md_assemble (str)
             section, perhaps an absolute address.  Emit a 32-bit branch.  */
          char *cond_jump
            = frag_more ((cris_arch == arch_crisv32
             section, perhaps an absolute address.  Emit a 32-bit branch.  */
          char *cond_jump
            = frag_more ((cris_arch == arch_crisv32
-                         || cris_arch == arch_cris_common_v10_v32)
+                         || cris_arch == arch_cris_common_v10_v32
+                         || pic)
                         ? 12 : 10);
 
          gen_cond_branch_32 (opcodep, cond_jump, frag_now,
                         ? 12 : 10);
 
          gen_cond_branch_32 (opcodep, cond_jump, frag_now,
@@ -1465,10 +1490,8 @@ md_assemble (str)
 /* Low level text-to-bits assembly.  */
 
 static void
 /* Low level text-to-bits assembly.  */
 
 static void
-cris_process_instruction (insn_text, out_insnp, prefixp)
-     char *insn_text;
-     struct cris_instruction *out_insnp;
-     struct cris_prefix *prefixp;
+cris_process_instruction (char *insn_text, struct cris_instruction *out_insnp,
+                         struct cris_prefix *prefixp)
 {
   char *s;
   char modified_char = 0;
 {
   char *s;
   char modified_char = 0;
@@ -1805,7 +1828,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
                     pseudo yet, so some of this is just unused
                     framework.  */
                  if (out_insnp->spec_reg->warning)
                     pseudo yet, so some of this is just unused
                     framework.  */
                  if (out_insnp->spec_reg->warning)
-                   as_warn (out_insnp->spec_reg->warning);
+                   as_warn ("%s", out_insnp->spec_reg->warning);
                  else if (out_insnp->spec_reg->applicable_version
                           == cris_ver_warning)
                    /* Others have a generic warning.  */
                  else if (out_insnp->spec_reg->applicable_version
                           == cris_ver_warning)
                    /* Others have a generic warning.  */
@@ -1875,7 +1898,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
                         whether or not this is autoincrement mode.  */
                      out_insnp->opcode |= (mode << 10);
 
                         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.  */
                         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.  */
@@ -1889,8 +1912,8 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
 
            case 'N':
            case 'Y':
 
            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))
                {
                 specifier makes sense.  */
              if (cris_get_expression (&s, &out_insnp->expr))
                {
@@ -1913,9 +1936,10 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
                     relocation.  */
                  out_insnp->expr.X_add_number += 6;
 
                     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;
                }
 
                  continue;
                }
@@ -2180,13 +2204,18 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
                }
 
              /* If there was a relocation specified for the immediate
                }
 
              /* 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
                 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))
                      != (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
+                       || out_insnp->reloc == BFD_RELOC_CRIS_32_IE
+                       ? _("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)
            }
          else if (instruction->op == cris_muls_op
                   || instruction->op == cris_mulu_op)
@@ -2210,9 +2239,7 @@ cris_process_instruction (insn_text, out_insnp, prefixp)
    Return 1 iff a correct size modifier is found, else 0.  */
 
 static int
    Return 1 iff a correct size modifier is found, else 0.  */
 
 static int
-get_bwd_size_modifier (cPP, size_bitsp)
-     char **cPP;
-     int *size_bitsp;
+get_bwd_size_modifier (char **cPP, int *size_bitsp)
 {
   if (**cPP != '.')
     return 0;
 {
   if (**cPP != '.')
     return 0;
@@ -2262,9 +2289,7 @@ get_bwd_size_modifier (cPP, size_bitsp)
    Return 1 iff a correct size modifier is found, else 0.  */
 
 static int
    Return 1 iff a correct size modifier is found, else 0.  */
 
 static int
-get_bw_size_modifier (cPP, size_bitsp)
-     char **cPP;
-     int *size_bitsp;
+get_bw_size_modifier (char **cPP, int *size_bitsp)
 {
   if (**cPP != '.')
     return 0;
 {
   if (**cPP != '.')
     return 0;
@@ -2309,9 +2334,7 @@ get_bw_size_modifier (cPP, size_bitsp)
            else 0.  */
 
 static int
            else 0.  */
 
 static int
-get_gen_reg (cPP, regnop)
-     char **cPP;
-     int *regnop;
+get_gen_reg (char **cPP, int *regnop)
 {
   char *oldp;
   oldp = *cPP;
 {
   char *oldp;
   oldp = *cPP;
@@ -2434,9 +2457,7 @@ get_gen_reg (cPP, regnop)
    Return 1 iff a correct special register name is found.  */
 
 static int
    Return 1 iff a correct special register name is found.  */
 
 static int
-get_spec_reg (cPP, sregpp)
-     char **cPP;
-     const struct cris_spec_reg **sregpp;
+get_spec_reg (char **cPP, const struct cris_spec_reg **sregpp)
 {
   char *s1;
   const char *s2;
 {
   char *s1;
   const char *s2;
@@ -2494,9 +2515,7 @@ get_spec_reg (cPP, sregpp)
    Return 1 iff a correct support-register name is found.  */
 
 static int
    Return 1 iff a correct support-register name is found.  */
 
 static int
-get_sup_reg (cPP, regnop)
-     char **cPP;
-     int *regnop;
+get_sup_reg (char **cPP, int *regnop)
 {
   char *s1;
   const char *s2;
 {
   char *s1;
   const char *s2;
@@ -2565,14 +2584,9 @@ get_sup_reg (cPP, regnop)
    Return 1 iff a correct indirect operand is found.  */
 
 static int
    Return 1 iff a correct indirect operand is found.  */
 
 static int
-get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
-                               imm_foundp, imm_exprP)
-     char **cPP;
-     struct cris_prefix *prefixp;
-     int *is_autoincp;
-     int *src_regnop;
-     int *imm_foundp;
-     expressionS *imm_exprP;
+get_autoinc_prefix_or_indir_op (char **cPP, struct cris_prefix *prefixp,
+                               int *is_autoincp, int *src_regnop,
+                               int *imm_foundp, expressionS *imm_exprP)
 {
   /* Assume there was no immediate mode expression.  */
   *imm_foundp = 0;
 {
   /* Assume there was no immediate mode expression.  */
   *imm_foundp = 0;
@@ -2716,8 +2730,8 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
 
                          /* We tentatively put an opcode corresponding to
                             a 32-bit operand here, although it may be
 
                          /* 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)
                          prefixp->opcode
                            = (BDAP_INDIR_OPCODE
                               | (prefixp->base_reg_number << 12)
@@ -2727,18 +2741,18 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
 
                          /* This can have a PIC suffix, specifying reloc
                             type to use.  */
 
                          /* 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;
 
                            {
                              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
 
                              /* 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))
                              if (relocsize != 4)
                                prefixp->opcode
                                  = ((prefixp->opcode & ~(3 << 4))
@@ -2764,8 +2778,9 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
                             in the blanks and break out to match the
                             final ']'.
 
                             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;
                        }
                          prefixp->kind = PREFIX_BDAP_IMM;
                          break;
                        }
@@ -2803,8 +2818,8 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
 
       /* This can have a PIC suffix, specifying reloc type to use.  The
         caller must check that the reloc size matches the operand size.  */
 
       /* 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;
     }
 
       return 1;
     }
@@ -2827,9 +2842,7 @@ get_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop,
    Returns 1 iff a correct indirect operand is found.  */
 
 static int
    Returns 1 iff a correct indirect operand is found.  */
 
 static int
-get_3op_or_dip_prefix_op (cPP, prefixp)
-     char **cPP;
-     struct cris_prefix *prefixp;
+get_3op_or_dip_prefix_op (char **cPP, struct cris_prefix *prefixp)
 {
   int reg_number;
 
 {
   int reg_number;
 
@@ -2974,15 +2987,15 @@ get_3op_or_dip_prefix_op (cPP, prefixp)
                   | REG_PC /* << 0 */);
 
              /* This can have a PIC suffix, specifying reloc type to use.  */
                   | 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;
 
                {
                  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.  */
 
                  /* 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))
                  if (relocsize != 4)
                    prefixp->opcode
                      = ((prefixp->opcode & ~(3 << 4))
@@ -3038,6 +3051,10 @@ get_3op_or_dip_prefix_op (cPP, prefixp)
       prefixp->kind = PREFIX_DIP;
       prefixp->opcode = DIP_OPCODE | (AUTOINCR_BIT << 8) | REG_PC;
       prefixp->reloc = BFD_RELOC_32;
       prefixp->kind = PREFIX_DIP;
       prefixp->opcode = DIP_OPCODE | (AUTOINCR_BIT << 8) | REG_PC;
       prefixp->reloc = BFD_RELOC_32;
+
+      /* For :GD and :IE, it makes sense to have TLS specifiers here.  */
+      if ((pic || tls) && **cPP == RELOC_SUFFIX_CHAR)
+       cris_get_reloc_suffix (cPP, &prefixp->reloc, &prefixp->expr);
     }
   else
     /* Neither '[' nor register nor expression.  We lose.  */
     }
   else
     /* Neither '[' nor register nor expression.  We lose.  */
@@ -3065,9 +3082,7 @@ get_3op_or_dip_prefix_op (cPP, prefixp)
    Return 1 iff a correct expression is found.  */
 
 static int
    Return 1 iff a correct expression is found.  */
 
 static int
-cris_get_expression (cPP, exprP)
-     char **cPP;
-     expressionS *exprP;
+cris_get_expression (char **cPP, expressionS *exprP)
 {
   char *saved_input_line_pointer;
   segT exp;
 {
   char *saved_input_line_pointer;
   segT exp;
@@ -3114,9 +3129,7 @@ cris_get_expression (cPP, exprP)
    Return 1 iff a correct flags expression is found.  */
 
 static int
    Return 1 iff a correct flags expression is found.  */
 
 static int
-get_flags (cPP, flagsp)
-     char **cPP;
-     int *flagsp;
+get_flags (char **cPP, int *flagsp)
 {
   for (;;)
     {
 {
   for (;;)
     {
@@ -3225,9 +3238,7 @@ get_flags (cPP, flagsp)
    exprP       Pointer to structure containing the offset expression.  */
 
 static void
    exprP       Pointer to structure containing the offset expression.  */
 
 static void
-gen_bdap (base_regno, exprP)
-     int base_regno;
-     expressionS *exprP;
+gen_bdap (int base_regno, expressionS *exprP)
 {
   unsigned int opcode;
   char *opcodep;
 {
   unsigned int opcode;
   char *opcodep;
@@ -3292,8 +3303,7 @@ gen_bdap (base_regno, exprP)
    offset  The displacement value in bytes.  */
 
 static int
    offset  The displacement value in bytes.  */
 
 static int
-branch_disp (offset)
-     int offset;
+branch_disp (int offset)
 {
   int disp;
 
 {
   int disp;
 
@@ -3325,13 +3335,8 @@ branch_disp (offset)
    add_num.  */
 
 static void
    add_num.  */
 
 static void
-gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num)
-     char *opcodep;
-     char *writep;
-     fragS *fragP;
-     symbolS *add_symP;
-     symbolS *sub_symP;
-     long int add_num;
+gen_cond_branch_32 (char *opcodep, char *writep, fragS *fragP,
+                   symbolS *add_symP, symbolS *sub_symP, long int add_num)
 {
   int nop_opcode;
   int opc_offset;
 {
   int nop_opcode;
   int opc_offset;
@@ -3343,6 +3348,12 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num)
       opc_offset = 10;
       branch_offset = -2 - 8;
     }
       opc_offset = 10;
       branch_offset = -2 - 8;
     }
+  else if (pic)
+    {
+      nop_opcode = NOP_OPCODE;
+      opc_offset = 10;
+      branch_offset = -2 - 8;
+    }
   else
     {
       nop_opcode = NOP_OPCODE;
   else
     {
       nop_opcode = NOP_OPCODE;
@@ -3381,18 +3392,20 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num)
      merged later.  */
 
   md_number_to_chars (opcodep, BA_QUICK_OPCODE
      merged later.  */
 
   md_number_to_chars (opcodep, BA_QUICK_OPCODE
-                     + (cris_arch == arch_crisv32 ? 12 : 8), 2);
+                     + (cris_arch == arch_crisv32 ? 12 : (pic ? 10 : 8)),
+                     2);
   md_number_to_chars (writep, nop_opcode, 2);
 
   /* Then the extended thing, the 32-bit jump insn.
        opcodep+4: JUMP [PC+]
      or, in the PIC case,
   md_number_to_chars (writep, nop_opcode, 2);
 
   /* Then the extended thing, the 32-bit jump insn.
        opcodep+4: JUMP [PC+]
      or, in the PIC case,
-       opcodep+4: ADD [PC+],PC.  */
+       opcodep+4: MOVE [PC=PC+N],P0.  */
 
   md_number_to_chars (writep + 2,
                      cris_arch == arch_crisv32
                      ? BA_DWORD_OPCODE
 
   md_number_to_chars (writep + 2,
                      cris_arch == arch_crisv32
                      ? BA_DWORD_OPCODE
-                     : (pic ? ADD_PC_INCR_OPCODE : JUMP_PC_INCR_OPCODE), 2);
+                     : (pic ? MOVE_PC_INCR_OPCODE_PREFIX
+                        : JUMP_PC_INCR_OPCODE), 2);
 
   /* We have to fill in the actual value too.
        opcodep+6: .DWORD
 
   /* We have to fill in the actual value too.
        opcodep+6: .DWORD
@@ -3428,16 +3441,24 @@ gen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num)
   if (cris_arch == arch_crisv32)
     /* Follow it with a "NOP" for CRISv32.  */
     md_number_to_chars (writep + 8, NOP_OPCODE_V32, 2);
   if (cris_arch == arch_crisv32)
     /* Follow it with a "NOP" for CRISv32.  */
     md_number_to_chars (writep + 8, NOP_OPCODE_V32, 2);
+  else if (pic)
+    /* ...and the rest of the move-opcode for pre-v32 PIC.  */
+    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
 
 static unsigned int
-cris_get_pic_reloc_size (reloc)
-     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;
 }
 
     ? 2 : 4;
 }
 
@@ -3445,10 +3466,8 @@ cris_get_pic_reloc_size (reloc)
    Adjust *EXPRP with any addend found after the PIC suffix.  */
 
 static void
    Adjust *EXPRP with any addend found after the PIC suffix.  */
 
 static void
-cris_get_pic_suffix (cPP, relocp, exprP)
-     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;
 {
   char *s = *cPP;
   unsigned int i;
@@ -3459,10 +3478,14 @@ cris_get_pic_suffix (cPP, relocp, exprP)
     const char *const suffix;
     unsigned int len;
     bfd_reloc_code_real_type reloc;
     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
   } 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),
       /* Keep this in order with longest unambiguous prefix first.  */
       PICMAP ("GOTPLT16", BFD_RELOC_CRIS_16_GOTPLT),
       PICMAP ("GOTPLT", BFD_RELOC_CRIS_32_GOTPLT),
@@ -3470,7 +3493,17 @@ cris_get_pic_suffix (cPP, relocp, exprP)
       PICMAP ("PLT", BFD_RELOC_CRIS_32_PLT_PCREL),
       PICMAP ("GOTOFF", BFD_RELOC_CRIS_32_GOTREL),
       PICMAP ("GOT16", BFD_RELOC_CRIS_16_GOT),
       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),
+      TLSMAP ("IE", BFD_RELOC_CRIS_32_IE),
+      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.  */
     };
 
   /* We've already seen the ':', so consume it.  */
@@ -3479,7 +3512,11 @@ cris_get_pic_suffix (cPP, relocp, exprP)
   for (i = 0; i < sizeof (pic_suffixes)/sizeof (pic_suffixes[0]); i++)
     {
       if (strncmp (s, pic_suffixes[i].suffix, pic_suffixes[i].len) == 0
   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.   */
        {
          /* We have a match.  Consume the suffix and set the relocation
             type.   */
@@ -3536,10 +3573,8 @@ cris_get_pic_suffix (cPP, relocp, exprP)
    find out the correct bit patterns and use them.  */
 
 char *
    find out the correct bit patterns and use them.  */
 
 char *
-md_atof (type, litp, sizep)
-     char type ATTRIBUTE_UNUSED;
-     char *litp ATTRIBUTE_UNUSED;
-     int *sizep ATTRIBUTE_UNUSED;
+md_atof (int type ATTRIBUTE_UNUSED, char *litp ATTRIBUTE_UNUSED,
+        int *sizep ATTRIBUTE_UNUSED)
 {
   /* FIXME:  Is this function mentioned in the internals.texi manual?  If
      not, add it.  */
 {
   /* FIXME:  Is this function mentioned in the internals.texi manual?  If
      not, add it.  */
@@ -3562,12 +3597,7 @@ md_atof (type, litp, sizep)
    seg       The segment containing this number.  */
 
 static void
    seg       The segment containing this number.  */
 
 static void
-cris_number_to_imm (bufp, val, n, fixP, seg)
-     char *bufp;
-     long val;
-     int n;
-     fixS *fixP;
-     segT seg;
+cris_number_to_imm (char *bufp, long val, int n, fixS *fixP, segT seg)
 {
   segT sym_seg;
 
 {
   segT sym_seg;
 
@@ -3594,10 +3624,12 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
        ;
       }
 
        ;
       }
 
-  /* Only do this for old-arch binaries.  */
+  /* Only use the computed value for old-arch binaries.  For all
+     others, where we're going to output a relocation, put 0 in the
+     code.  */
   if (cris_arch != arch_cris_any_v0_v10
       && (fixP->fx_addsy != NULL || fixP->fx_pcrel))
   if (cris_arch != arch_cris_any_v0_v10
       && (fixP->fx_addsy != NULL || fixP->fx_pcrel))
-    return;
+    val = 0;
 
   switch (fixP->fx_r_type)
     {
 
   switch (fixP->fx_r_type)
     {
@@ -3606,6 +3638,22 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
         regression tests on the object file contents.  FIXME:  Seems
         uninteresting now that we have a test suite.  */
 
         regression tests on the object file contents.  FIXME:  Seems
         uninteresting now that we have a test suite.  */
 
+    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_IE:
+    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:
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+      if (IS_ELF && fixP->fx_addsy != NULL)
+       S_SET_THREAD_LOCAL (fixP->fx_addsy);
+#endif
+      /* Fall through.  */
+
     case BFD_RELOC_CRIS_16_GOT:
     case BFD_RELOC_CRIS_32_GOT:
     case BFD_RELOC_CRIS_32_GOTREL:
     case BFD_RELOC_CRIS_16_GOT:
     case BFD_RELOC_CRIS_32_GOT:
     case BFD_RELOC_CRIS_32_GOTREL:
@@ -3615,13 +3663,14 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
     case BFD_RELOC_CRIS_32_PLT_PCREL:
       /* We don't want to put in any kind of non-zero bits in the data
         being relocated for these.  */
     case BFD_RELOC_CRIS_32_PLT_PCREL:
       /* We don't want to put in any kind of non-zero bits in the data
         being relocated for these.  */
+      md_number_to_chars (bufp, 0, n);
       break;
 
     case BFD_RELOC_32_PCREL:
       break;
 
     case BFD_RELOC_32_PCREL:
-      /* If this one isn't fully resolved, we don't want to put anything
+      /* If this one isn't fully resolved, we don't want to put non-zero
         in the object.  */
       if (fixP->fx_addsy != NULL || fixP->fx_pcrel)
         in the object.  */
       if (fixP->fx_addsy != NULL || fixP->fx_pcrel)
-       break;
+       val = 0;
 
       /* Fall through.  */
     case BFD_RELOC_32:
 
       /* Fall through.  */
     case BFD_RELOC_32:
@@ -3643,38 +3692,30 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
       if (val > 0xffff || val < -32768)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 16 bit range: %ld"), val);
       if (val > 0xffff || val < -32768)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 16 bit range: %ld"), val);
-      if (! fixP->fx_addsy)
-       {
-         bufp[1] = (val >> 8) & 0xFF;
-         bufp[0] = val & 0xFF;
-       }
+      bufp[1] = (val >> 8) & 0xFF;
+      bufp[0] = val & 0xFF;
       break;
 
     case BFD_RELOC_CRIS_SIGNED_16:
       if (val > 32767 || val < -32768)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 16 bit signed range: %ld"), val);
       break;
 
     case BFD_RELOC_CRIS_SIGNED_16:
       if (val > 32767 || val < -32768)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 16 bit signed range: %ld"), val);
-      if (! fixP->fx_addsy)
-       {
-         bufp[1] = (val >> 8) & 0xFF;
-         bufp[0] = val & 0xFF;
-       }
+      bufp[1] = (val >> 8) & 0xFF;
+      bufp[0] = val & 0xFF;
       break;
 
     case BFD_RELOC_8:
     case BFD_RELOC_8_PCREL:
       if (val > 255 || val < -128)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 8 bit range: %ld"), val);
       break;
 
     case BFD_RELOC_8:
     case BFD_RELOC_8_PCREL:
       if (val > 255 || val < -128)
        as_bad_where (fixP->fx_file, fixP->fx_line, _("Value not in 8 bit range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] = val & 0xFF;
+      bufp[0] = val & 0xFF;
       break;
 
     case BFD_RELOC_CRIS_SIGNED_8:
       if (val > 127 || val < -128)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 8 bit signed range: %ld"), val);
       break;
 
     case BFD_RELOC_CRIS_SIGNED_8:
       if (val > 127 || val < -128)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 8 bit signed range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] = val & 0xFF;
+      bufp[0] = val & 0xFF;
       break;
 
     case BFD_RELOC_CRIS_LAPCQ_OFFSET:
       break;
 
     case BFD_RELOC_CRIS_LAPCQ_OFFSET:
@@ -3684,37 +3725,32 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
       if (val > 15 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 4 bit unsigned range: %ld"), val);
       if (val > 15 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 4 bit unsigned range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] |= val & 0x0F;
+      bufp[0] |= val & 0x0F;
       break;
 
     case BFD_RELOC_CRIS_UNSIGNED_5:
       if (val > 31 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 5 bit unsigned range: %ld"), val);
       break;
 
     case BFD_RELOC_CRIS_UNSIGNED_5:
       if (val > 31 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 5 bit unsigned range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] |= val & 0x1F;
+      bufp[0] |= val & 0x1F;
       break;
 
     case BFD_RELOC_CRIS_SIGNED_6:
       if (val > 31 || val < -32)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 6 bit range: %ld"), val);
       break;
 
     case BFD_RELOC_CRIS_SIGNED_6:
       if (val > 31 || val < -32)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 6 bit range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] |= val & 0x3F;
+      bufp[0] |= val & 0x3F;
       break;
 
     case BFD_RELOC_CRIS_UNSIGNED_6:
       if (val > 63 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 6 bit unsigned range: %ld"), val);
       break;
 
     case BFD_RELOC_CRIS_UNSIGNED_6:
       if (val > 63 || val < 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("Value not in 6 bit unsigned range: %ld"), val);
-      if (! fixP->fx_addsy)
-       bufp[0] |= val & 0x3F;
+      bufp[0] |= val & 0x3F;
       break;
 
     case BFD_RELOC_CRIS_BDISP8:
       break;
 
     case BFD_RELOC_CRIS_BDISP8:
-      if (! fixP->fx_addsy)
-       bufp[0] = branch_disp (val);
+      bufp[0] = branch_disp (val);
       break;
 
     case BFD_RELOC_NONE:
       break;
 
     case BFD_RELOC_NONE:
@@ -3747,9 +3783,7 @@ cris_number_to_imm (bufp, val, n, fixP, seg)
    GAS does not understand.  */
 
 int
    GAS does not understand.  */
 
 int
-md_parse_option (arg, argp)
-     int arg;
-     char *argp ATTRIBUTE_UNUSED;
+md_parse_option (int arg, char *argp ATTRIBUTE_UNUSED)
 {
   switch (arg)
     {
 {
   switch (arg)
     {
@@ -3779,6 +3813,10 @@ md_parse_option (arg, argp)
 
     case OPTION_PIC:
       pic = TRUE;
 
     case OPTION_PIC:
       pic = TRUE;
+      if (cris_arch != arch_crisv32)
+       md_long_jump_size = cris_any_v0_v10_long_jump_size_pic;
+      else
+       md_long_jump_size = crisv32_long_jump_size;
       break;
 
     case OPTION_ARCH:
       break;
 
     case OPTION_ARCH:
@@ -3797,7 +3835,12 @@ md_parse_option (arg, argp)
            md_long_jump_size = crisv32_long_jump_size;
          }
        else
            md_long_jump_size = crisv32_long_jump_size;
          }
        else
-         md_long_jump_size = cris_any_v0_v10_long_jump_size;
+         {
+           if (pic)
+             md_long_jump_size = cris_any_v0_v10_long_jump_size_pic;
+           else
+             md_long_jump_size = cris_any_v0_v10_long_jump_size;
+         }
       }
       break;
 
       }
       break;
 
@@ -3818,9 +3861,7 @@ md_parse_option (arg, argp)
 
 /* Round up a section size to the appropriate boundary.  */
 valueT
 
 /* Round up a section size to the appropriate boundary.  */
 valueT
-md_section_align (segment, size)
-     segT segment;
-     valueT size;
+md_section_align (segT segment, valueT size)
 {
   /* Round all sects to multiple of 4, except the bss section, which
      we'll round to word-size.
 {
   /* Round all sects to multiple of 4, except the bss section, which
      we'll round to word-size.
@@ -3848,9 +3889,7 @@ md_section_align (segment, size)
 
 /* Generate a machine-dependent relocation.  */
 arelent *
 
 /* Generate a machine-dependent relocation.  */
 arelent *
-tc_gen_reloc (section, fixP)
-     asection *section ATTRIBUTE_UNUSED;
-     fixS *fixP;
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
 {
   arelent *relP;
   bfd_reloc_code_real_type code;
 {
   arelent *relP;
   bfd_reloc_code_real_type code;
@@ -3881,6 +3920,16 @@ tc_gen_reloc (section, fixP)
     case BFD_RELOC_CRIS_UNSIGNED_8:
     case BFD_RELOC_CRIS_UNSIGNED_16:
     case BFD_RELOC_CRIS_LAPCQ_OFFSET:
     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_IE:
+    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:
       code = fixP->fx_r_type;
       break;
     default:
@@ -3890,7 +3939,7 @@ tc_gen_reloc (section, fixP)
     }
 
   relP = (arelent *) xmalloc (sizeof (arelent));
     }
 
   relP = (arelent *) xmalloc (sizeof (arelent));
-  assert (relP != 0);
+  gas_assert (relP != 0);
   relP->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
   relP->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
@@ -3944,8 +3993,7 @@ tc_gen_reloc (section, fixP)
 /* Machine-dependent usage-output.  */
 
 void
 /* Machine-dependent usage-output.  */
 
 void
-md_show_usage (stream)
-     FILE *stream;
+md_show_usage (FILE *stream)
 {
   /* The messages are formatted to line up with the generic options.  */
   fprintf (stream, _("CRIS-specific options:\n"));
 {
   /* The messages are formatted to line up with the generic options.  */
   fprintf (stream, _("CRIS-specific options:\n"));
@@ -3972,10 +4020,7 @@ md_show_usage (stream)
    enough info to complete immediately) to the data in a frag.  */
 
 void
    enough info to complete immediately) to the data in a frag.  */
 
 void
-md_apply_fix3 (fixP, valP, seg)
-     fixS *fixP;
-     valueT *valP;
-     segT seg;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 {
   /* This assignment truncates upper bits if valueT is 64 bits (as with
      --enable-64-bit-bfd), which is fine here, though we cast to avoid
 {
   /* This assignment truncates upper bits if valueT is 64 bits (as with
      --enable-64-bit-bfd), which is fine here, though we cast to avoid
@@ -4009,8 +4054,7 @@ md_apply_fix3 (fixP, valP, seg)
    the address of the fixup plus its size.  */
 
 long
    the address of the fixup plus its size.  */
 
 long
-md_pcrel_from (fixP)
-     fixS *fixP;
+md_pcrel_from (fixS *fixP)
 {
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 
 {
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 
@@ -4032,8 +4076,7 @@ md_pcrel_from (fixP)
 
 /* We have no need to give defaults for symbol-values.  */
 symbolS *
 
 /* We have no need to give defaults for symbol-values.  */
 symbolS *
-md_undefined_symbol (name)
-     char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 {
   return 0;
 }
@@ -4043,8 +4086,7 @@ md_undefined_symbol (name)
    against section symbols, and guarantees that a relocation will be
    emitted even when the value can be resolved locally.  */
 int
    against section symbols, and guarantees that a relocation will be
    emitted even when the value can be resolved locally.  */
 int
-md_cris_force_relocation (fixp)
-     struct fix *fixp;
+md_cris_force_relocation (struct fix *fixp)
 {
   switch (fixp->fx_r_type)
     {
 {
   switch (fixp->fx_r_type)
     {
@@ -4068,9 +4110,7 @@ md_cris_force_relocation (fixp)
    knows about how to handle broken words.  */
 
 void
    knows about how to handle broken words.  */
 
 void
-tc_cris_check_adjusted_broken_word (new_offset, brokwP)
-     offsetT new_offset;
-     struct broken_word *brokwP;
+tc_cris_check_adjusted_broken_word (offsetT new_offset, struct broken_word *brokwP)
 {
   if (new_offset > 32767 || new_offset < -32768)
     /* We really want a genuine error, not a warning, so make it one.  */
 {
   if (new_offset > 32767 || new_offset < -32768)
     /* We really want a genuine error, not a warning, so make it one.  */
@@ -4081,21 +4121,24 @@ tc_cris_check_adjusted_broken_word (new_offset, brokwP)
 
 /* Make a leading REGISTER_PREFIX_CHAR mandatory for all registers.  */
 
 
 /* Make a leading REGISTER_PREFIX_CHAR mandatory for all registers.  */
 
-static void cris_force_reg_prefix ()
+static void
+cris_force_reg_prefix (void)
 {
   demand_register_prefix = TRUE;
 }
 
 /* Do not demand a leading REGISTER_PREFIX_CHAR for all registers.  */
 
 {
   demand_register_prefix = TRUE;
 }
 
 /* Do not demand a leading REGISTER_PREFIX_CHAR for all registers.  */
 
-static void cris_relax_reg_prefix ()
+static void
+cris_relax_reg_prefix (void)
 {
   demand_register_prefix = FALSE;
 }
 
 /* Adjust for having a leading '_' on all user symbols.  */
 
 {
   demand_register_prefix = FALSE;
 }
 
 /* Adjust for having a leading '_' on all user symbols.  */
 
-static void cris_sym_leading_underscore ()
+static void
+cris_sym_leading_underscore (void)
 {
   /* We can't really do anything more than assert that what the program
      thinks symbol starts with agrees with the command-line options, since
 {
   /* We can't really do anything more than assert that what the program
      thinks symbol starts with agrees with the command-line options, since
@@ -4108,7 +4151,7 @@ static void cris_sym_leading_underscore ()
 
 /* Adjust for not having any particular prefix on user symbols.  */
 
 
 /* Adjust for not having any particular prefix on user symbols.  */
 
-static void cris_sym_no_leading_underscore ()
+static void cris_sym_no_leading_underscore (void)
 {
   if (symbols_have_leading_underscore)
     as_bad (_(".syntax %s requires command-line option `--no-underscore'"),
 {
   if (symbols_have_leading_underscore)
     as_bad (_(".syntax %s requires command-line option `--no-underscore'"),
@@ -4119,13 +4162,12 @@ static void cris_sym_no_leading_underscore ()
    syntax the assembly code has.  */
 
 static void
    syntax the assembly code has.  */
 
 static void
-s_syntax (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+s_syntax (int ignore ATTRIBUTE_UNUSED)
 {
   static const struct syntaxes
   {
     const char *const operand;
 {
   static const struct syntaxes
   {
     const char *const operand;
-    void (*fn) PARAMS ((void));
+    void (*fn) (void);
   } syntax_table[] =
     {{SYNTAX_ENFORCE_REG_PREFIX, cris_force_reg_prefix},
      {SYNTAX_RELAX_REG_PREFIX, cris_relax_reg_prefix},
   } syntax_table[] =
     {{SYNTAX_ENFORCE_REG_PREFIX, cris_force_reg_prefix},
      {SYNTAX_RELAX_REG_PREFIX, cris_relax_reg_prefix},
@@ -4156,8 +4198,7 @@ s_syntax (ignore)
    not emitting ELF.  */
 
 static void
    not emitting ELF.  */
 
 static void
-s_cris_file (dummy)
-     int dummy;
+s_cris_file (int dummy)
 {
   if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
     as_bad (_("Pseudodirective .file is only valid when generating ELF"));
 {
   if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
     as_bad (_("Pseudodirective .file is only valid when generating ELF"));
@@ -4169,8 +4210,7 @@ s_cris_file (dummy)
    emitting ELF.  */
 
 static void
    emitting ELF.  */
 
 static void
-s_cris_loc (dummy)
-     int dummy;
+s_cris_loc (int dummy)
 {
   if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
     as_bad (_("Pseudodirective .loc is only valid when generating ELF"));
 {
   if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
     as_bad (_("Pseudodirective .loc is only valid when generating ELF"));
@@ -4178,14 +4218,37 @@ s_cris_loc (dummy)
     dwarf2_directive_loc (dummy);
 }
 
     dwarf2_directive_loc (dummy);
 }
 
+/* Worker for .dtpoffd: generate a R_CRIS_32_DTPREL reloc, as for
+   expr:DTPREL but for use in debug info.  */
+
+static void
+s_cris_dtpoff (int bytes)
+{
+  expressionS ex;
+  char *p;
+
+  if (bytes != 4)
+    as_fatal (_("internal inconsistency problem: %s called for %d bytes"),
+             __FUNCTION__, bytes);
+
+  expression (&ex);
+
+  p = frag_more (bytes);
+  md_number_to_chars (p, 0, bytes);
+  fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE,
+              BFD_RELOC_CRIS_32_DTPREL);
+
+  demand_empty_rest_of_line ();
+}
+
+
 /* Translate a <arch> string (as common to --march=<arch> and .arch <arch>)
    into an enum.  If the string *STR is recognized, *STR is updated to point
    to the end of the string.  If the string is not recognized,
    arch_cris_unknown is returned.  */
 
 static enum cris_archs
 /* Translate a <arch> string (as common to --march=<arch> and .arch <arch>)
    into an enum.  If the string *STR is recognized, *STR is updated to point
    to the end of the string.  If the string is not recognized,
    arch_cris_unknown is returned.  */
 
 static enum cris_archs
-cris_arch_from_string (str)
-     char **str;
+cris_arch_from_string (char **str)
 {
   static const struct cris_arch_struct
   {
 {
   static const struct cris_arch_struct
   {
@@ -4222,9 +4285,8 @@ cris_arch_from_string (str)
    IVER.  */
 
 static int
    IVER.  */
 
 static int
-cris_insn_ver_valid_for_arch (iver, arch)
-     enum cris_insn_version_usage iver;
-     enum cris_archs arch;
+cris_insn_ver_valid_for_arch (enum cris_insn_version_usage iver,
+                             enum cris_archs arch)
 {
   switch (arch)
     {
 {
   switch (arch)
     {
@@ -4306,8 +4368,7 @@ cris_insn_ver_valid_for_arch (iver, arch)
    default --march=<ARCHCHOICE2> option.  */
 
 static void
    default --march=<ARCHCHOICE2> option.  */
 
 static void
-s_cris_arch (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+s_cris_arch (int dummy ATTRIBUTE_UNUSED)
 {
   /* Right now we take the easy route and check for sameness.  It's not
      obvious that allowing e.g. --march=v32 and .arch common_v0_v32
 {
   /* Right now we take the easy route and check for sameness.  It's not
      obvious that allowing e.g. --march=v32 and .arch common_v0_v32
This page took 0.044841 seconds and 4 git commands to generate.