2000-12-03 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index b9d7dd425ec5143d5c47017b3b44ceb7f6ea0759..9985f437064b3dcc9e469c91471c4d87a7f7ae49 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
-   Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
@@ -17,7 +18,7 @@
    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
    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. */
+   02111-1307, USA.  */
 
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
@@ -53,6 +54,7 @@ static int set_target_endian = 0;
 
 static boolean reg_names_p = TARGET_REG_NAMES_P;
 
 
 static boolean reg_names_p = TARGET_REG_NAMES_P;
 
+static boolean register_name PARAMS ((expressionS *));
 static void ppc_set_cpu PARAMS ((void));
 static unsigned long ppc_insert_operand
   PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
 static void ppc_set_cpu PARAMS ((void));
 static unsigned long ppc_insert_operand
   PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
@@ -79,9 +81,13 @@ static void ppc_function PARAMS ((int));
 static void ppc_extern PARAMS ((int));
 static void ppc_lglobl PARAMS ((int));
 static void ppc_section PARAMS ((int));
 static void ppc_extern PARAMS ((int));
 static void ppc_lglobl PARAMS ((int));
 static void ppc_section PARAMS ((int));
+static void ppc_named_section PARAMS ((int));
 static void ppc_stabx PARAMS ((int));
 static void ppc_rename PARAMS ((int));
 static void ppc_toc PARAMS ((int));
 static void ppc_stabx PARAMS ((int));
 static void ppc_rename PARAMS ((int));
 static void ppc_toc PARAMS ((int));
+static void ppc_xcoff_cons PARAMS ((int));
+static void ppc_machine PARAMS ((int));
+static void ppc_vbyte PARAMS ((int));
 #endif
 
 #ifdef OBJ_ELF
 #endif
 
 #ifdef OBJ_ELF
@@ -110,6 +116,7 @@ static void ppc_pe_tocd PARAMS ((int));
 /* Generic assembler global variables which must be defined by all
    targets.  */
 
 /* Generic assembler global variables which must be defined by all
    targets.  */
 
+#ifdef OBJ_ELF
 /* This string holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  The macro
    tc_comment_chars points to this.  We use this, rather than the
 /* This string holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  The macro
    tc_comment_chars points to this.  We use this, rather than the
@@ -122,6 +129,9 @@ const char *ppc_comment_chars = ppc_solaris_comment_chars;
 #else
 const char *ppc_comment_chars = ppc_eabi_comment_chars;
 #endif
 #else
 const char *ppc_comment_chars = ppc_eabi_comment_chars;
 #endif
+#else
+const char comment_chars[] = "#";
+#endif
 
 /* Characters which start a comment at the beginning of a line.  */
 const char line_comment_chars[] = "#";
 
 /* Characters which start a comment at the beginning of a line.  */
 const char line_comment_chars[] = "#";
@@ -168,9 +178,16 @@ const pseudo_typeS md_pseudo_table[] =
   { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
   { "rename",  ppc_rename,     0 },
   { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
   { "rename",  ppc_rename,     0 },
+  { "section", ppc_named_section, 0 },
   { "stabx",   ppc_stabx,      0 },
   { "text",    ppc_section,    't' },
   { "toc",     ppc_toc,        0 },
   { "stabx",   ppc_stabx,      0 },
   { "text",    ppc_section,    't' },
   { "toc",     ppc_toc,        0 },
+  { "long",    ppc_xcoff_cons, 2 },
+  { "llong",   ppc_xcoff_cons, 3 },
+  { "word",    ppc_xcoff_cons, 1 },
+  { "short",   ppc_xcoff_cons, 1 },
+  { "vbyte",    ppc_vbyte,     0 },
+  { "machine",  ppc_machine,    0 },
 #endif
 
 #ifdef OBJ_ELF
 #endif
 
 #ifdef OBJ_ELF
@@ -222,11 +239,14 @@ struct pd_reg
    1. r<reg_num> which has the value <reg_num>.
    2. r.<reg_num> which has the value <reg_num>.
 
    1. r<reg_num> which has the value <reg_num>.
    2. r.<reg_num> which has the value <reg_num>.
 
-
    Each floating point register has predefined names of the form:
    1. f<reg_num> which has the value <reg_num>.
    2. f.<reg_num> which has the value <reg_num>.
 
    Each floating point register has predefined names of the form:
    1. f<reg_num> which has the value <reg_num>.
    2. f.<reg_num> which has the value <reg_num>.
 
+   Each vector unit register has predefined names of the form:
+   1. v<reg_num> which has the value <reg_num>.
+   2. v.<reg_num> which has the value <reg_num>.
+
    Each condition register has predefined names of the form:
    1. cr<reg_num> which has the value <reg_num>.
    2. cr.<reg_num> which has the value <reg_num>.
    Each condition register has predefined names of the form:
    1. cr<reg_num> which has the value <reg_num>.
    2. cr.<reg_num> which has the value <reg_num>.
@@ -246,7 +266,7 @@ struct pd_reg
    srr0           has the value 26
    srr1           has the value 27
 
    srr0           has the value 26
    srr1           has the value 27
 
-   The table is sorted. Suitable for searching by a binary search. */
+   The table is sorted. Suitable for searching by a binary search.  */
 
 static const struct pd_reg pre_defined_registers[] =
 {
 
 static const struct pd_reg pre_defined_registers[] =
 {
@@ -275,70 +295,70 @@ static const struct pd_reg pre_defined_registers[] =
   { "dsisr", 18 },  /* Data Storage Interrupt Status Register */
 
   { "f.0", 0 },     /* Floating point registers */
   { "dsisr", 18 },  /* Data Storage Interrupt Status Register */
 
   { "f.0", 0 },     /* Floating point registers */
-  { "f.1", 1 }, 
-  { "f.10", 10 }, 
-  { "f.11", 11 }, 
-  { "f.12", 12 }, 
-  { "f.13", 13 }, 
-  { "f.14", 14 }, 
-  { "f.15", 15 }, 
-  { "f.16", 16 }, 
-  { "f.17", 17 }, 
-  { "f.18", 18 }, 
-  { "f.19", 19 }, 
-  { "f.2", 2 }, 
-  { "f.20", 20 }, 
-  { "f.21", 21 }, 
-  { "f.22", 22 }, 
-  { "f.23", 23 }, 
-  { "f.24", 24 }, 
-  { "f.25", 25 }, 
-  { "f.26", 26 }, 
-  { "f.27", 27 }, 
-  { "f.28", 28 }, 
-  { "f.29", 29 }, 
-  { "f.3", 3 }, 
+  { "f.1", 1 },
+  { "f.10", 10 },
+  { "f.11", 11 },
+  { "f.12", 12 },
+  { "f.13", 13 },
+  { "f.14", 14 },
+  { "f.15", 15 },
+  { "f.16", 16 },
+  { "f.17", 17 },
+  { "f.18", 18 },
+  { "f.19", 19 },
+  { "f.2", 2 },
+  { "f.20", 20 },
+  { "f.21", 21 },
+  { "f.22", 22 },
+  { "f.23", 23 },
+  { "f.24", 24 },
+  { "f.25", 25 },
+  { "f.26", 26 },
+  { "f.27", 27 },
+  { "f.28", 28 },
+  { "f.29", 29 },
+  { "f.3", 3 },
   { "f.30", 30 },
   { "f.31", 31 },
   { "f.30", 30 },
   { "f.31", 31 },
-  { "f.4", 4 }, 
-  { "f.5", 5 }, 
-  { "f.6", 6 }, 
-  { "f.7", 7 }, 
-  { "f.8", 8 }, 
-  { "f.9", 9 }, 
-
-  { "f0", 0 }, 
-  { "f1", 1 }, 
-  { "f10", 10 }, 
-  { "f11", 11 }, 
-  { "f12", 12 }, 
-  { "f13", 13 }, 
-  { "f14", 14 }, 
-  { "f15", 15 }, 
-  { "f16", 16 }, 
-  { "f17", 17 }, 
-  { "f18", 18 }, 
-  { "f19", 19 }, 
-  { "f2", 2 }, 
-  { "f20", 20 }, 
-  { "f21", 21 }, 
-  { "f22", 22 }, 
-  { "f23", 23 }, 
-  { "f24", 24 }, 
-  { "f25", 25 }, 
-  { "f26", 26 }, 
-  { "f27", 27 }, 
-  { "f28", 28 }, 
-  { "f29", 29 }, 
-  { "f3", 3 }, 
+  { "f.4", 4 },
+  { "f.5", 5 },
+  { "f.6", 6 },
+  { "f.7", 7 },
+  { "f.8", 8 },
+  { "f.9", 9 },
+
+  { "f0", 0 },
+  { "f1", 1 },
+  { "f10", 10 },
+  { "f11", 11 },
+  { "f12", 12 },
+  { "f13", 13 },
+  { "f14", 14 },
+  { "f15", 15 },
+  { "f16", 16 },
+  { "f17", 17 },
+  { "f18", 18 },
+  { "f19", 19 },
+  { "f2", 2 },
+  { "f20", 20 },
+  { "f21", 21 },
+  { "f22", 22 },
+  { "f23", 23 },
+  { "f24", 24 },
+  { "f25", 25 },
+  { "f26", 26 },
+  { "f27", 27 },
+  { "f28", 28 },
+  { "f29", 29 },
+  { "f3", 3 },
   { "f30", 30 },
   { "f31", 31 },
   { "f30", 30 },
   { "f31", 31 },
-  { "f4", 4 }, 
-  { "f5", 5 }, 
-  { "f6", 6 }, 
-  { "f7", 7 }, 
-  { "f8", 8 }, 
-  { "f9", 9 }, 
+  { "f4", 4 },
+  { "f5", 5 },
+  { "f6", 6 },
+  { "f7", 7 },
+  { "f8", 8 },
+  { "f9", 9 },
 
   { "fpscr", 0 },
 
 
   { "fpscr", 0 },
 
@@ -425,11 +445,77 @@ static const struct pd_reg pre_defined_registers[] =
   { "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
   { "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
 
   { "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
   { "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
 
+  { "v.0", 0 },     /* Vector registers */
+  { "v.1", 1 },
+  { "v.10", 10 },
+  { "v.11", 11 },
+  { "v.12", 12 },
+  { "v.13", 13 },
+  { "v.14", 14 },
+  { "v.15", 15 },
+  { "v.16", 16 },
+  { "v.17", 17 },
+  { "v.18", 18 },
+  { "v.19", 19 },
+  { "v.2", 2 },
+  { "v.20", 20 },
+  { "v.21", 21 },
+  { "v.22", 22 },
+  { "v.23", 23 },
+  { "v.24", 24 },
+  { "v.25", 25 },
+  { "v.26", 26 },
+  { "v.27", 27 },
+  { "v.28", 28 },
+  { "v.29", 29 },
+  { "v.3", 3 },
+  { "v.30", 30 },
+  { "v.31", 31 },
+  { "v.4", 4 },
+  { "v.5", 5 },
+  { "v.6", 6 },
+  { "v.7", 7 },
+  { "v.8", 8 },
+  { "v.9", 9 },
+
+  { "v0", 0 },
+  { "v1", 1 },
+  { "v10", 10 },
+  { "v11", 11 },
+  { "v12", 12 },
+  { "v13", 13 },
+  { "v14", 14 },
+  { "v15", 15 },
+  { "v16", 16 },
+  { "v17", 17 },
+  { "v18", 18 },
+  { "v19", 19 },
+  { "v2", 2 },
+  { "v20", 20 },
+  { "v21", 21 },
+  { "v22", 22 },
+  { "v23", 23 },
+  { "v24", 24 },
+  { "v25", 25 },
+  { "v26", 26 },
+  { "v27", 27 },
+  { "v28", 28 },
+  { "v29", 29 },
+  { "v3", 3 },
+  { "v30", 30 },
+  { "v31", 31 },
+  { "v4", 4 },
+  { "v5", 5 },
+  { "v6", 6 },
+  { "v7", 7 },
+  { "v8", 8 },
+  { "v9", 9 },
+
   { "xer", 1 },
 
 };
 
   { "xer", 1 },
 
 };
 
-#define REG_NAME_CNT   (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+#define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
 
 /* Given NAME, find the register number associated with that name, return
    the integer value associated with the given name or -1 on failure.  */
 
 /* Given NAME, find the register number associated with that name, return
    the integer value associated with the given name or -1 on failure.  */
@@ -498,11 +584,11 @@ register_name (expressionP)
   reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
 
   /* look to see if it's in the register table */
   reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
 
   /* look to see if it's in the register table */
-  if (reg_number >= 0) 
+  if (reg_number >= 0)
     {
       expressionP->X_op = O_register;
       expressionP->X_add_number = reg_number;
     {
       expressionP->X_op = O_register;
       expressionP->X_add_number = reg_number;
-      
+
       /* make the rest nice */
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
       /* make the rest nice */
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
@@ -575,7 +661,10 @@ static int ppc_cpu = 0;
 
 /* The size of the processor we are assembling for.  This is either
    PPC_OPCODE_32 or PPC_OPCODE_64.  */
 
 /* The size of the processor we are assembling for.  This is either
    PPC_OPCODE_32 or PPC_OPCODE_64.  */
-static int ppc_size = PPC_OPCODE_32;
+static unsigned long ppc_size = PPC_OPCODE_32;
+
+/* Whether to target xcoff64 */
+static int ppc_xcoff64 = 0;
 
 /* Opcode hash table.  */
 static struct hash_control *ppc_hash;
 
 /* Opcode hash table.  */
 static struct hash_control *ppc_hash;
@@ -656,7 +745,7 @@ static segT reldata_section;
 static segT rdata_section;
 static segT tocdata_section;
 
 static segT rdata_section;
 static segT tocdata_section;
 
-/* The current section and the previous section. See ppc_previous. */
+/* The current section and the previous section. See ppc_previous.  */
 static segT ppc_previous_section;
 static segT ppc_current_section;
 
 static segT ppc_previous_section;
 static segT ppc_current_section;
 
@@ -665,11 +754,6 @@ static segT ppc_current_section;
 #ifdef OBJ_ELF
 symbolS *GOT_symbol;           /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
 #endif /* OBJ_ELF */
 #ifdef OBJ_ELF
 symbolS *GOT_symbol;           /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
 #endif /* OBJ_ELF */
-
-#ifndef WORKING_DOT_WORD
-const int md_short_jump_size = 4;
-const int md_long_jump_size = 4;
-#endif
 \f
 #ifdef OBJ_ELF
 CONST char *md_shortopts = "b:l:usm:K:VQ:";
 \f
 #ifdef OBJ_ELF
 CONST char *md_shortopts = "b:l:usm:K:VQ:";
@@ -679,7 +763,7 @@ CONST char *md_shortopts = "um:";
 struct option md_longopts[] = {
   {NULL, no_argument, NULL, 0}
 };
 struct option md_longopts[] = {
   {NULL, no_argument, NULL, 0}
 };
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
 
 int
 md_parse_option (c, arg)
 
 int
 md_parse_option (c, arg)
@@ -731,6 +815,16 @@ md_parse_option (c, arg)
       break;
 #endif
 
       break;
 #endif
 
+      /* a64 and a32 determine whether to use XCOFF64 or XCOFF32.  */
+    case 'a':
+      if (strcmp (arg, "64") == 0)
+       ppc_xcoff64 = 1;
+      else if (strcmp (arg, "32") == 0)
+       ppc_xcoff64 = 0;
+      else
+       return 0;
+      break;
+
     case 'm':
       /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
          (RIOS2).  */
     case 'm':
       /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
          (RIOS2).  */
@@ -740,7 +834,7 @@ md_parse_option (c, arg)
       else if (strcmp (arg, "pwr") == 0)
        ppc_cpu = PPC_OPCODE_POWER;
       /* -m601 means to assemble for the Motorola PowerPC 601, which includes
       else if (strcmp (arg, "pwr") == 0)
        ppc_cpu = PPC_OPCODE_POWER;
       /* -m601 means to assemble for the Motorola PowerPC 601, which includes
-         instructions that are holdovers from the Power. */
+         instructions that are holdovers from the Power.  */
       else if (strcmp (arg, "601") == 0)
        ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601;
       /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
       else if (strcmp (arg, "601") == 0)
        ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601;
       /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
@@ -748,9 +842,12 @@ md_parse_option (c, arg)
       else if (strcmp (arg, "ppc") == 0
               || strcmp (arg, "ppc32") == 0
               || strcmp (arg, "403") == 0
       else if (strcmp (arg, "ppc") == 0
               || strcmp (arg, "ppc32") == 0
               || strcmp (arg, "403") == 0
+              || strcmp (arg, "405") == 0
               || strcmp (arg, "603") == 0
               || strcmp (arg, "604") == 0)
        ppc_cpu = PPC_OPCODE_PPC;
               || strcmp (arg, "603") == 0
               || strcmp (arg, "604") == 0)
        ppc_cpu = PPC_OPCODE_PPC;
+      else if (strcmp (arg, "7400") == 0)
+        ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
       /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
          620.  */
       else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
       /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
          620.  */
       else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
@@ -758,6 +855,11 @@ md_parse_option (c, arg)
          ppc_cpu = PPC_OPCODE_PPC;
          ppc_size = PPC_OPCODE_64;
        }
          ppc_cpu = PPC_OPCODE_PPC;
          ppc_size = PPC_OPCODE_64;
        }
+      else if (strcmp (arg, "ppc64bridge") == 0)
+       {
+         ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE;
+         ppc_size = PPC_OPCODE_64;
+       }
       /* -mcom means assemble for the common intersection between Power
         and PowerPC.  At present, we just allow the union, rather
         than the intersection.  */
       /* -mcom means assemble for the common intersection between Power
         and PowerPC.  At present, we just allow the union, rather
         than the intersection.  */
@@ -818,7 +920,7 @@ md_parse_option (c, arg)
 #endif
       else
        {
 #endif
       else
        {
-         as_bad ("invalid switch -m%s", arg);
+         as_bad (_("invalid switch -m%s"), arg);
          return 0;
        }
       break;
          return 0;
        }
       break;
@@ -855,21 +957,22 @@ void
 md_show_usage (stream)
      FILE *stream;
 {
 md_show_usage (stream)
      FILE *stream;
 {
-  fprintf(stream, "\
+  fprintf (stream, _("\
 PowerPC options:\n\
 -u                     ignored\n\
 -mpwrx, -mpwr2         generate code for IBM POWER/2 (RIOS2)\n\
 -mpwr                  generate code for IBM POWER (RIOS1)\n\
 -m601                  generate code for Motorola PowerPC 601\n\
 PowerPC options:\n\
 -u                     ignored\n\
 -mpwrx, -mpwr2         generate code for IBM POWER/2 (RIOS2)\n\
 -mpwr                  generate code for IBM POWER (RIOS1)\n\
 -m601                  generate code for Motorola PowerPC 601\n\
--mppc, -mppc32, -m403, -m603, -m604\n\
+-mppc, -mppc32, -m403, -m405, -m603, -m604\n\
                        generate code for Motorola PowerPC 603/604\n\
 -mppc64, -m620         generate code for Motorola PowerPC 620\n\
                        generate code for Motorola PowerPC 603/604\n\
 -mppc64, -m620         generate code for Motorola PowerPC 620\n\
+-mppc64bridge          generate code for PowerPC 64, including bridge insns\n\
 -mcom                  generate code Power/PowerPC common instructions\n\
 -many                  generate code for any architecture (PWR/PWRX/PPC)\n\
 -mregnames             Allow symbolic names for registers\n\
 -mcom                  generate code Power/PowerPC common instructions\n\
 -many                  generate code for any architecture (PWR/PWRX/PPC)\n\
 -mregnames             Allow symbolic names for registers\n\
--mno-regnames          Do not allow symbolic names for registers\n");
+-mno-regnames          Do not allow symbolic names for registers\n"));
 #ifdef OBJ_ELF
 #ifdef OBJ_ELF
-  fprintf(stream, "\
+  fprintf (stream, _("\
 -mrelocatable          support for GCC's -mrelocatble option\n\
 -mrelocatable-lib      support for GCC's -mrelocatble-lib option\n\
 -memb                  set PPC_EMB bit in ELF flags\n\
 -mrelocatable          support for GCC's -mrelocatble option\n\
 -mrelocatable-lib      support for GCC's -mrelocatble-lib option\n\
 -memb                  set PPC_EMB bit in ELF flags\n\
@@ -879,7 +982,7 @@ PowerPC options:\n\
 -msolaris              generate code for Solaris\n\
 -mno-solaris           do not generate code for Solaris\n\
 -V                     print assembler version number\n\
 -msolaris              generate code for Solaris\n\
 -mno-solaris           do not generate code for Solaris\n\
 -V                     print assembler version number\n\
--Qy, -Qn               ignored\n");
+-Qy, -Qn               ignored\n"));
 #endif
 }
 \f
 #endif
 }
 \f
@@ -904,7 +1007,7 @@ ppc_set_cpu ()
               || strcmp (default_cpu, "powerpcle") == 0)
        ppc_cpu = PPC_OPCODE_PPC;
       else
               || strcmp (default_cpu, "powerpcle") == 0)
        ppc_cpu = PPC_OPCODE_PPC;
       else
-       as_fatal ("Unknown default cpu = %s, os = %s", default_cpu, default_os);
+       as_fatal (_("Unknown default cpu = %s, os = %s"), default_cpu, default_os);
     }
 }
 
     }
 }
 
@@ -929,10 +1032,41 @@ ppc_arch ()
        return bfd_arch_powerpc;
     }
 
        return bfd_arch_powerpc;
     }
 
-  as_fatal ("Neither Power nor PowerPC opcodes were selected.");
+  as_fatal (_("Neither Power nor PowerPC opcodes were selected."));
   return bfd_arch_unknown;
 }
 
   return bfd_arch_unknown;
 }
 
+unsigned long
+ppc_mach ()
+{
+  return (ppc_size == PPC_OPCODE_64) ? 620 : 0;
+}
+
+int
+ppc_subseg_align()
+{
+  return (ppc_xcoff64) ? 3 : 2;
+}
+
+extern char*
+ppc_target_format()
+{
+#ifdef OBJ_COFF
+#ifdef TE_PE
+  return (target_big_endian ? "pe-powerpc" : "pe-powerpcle");
+#elif TE_POWERMAC
+#else
+  return (ppc_xcoff64 ? "aixcoff64-rs6000" : "aixcoff-rs6000");
+#endif
+#ifdef TE_POWERMAC
+  return "xcoff-powermac";
+#endif
+#endif
+#ifdef OBJ_ELF
+  return (target_big_endian ? "elf32-powerpc" : "elf32-powerpcle");
+#endif
+}
+
 /* This function is called when the assembler starts up.  It is called
    after the options have been parsed and the output file has been
    opened.  */
 /* This function is called when the assembler starts up.  It is called
    after the options have been parsed and the output file has been
    opened.  */
@@ -949,7 +1083,7 @@ md_begin ()
   ppc_set_cpu ();
 
 #ifdef OBJ_ELF
   ppc_set_cpu ();
 
 #ifdef OBJ_ELF
-  /* Set the ELF flags if desired. */
+  /* Set the ELF flags if desired.  */
   if (ppc_flags && !msolaris)
     bfd_set_private_flags (stdoutput, ppc_flags);
 #endif
   if (ppc_flags && !msolaris)
     bfd_set_private_flags (stdoutput, ppc_flags);
 #endif
@@ -964,7 +1098,8 @@ md_begin ()
 
       if ((op->flags & ppc_cpu) != 0
          && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
 
       if ((op->flags & ppc_cpu) != 0
          && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
-             || (op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == ppc_size))
+             || (op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == ppc_size
+             || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0))
        {
          const char *retval;
 
        {
          const char *retval;
 
@@ -976,7 +1111,7 @@ md_begin ()
                  && (op->flags & PPC_OPCODE_POWER) != 0)
                continue;
 
                  && (op->flags & PPC_OPCODE_POWER) != 0)
                continue;
 
-             as_bad ("Internal assembler error for instruction %s", op->name);
+             as_bad (_("Internal assembler error for instruction %s"), op->name);
              dup_insn = true;
            }
        }
              dup_insn = true;
            }
        }
@@ -995,7 +1130,7 @@ md_begin ()
          retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
          if (retval != (const char *) NULL)
            {
          retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
          if (retval != (const char *) NULL)
            {
-             as_bad ("Internal assembler error for macro %s", macro->name);
+             as_bad (_("Internal assembler error for macro %s"), macro->name);
              dup_insn = true;
            }
        }
              dup_insn = true;
            }
        }
@@ -1018,15 +1153,15 @@ md_begin ()
      text csects to precede the data csects.  These symbols will not
      be output.  */
   ppc_text_csects = symbol_make ("dummy\001");
      text csects to precede the data csects.  These symbols will not
      be output.  */
   ppc_text_csects = symbol_make ("dummy\001");
-  ppc_text_csects->sy_tc.within = ppc_text_csects;
+  symbol_get_tc (ppc_text_csects)->within = ppc_text_csects;
   ppc_data_csects = symbol_make ("dummy\001");
   ppc_data_csects = symbol_make ("dummy\001");
-  ppc_data_csects->sy_tc.within = ppc_data_csects;
+  symbol_get_tc (ppc_data_csects)->within = ppc_data_csects;
 #endif
 
 #ifdef TE_PE
 
   ppc_current_section = text_section;
 #endif
 
 #ifdef TE_PE
 
   ppc_current_section = text_section;
-  ppc_previous_section = 0;  
+  ppc_previous_section = 0;
 
 #endif
 }
 
 #endif
 }
@@ -1048,12 +1183,26 @@ ppc_insert_operand (insn, operand, val, file, line)
 
       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
        {
 
       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
        {
-         if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0
-             && ppc_size == PPC_OPCODE_32)
+         if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
            max = (1 << operand->bits) - 1;
          else
            max = (1 << (operand->bits - 1)) - 1;
          min = - (1 << (operand->bits - 1));
            max = (1 << operand->bits) - 1;
          else
            max = (1 << (operand->bits - 1)) - 1;
          min = - (1 << (operand->bits - 1));
+
+         if (ppc_size == PPC_OPCODE_32)
+           {
+             /* Some people write 32 bit hex constants with the sign
+                extension done by hand.  This shouldn't really be
+                valid, but, to permit this code to assemble on a 64
+                bit host, we sign extend the 32 bit value.  */
+             if (val > 0
+                 && (val & (offsetT) 0x80000000) != 0
+                 && (val & (offsetT) 0xffffffff) == val)
+               {
+                 val -= 0x80000000;
+                 val -= 0x80000000;
+               }
+           }
        }
       else
        {
        }
       else
        {
@@ -1069,7 +1218,7 @@ ppc_insert_operand (insn, operand, val, file, line)
       if (test < (offsetT) min || test > (offsetT) max)
        {
          const char *err =
       if (test < (offsetT) min || test > (offsetT) max)
        {
          const char *err =
-           "operand out of range (%s not between %ld and %ld)";
+           _("operand out of range (%s not between %ld and %ld)");
          char buf[100];
 
          sprint_value (buf, test);
          char buf[100];
 
          sprint_value (buf, test);
@@ -1117,7 +1266,7 @@ ppc_elf_suffix (str_p, exp_p)
   int len;
   struct map_bfd *ptr;
 
   int len;
   struct map_bfd *ptr;
 
-#define MAP(str,reloc) { str, sizeof(str)-1, reloc }
+#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
 
   static struct map_bfd mapping[] = {
     MAP ("l",          BFD_RELOC_LO16),
 
   static struct map_bfd mapping[] = {
     MAP ("l",          BFD_RELOC_LO16),
@@ -1130,12 +1279,12 @@ ppc_elf_suffix (str_p, exp_p)
     MAP ("got@h",      BFD_RELOC_HI16_GOTOFF),
     MAP ("got@ha",     BFD_RELOC_HI16_S_GOTOFF),
     MAP ("fixup",      BFD_RELOC_CTOR),                /* warnings with -mrelocatable */
     MAP ("got@h",      BFD_RELOC_HI16_GOTOFF),
     MAP ("got@ha",     BFD_RELOC_HI16_S_GOTOFF),
     MAP ("fixup",      BFD_RELOC_CTOR),                /* warnings with -mrelocatable */
+    MAP ("plt",                BFD_RELOC_24_PLT_PCREL),
     MAP ("pltrel24",   BFD_RELOC_24_PLT_PCREL),
     MAP ("copy",       BFD_RELOC_PPC_COPY),
     MAP ("globdat",    BFD_RELOC_PPC_GLOB_DAT),
     MAP ("local24pc",  BFD_RELOC_PPC_LOCAL24PC),
     MAP ("local",      BFD_RELOC_PPC_LOCAL24PC),
     MAP ("pltrel24",   BFD_RELOC_24_PLT_PCREL),
     MAP ("copy",       BFD_RELOC_PPC_COPY),
     MAP ("globdat",    BFD_RELOC_PPC_GLOB_DAT),
     MAP ("local24pc",  BFD_RELOC_PPC_LOCAL24PC),
     MAP ("local",      BFD_RELOC_PPC_LOCAL24PC),
-    MAP ("plt",                BFD_RELOC_32_PLTOFF),
     MAP ("pltrel",     BFD_RELOC_32_PLT_PCREL),
     MAP ("plt@l",      BFD_RELOC_LO16_PLTOFF),
     MAP ("plt@h",      BFD_RELOC_HI16_PLTOFF),
     MAP ("pltrel",     BFD_RELOC_32_PLT_PCREL),
     MAP ("plt@l",      BFD_RELOC_LO16_PLTOFF),
     MAP ("plt@h",      BFD_RELOC_HI16_PLTOFF),
@@ -1182,8 +1331,17 @@ ppc_elf_suffix (str_p, exp_p)
 
   ch = ident[0];
   for (ptr = &mapping[0]; ptr->length > 0; ptr++)
 
   ch = ident[0];
   for (ptr = &mapping[0]; ptr->length > 0; ptr++)
-    if (ch == ptr->string[0] && len == ptr->length && memcmp (ident, ptr->string, ptr->length) == 0)
+    if (ch == ptr->string[0]
+       && len == ptr->length
+       && memcmp (ident, ptr->string, ptr->length) == 0)
       {
       {
+       if (exp_p->X_add_number != 0
+           && (ptr->reloc == BFD_RELOC_16_GOTOFF
+               || ptr->reloc == BFD_RELOC_LO16_GOTOFF
+               || ptr->reloc == BFD_RELOC_HI16_GOTOFF
+               || ptr->reloc == BFD_RELOC_HI16_S_GOTOFF))
+         as_warn (_("identifier+constant@got means identifier@got+constant"));
+
        /* Now check for identifier@suffix+constant */
        if (*str == '-' || *str == '+')
          {
        /* Now check for identifier@suffix+constant */
        if (*str == '-' || *str == '+')
          {
@@ -1209,9 +1367,9 @@ ppc_elf_suffix (str_p, exp_p)
   return BFD_RELOC_UNUSED;
 }
 
   return BFD_RELOC_UNUSED;
 }
 
-/* Like normal .long/.short/.word, except support @got, etc. */
+/* Like normal .long/.short/.word, except support @got, etc.  */
 /* clobbers input_line_pointer, checks */
 /* clobbers input_line_pointer, checks */
-/* end-of-line. */
+/* end-of-line.  */
 static void
 ppc_elf_cons (nbytes)
      register int nbytes;      /* 1=.byte, 2=.word, 4=.long */
 static void
 ppc_elf_cons (nbytes)
      register int nbytes;      /* 1=.byte, 2=.word, 4=.long */
@@ -1236,7 +1394,7 @@ ppc_elf_cons (nbytes)
          int size = bfd_get_reloc_size (reloc_howto);
 
          if (size > nbytes)
          int size = bfd_get_reloc_size (reloc_howto);
 
          if (size > nbytes)
-           as_bad ("%s relocations do not fit in %d bytes\n", reloc_howto->name, nbytes);
+           as_bad (_("%s relocations do not fit in %d bytes\n"), reloc_howto->name, nbytes);
 
          else
            {
 
          else
            {
@@ -1251,7 +1409,7 @@ ppc_elf_cons (nbytes)
     }
   while (*input_line_pointer++ == ',');
 
     }
   while (*input_line_pointer++ == ',');
 
-  input_line_pointer--;                /* Put terminator back into stream. */
+  input_line_pointer--;                /* Put terminator back into stream.  */
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
 
@@ -1273,7 +1431,7 @@ ppc_elf_rdata (xxx)
 /* Pseudo op to make file scope bss items */
 static void
 ppc_elf_lcomm(xxx)
 /* Pseudo op to make file scope bss items */
 static void
 ppc_elf_lcomm(xxx)
-     int xxx;
+     int xxx ATTRIBUTE_UNUSED;
 {
   register char *name;
   register char c;
 {
   register char *name;
   register char c;
@@ -1295,7 +1453,7 @@ ppc_elf_lcomm(xxx)
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad ("Expected comma after symbol-name: rest of line ignored.");
+      as_bad (_("Expected comma after symbol-name: rest of line ignored."));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -1303,7 +1461,7 @@ ppc_elf_lcomm(xxx)
   input_line_pointer++;                /* skip ',' */
   if ((size = get_absolute_expression ()) < 0)
     {
   input_line_pointer++;                /* skip ',' */
   if ((size = get_absolute_expression ()) < 0)
     {
-      as_warn (".COMMon length (%ld.) <0! Ignored.", (long) size);
+      as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -1317,7 +1475,7 @@ ppc_elf_lcomm(xxx)
       align = get_absolute_expression ();
       if (align <= 0)
        {
       align = get_absolute_expression ();
       if (align <= 0)
        {
-         as_warn ("ignoring bad alignment");
+         as_warn (_("ignoring bad alignment"));
          align = 8;
        }
     }
          align = 8;
        }
     }
@@ -1326,9 +1484,9 @@ ppc_elf_lcomm(xxx)
   symbolP = symbol_find_or_make (name);
   *p = c;
 
   symbolP = symbol_find_or_make (name);
   *p = c;
 
-  if (S_IS_DEFINED (symbolP))
+  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
     {
     {
-      as_bad ("Ignoring attempt to re-define symbol `%s'.",
+      as_bad (_("Ignoring attempt to re-define symbol `%s'."),
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       return;
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       return;
@@ -1336,7 +1494,7 @@ ppc_elf_lcomm(xxx)
 
   if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
     {
 
   if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
     {
-      as_bad ("Length of .lcomm \"%s\" is already %ld. Not changed to %ld.",
+      as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
              S_GET_NAME (symbolP),
              (long) S_GET_VALUE (symbolP),
              (long) size);
              S_GET_NAME (symbolP),
              (long) S_GET_VALUE (symbolP),
              (long) size);
@@ -1354,7 +1512,7 @@ ppc_elf_lcomm(xxx)
       for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
       if (align != 1)
        {
       for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
       if (align != 1)
        {
-         as_bad ("Common alignment not a power of 2");
+         as_bad (_("Common alignment not a power of 2"));
          ignore_rest_of_line ();
          return;
        }
          ignore_rest_of_line ();
          return;
        }
@@ -1365,16 +1523,15 @@ ppc_elf_lcomm(xxx)
   record_alignment (bss_section, align2);
   subseg_set (bss_section, 0);
   if (align2)
   record_alignment (bss_section, align2);
   subseg_set (bss_section, 0);
   if (align2)
-    frag_align (align2, 0);
+    frag_align (align2, 0, 0);
   if (S_GET_SEGMENT (symbolP) == bss_section)
   if (S_GET_SEGMENT (symbolP) == bss_section)
-    symbolP->sy_frag->fr_symbol = 0;
-  symbolP->sy_frag = frag_now;
+    symbol_get_frag (symbolP)->fr_symbol = 0;
+  symbol_set_frag (symbolP, frag_now);
   pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
                    (char *) 0);
   *pfrag = 0;
   S_SET_SIZE (symbolP, size);
   S_SET_SEGMENT (symbolP, bss_section);
   pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
                    (char *) 0);
   *pfrag = 0;
   S_SET_SIZE (symbolP, size);
   S_SET_SEGMENT (symbolP, bss_section);
-  S_CLEAR_EXTERNAL (symbolP);
   subseg_set (old_sec, old_subsec);
   demand_empty_rest_of_line ();
 }
   subseg_set (old_sec, old_subsec);
   demand_empty_rest_of_line ();
 }
@@ -1412,13 +1569,14 @@ ppc_elf_validate_fix (fixp, seg)
          && strcmp (segment_name (seg), ".fixup") != 0
          && strcmp (segment_name (seg), ".stab") != 0
          && strcmp (segment_name (seg), ".gcc_except_table") != 0
          && strcmp (segment_name (seg), ".fixup") != 0
          && strcmp (segment_name (seg), ".stab") != 0
          && strcmp (segment_name (seg), ".gcc_except_table") != 0
+         && strcmp (segment_name (seg), ".eh_frame") != 0
          && strcmp (segment_name (seg), ".ex_shared") != 0)
        {
          if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
              || fixp->fx_r_type != BFD_RELOC_CTOR)
            {
              as_bad_where (fixp->fx_file, fixp->fx_line,
          && strcmp (segment_name (seg), ".ex_shared") != 0)
        {
          if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
              || fixp->fx_r_type != BFD_RELOC_CTOR)
            {
              as_bad_where (fixp->fx_file, fixp->fx_line,
-                           "Relocation cannot be done when using -mrelocatable");
+                           _("Relocation cannot be done when using -mrelocatable"));
            }
        }
       return;
            }
        }
       return;
@@ -1437,7 +1595,7 @@ ppc_elf_validate_fix (fixp, seg)
  *
  *      Anything else is an error of one kind or another.
  *
  *
  *      Anything else is an error of one kind or another.
  *
- * out:        
+ * out:
  *   return value: success or failure
  *   toc_kind:     kind of toc reference
  *   input_line_pointer:
  *   return value: success or failure
  *   toc_kind:     kind of toc reference
  *   input_line_pointer:
@@ -1453,8 +1611,8 @@ ppc_elf_validate_fix (fixp, seg)
  *
  */
 
  *
  */
 
-enum toc_size_qualifier 
-{ 
+enum toc_size_qualifier
+{
   default_toc, /* The toc cell constructed should be the system default size */
   data_in_toc, /* This is a direct reference to a toc cell                   */
   must_be_32,  /* The toc cell constructed must be 32 bits wide              */
   default_toc, /* The toc cell constructed should be the system default size */
   data_in_toc, /* This is a direct reference to a toc cell                   */
   must_be_32,  /* The toc cell constructed must be 32 bits wide              */
@@ -1476,30 +1634,30 @@ parse_toc_entry(toc_kind)
   /* skip over the '[' , and whitespace */
   ++input_line_pointer;
   SKIP_WHITESPACE ();
   /* skip over the '[' , and whitespace */
   ++input_line_pointer;
   SKIP_WHITESPACE ();
-  
+
   /* find the spelling of the operand */
   toc_spec = input_line_pointer;
   c = get_symbol_end ();
 
   /* find the spelling of the operand */
   toc_spec = input_line_pointer;
   c = get_symbol_end ();
 
-  if (strcmp(toc_spec, "toc") == 0) 
+  if (strcmp(toc_spec, "toc") == 0)
     {
       t = default_toc;
     }
     {
       t = default_toc;
     }
-  else if (strcmp(toc_spec, "tocv") == 0) 
+  else if (strcmp(toc_spec, "tocv") == 0)
     {
       t = data_in_toc;
     }
     {
       t = data_in_toc;
     }
-  else if (strcmp(toc_spec, "toc32") == 0) 
+  else if (strcmp(toc_spec, "toc32") == 0)
     {
       t = must_be_32;
     }
     {
       t = must_be_32;
     }
-  else if (strcmp(toc_spec, "toc64") == 0) 
+  else if (strcmp(toc_spec, "toc64") == 0)
     {
       t = must_be_64;
     }
   else
     {
     {
       t = must_be_64;
     }
   else
     {
-      as_bad ("syntax error: invalid toc specifier `%s'", toc_spec);
+      as_bad (_("syntax error: invalid toc specifier `%s'"), toc_spec);
       *input_line_pointer = c;   /* put back the delimiting char */
       input_line_pointer = start; /* reset input_line pointer */
       return 0;
       *input_line_pointer = c;   /* put back the delimiting char */
       input_line_pointer = start; /* reset input_line pointer */
       return 0;
@@ -1508,12 +1666,12 @@ parse_toc_entry(toc_kind)
   /* now find the ']' */
   *input_line_pointer = c;   /* put back the delimiting char */
 
   /* now find the ']' */
   *input_line_pointer = c;   /* put back the delimiting char */
 
-  SKIP_WHITESPACE ();       /* leading whitespace could be there. */
-  c = *input_line_pointer++; /* input_line_pointer->past char in c. */
+  SKIP_WHITESPACE ();       /* leading whitespace could be there.  */
+  c = *input_line_pointer++; /* input_line_pointer->past char in c.  */
 
   if (c != ']')
     {
 
   if (c != ']')
     {
-      as_bad ("syntax error: expected `]', found  `%c'", c);
+      as_bad (_("syntax error: expected `]', found  `%c'"), c);
       input_line_pointer = start; /* reset input_line pointer */
       return 0;
     }
       input_line_pointer = start; /* reset input_line pointer */
       return 0;
     }
@@ -1572,7 +1730,7 @@ md_assemble (str)
 
       macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);
       if (macro == (const struct powerpc_macro *) NULL)
 
       macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);
       if (macro == (const struct powerpc_macro *) NULL)
-       as_bad ("Unrecognized opcode: `%s'", str);
+       as_bad (_("Unrecognized opcode: `%s'"), str);
       else
        ppc_macro (s, macro);
 
       else
        ppc_macro (s, macro);
 
@@ -1682,13 +1840,13 @@ md_assemble (str)
       input_line_pointer = str;
 
 #ifdef TE_PE
       input_line_pointer = str;
 
 #ifdef TE_PE
-      if (*input_line_pointer == '[') 
+      if (*input_line_pointer == '[')
        {
          /* We are expecting something like the second argument here:
 
                lwz r4,[toc].GS.0.static_int(rtoc)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        {
          /* We are expecting something like the second argument here:
 
                lwz r4,[toc].GS.0.static_int(rtoc)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-            The argument following the `]' must be a symbol name, and the 
+            The argument following the `]' must be a symbol name, and the
              register must be the toc register: 'rtoc' or '2'
 
             The effect is to 0 as the displacement field
              register must be the toc register: 'rtoc' or '2'
 
             The effect is to 0 as the displacement field
@@ -1716,7 +1874,7 @@ md_assemble (str)
          /* go parse off the [tocXX] part */
          valid_toc = parse_toc_entry(&toc_kind);
 
          /* go parse off the [tocXX] part */
          valid_toc = parse_toc_entry(&toc_kind);
 
-         if (!valid_toc) 
+         if (!valid_toc)
            {
              /* Note: message has already been issued.     */
              /* FIXME: what sort of recovery should we do? */
            {
              /* Note: message has already been issued.     */
              /* FIXME: what sort of recovery should we do? */
@@ -1742,12 +1900,13 @@ md_assemble (str)
              /* FIXME: It's a little confusing what the tocv qualifier can */
              /*        be used for. At the very least, I've seen three     */
              /*        uses, only one of which I'm sure I can explain.     */
              /* FIXME: It's a little confusing what the tocv qualifier can */
              /*        be used for. At the very least, I've seen three     */
              /*        uses, only one of which I'm sure I can explain.     */
-             if (ex.X_op == O_symbol) 
-               {                 
+             if (ex.X_op == O_symbol)
+               {
                  assert (ex.X_add_symbol != NULL);
                  assert (ex.X_add_symbol != NULL);
-                 if (ex.X_add_symbol->bsym->section != tocdata_section)
+                 if (symbol_get_bfdsym (ex.X_add_symbol)->section
+                     != tocdata_section)
                    {
                    {
-                     as_bad("[tocv] symbol is not a toc symbol");
+                     as_bad(_("[tocv] symbol is not a toc symbol"));
                    }
                }
 
                    }
                }
 
@@ -1758,24 +1917,24 @@ md_assemble (str)
              /*        entries. We don't support them today. Is this the   */
              /*        right way to say that?                              */
              toc_reloc = BFD_RELOC_UNUSED;
              /*        entries. We don't support them today. Is this the   */
              /*        right way to say that?                              */
              toc_reloc = BFD_RELOC_UNUSED;
-             as_bad ("Unimplemented toc32 expression modifier");
+             as_bad (_("Unimplemented toc32 expression modifier"));
              break;
            case must_be_64:
              /* FIXME: see above */
              toc_reloc = BFD_RELOC_UNUSED;
              break;
            case must_be_64:
              /* FIXME: see above */
              toc_reloc = BFD_RELOC_UNUSED;
-             as_bad ("Unimplemented toc64 expression modifier");
+             as_bad (_("Unimplemented toc64 expression modifier"));
              break;
            default:
              break;
            default:
-             fprintf(stderr, 
-                     "Unexpected return value [%d] from parse_toc_entry!\n",
+             fprintf (stderr,
+                     _("Unexpected return value [%d] from parse_toc_entry!\n"),
                      toc_kind);
                      toc_kind);
-             abort();
+             abort ();
              break;
            }
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
              break;
            }
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
-           as_fatal ("too many fixups");
+           as_fatal (_("too many fixups"));
 
          fixups[fc].reloc = toc_reloc;
          fixups[fc].exp = ex;
 
          fixups[fc].reloc = toc_reloc;
          fixups[fc].exp = ex;
@@ -1807,9 +1966,9 @@ md_assemble (str)
       input_line_pointer = hold;
 
       if (ex.X_op == O_illegal)
       input_line_pointer = hold;
 
       if (ex.X_op == O_illegal)
-       as_bad ("illegal operand");
+       as_bad (_("illegal operand"));
       else if (ex.X_op == O_absent)
       else if (ex.X_op == O_absent)
-       as_bad ("missing operand");
+       as_bad (_("missing operand"));
       else if (ex.X_op == O_register)
        {
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
       else if (ex.X_op == O_register)
        {
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
@@ -1818,7 +1977,7 @@ md_assemble (str)
       else if (ex.X_op == O_constant)
        {
 #ifdef OBJ_ELF
       else if (ex.X_op == O_constant)
        {
 #ifdef OBJ_ELF
-         /* Allow @HA, @L, @H on constants. */
+         /* Allow @HA, @L, @H on constants.  */
          char *orig_str = str;
 
          if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
          char *orig_str = str;
 
          if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
@@ -1829,7 +1988,11 @@ md_assemble (str)
                break;
 
              case BFD_RELOC_LO16:
                break;
 
              case BFD_RELOC_LO16:
-               if (ex.X_unsigned)
+               /* X_unsigned is the default, so if the user has done
+                   something which cleared it, we always produce a
+                   signed value.  */
+               if (ex.X_unsigned
+                   && (operand->flags & PPC_OPERAND_SIGNED) == 0)
                  ex.X_add_number &= 0xffff;
                else
                  ex.X_add_number = (((ex.X_add_number & 0xffff)
                  ex.X_add_number &= 0xffff;
                else
                  ex.X_add_number = (((ex.X_add_number & 0xffff)
@@ -1842,8 +2005,9 @@ md_assemble (str)
                break;
 
              case BFD_RELOC_HI16_S:
                break;
 
              case BFD_RELOC_HI16_S:
-               ex.X_add_number = (((ex.X_add_number >> 16) & 0xffff)
-                                  + ((ex.X_add_number >> 15) & 1));
+               ex.X_add_number = ((((ex.X_add_number >> 16) & 0xffff)
+                                   + ((ex.X_add_number >> 15) & 1))
+                                  & 0xffff);
                break;
              }
 #endif
                break;
              }
 #endif
@@ -1878,7 +2042,7 @@ md_assemble (str)
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
-           as_fatal ("too many fixups");
+           as_fatal (_("too many fixups"));
          fixups[fc].exp = ex;
          fixups[fc].opindex = 0;
          fixups[fc].reloc = reloc;
          fixups[fc].exp = ex;
          fixups[fc].opindex = 0;
          fixups[fc].reloc = reloc;
@@ -1890,7 +2054,7 @@ md_assemble (str)
        {
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
        {
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
-           as_fatal ("too many fixups");
+           as_fatal (_("too many fixups"));
          fixups[fc].exp = ex;
          fixups[fc].opindex = *opindex_ptr;
          fixups[fc].reloc = BFD_RELOC_UNUSED;
          fixups[fc].exp = ex;
          fixups[fc].opindex = *opindex_ptr;
          fixups[fc].reloc = BFD_RELOC_UNUSED;
@@ -1915,7 +2079,7 @@ md_assemble (str)
       if (*str != endc
          && (endc != ',' || *str != '\0'))
        {
       if (*str != endc
          && (endc != ',' || *str != '\0'))
        {
-         as_bad ("syntax error; found `%c' but expected `%c'", *str, endc);
+         as_bad (_("syntax error; found `%c' but expected `%c'"), *str, endc);
          break;
        }
 
          break;
        }
 
@@ -1927,7 +2091,7 @@ md_assemble (str)
     ++str;
 
   if (*str != '\0')
     ++str;
 
   if (*str != '\0')
-    as_bad ("junk at end of line: `%s'", str);
+    as_bad (_("junk at end of line: `%s'"), str);
 
   /* Write out the instruction.  */
   f = frag_more (4);
 
   /* Write out the instruction.  */
   f = frag_more (4);
@@ -1958,7 +2122,7 @@ md_assemble (str)
          offset = target_big_endian ? (4 - size) : 0;
 
          if (size < 1 || size > 4)
          offset = target_big_endian ? (4 - size) : 0;
 
          if (size < 1 || size > 4)
-           abort();
+           abort ();
 
          fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
                              &fixups[i].exp, reloc_howto->pc_relative,
 
          fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
                              &fixups[i].exp, reloc_howto->pc_relative,
@@ -1988,29 +2152,6 @@ md_assemble (str)
     }
 }
 
     }
 }
 
-#ifndef WORKING_DOT_WORD
-/* Handle long and short jumps */
-void
-md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
-     char *ptr;
-     addressT from_addr, to_addr;
-     fragS *frag;
-     symbolS *to_symbol;
-{
-  abort ();
-}
-
-void
-md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
-     char *ptr;
-     addressT from_addr, to_addr;
-     fragS *frag;
-     symbolS *to_symbol;
-{
-  abort ();
-}
-#endif
-
 /* Handle a macro.  Gather all the operands, transform them as
    described by the macro, and call md_assemble recursively.  All the
    operands are separated by commas; we don't accept parentheses
 /* Handle a macro.  Gather all the operands, transform them as
    described by the macro, and call md_assemble recursively.  All the
    operands are separated by commas; we don't accept parentheses
@@ -2042,11 +2183,11 @@ ppc_macro (str, macro)
       if (s == (char *) NULL)
        break;
       *s++ = '\0';
       if (s == (char *) NULL)
        break;
       *s++ = '\0';
-    }  
+    }
 
   if (count != macro->operands)
     {
 
   if (count != macro->operands)
     {
-      as_bad ("wrong number of operands");
+      as_bad (_("wrong number of operands"));
       return;
     }
 
       return;
     }
 
@@ -2089,7 +2230,7 @@ ppc_macro (str, macro)
 
   /* Assemble the constructed instruction.  */
   md_assemble (complete);
 
   /* Assemble the constructed instruction.  */
   md_assemble (complete);
-}  
+}
 \f
 #ifdef OBJ_ELF
 /* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED */
 \f
 #ifdef OBJ_ELF
 /* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED */
@@ -2102,34 +2243,30 @@ ppc_section_letter (letter, ptr_msg)
   if (letter == 'e')
     return SHF_EXCLUDE;
 
   if (letter == 'e')
     return SHF_EXCLUDE;
 
-  *ptr_msg = "Bad .section directive: want a,w,x,e in string";
+  *ptr_msg = _("Bad .section directive: want a,w,x,e in string");
   return 0;
 }
 
 int
   return 0;
 }
 
 int
-ppc_section_word (ptr_str)
-     char **ptr_str;
+ppc_section_word (str, len)
+     char *str;
+     size_t len;
 {
 {
-  if (strncmp (*ptr_str, "exclude", sizeof ("exclude")-1) == 0)
-    {
-      *ptr_str += sizeof ("exclude")-1;
-      return SHF_EXCLUDE;
-    }
+  if (len == 7 && strncmp (str, "exclude", 7) == 0)
+    return SHF_EXCLUDE;
 
 
-  return 0;
+  return -1;
 }
 
 int
 }
 
 int
-ppc_section_type (ptr_str)
-     char **ptr_str;
+ppc_section_type (str, len)
+     char *str;
+     size_t len;
 {
 {
-  if (strncmp (*ptr_str, "ordered", sizeof ("ordered")-1) == 0)
-    {
-      *ptr_str += sizeof ("ordered")-1;
-      return SHT_ORDERED;
-    }
+  if (len == 7 && strncmp (str, "ordered", 7) == 0)
+    return SHT_ORDERED;
 
 
-  return 0;
+  return -1;
 }
 
 int
 }
 
 int
@@ -2156,7 +2293,7 @@ ppc_section_flags (flags, attr, type)
 
 static void
 ppc_byte (ignore)
 
 static void
 ppc_byte (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (*input_line_pointer != '\"')
     {
 {
   if (*input_line_pointer != '\"')
     {
@@ -2220,7 +2357,7 @@ ppc_comm (lcomm)
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing size");
+      as_bad (_("missing size"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -2229,7 +2366,7 @@ ppc_comm (lcomm)
   size = get_absolute_expression ();
   if (size < 0)
     {
   size = get_absolute_expression ();
   if (size < 0)
     {
-      as_bad ("negative size");
+      as_bad (_("negative size"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -2245,7 +2382,7 @@ ppc_comm (lcomm)
          align = get_absolute_expression ();
          if (align <= 0)
            {
          align = get_absolute_expression ();
          if (align <= 0)
            {
-             as_warn ("ignoring bad alignment");
+             as_warn (_("ignoring bad alignment"));
              align = 3;
            }
        }
              align = 3;
            }
        }
@@ -2270,7 +2407,7 @@ ppc_comm (lcomm)
         argument.  */
       if (*input_line_pointer != ',')
        {
         argument.  */
       if (*input_line_pointer != ',')
        {
-         as_bad ("missing real symbol name");
+         as_bad (_("missing real symbol name"));
          ignore_rest_of_line ();
          return;
        }
          ignore_rest_of_line ();
          return;
        }
@@ -2278,7 +2415,7 @@ ppc_comm (lcomm)
 
       lcomm_name = input_line_pointer;
       lcomm_endc = get_symbol_end ();
 
       lcomm_name = input_line_pointer;
       lcomm_endc = get_symbol_end ();
-      
+
       lcomm_sym = symbol_find_or_make (lcomm_name);
 
       *input_line_pointer = lcomm_endc;
       lcomm_sym = symbol_find_or_make (lcomm_name);
 
       *input_line_pointer = lcomm_endc;
@@ -2291,13 +2428,13 @@ ppc_comm (lcomm)
   if (S_IS_DEFINED (sym)
       || S_GET_VALUE (sym) != 0)
     {
   if (S_IS_DEFINED (sym)
       || S_GET_VALUE (sym) != 0)
     {
-      as_bad ("attempt to redefine symbol");
+      as_bad (_("attempt to redefine symbol"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
-    
+
   record_alignment (bss_section, align);
   record_alignment (bss_section, align);
-         
+
   if (! lcomm
       || ! S_IS_DEFINED (lcomm_sym))
     {
   if (! lcomm
       || ! S_IS_DEFINED (lcomm_sym))
     {
@@ -2312,38 +2449,38 @@ ppc_comm (lcomm)
        }
       else
        {
        }
       else
        {
-         lcomm_sym->sy_tc.output = 1;
+         symbol_get_tc (lcomm_sym)->output = 1;
          def_sym = lcomm_sym;
          def_size = 0;
        }
 
       subseg_set (bss_section, 1);
          def_sym = lcomm_sym;
          def_size = 0;
        }
 
       subseg_set (bss_section, 1);
-      frag_align (align, 0);
-  
-      def_sym->sy_frag = frag_now;
+      frag_align (align, 0, 0);
+
+      symbol_set_frag (def_sym, frag_now);
       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, def_sym,
                        def_size, (char *) NULL);
       *pfrag = 0;
       S_SET_SEGMENT (def_sym, bss_section);
       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, def_sym,
                        def_size, (char *) NULL);
       *pfrag = 0;
       S_SET_SEGMENT (def_sym, bss_section);
-      def_sym->sy_tc.align = align;
+      symbol_get_tc (def_sym)->align = align;
     }
   else if (lcomm)
     {
       /* Align the size of lcomm_sym.  */
     }
   else if (lcomm)
     {
       /* Align the size of lcomm_sym.  */
-      lcomm_sym->sy_frag->fr_offset =
-       ((lcomm_sym->sy_frag->fr_offset + (1 << align) - 1)
+      symbol_get_frag (lcomm_sym)->fr_offset =
+       ((symbol_get_frag (lcomm_sym)->fr_offset + (1 << align) - 1)
         &~ ((1 << align) - 1));
         &~ ((1 << align) - 1));
-      if (align > lcomm_sym->sy_tc.align)
-       lcomm_sym->sy_tc.align = align;
+      if (align > symbol_get_tc (lcomm_sym)->align)
+       symbol_get_tc (lcomm_sym)->align = align;
     }
 
   if (lcomm)
     {
       /* Make sym an offset from lcomm_sym.  */
       S_SET_SEGMENT (sym, bss_section);
     }
 
   if (lcomm)
     {
       /* Make sym an offset from lcomm_sym.  */
       S_SET_SEGMENT (sym, bss_section);
-      sym->sy_frag = lcomm_sym->sy_frag;
-      S_SET_VALUE (sym, lcomm_sym->sy_frag->fr_offset);
-      lcomm_sym->sy_frag->fr_offset += size;
+      symbol_set_frag (sym, symbol_get_frag (lcomm_sym));
+      S_SET_VALUE (sym, symbol_get_frag (lcomm_sym)->fr_offset);
+      symbol_get_frag (lcomm_sym)->fr_offset += size;
     }
 
   subseg_set (current_seg, current_subseg);
     }
 
   subseg_set (current_seg, current_subseg);
@@ -2359,7 +2496,7 @@ ppc_comm (lcomm)
 
 static void
 ppc_csect (ignore)
 
 static void
 ppc_csect (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2367,7 +2504,7 @@ ppc_csect (ignore)
 
   name = input_line_pointer;
   endc = get_symbol_end ();
 
   name = input_line_pointer;
   endc = get_symbol_end ();
-  
+
   sym = symbol_find_or_make (name);
 
   *input_line_pointer = endc;
   sym = symbol_find_or_make (name);
 
   *input_line_pointer = endc;
@@ -2375,7 +2512,7 @@ ppc_csect (ignore)
   if (S_GET_NAME (sym)[0] == '\0')
     {
       /* An unnamed csect is assumed to be [PR].  */
   if (S_GET_NAME (sym)[0] == '\0')
     {
       /* An unnamed csect is assumed to be [PR].  */
-      sym->sy_tc.class = XMC_PR;
+      symbol_get_tc (sym)->class = XMC_PR;
     }
 
   ppc_change_csect (sym);
     }
 
   ppc_change_csect (sym);
@@ -2383,7 +2520,7 @@ ppc_csect (ignore)
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
-      sym->sy_tc.align = get_absolute_expression ();
+      symbol_get_tc (sym)->align = get_absolute_expression ();
     }
 
   demand_empty_rest_of_line ();
     }
 
   demand_empty_rest_of_line ();
@@ -2396,18 +2533,19 @@ ppc_change_csect (sym)
      symbolS *sym;
 {
   if (S_IS_DEFINED (sym))
      symbolS *sym;
 {
   if (S_IS_DEFINED (sym))
-    subseg_set (S_GET_SEGMENT (sym), sym->sy_tc.subseg);
+    subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
   else
     {
       symbolS **list_ptr;
       int after_toc;
   else
     {
       symbolS **list_ptr;
       int after_toc;
+      int hold_chunksize;
       symbolS *list;
 
       /* This is a new csect.  We need to look at the symbol class to
         figure out whether it should go in the text section or the
         data section.  */
       after_toc = 0;
       symbolS *list;
 
       /* This is a new csect.  We need to look at the symbol class to
         figure out whether it should go in the text section or the
         data section.  */
       after_toc = 0;
-      switch (sym->sy_tc.class)
+      switch (symbol_get_tc (sym)->class)
        {
        case XMC_PR:
        case XMC_RO:
        {
        case XMC_PR:
        case XMC_RO:
@@ -2418,7 +2556,7 @@ ppc_change_csect (sym)
        case XMC_TI:
        case XMC_TB:
          S_SET_SEGMENT (sym, text_section);
        case XMC_TI:
        case XMC_TB:
          S_SET_SEGMENT (sym, text_section);
-         sym->sy_tc.subseg = ppc_text_subsegment;
+         symbol_get_tc (sym)->subseg = ppc_text_subsegment;
          ++ppc_text_subsegment;
          list_ptr = &ppc_text_csects;
          break;
          ++ppc_text_subsegment;
          list_ptr = &ppc_text_csects;
          break;
@@ -2430,10 +2568,11 @@ ppc_change_csect (sym)
        case XMC_BS:
        case XMC_UC:
          if (ppc_toc_csect != NULL
        case XMC_BS:
        case XMC_UC:
          if (ppc_toc_csect != NULL
-             && ppc_toc_csect->sy_tc.subseg + 1 == ppc_data_subsegment)
+             && (symbol_get_tc (ppc_toc_csect)->subseg + 1
+                 == ppc_data_subsegment))
            after_toc = 1;
          S_SET_SEGMENT (sym, data_section);
            after_toc = 1;
          S_SET_SEGMENT (sym, data_section);
-         sym->sy_tc.subseg = ppc_data_subsegment;
+         symbol_get_tc (sym)->subseg = ppc_data_subsegment;
          ++ppc_data_subsegment;
          list_ptr = &ppc_data_csects;
          break;
          ++ppc_data_subsegment;
          list_ptr = &ppc_data_csects;
          break;
@@ -2441,25 +2580,36 @@ ppc_change_csect (sym)
          abort ();
        }
 
          abort ();
        }
 
-      subseg_new (segment_name (S_GET_SEGMENT (sym)), sym->sy_tc.subseg);
+      /* We set the obstack chunk size to a small value before
+         changing subsegments, so that we don't use a lot of memory
+         space for what may be a small section.  */
+      hold_chunksize = chunksize;
+      chunksize = 64;
+
+      subseg_new (segment_name (S_GET_SEGMENT (sym)),
+                 symbol_get_tc (sym)->subseg);
+
+      chunksize = hold_chunksize;
+
       if (after_toc)
        ppc_after_toc_frag = frag_now;
 
       if (after_toc)
        ppc_after_toc_frag = frag_now;
 
-      sym->sy_frag = frag_now;
+      symbol_set_frag (sym, frag_now);
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
 
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
 
-      sym->sy_tc.align = 2;
-      sym->sy_tc.output = 1;
-      sym->sy_tc.within = sym;
-         
+      symbol_get_tc (sym)->align = (ppc_xcoff64) ? 3 : 2;
+      symbol_get_tc (sym)->output = 1;
+      symbol_get_tc (sym)->within = sym;
+
       for (list = *list_ptr;
       for (list = *list_ptr;
-          list->sy_tc.next != (symbolS *) NULL;
-          list = list->sy_tc.next)
+          symbol_get_tc (list)->next != (symbolS *) NULL;
+          list = symbol_get_tc (list)->next)
        ;
        ;
-      list->sy_tc.next = sym;
-         
+      symbol_get_tc (list)->next = sym;
+
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
-      symbol_append (sym, list->sy_tc.within, &symbol_rootP, &symbol_lastP);
+      symbol_append (sym, symbol_get_tc (list)->within, &symbol_rootP,
+                    &symbol_lastP);
     }
 
   ppc_current_csect = sym;
     }
 
   ppc_current_csect = sym;
@@ -2490,11 +2640,48 @@ ppc_section (type)
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
 
+/* This function handles the .section pseudo-op.  This is mostly to
+   give an error, since XCOFF only supports .text, .data and .bss, but
+   we do permit the user to name the text or data section.  */
+
+static void
+ppc_named_section (ignore)
+     int ignore ATTRIBUTE_UNUSED;
+{
+  char *user_name;
+  const char *real_name;
+  char c;
+  symbolS *sym;
+
+  user_name = input_line_pointer;
+  c = get_symbol_end ();
+
+  if (strcmp (user_name, ".text") == 0)
+    real_name = ".text[PR]";
+  else if (strcmp (user_name, ".data") == 0)
+    real_name = ".data[RW]";
+  else
+    {
+      as_bad (_("The XCOFF file format does not support arbitrary sections"));
+      *input_line_pointer = c;
+      ignore_rest_of_line ();
+      return;
+    }
+
+  *input_line_pointer = c;
+
+  sym = symbol_find_or_make (real_name);
+
+  ppc_change_csect (sym);
+
+  demand_empty_rest_of_line ();
+}
+
 /* The .extern pseudo-op.  We create an undefined symbol.  */
 
 static void
 ppc_extern (ignore)
 /* The .extern pseudo-op.  We create an undefined symbol.  */
 
 static void
 ppc_extern (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2513,7 +2700,7 @@ ppc_extern (ignore)
 
 static void
 ppc_lglobl (ignore)
 
 static void
 ppc_lglobl (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2526,7 +2713,7 @@ ppc_lglobl (ignore)
 
   *input_line_pointer = endc;
 
 
   *input_line_pointer = endc;
 
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
@@ -2536,7 +2723,7 @@ ppc_lglobl (ignore)
 
 static void
 ppc_rename (ignore)
 
 static void
 ppc_rename (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2552,13 +2739,13 @@ ppc_rename (ignore)
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing rename string");
+      as_bad (_("missing rename string"));
       ignore_rest_of_line ();
       return;
     }
   ++input_line_pointer;
 
       ignore_rest_of_line ();
       return;
     }
   ++input_line_pointer;
 
-  sym->sy_tc.real_name = demand_copy_C_string (&len);
+  symbol_get_tc (sym)->real_name = demand_copy_C_string (&len);
 
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
@@ -2572,7 +2759,7 @@ ppc_rename (ignore)
 
 static void
 ppc_stabx (ignore)
 
 static void
 ppc_stabx (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   int len;
 {
   char *name;
   int len;
@@ -2583,7 +2770,7 @@ ppc_stabx (ignore)
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing value");
+      as_bad (_("missing value"));
       return;
     }
   ++input_line_pointer;
       return;
     }
   ++input_line_pointer;
@@ -2592,7 +2779,7 @@ ppc_stabx (ignore)
   sym = symbol_make (name);
   ppc_stab_symbol = false;
 
   sym = symbol_make (name);
   ppc_stab_symbol = false;
 
-  sym->sy_tc.real_name = name;
+  symbol_get_tc (sym)->real_name = name;
 
   (void) expression (&exp);
 
 
   (void) expression (&exp);
 
@@ -2601,22 +2788,22 @@ ppc_stabx (ignore)
     case O_illegal:
     case O_absent:
     case O_big:
     case O_illegal:
     case O_absent:
     case O_big:
-      as_bad ("illegal .stabx expression; zero assumed");
+      as_bad (_("illegal .stabx expression; zero assumed"));
       exp.X_add_number = 0;
       /* Fall through.  */
     case O_constant:
       S_SET_VALUE (sym, (valueT) exp.X_add_number);
       exp.X_add_number = 0;
       /* Fall through.  */
     case O_constant:
       S_SET_VALUE (sym, (valueT) exp.X_add_number);
-      sym->sy_frag = &zero_address_frag;
+      symbol_set_frag (sym, &zero_address_frag);
       break;
 
     case O_symbol:
       if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section)
       break;
 
     case O_symbol:
       if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section)
-       sym->sy_value = exp;
+       symbol_set_value_expression (sym, &exp);
       else
        {
          S_SET_VALUE (sym,
                       exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
       else
        {
          S_SET_VALUE (sym,
                       exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
-         sym->sy_frag = exp.X_add_symbol->sy_frag;
+         symbol_set_frag (sym, symbol_get_frag (exp.X_add_symbol));
        }
       break;
 
        }
       break;
 
@@ -2624,16 +2811,16 @@ ppc_stabx (ignore)
       /* The value is some complex expression.  This will probably
          fail at some later point, but this is probably the right
          thing to do here.  */
       /* The value is some complex expression.  This will probably
          fail at some later point, but this is probably the right
          thing to do here.  */
-      sym->sy_value = exp;
+      symbol_set_value_expression (sym, &exp);
       break;
     }
 
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
       break;
     }
 
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
-  sym->bsym->flags |= BSF_DEBUGGING;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing class");
+      as_bad (_("missing class"));
       return;
     }
   ++input_line_pointer;
       return;
     }
   ++input_line_pointer;
@@ -2642,17 +2829,17 @@ ppc_stabx (ignore)
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing type");
+      as_bad (_("missing type"));
       return;
     }
   ++input_line_pointer;
 
   S_SET_DATA_TYPE (sym, get_absolute_expression ());
 
       return;
     }
   ++input_line_pointer;
 
   S_SET_DATA_TYPE (sym, get_absolute_expression ());
 
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
 
   if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
-    sym->sy_tc.within = ppc_current_block;
+    symbol_get_tc (sym)->within = ppc_current_block;
 
   if (exp.X_op != O_symbol
       || ! S_IS_EXTERNAL (exp.X_add_symbol)
 
   if (exp.X_op != O_symbol
       || ! S_IS_EXTERNAL (exp.X_add_symbol)
@@ -2662,8 +2849,8 @@ ppc_stabx (ignore)
     {
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_append (sym, exp.X_add_symbol, &symbol_rootP, &symbol_lastP);
     {
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_append (sym, exp.X_add_symbol, &symbol_rootP, &symbol_lastP);
-      if (ppc_current_csect->sy_tc.within == exp.X_add_symbol)
-       ppc_current_csect->sy_tc.within = sym;
+      if (symbol_get_tc (ppc_current_csect)->within == exp.X_add_symbol)
+       symbol_get_tc (ppc_current_csect)->within = sym;
     }
 
   demand_empty_rest_of_line ();
     }
 
   demand_empty_rest_of_line ();
@@ -2679,7 +2866,7 @@ ppc_stabx (ignore)
 
 static void
 ppc_function (ignore)
 
 static void
 ppc_function (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2703,7 +2890,7 @@ ppc_function (ignore)
 
   if (*input_line_pointer != ',')
     {
 
   if (*input_line_pointer != ',')
     {
-      as_bad ("missing symbol name");
+      as_bad (_("missing symbol name"));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -2718,15 +2905,19 @@ ppc_function (ignore)
 
   if (ext_sym != lab_sym)
     {
 
   if (ext_sym != lab_sym)
     {
-      ext_sym->sy_value.X_op = O_symbol;
-      ext_sym->sy_value.X_add_symbol = lab_sym;
-      ext_sym->sy_value.X_op_symbol = NULL;
-      ext_sym->sy_value.X_add_number = 0;
+      expressionS exp;
+
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = lab_sym;
+      exp.X_op_symbol = NULL;
+      exp.X_add_number = 0;
+      exp.X_unsigned = 0;
+      symbol_set_value_expression (ext_sym, &exp);
     }
 
     }
 
-  if (ext_sym->sy_tc.class == -1)
-    ext_sym->sy_tc.class = XMC_PR;
-  ext_sym->sy_tc.output = 1;
+  if (symbol_get_tc (ext_sym)->class == -1)
+    symbol_get_tc (ext_sym)->class = XMC_PR;
+  symbol_get_tc (ext_sym)->output = 1;
 
   if (*input_line_pointer == ',')
     {
 
   if (*input_line_pointer == ',')
     {
@@ -2744,11 +2935,11 @@ ppc_function (ignore)
            {
              /* The fifth argument is the function size.  */
              ++input_line_pointer;
            {
              /* The fifth argument is the function size.  */
              ++input_line_pointer;
-             ext_sym->sy_tc.size = symbol_new ("L0\001",
-                                               absolute_section,
-                                               (valueT) 0,
-                                               &zero_address_frag);
-             pseudo_set (ext_sym->sy_tc.size);
+             symbol_get_tc (ext_sym)->size = symbol_new ("L0\001",
+                                                         absolute_section,
+                                                         (valueT) 0,
+                                                         &zero_address_frag);
+             pseudo_set (symbol_get_tc (ext_sym)->size);
            }
        }
     }
            }
        }
     }
@@ -2766,13 +2957,13 @@ ppc_function (ignore)
 
 static void
 ppc_bf (ignore)
 
 static void
 ppc_bf (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   sym = symbol_make (".bf");
   S_SET_SEGMENT (sym, text_section);
 {
   symbolS *sym;
 
   sym = symbol_make (".bf");
   S_SET_SEGMENT (sym, text_section);
-  sym->sy_frag = frag_now;
+  symbol_set_frag (sym, frag_now);
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_FCN);
 
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_FCN);
 
@@ -2781,7 +2972,7 @@ ppc_bf (ignore)
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, coff_line_base);
 
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, coff_line_base);
 
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -2794,18 +2985,18 @@ ppc_bf (ignore)
 
 static void
 ppc_ef (ignore)
 
 static void
 ppc_ef (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   sym = symbol_make (".ef");
   S_SET_SEGMENT (sym, text_section);
 {
   symbolS *sym;
 
   sym = symbol_make (".ef");
   S_SET_SEGMENT (sym, text_section);
-  sym->sy_frag = frag_now;
+  symbol_set_frag (sym, frag_now);
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_FCN);
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_FCN);
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -2820,6 +3011,8 @@ static void
 ppc_biei (ei)
      int ei;
 {
 ppc_biei (ei)
      int ei;
 {
+  static symbolS *last_biei;
+
   char *name;
   int len;
   symbolS *sym;
   char *name;
   int len;
   symbolS *sym;
@@ -2837,12 +3030,12 @@ ppc_biei (ei)
      .text section.  */
   S_SET_SEGMENT (sym, text_section);
   S_SET_VALUE (sym, coff_n_line_nos);
      .text section.  */
   S_SET_SEGMENT (sym, text_section);
   S_SET_VALUE (sym, coff_n_line_nos);
-  sym->bsym->flags |= BSF_DEBUGGING;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
 
   S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL);
 
   S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL);
-  sym->sy_tc.output = 1;
-  
-  for (look = symbol_rootP;
+  symbol_get_tc (sym)->output = 1;
+
+  for (look = last_biei ? last_biei : symbol_rootP;
        (look != (symbolS *) NULL
        && (S_GET_STORAGE_CLASS (look) == C_FILE
            || S_GET_STORAGE_CLASS (look) == C_BINCL
        (look != (symbolS *) NULL
        && (S_GET_STORAGE_CLASS (look) == C_FILE
            || S_GET_STORAGE_CLASS (look) == C_BINCL
@@ -2853,6 +3046,7 @@ ppc_biei (ei)
     {
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_insert (sym, look, &symbol_rootP, &symbol_lastP);
     {
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_insert (sym, look, &symbol_rootP, &symbol_lastP);
+      last_biei = sym;
     }
 
   demand_empty_rest_of_line ();
     }
 
   demand_empty_rest_of_line ();
@@ -2864,7 +3058,7 @@ ppc_biei (ei)
 
 static void
 ppc_bs (ignore)
 
 static void
 ppc_bs (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -2872,7 +3066,7 @@ ppc_bs (ignore)
   symbolS *sym;
 
   if (ppc_current_block != NULL)
   symbolS *sym;
 
   if (ppc_current_block != NULL)
-    as_bad ("nested .bs blocks");
+    as_bad (_("nested .bs blocks"));
 
   name = input_line_pointer;
   endc = get_symbol_end ();
 
   name = input_line_pointer;
   endc = get_symbol_end ();
@@ -2884,10 +3078,10 @@ ppc_bs (ignore)
   sym = symbol_make (".bs");
   S_SET_SEGMENT (sym, now_seg);
   S_SET_STORAGE_CLASS (sym, C_BSTAT);
   sym = symbol_make (".bs");
   S_SET_SEGMENT (sym, now_seg);
   S_SET_STORAGE_CLASS (sym, C_BSTAT);
-  sym->bsym->flags |= BSF_DEBUGGING;
-  sym->sy_tc.output = 1;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
+  symbol_get_tc (sym)->output = 1;
 
 
-  sym->sy_tc.within = csect;
+  symbol_get_tc (sym)->within = csect;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -2900,18 +3094,18 @@ ppc_bs (ignore)
 
 static void
 ppc_es (ignore)
 
 static void
 ppc_es (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   if (ppc_current_block == NULL)
 {
   symbolS *sym;
 
   if (ppc_current_block == NULL)
-    as_bad (".es without preceding .bs");
+    as_bad (_(".es without preceding .bs"));
 
   sym = symbol_make (".es");
   S_SET_SEGMENT (sym, now_seg);
   S_SET_STORAGE_CLASS (sym, C_ESTAT);
 
   sym = symbol_make (".es");
   S_SET_SEGMENT (sym, now_seg);
   S_SET_STORAGE_CLASS (sym, C_ESTAT);
-  sym->bsym->flags |= BSF_DEBUGGING;
-  sym->sy_tc.output = 1;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
+  symbol_get_tc (sym)->output = 1;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -2925,20 +3119,20 @@ ppc_es (ignore)
 
 static void
 ppc_bb (ignore)
 
 static void
 ppc_bb (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   sym = symbol_make (".bb");
   S_SET_SEGMENT (sym, text_section);
 {
   symbolS *sym;
 
   sym = symbol_make (".bb");
   S_SET_SEGMENT (sym, text_section);
-  sym->sy_frag = frag_now;
+  symbol_set_frag (sym, frag_now);
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_BLOCK);
 
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
 
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_BLOCK);
 
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
 
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   SF_SET_PROCESS (sym);
 
 
   SF_SET_PROCESS (sym);
 
@@ -2952,18 +3146,18 @@ ppc_bb (ignore)
 
 static void
 ppc_eb (ignore)
 
 static void
 ppc_eb (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   sym = symbol_make (".eb");
   S_SET_SEGMENT (sym, text_section);
 {
   symbolS *sym;
 
   sym = symbol_make (".eb");
   S_SET_SEGMENT (sym, text_section);
-  sym->sy_frag = frag_now;
+  symbol_set_frag (sym, frag_now);
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_BLOCK);
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
   S_SET_VALUE (sym, frag_now_fix ());
   S_SET_STORAGE_CLASS (sym, C_BLOCK);
   S_SET_NUMBER_AUXILIARY (sym, 1);
   SA_SET_SYM_LNNO (sym, get_absolute_expression ());
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   SF_SET_PROCESS (sym);
 
 
   SF_SET_PROCESS (sym);
 
@@ -2977,7 +3171,7 @@ ppc_eb (ignore)
 
 static void
 ppc_bc (ignore)
 
 static void
 ppc_bc (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   int len;
 {
   char *name;
   int len;
@@ -2986,10 +3180,10 @@ ppc_bc (ignore)
   name = demand_copy_C_string (&len);
   sym = symbol_make (name);
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
   name = demand_copy_C_string (&len);
   sym = symbol_make (name);
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
-  sym->bsym->flags |= BSF_DEBUGGING;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
   S_SET_STORAGE_CLASS (sym, C_BCOMM);
   S_SET_VALUE (sym, 0);
   S_SET_STORAGE_CLASS (sym, C_BCOMM);
   S_SET_VALUE (sym, 0);
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -3000,16 +3194,16 @@ ppc_bc (ignore)
 
 static void
 ppc_ec (ignore)
 
 static void
 ppc_ec (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *sym;
 
   sym = symbol_make (".ec");
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
 {
   symbolS *sym;
 
   sym = symbol_make (".ec");
   S_SET_SEGMENT (sym, ppc_coff_debug_section);
-  sym->bsym->flags |= BSF_DEBUGGING;
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
   S_SET_STORAGE_CLASS (sym, C_ECOMM);
   S_SET_VALUE (sym, 0);
   S_SET_STORAGE_CLASS (sym, C_ECOMM);
   S_SET_VALUE (sym, 0);
-  sym->sy_tc.output = 1;
+  symbol_get_tc (sym)->output = 1;
 
   ppc_frob_label (sym);
 
 
   ppc_frob_label (sym);
 
@@ -3020,16 +3214,16 @@ ppc_ec (ignore)
 
 static void
 ppc_toc (ignore)
 
 static void
 ppc_toc (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (ppc_toc_csect != (symbolS *) NULL)
 {
   if (ppc_toc_csect != (symbolS *) NULL)
-    subseg_set (data_section, ppc_toc_csect->sy_tc.subseg);
+    subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg);
   else
     {
       subsegT subseg;
       symbolS *sym;
       symbolS *list;
   else
     {
       subsegT subseg;
       symbolS *sym;
       symbolS *list;
-    
+
       subseg = ppc_data_subsegment;
       ++ppc_data_subsegment;
 
       subseg = ppc_data_subsegment;
       ++ppc_data_subsegment;
 
@@ -3037,23 +3231,24 @@ ppc_toc (ignore)
       ppc_toc_frag = frag_now;
 
       sym = symbol_find_or_make ("TOC[TC0]");
       ppc_toc_frag = frag_now;
 
       sym = symbol_find_or_make ("TOC[TC0]");
-      sym->sy_frag = frag_now;
+      symbol_set_frag (sym, frag_now);
       S_SET_SEGMENT (sym, data_section);
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
       S_SET_SEGMENT (sym, data_section);
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
-      sym->sy_tc.subseg = subseg;
-      sym->sy_tc.output = 1;
-      sym->sy_tc.within = sym;
+      symbol_get_tc (sym)->subseg = subseg;
+      symbol_get_tc (sym)->output = 1;
+      symbol_get_tc (sym)->within = sym;
 
       ppc_toc_csect = sym;
 
       ppc_toc_csect = sym;
-         
+
       for (list = ppc_data_csects;
       for (list = ppc_data_csects;
-          list->sy_tc.next != (symbolS *) NULL;
-          list = list->sy_tc.next)
+          symbol_get_tc (list)->next != (symbolS *) NULL;
+          list = symbol_get_tc (list)->next)
        ;
        ;
-      list->sy_tc.next = sym;
+      symbol_get_tc (list)->next = sym;
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
-      symbol_append (sym, list->sy_tc.within, &symbol_rootP, &symbol_lastP);
+      symbol_append (sym, symbol_get_tc (list)->within, &symbol_rootP,
+                    &symbol_lastP);
     }
 
   ppc_current_csect = ppc_toc_csect;
     }
 
   ppc_current_csect = ppc_toc_csect;
@@ -3061,6 +3256,53 @@ ppc_toc (ignore)
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
 
+/* The AIX assembler automatically aligns the operands of a .long or
+   .short pseudo-op, and we want to be compatible.  */
+
+static void
+ppc_xcoff_cons (log_size)
+     int log_size;
+{
+  frag_align (log_size, 0, 0);
+  record_alignment (now_seg, log_size);
+  cons (1 << log_size);
+}
+
+static void
+ppc_machine(dummy)
+    int dummy ATTRIBUTE_UNUSED;
+{
+    discard_rest_of_line();
+   /* What does aix use this for?  */
+}
+
+static void
+ppc_vbyte (dummy)
+     int dummy ATTRIBUTE_UNUSED;
+{
+  expressionS exp;
+  int byte_count;
+
+  (void) expression (&exp);
+
+  if (exp.X_op != O_constant)
+    {
+      as_bad (_("non-constant byte count"));
+      return;
+    }
+
+  byte_count = exp.X_add_number;
+
+  if (*input_line_pointer != ',')
+    {
+      as_bad (_("missing value"));
+      return;
+    }
+
+  ++input_line_pointer;
+  cons (byte_count);
+}
+
 #endif /* OBJ_XCOFF */
 \f
 /* The .tc pseudo-op.  This is used when generating either XCOFF or
 #endif /* OBJ_XCOFF */
 \f
 /* The .tc pseudo-op.  This is used when generating either XCOFF or
@@ -3077,7 +3319,7 @@ ppc_toc (ignore)
 
 static void
 ppc_tc (ignore)
 
 static void
 ppc_tc (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 #ifdef OBJ_XCOFF
 
 {
 #ifdef OBJ_XCOFF
 
@@ -3090,7 +3332,7 @@ ppc_tc (ignore)
     if (ppc_toc_csect == (symbolS *) NULL
        || ppc_toc_csect != ppc_current_csect)
       {
     if (ppc_toc_csect == (symbolS *) NULL
        || ppc_toc_csect != ppc_current_csect)
       {
-       as_bad (".tc not in .toc section");
+       as_bad (_(".tc not in .toc section"));
        ignore_rest_of_line ();
        return;
       }
        ignore_rest_of_line ();
        return;
       }
@@ -3106,16 +3348,16 @@ ppc_tc (ignore)
       {
        symbolS *label;
 
       {
        symbolS *label;
 
-       label = ppc_current_csect->sy_tc.within;
-       if (label->sy_tc.class != XMC_TC0)
+       label = symbol_get_tc (ppc_current_csect)->within;
+       if (symbol_get_tc (label)->class != XMC_TC0)
          {
          {
-           as_bad (".tc with no label");
+           as_bad (_(".tc with no label"));
            ignore_rest_of_line ();
            return;
          }
 
        S_SET_SEGMENT (label, S_GET_SEGMENT (sym));
            ignore_rest_of_line ();
            return;
          }
 
        S_SET_SEGMENT (label, S_GET_SEGMENT (sym));
-       label->sy_frag = sym->sy_frag;
+       symbol_set_frag (label, symbol_get_frag (sym));
        S_SET_VALUE (label, S_GET_VALUE (sym));
 
        while (! is_end_of_line[(unsigned char) *input_line_pointer])
        S_SET_VALUE (label, S_GET_VALUE (sym));
 
        while (! is_end_of_line[(unsigned char) *input_line_pointer])
@@ -3125,10 +3367,10 @@ ppc_tc (ignore)
       }
 
     S_SET_SEGMENT (sym, now_seg);
       }
 
     S_SET_SEGMENT (sym, now_seg);
-    sym->sy_frag = frag_now;
+    symbol_set_frag (sym, frag_now);
     S_SET_VALUE (sym, (valueT) frag_now_fix ());
     S_SET_VALUE (sym, (valueT) frag_now_fix ());
-    sym->sy_tc.class = XMC_TC;
-    sym->sy_tc.output = 1;
+    symbol_get_tc (sym)->class = XMC_TC;
+    symbol_get_tc (sym)->output = 1;
 
     ppc_frob_label (sym);
   }
 
     ppc_frob_label (sym);
   }
@@ -3144,7 +3386,7 @@ ppc_tc (ignore)
     ++input_line_pointer;
 
   /* Align to a four byte boundary.  */
     ++input_line_pointer;
 
   /* Align to a four byte boundary.  */
-  frag_align (2, 0);
+  frag_align (2, 0, 0);
   record_alignment (now_seg, 2);
 
 #endif /* ! defined (OBJ_XCOFF) */
   record_alignment (now_seg, 2);
 
 #endif /* ! defined (OBJ_XCOFF) */
@@ -3154,7 +3396,7 @@ ppc_tc (ignore)
   else
     {
       ++input_line_pointer;
   else
     {
       ++input_line_pointer;
-      cons (4);
+      cons ((ppc_size == PPC_OPCODE_64) ? 8 : 4);
     }
 }
 \f
     }
 }
 \f
@@ -3178,13 +3420,13 @@ ppc_set_current_section (new)
 */
 static void
 ppc_previous(ignore)
 */
 static void
 ppc_previous(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   symbolS *tmp;
 
 {
   symbolS *tmp;
 
-  if (ppc_previous_section == NULL) 
+  if (ppc_previous_section == NULL)
     {
     {
-      as_warn("No previous section to return to. Directive ignored.");
+      as_warn(_("No previous section to return to. Directive ignored."));
       return;
     }
 
       return;
     }
 
@@ -3211,16 +3453,16 @@ ppc_previous(ignore)
 */
 static void
 ppc_pdata(ignore)
 */
 static void
 ppc_pdata(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 {
-  if (pdata_section == 0) 
+  if (pdata_section == 0)
     {
       pdata_section = subseg_new (".pdata", 0);
     {
       pdata_section = subseg_new (".pdata", 0);
-      
+
       bfd_set_section_flags (stdoutput, pdata_section,
                             (SEC_ALLOC | SEC_LOAD | SEC_RELOC
                              | SEC_READONLY | SEC_DATA ));
       bfd_set_section_flags (stdoutput, pdata_section,
                             (SEC_ALLOC | SEC_LOAD | SEC_RELOC
                              | SEC_READONLY | SEC_DATA ));
-      
+
       bfd_set_section_alignment (stdoutput, pdata_section, 2);
     }
   else
       bfd_set_section_alignment (stdoutput, pdata_section, 2);
     }
   else
@@ -3246,9 +3488,9 @@ ppc_pdata(ignore)
 */
 static void
 ppc_ydata(ignore)
 */
 static void
 ppc_ydata(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
 {
-  if (ydata_section == 0) 
+  if (ydata_section == 0)
     {
       ydata_section = subseg_new (".ydata", 0);
       bfd_set_section_flags (stdoutput, ydata_section,
     {
       ydata_section = subseg_new (".ydata", 0);
       bfd_set_section_flags (stdoutput, ydata_section,
@@ -3283,14 +3525,14 @@ ppc_ydata(ignore)
 */
 static void
 ppc_reldata(ignore)
 */
 static void
 ppc_reldata(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (reldata_section == 0)
     {
       reldata_section = subseg_new (".reldata", 0);
 
       bfd_set_section_flags (stdoutput, reldata_section,
 {
   if (reldata_section == 0)
     {
       reldata_section = subseg_new (".reldata", 0);
 
       bfd_set_section_flags (stdoutput, reldata_section,
-                            ( SEC_ALLOC | SEC_LOAD | SEC_RELOC 
+                            ( SEC_ALLOC | SEC_LOAD | SEC_RELOC
                              | SEC_DATA ));
 
       bfd_set_section_alignment (stdoutput, reldata_section, 2);
                              | SEC_DATA ));
 
       bfd_set_section_alignment (stdoutput, reldata_section, 2);
@@ -3314,7 +3556,7 @@ ppc_reldata(ignore)
 */
 static void
 ppc_rdata(ignore)
 */
 static void
 ppc_rdata(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (rdata_section == 0)
     {
 {
   if (rdata_section == 0)
     {
@@ -3333,7 +3575,7 @@ ppc_rdata(ignore)
 }
 
 /* pseudo-op: .ualong
 }
 
 /* pseudo-op: .ualong
-   behaviour: much like .int, with the exception that no alignment is 
+   behaviour: much like .int, with the exception that no alignment is
               performed.
              FIXME: test the alignment statement
    errors:    None
               performed.
              FIXME: test the alignment statement
    errors:    None
@@ -3341,7 +3583,7 @@ ppc_rdata(ignore)
 */
 static void
 ppc_ualong(ignore)
 */
 static void
 ppc_ualong(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   /* try for long */
   cons ( 4 );
 {
   /* try for long */
   cons ( 4 );
@@ -3356,7 +3598,7 @@ ppc_ualong(ignore)
 */
 static void
 ppc_znop(ignore)
 */
 static void
 ppc_znop(ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   unsigned long insn;
   const struct powerpc_opcode *opcode;
 {
   unsigned long insn;
   const struct powerpc_opcode *opcode;
@@ -3404,10 +3646,10 @@ ppc_znop(ignore)
 
 }
 
 
 }
 
-/* pseudo-op: 
-   behaviour: 
-   errors:    
-   warnings:  
+/* pseudo-op:
+   behaviour:
+   errors:
+   warnings:
 */
 static void
 ppc_pe_comm(lcomm)
 */
 static void
 ppc_pe_comm(lcomm)
@@ -3429,7 +3671,7 @@ ppc_pe_comm(lcomm)
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad ("Expected comma after symbol-name: rest of line ignored.");
+      as_bad (_("Expected comma after symbol-name: rest of line ignored."));
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -3437,7 +3679,7 @@ ppc_pe_comm(lcomm)
   input_line_pointer++;                /* skip ',' */
   if ((temp = get_absolute_expression ()) < 0)
     {
   input_line_pointer++;                /* skip ',' */
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
+      as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
       ignore_rest_of_line ();
       return;
     }
       ignore_rest_of_line ();
       return;
     }
@@ -3453,7 +3695,7 @@ ppc_pe_comm(lcomm)
          align = get_absolute_expression ();
          if (align <= 0)
            {
          align = get_absolute_expression ();
          if (align <= 0)
            {
-             as_warn ("ignoring bad alignment");
+             as_warn (_("ignoring bad alignment"));
              align = 3;
            }
        }
              align = 3;
            }
        }
@@ -3463,9 +3705,9 @@ ppc_pe_comm(lcomm)
   symbolP = symbol_find_or_make (name);
 
   *p = c;
   symbolP = symbol_find_or_make (name);
 
   *p = c;
-  if (S_IS_DEFINED (symbolP))
+  if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
     {
     {
-      as_bad ("Ignoring attempt to re-define symbol `%s'.",
+      as_bad (_("Ignoring attempt to re-define symbol `%s'."),
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       return;
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       return;
@@ -3474,7 +3716,7 @@ ppc_pe_comm(lcomm)
   if (S_GET_VALUE (symbolP))
     {
       if (S_GET_VALUE (symbolP) != (valueT) temp)
   if (S_GET_VALUE (symbolP))
     {
       if (S_GET_VALUE (symbolP) != (valueT) temp)
-       as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.",
+       as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
                S_GET_NAME (symbolP),
                (long) S_GET_VALUE (symbolP),
                (long) temp);
                S_GET_NAME (symbolP),
                (long) S_GET_VALUE (symbolP),
                (long) temp);
@@ -3507,7 +3749,7 @@ ppc_pe_comm(lcomm)
  * additions/changes for the moto-pas assembler support. There are three
  * categories:
  *
  * additions/changes for the moto-pas assembler support. There are three
  * categories:
  *
- * FIXME: I just noticed this. This doesn't work at all really. It it 
+ * FIXME: I just noticed this. This doesn't work at all really. It it
  *        setting bits that bfd probably neither understands or uses. The
  *        correct approach (?) will have to incorporate extra fields attached
  *        to the section to hold the system specific stuff. (krk)
  *        setting bits that bfd probably neither understands or uses. The
  *        correct approach (?) will have to incorporate extra fields attached
  *        to the section to hold the system specific stuff. (krk)
@@ -3540,7 +3782,7 @@ ppc_pe_comm(lcomm)
 
 void
 ppc_pe_section (ignore)
 
 void
 ppc_pe_section (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   /* Strip out the section name */
   char *section_name;
 {
   /* Strip out the section name */
   char *section_name;
@@ -3603,10 +3845,10 @@ ppc_pe_section (ignore)
                {
                  /* Section Contents */
                case 'a': /* unknown */
                {
                  /* Section Contents */
                case 'a': /* unknown */
-                 as_bad ("Unsupported section attribute -- 'a'");
+                 as_bad (_("Unsupported section attribute -- 'a'"));
                  break;
                case 'c': /* code section */
                  break;
                case 'c': /* code section */
-                 flags |= SEC_CODE; 
+                 flags |= SEC_CODE;
                  break;
                case 'd': /* section has initialized data */
                  flags |= SEC_DATA;
                  break;
                case 'd': /* section has initialized data */
                  flags |= SEC_DATA;
@@ -3622,7 +3864,7 @@ ppc_pe_section (ignore)
                  flags |= SEC_HAS_CONTENTS;
                  break;
                case 'n': /* section can be discarded */
                  flags |= SEC_HAS_CONTENTS;
                  break;
                case 'n': /* section can be discarded */
-                 flags &=~ SEC_LOAD; 
+                 flags &=~ SEC_LOAD;
                  break;
                case 'R': /* Remove section at link time */
                  flags |= SEC_NEVER_LOAD;
                  break;
                case 'R': /* Remove section at link time */
                  flags |= SEC_NEVER_LOAD;
@@ -3673,7 +3915,7 @@ ppc_pe_section (ignore)
                  break;
 
                default:
                  break;
 
                default:
-                 as_bad("unknown section attribute '%c'",
+                 as_bad(_("unknown section attribute '%c'"),
                         *input_line_pointer);
                  break;
                }
                         *input_line_pointer);
                  break;
                }
@@ -3691,7 +3933,7 @@ ppc_pe_section (ignore)
   if (flags != SEC_NO_FLAGS)
     {
       if (! bfd_set_section_flags (stdoutput, sec, flags))
   if (flags != SEC_NO_FLAGS)
     {
       if (! bfd_set_section_flags (stdoutput, sec, flags))
-       as_bad ("error setting flags for \"%s\": %s",
+       as_bad (_("error setting flags for \"%s\": %s"),
                bfd_section_name (stdoutput, sec),
                bfd_errmsg (bfd_get_error ()));
     }
                bfd_section_name (stdoutput, sec),
                bfd_errmsg (bfd_get_error ()));
     }
@@ -3702,7 +3944,7 @@ ppc_pe_section (ignore)
 
 static void
 ppc_pe_function (ignore)
 
 static void
 ppc_pe_function (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3725,7 +3967,7 @@ ppc_pe_function (ignore)
 
 static void
 ppc_pe_tocd (ignore)
 
 static void
 ppc_pe_tocd (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   if (tocdata_section == 0)
     {
 {
   if (tocdata_section == 0)
     {
@@ -3793,7 +4035,7 @@ ppc_canonicalize_symbol_name (name)
          *s = toupper (*s);
 
       if (*s == '\0' || s[1] != '\0')
          *s = toupper (*s);
 
       if (*s == '\0' || s[1] != '\0')
-       as_bad ("bad symbol suffix");
+       as_bad (_("bad symbol suffix"));
 
       *s = ']';
     }
 
       *s = ']';
     }
@@ -3808,16 +4050,18 @@ void
 ppc_symbol_new_hook (sym)
      symbolS *sym;
 {
 ppc_symbol_new_hook (sym)
      symbolS *sym;
 {
+  struct ppc_tc_sy *tc;
   const char *s;
 
   const char *s;
 
-  sym->sy_tc.next = NULL;
-  sym->sy_tc.output = 0;
-  sym->sy_tc.class = -1;
-  sym->sy_tc.real_name = NULL;
-  sym->sy_tc.subseg = 0;
-  sym->sy_tc.align = 0;
-  sym->sy_tc.size = NULL;
-  sym->sy_tc.within = NULL;
+  tc = symbol_get_tc (sym);
+  tc->next = NULL;
+  tc->output = 0;
+  tc->class = -1;
+  tc->real_name = NULL;
+  tc->subseg = 0;
+  tc->align = 0;
+  tc->size = NULL;
+  tc->within = NULL;
 
   if (ppc_stab_symbol)
     return;
 
   if (ppc_stab_symbol)
     return;
@@ -3835,56 +4079,56 @@ ppc_symbol_new_hook (sym)
     {
     case 'B':
       if (strcmp (s, "BS]") == 0)
     {
     case 'B':
       if (strcmp (s, "BS]") == 0)
-       sym->sy_tc.class = XMC_BS;
+       tc->class = XMC_BS;
       break;
     case 'D':
       if (strcmp (s, "DB]") == 0)
       break;
     case 'D':
       if (strcmp (s, "DB]") == 0)
-       sym->sy_tc.class = XMC_DB;
+       tc->class = XMC_DB;
       else if (strcmp (s, "DS]") == 0)
       else if (strcmp (s, "DS]") == 0)
-       sym->sy_tc.class = XMC_DS;
+       tc->class = XMC_DS;
       break;
     case 'G':
       if (strcmp (s, "GL]") == 0)
       break;
     case 'G':
       if (strcmp (s, "GL]") == 0)
-       sym->sy_tc.class = XMC_GL;
+       tc->class = XMC_GL;
       break;
     case 'P':
       if (strcmp (s, "PR]") == 0)
       break;
     case 'P':
       if (strcmp (s, "PR]") == 0)
-       sym->sy_tc.class = XMC_PR;
+       tc->class = XMC_PR;
       break;
     case 'R':
       if (strcmp (s, "RO]") == 0)
       break;
     case 'R':
       if (strcmp (s, "RO]") == 0)
-       sym->sy_tc.class = XMC_RO;
+       tc->class = XMC_RO;
       else if (strcmp (s, "RW]") == 0)
       else if (strcmp (s, "RW]") == 0)
-       sym->sy_tc.class = XMC_RW;
+       tc->class = XMC_RW;
       break;
     case 'S':
       if (strcmp (s, "SV]") == 0)
       break;
     case 'S':
       if (strcmp (s, "SV]") == 0)
-       sym->sy_tc.class = XMC_SV;
+       tc->class = XMC_SV;
       break;
     case 'T':
       if (strcmp (s, "TC]") == 0)
       break;
     case 'T':
       if (strcmp (s, "TC]") == 0)
-       sym->sy_tc.class = XMC_TC;
+       tc->class = XMC_TC;
       else if (strcmp (s, "TI]") == 0)
       else if (strcmp (s, "TI]") == 0)
-       sym->sy_tc.class = XMC_TI;
+       tc->class = XMC_TI;
       else if (strcmp (s, "TB]") == 0)
       else if (strcmp (s, "TB]") == 0)
-       sym->sy_tc.class = XMC_TB;
+       tc->class = XMC_TB;
       else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
       else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
-       sym->sy_tc.class = XMC_TC0;
+       tc->class = XMC_TC0;
       break;
     case 'U':
       if (strcmp (s, "UA]") == 0)
       break;
     case 'U':
       if (strcmp (s, "UA]") == 0)
-       sym->sy_tc.class = XMC_UA;
+       tc->class = XMC_UA;
       else if (strcmp (s, "UC]") == 0)
       else if (strcmp (s, "UC]") == 0)
-       sym->sy_tc.class = XMC_UC;
+       tc->class = XMC_UC;
       break;
     case 'X':
       if (strcmp (s, "XO]") == 0)
       break;
     case 'X':
       if (strcmp (s, "XO]") == 0)
-       sym->sy_tc.class = XMC_XO;
+       tc->class = XMC_XO;
       break;
     }
 
       break;
     }
 
-  if (sym->sy_tc.class == -1)
-    as_bad ("Unrecognized symbol suffix");
+  if (tc->class == -1)
+    as_bad (_("Unrecognized symbol suffix"));
 }
 
 /* Set the class of a label based on where it is defined.  This
 }
 
 /* Set the class of a label based on where it is defined.  This
@@ -3897,13 +4141,13 @@ ppc_frob_label (sym)
 {
   if (ppc_current_csect != (symbolS *) NULL)
     {
 {
   if (ppc_current_csect != (symbolS *) NULL)
     {
-      if (sym->sy_tc.class == -1)
-       sym->sy_tc.class = ppc_current_csect->sy_tc.class;
+      if (symbol_get_tc (sym)->class == -1)
+       symbol_get_tc (sym)->class = symbol_get_tc (ppc_current_csect)->class;
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
-      symbol_append (sym, ppc_current_csect->sy_tc.within, &symbol_rootP,
-                    &symbol_lastP);
-      ppc_current_csect->sy_tc.within = sym;
+      symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
+                    &symbol_rootP, &symbol_lastP);
+      symbol_get_tc (ppc_current_csect)->within = sym;
     }
 }
 
     }
 }
 
@@ -3927,15 +4171,15 @@ ppc_frob_symbol (sym)
 
   /* Discard symbols that should not be included in the output symbol
      table.  */
 
   /* Discard symbols that should not be included in the output symbol
      table.  */
-  if (! sym->sy_used_in_reloc
-      && ((sym->bsym->flags & BSF_SECTION_SYM) != 0
+  if (! symbol_used_in_reloc_p (sym)
+      && ((symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0
          || (! S_IS_EXTERNAL (sym)
          || (! S_IS_EXTERNAL (sym)
-             && ! sym->sy_tc.output
+             && ! symbol_get_tc (sym)->output
              && S_GET_STORAGE_CLASS (sym) != C_FILE)))
     return 1;
 
              && S_GET_STORAGE_CLASS (sym) != C_FILE)))
     return 1;
 
-  if (sym->sy_tc.real_name != (char *) NULL)
-    S_SET_NAME (sym, sym->sy_tc.real_name);
+  if (symbol_get_tc (sym)->real_name != (char *) NULL)
+    S_SET_NAME (sym, symbol_get_tc (sym)->real_name);
   else
     {
       const char *name;
   else
     {
       const char *name;
@@ -3966,19 +4210,20 @@ ppc_frob_symbol (sym)
   if (SF_GET_FUNCTION (sym))
     {
       if (ppc_last_function != (symbolS *) NULL)
   if (SF_GET_FUNCTION (sym))
     {
       if (ppc_last_function != (symbolS *) NULL)
-       as_bad ("two .function pseudo-ops with no intervening .ef");
+       as_bad (_("two .function pseudo-ops with no intervening .ef"));
       ppc_last_function = sym;
       ppc_last_function = sym;
-      if (sym->sy_tc.size != (symbolS *) NULL)
+      if (symbol_get_tc (sym)->size != (symbolS *) NULL)
        {
        {
-         resolve_symbol_value (sym->sy_tc.size);
-         SA_SET_SYM_FSIZE (sym, (long) S_GET_VALUE (sym->sy_tc.size));
+         resolve_symbol_value (symbol_get_tc (sym)->size, 1);
+         SA_SET_SYM_FSIZE (sym,
+                           (long) S_GET_VALUE (symbol_get_tc (sym)->size));
        }
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_FCN
           && strcmp (S_GET_NAME (sym), ".ef") == 0)
     {
       if (ppc_last_function == (symbolS *) NULL)
        }
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_FCN
           && strcmp (S_GET_NAME (sym), ".ef") == 0)
     {
       if (ppc_last_function == (symbolS *) NULL)
-       as_bad (".ef with no preceding .function");
+       as_bad (_(".ef with no preceding .function"));
       else
        {
          set_end = ppc_last_function;
       else
        {
          set_end = ppc_last_function;
@@ -3991,7 +4236,7 @@ ppc_frob_symbol (sym)
     }
 
   if (! S_IS_EXTERNAL (sym)
     }
 
   if (! S_IS_EXTERNAL (sym)
-      && (sym->bsym->flags & BSF_SECTION_SYM) == 0
+      && (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) == 0
       && S_GET_STORAGE_CLASS (sym) != C_FILE
       && S_GET_STORAGE_CLASS (sym) != C_FCN
       && S_GET_STORAGE_CLASS (sym) != C_BLOCK
       && S_GET_STORAGE_CLASS (sym) != C_FILE
       && S_GET_STORAGE_CLASS (sym) != C_FCN
       && S_GET_STORAGE_CLASS (sym) != C_BLOCK
@@ -4011,39 +4256,39 @@ ppc_frob_symbol (sym)
       /* Create a csect aux.  */
       i = S_GET_NUMBER_AUXILIARY (sym);
       S_SET_NUMBER_AUXILIARY (sym, i + 1);
       /* Create a csect aux.  */
       i = S_GET_NUMBER_AUXILIARY (sym);
       S_SET_NUMBER_AUXILIARY (sym, i + 1);
-      a = &coffsymbol (sym->bsym)->native[i + 1].u.auxent;
-      if (sym->sy_tc.class == XMC_TC0)
+      a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent;
+      if (symbol_get_tc (sym)->class == XMC_TC0)
        {
          /* This is the TOC table.  */
          know (strcmp (S_GET_NAME (sym), "TOC") == 0);
          a->x_csect.x_scnlen.l = 0;
          a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
        }
        {
          /* This is the TOC table.  */
          know (strcmp (S_GET_NAME (sym), "TOC") == 0);
          a->x_csect.x_scnlen.l = 0;
          a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
        }
-      else if (sym->sy_tc.subseg != 0)
+      else if (symbol_get_tc (sym)->subseg != 0)
        {
          /* This is a csect symbol.  x_scnlen is the size of the
             csect.  */
        {
          /* This is a csect symbol.  x_scnlen is the size of the
             csect.  */
-         if (sym->sy_tc.next == (symbolS *) NULL)
+         if (symbol_get_tc (sym)->next == (symbolS *) NULL)
            a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
                                                       S_GET_SEGMENT (sym))
                                     - S_GET_VALUE (sym));
          else
            {
            a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
                                                       S_GET_SEGMENT (sym))
                                     - S_GET_VALUE (sym));
          else
            {
-             resolve_symbol_value (sym->sy_tc.next);
-             a->x_csect.x_scnlen.l = (S_GET_VALUE (sym->sy_tc.next)
+             resolve_symbol_value (symbol_get_tc (sym)->next, 1);
+             a->x_csect.x_scnlen.l = (S_GET_VALUE (symbol_get_tc (sym)->next)
                                       - S_GET_VALUE (sym));
            }
                                       - S_GET_VALUE (sym));
            }
-         a->x_csect.x_smtyp = (sym->sy_tc.align << 3) | XTY_SD;
+         a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_SD;
        }
       else if (S_GET_SEGMENT (sym) == bss_section)
        {
          /* This is a common symbol.  */
        }
       else if (S_GET_SEGMENT (sym) == bss_section)
        {
          /* This is a common symbol.  */
-         a->x_csect.x_scnlen.l = sym->sy_frag->fr_offset;
-         a->x_csect.x_smtyp = (sym->sy_tc.align << 3) | XTY_CM;
+         a->x_csect.x_scnlen.l = symbol_get_frag (sym)->fr_offset;
+         a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM;
          if (S_IS_EXTERNAL (sym))
          if (S_IS_EXTERNAL (sym))
-           sym->sy_tc.class = XMC_RW;
+           symbol_get_tc (sym)->class = XMC_RW;
          else
          else
-           sym->sy_tc.class = XMC_BS;
+           symbol_get_tc (sym)->class = XMC_BS;
        }
       else if (S_GET_SEGMENT (sym) == absolute_section)
        {
        }
       else if (S_GET_SEGMENT (sym) == absolute_section)
        {
@@ -4051,8 +4296,8 @@ ppc_frob_symbol (sym)
              ppc_adjust_symtab.  */
          ppc_saw_abs = true;
          a->x_csect.x_smtyp = XTY_LD;
              ppc_adjust_symtab.  */
          ppc_saw_abs = true;
          a->x_csect.x_smtyp = XTY_LD;
-         if (sym->sy_tc.class == -1)
-           sym->sy_tc.class = XMC_XO;
+         if (symbol_get_tc (sym)->class == -1)
+           symbol_get_tc (sym)->class = XMC_XO;
        }
       else if (! S_IS_DEFINED (sym))
        {
        }
       else if (! S_IS_DEFINED (sym))
        {
@@ -4060,17 +4305,17 @@ ppc_frob_symbol (sym)
          a->x_csect.x_scnlen.l = 0;
          a->x_csect.x_smtyp = XTY_ER;
        }
          a->x_csect.x_scnlen.l = 0;
          a->x_csect.x_smtyp = XTY_ER;
        }
-      else if (sym->sy_tc.class == XMC_TC)
+      else if (symbol_get_tc (sym)->class == XMC_TC)
        {
          symbolS *next;
 
          /* This is a TOC definition.  x_scnlen is the size of the
             TOC entry.  */
          next = symbol_next (sym);
        {
          symbolS *next;
 
          /* This is a TOC definition.  x_scnlen is the size of the
             TOC entry.  */
          next = symbol_next (sym);
-         while (next->sy_tc.class == XMC_TC0)
+         while (symbol_get_tc (next)->class == XMC_TC0)
            next = symbol_next (next);
          if (next == (symbolS *) NULL
            next = symbol_next (next);
          if (next == (symbolS *) NULL
-             || next->sy_tc.class != XMC_TC)
+             || symbol_get_tc (next)->class != XMC_TC)
            {
              if (ppc_after_toc_frag == (fragS *) NULL)
                a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
            {
              if (ppc_after_toc_frag == (fragS *) NULL)
                a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
@@ -4082,7 +4327,7 @@ ppc_frob_symbol (sym)
            }
          else
            {
            }
          else
            {
-             resolve_symbol_value (next);
+             resolve_symbol_value (next, 1);
              a->x_csect.x_scnlen.l = (S_GET_VALUE (next)
                                       - S_GET_VALUE (sym));
            }
              a->x_csect.x_scnlen.l = (S_GET_VALUE (next)
                                       - S_GET_VALUE (sym));
            }
@@ -4102,40 +4347,43 @@ ppc_frob_symbol (sym)
            abort ();
 
          /* Skip the initial dummy symbol.  */
            abort ();
 
          /* Skip the initial dummy symbol.  */
-         csect = csect->sy_tc.next;
+         csect = symbol_get_tc (csect)->next;
 
          if (csect == (symbolS *) NULL)
            {
 
          if (csect == (symbolS *) NULL)
            {
-             as_warn ("warning: symbol %s has no csect", S_GET_NAME (sym));
+             as_warn (_("warning: symbol %s has no csect"), S_GET_NAME (sym));
              a->x_csect.x_scnlen.l = 0;
            }
          else
            {
              a->x_csect.x_scnlen.l = 0;
            }
          else
            {
-             while (csect->sy_tc.next != (symbolS *) NULL)
+             while (symbol_get_tc (csect)->next != (symbolS *) NULL)
                {
                {
-                 resolve_symbol_value (csect->sy_tc.next);
-                 if (S_GET_VALUE (csect->sy_tc.next) > S_GET_VALUE (sym))
+                 resolve_symbol_value (symbol_get_tc (csect)->next, 1);
+                 if (S_GET_VALUE (symbol_get_tc (csect)->next)
+                     > S_GET_VALUE (sym))
                    break;
                    break;
-                 csect = csect->sy_tc.next;
+                 csect = symbol_get_tc (csect)->next;
                }
 
                }
 
-             a->x_csect.x_scnlen.p = coffsymbol (csect->bsym)->native;
-             coffsymbol (sym->bsym)->native[i + 1].fix_scnlen = 1;
+             a->x_csect.x_scnlen.p =
+               coffsymbol (symbol_get_bfdsym (csect))->native;
+             coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].fix_scnlen =
+               1;
            }
          a->x_csect.x_smtyp = XTY_LD;
        }
            }
          a->x_csect.x_smtyp = XTY_LD;
        }
-       
+
       a->x_csect.x_parmhash = 0;
       a->x_csect.x_snhash = 0;
       a->x_csect.x_parmhash = 0;
       a->x_csect.x_snhash = 0;
-      if (sym->sy_tc.class == -1)
+      if (symbol_get_tc (sym)->class == -1)
        a->x_csect.x_smclas = XMC_PR;
       else
        a->x_csect.x_smclas = XMC_PR;
       else
-       a->x_csect.x_smclas = sym->sy_tc.class;
+       a->x_csect.x_smclas = symbol_get_tc (sym)->class;
       a->x_csect.x_stab = 0;
       a->x_csect.x_snstab = 0;
 
       /* Don't let the COFF backend resort these symbols.  */
       a->x_csect.x_stab = 0;
       a->x_csect.x_snstab = 0;
 
       /* Don't let the COFF backend resort these symbols.  */
-      sym->bsym->flags |= BSF_NOT_AT_END;
+      symbol_get_bfdsym (sym)->flags |= BSF_NOT_AT_END;
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_BSTAT)
     {
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_BSTAT)
     {
@@ -4143,8 +4391,10 @@ ppc_frob_symbol (sym)
         csect symbol.  BFD will do that for us if we set the right
         flags.  */
       S_SET_VALUE (sym,
         csect symbol.  BFD will do that for us if we set the right
         flags.  */
       S_SET_VALUE (sym,
-                  (valueT) coffsymbol (sym->sy_tc.within->bsym)->native);
-      coffsymbol (sym->bsym)->native->fix_value = 1;
+                  ((valueT)
+                   coffsymbol (symbol_get_bfdsym
+                               (symbol_get_tc (sym)->within))->native));
+      coffsymbol (symbol_get_bfdsym (sym))->native->fix_value = 1;
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
     {
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
     {
@@ -4152,9 +4402,9 @@ ppc_frob_symbol (sym)
       symbolS *csect;
 
       /* The value is the offset from the enclosing csect.  */
       symbolS *csect;
 
       /* The value is the offset from the enclosing csect.  */
-      block = sym->sy_tc.within;
-      csect = block->sy_tc.within;
-      resolve_symbol_value (csect);
+      block = symbol_get_tc (sym)->within;
+      csect = symbol_get_tc (block)->within;
+      resolve_symbol_value (csect, 1);
       S_SET_VALUE (sym, S_GET_VALUE (sym) - S_GET_VALUE (csect));
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_BINCL
       S_SET_VALUE (sym, S_GET_VALUE (sym) - S_GET_VALUE (csect));
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_BINCL
@@ -4163,7 +4413,7 @@ ppc_frob_symbol (sym)
       /* We want the value to be a file offset into the line numbers.
          BFD will do that for us if we set the right flags.  We have
          already set the value correctly.  */
       /* We want the value to be a file offset into the line numbers.
          BFD will do that for us if we set the right flags.  We have
          already set the value correctly.  */
-      coffsymbol (sym->bsym)->native->fix_line = 1;
+      coffsymbol (symbol_get_bfdsym (sym))->native->fix_line = 1;
     }
 
   return 0;
     }
 
   return 0;
@@ -4191,11 +4441,11 @@ ppc_adjust_symtab ()
 
       csect = symbol_create (".abs[XO]", absolute_section,
                             S_GET_VALUE (sym), &zero_address_frag);
 
       csect = symbol_create (".abs[XO]", absolute_section,
                             S_GET_VALUE (sym), &zero_address_frag);
-      csect->bsym->value = S_GET_VALUE (sym);
+      symbol_get_bfdsym (csect)->value = S_GET_VALUE (sym);
       S_SET_STORAGE_CLASS (csect, C_HIDEXT);
       i = S_GET_NUMBER_AUXILIARY (csect);
       S_SET_NUMBER_AUXILIARY (csect, i + 1);
       S_SET_STORAGE_CLASS (csect, C_HIDEXT);
       i = S_GET_NUMBER_AUXILIARY (csect);
       S_SET_NUMBER_AUXILIARY (csect, i + 1);
-      a = &coffsymbol (csect->bsym)->native[i + 1].u.auxent;
+      a = &coffsymbol (symbol_get_bfdsym (csect))->native[i + 1].u.auxent;
       a->x_csect.x_scnlen.l = 0;
       a->x_csect.x_smtyp = XTY_SD;
       a->x_csect.x_parmhash = 0;
       a->x_csect.x_scnlen.l = 0;
       a->x_csect.x_smtyp = XTY_SD;
       a->x_csect.x_parmhash = 0;
@@ -4207,9 +4457,9 @@ ppc_adjust_symtab ()
       symbol_insert (csect, sym, &symbol_rootP, &symbol_lastP);
 
       i = S_GET_NUMBER_AUXILIARY (sym);
       symbol_insert (csect, sym, &symbol_rootP, &symbol_lastP);
 
       i = S_GET_NUMBER_AUXILIARY (sym);
-      a = &coffsymbol (sym->bsym)->native[i].u.auxent;
-      a->x_csect.x_scnlen.p = coffsymbol (csect->bsym)->native;
-      coffsymbol (sym->bsym)->native[i].fix_scnlen = 1;
+      a = &coffsymbol (symbol_get_bfdsym (sym))->native[i].u.auxent;
+      a->x_csect.x_scnlen.p = coffsymbol (symbol_get_bfdsym (csect))->native;
+      coffsymbol (symbol_get_bfdsym (sym))->native[i].fix_scnlen = 1;
     }
 
   ppc_saw_abs = false;
     }
 
   ppc_saw_abs = false;
@@ -4231,8 +4481,8 @@ ppc_frob_section (sec)
 #endif /* OBJ_XCOFF */
 \f
 /* Turn a string in input_line_pointer into a floating point constant
 #endif /* OBJ_XCOFF */
 \f
 /* Turn a string in input_line_pointer into a floating point constant
-   of type type, and store the appropriate bytes in *litp.  The number
-   of LITTLENUMS emitted is stored in *sizep .  An error message is
+   of type TYPE, and store the appropriate bytes in *LITP.  The number
+   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
    returned, or NULL on OK.  */
 
 char *
    returned, or NULL on OK.  */
 
 char *
@@ -4258,7 +4508,7 @@ md_atof (type, litp, sizep)
 
     default:
       *sizep = 0;
 
     default:
       *sizep = 0;
-      return "bad call to md_atof";
+      return _("bad call to md_atof");
     }
 
   t = atof_ieee (input_line_pointer, type, words);
     }
 
   t = atof_ieee (input_line_pointer, type, words);
@@ -4283,7 +4533,7 @@ md_atof (type, litp, sizep)
          litp += 2;
        }
     }
          litp += 2;
        }
     }
-     
+
   return NULL;
 }
 
   return NULL;
 }
 
@@ -4318,8 +4568,8 @@ md_section_align (seg, addr)
 
 int
 md_estimate_size_before_relax (fragp, seg)
 
 int
 md_estimate_size_before_relax (fragp, seg)
-     fragS *fragp;
-     asection *seg;
+     fragS *fragp ATTRIBUTE_UNUSED;
+     asection *seg ATTRIBUTE_UNUSED;
 {
   abort ();
   return 0;
 {
   abort ();
   return 0;
@@ -4329,9 +4579,9 @@ md_estimate_size_before_relax (fragp, seg)
 
 void
 md_convert_frag (abfd, sec, fragp)
 
 void
 md_convert_frag (abfd, sec, fragp)
-     bfd *abfd;
-     asection *sec;
-     fragS *fragp;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
+     fragS *fragp ATTRIBUTE_UNUSED;
 {
   abort ();
 }
 {
   abort ();
 }
@@ -4341,7 +4591,7 @@ md_convert_frag (abfd, sec, fragp)
 /*ARGSUSED*/
 symbolS *
 md_undefined_symbol (name)
 /*ARGSUSED*/
 symbolS *
 md_undefined_symbol (name)
-     char *name;
+     char *name ATTRIBUTE_UNUSED;
 {
   return 0;
 }
 {
   return 0;
 }
@@ -4354,15 +4604,8 @@ md_undefined_symbol (name)
 long
 md_pcrel_from_section (fixp, sec)
      fixS *fixp;
 long
 md_pcrel_from_section (fixp, sec)
      fixS *fixp;
-     segT sec;
+     segT sec ATTRIBUTE_UNUSED;
 {
 {
-#ifdef OBJ_ELF
-  if (fixp->fx_addsy != (symbolS *) NULL
-      && (! S_IS_DEFINED (fixp->fx_addsy)
-         || TC_FORCE_RELOCATION_SECTION (fixp, sec)))
-    return 0;
-#endif
-
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
@@ -4379,7 +4622,7 @@ ppc_fix_adjustable (fix)
 {
   valueT val;
 
 {
   valueT val;
 
-  resolve_symbol_value (fix->fx_addsy);
+  resolve_symbol_value (fix->fx_addsy, 1);
   val = S_GET_VALUE (fix->fx_addsy);
   if (ppc_toc_csect != (symbolS *) NULL
       && fix->fx_addsy != (symbolS *) NULL
   val = S_GET_VALUE (fix->fx_addsy);
   if (ppc_toc_csect != (symbolS *) NULL
       && fix->fx_addsy != (symbolS *) NULL
@@ -4395,11 +4638,11 @@ ppc_fix_adjustable (fix)
           sy != (symbolS *) NULL;
           sy = symbol_next (sy))
        {
           sy != (symbolS *) NULL;
           sy = symbol_next (sy))
        {
-         if (sy->sy_tc.class == XMC_TC0)
+         if (symbol_get_tc (sy)->class == XMC_TC0)
            continue;
            continue;
-         if (sy->sy_tc.class != XMC_TC)
+         if (symbol_get_tc (sy)->class != XMC_TC)
            break;
            break;
-         resolve_symbol_value (sy);
+         resolve_symbol_value (sy, 1);
          if (val == S_GET_VALUE (sy))
            {
              fix->fx_addsy = sy;
          if (val == S_GET_VALUE (sy))
            {
              fix->fx_addsy = sy;
@@ -4409,15 +4652,21 @@ ppc_fix_adjustable (fix)
        }
 
       as_bad_where (fix->fx_file, fix->fx_line,
        }
 
       as_bad_where (fix->fx_file, fix->fx_line,
-                   "symbol in .toc does not match any .tc");
+                   _("symbol in .toc does not match any .tc"));
     }
 
   /* Possibly adjust the reloc to be against the csect.  */
   if (fix->fx_addsy != (symbolS *) NULL
     }
 
   /* Possibly adjust the reloc to be against the csect.  */
   if (fix->fx_addsy != (symbolS *) NULL
-      && fix->fx_addsy->sy_tc.subseg == 0
-      && fix->fx_addsy->sy_tc.class != XMC_TC0
-      && fix->fx_addsy->sy_tc.class != XMC_TC
-      && S_GET_SEGMENT (fix->fx_addsy) != bss_section)
+      && symbol_get_tc (fix->fx_addsy)->subseg == 0
+      && symbol_get_tc (fix->fx_addsy)->class != XMC_TC0
+      && symbol_get_tc (fix->fx_addsy)->class != XMC_TC
+      && S_GET_SEGMENT (fix->fx_addsy) != bss_section
+      /* Don't adjust if this is a reloc in the toc section.  */
+      && (S_GET_SEGMENT (fix->fx_addsy) != data_section
+         || ppc_toc_csect == NULL
+         || val < ppc_toc_frag->fr_address
+         || (ppc_after_toc_frag != NULL
+             && val >= ppc_after_toc_frag->fr_address)))
     {
       symbolS *csect;
 
     {
       symbolS *csect;
 
@@ -4429,17 +4678,44 @@ ppc_fix_adjustable (fix)
        abort ();
 
       /* Skip the initial dummy symbol.  */
        abort ();
 
       /* Skip the initial dummy symbol.  */
-      csect = csect->sy_tc.next;
+      csect = symbol_get_tc (csect)->next;
 
       if (csect != (symbolS *) NULL)
        {
 
       if (csect != (symbolS *) NULL)
        {
-         while (csect->sy_tc.next != (symbolS *) NULL
-                && (csect->sy_tc.next->sy_frag->fr_address
-                    <= fix->fx_addsy->sy_frag->fr_address))
-           csect = csect->sy_tc.next;
+         while (symbol_get_tc (csect)->next != (symbolS *) NULL
+                && (symbol_get_frag (symbol_get_tc (csect)->next)->fr_address
+                    <= val))
+           {
+             /* If the csect address equals the symbol value, then we
+                 have to look through the full symbol table to see
+                 whether this is the csect we want.  Note that we will
+                 only get here if the csect has zero length.  */
+             if ((symbol_get_frag (csect)->fr_address == val)
+                 && S_GET_VALUE (csect) == S_GET_VALUE (fix->fx_addsy))
+               {
+                 symbolS *scan;
+
+                 for (scan = symbol_next (csect);
+                      scan != NULL;
+                      scan = symbol_next (scan))
+                   {
+                     if (symbol_get_tc (scan)->subseg != 0)
+                       break;
+                     if (scan == fix->fx_addsy)
+                       break;
+                   }
+
+                 /* If we found the symbol before the next csect
+                     symbol, then this is the csect we want.  */
+                 if (scan == fix->fx_addsy)
+                   break;
+               }
+
+             csect = symbol_get_tc (csect)->next;
+           }
 
          fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
 
          fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
-                            - csect->sy_frag->fr_address);
+                            - symbol_get_frag (csect)->fr_address);
          fix->fx_addsy = csect;
        }
     }
          fix->fx_addsy = csect;
        }
     }
@@ -4450,10 +4726,11 @@ ppc_fix_adjustable (fix)
       && S_GET_SEGMENT (fix->fx_addsy) == bss_section
       && ! S_IS_EXTERNAL (fix->fx_addsy))
     {
       && S_GET_SEGMENT (fix->fx_addsy) == bss_section
       && ! S_IS_EXTERNAL (fix->fx_addsy))
     {
-      resolve_symbol_value (fix->fx_addsy->sy_frag->fr_symbol);
-      fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
-                        - S_GET_VALUE (fix->fx_addsy->sy_frag->fr_symbol));
-      fix->fx_addsy = fix->fx_addsy->sy_frag->fr_symbol;
+      resolve_symbol_value (symbol_get_frag (fix->fx_addsy)->fr_symbol, 1);
+      fix->fx_offset +=
+       (S_GET_VALUE (fix->fx_addsy)
+        - S_GET_VALUE (symbol_get_frag (fix->fx_addsy)->fr_symbol));
+      fix->fx_addsy = symbol_get_frag (fix->fx_addsy)->fr_symbol;
     }
 
   return 0;
     }
 
   return 0;
@@ -4473,10 +4750,11 @@ ppc_force_relocation (fix)
      we need to force the relocation.  */
   if (fix->fx_pcrel
       && fix->fx_addsy != NULL
      we need to force the relocation.  */
   if (fix->fx_pcrel
       && fix->fx_addsy != NULL
-      && fix->fx_addsy->sy_tc.subseg != 0
-      && (fix->fx_addsy->sy_frag->fr_address > fix->fx_frag->fr_address
-         || (fix->fx_addsy->sy_tc.next != NULL
-             && (fix->fx_addsy->sy_tc.next->sy_frag->fr_address
+      && symbol_get_tc (fix->fx_addsy)->subseg != 0
+      && ((symbol_get_frag (fix->fx_addsy)->fr_address
+          > fix->fx_frag->fr_address)
+         || (symbol_get_tc (fix->fx_addsy)->next != NULL
+             && (symbol_get_frag (symbol_get_tc (fix->fx_addsy)->next)->fr_address
                  <= fix->fx_frag->fr_address))))
     return 1;
 
                  <= fix->fx_frag->fr_address))))
     return 1;
 
@@ -4492,7 +4770,7 @@ ppc_is_toc_sym (sym)
      symbolS *sym;
 {
 #ifdef OBJ_XCOFF
      symbolS *sym;
 {
 #ifdef OBJ_XCOFF
-  return sym->sy_tc.class == XMC_TC;
+  return symbol_get_tc (sym)->class == XMC_TC;
 #else
   return strcmp (segment_name (S_GET_SEGMENT (sym)), ".got") == 0;
 #endif
 #else
   return strcmp (segment_name (S_GET_SEGMENT (sym)), ".got") == 0;
 #endif
@@ -4515,17 +4793,39 @@ md_apply_fix3 (fixp, valuep, seg)
 {
   valueT value;
 
 {
   valueT value;
 
+#ifdef OBJ_ELF
+  value = *valuep;
+  if (fixp->fx_addsy != NULL)
+    {
+      /* `*valuep' may contain the value of the symbol on which the reloc
+        will be based; we have to remove it.  */
+      if (symbol_used_in_reloc_p (fixp->fx_addsy)
+         && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section
+         && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
+         && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy)))
+       value -= S_GET_VALUE (fixp->fx_addsy);
+
+      /* FIXME: Why '+'?  Better yet, what exactly is '*valuep'
+        supposed to be?  I think this is related to various similar
+        FIXMEs in tc-i386.c and tc-sparc.c.  */
+      if (fixp->fx_pcrel)
+       value += fixp->fx_frag->fr_address + fixp->fx_where;
+    }
+  else
+    {
+      fixp->fx_done = 1;
+    }
+#else
   /* FIXME FIXME FIXME: The value we are passed in *valuep includes
      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
      doing this relocation the code in write.c is going to call
   /* FIXME FIXME FIXME: The value we are passed in *valuep includes
      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
      doing this relocation the code in write.c is going to call
-     bfd_perform_relocation, which is also going to use the symbol
+     bfd_install_relocation, which is also going to use the symbol
      value.  That means that if the reloc is fully resolved we want to
      value.  That means that if the reloc is fully resolved we want to
-     use *valuep since bfd_perform_relocation is not being used.
+     use *valuep since bfd_install_relocation is not being used.
      However, if the reloc is not fully resolved we do not want to use
      *valuep, and must use fx_offset instead.  However, if the reloc
      is PC relative, we do want to use *valuep since it includes the
      result of md_pcrel_from.  This is confusing.  */
      However, if the reloc is not fully resolved we do not want to use
      *valuep, and must use fx_offset instead.  However, if the reloc
      is PC relative, we do want to use *valuep since it includes the
      result of md_pcrel_from.  This is confusing.  */
-
   if (fixp->fx_addsy == (symbolS *) NULL)
     {
       value = *valuep;
   if (fixp->fx_addsy == (symbolS *) NULL)
     {
       value = *valuep;
@@ -4544,10 +4844,11 @@ md_apply_fix3 (fixp, valuep, seg)
            {
              /* We can't actually support subtracting a symbol.  */
              as_bad_where (fixp->fx_file, fixp->fx_line,
            {
              /* We can't actually support subtracting a symbol.  */
              as_bad_where (fixp->fx_file, fixp->fx_line,
-                           "expression too complex");
+                           _("expression too complex"));
            }
        }
     }
            }
        }
     }
+#endif
 
   if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
 
   if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
@@ -4573,9 +4874,9 @@ md_apply_fix3 (fixp, valuep, seg)
          && operand->shift == 0
          && operand->insert == NULL
          && fixp->fx_addsy != NULL
          && operand->shift == 0
          && operand->insert == NULL
          && fixp->fx_addsy != NULL
-         && fixp->fx_addsy->sy_tc.subseg != 0
-         && fixp->fx_addsy->sy_tc.class != XMC_TC
-         && fixp->fx_addsy->sy_tc.class != XMC_TC0
+         && symbol_get_tc (fixp->fx_addsy)->subseg != 0
+         && symbol_get_tc (fixp->fx_addsy)->class != XMC_TC
+         && symbol_get_tc (fixp->fx_addsy)->class != XMC_TC0
          && S_GET_SEGMENT (fixp->fx_addsy) != bss_section)
        {
          value = fixp->fx_offset;
          && S_GET_SEGMENT (fixp->fx_addsy) != bss_section)
        {
          value = fixp->fx_offset;
@@ -4628,7 +4929,6 @@ md_apply_fix3 (fixp, valuep, seg)
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
               && operand->bits == 16
               && operand->shift == 0
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
               && operand->bits == 16
               && operand->shift == 0
-              && operand->insert == NULL
               && fixp->fx_addsy != NULL
               && ppc_is_toc_sym (fixp->fx_addsy))
        {
               && fixp->fx_addsy != NULL
               && ppc_is_toc_sym (fixp->fx_addsy))
        {
@@ -4646,10 +4946,10 @@ md_apply_fix3 (fixp, valuep, seg)
              symbol.  */
          if (expr_symbol_where (fixp->fx_addsy, &sfile, &sline))
            as_bad_where (fixp->fx_file, fixp->fx_line,
              symbol.  */
          if (expr_symbol_where (fixp->fx_addsy, &sfile, &sline))
            as_bad_where (fixp->fx_file, fixp->fx_line,
-                         "unresolved expression that must be resolved");
+                         _("unresolved expression that must be resolved"));
          else
            as_bad_where (fixp->fx_file, fixp->fx_line,
          else
            as_bad_where (fixp->fx_file, fixp->fx_line,
-                         "unsupported relocation type");
+                         _("unsupported relocation type"));
          fixp->fx_done = 1;
          return 1;
        }
          fixp->fx_done = 1;
          return 1;
        }
@@ -4675,9 +4975,15 @@ md_apply_fix3 (fixp, valuep, seg)
                              value, 4);
          break;
 
                              value, 4);
          break;
 
+       case BFD_RELOC_64:
+         if (fixp->fx_pcrel)
+           fixp->fx_r_type = BFD_RELOC_64_PCREL;
+                                       /* fall through */
+       case BFD_RELOC_64_PCREL:
+         md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+                             value, 8);
+         break;
        case BFD_RELOC_LO16:
        case BFD_RELOC_LO16:
-       case BFD_RELOC_HI16:
-       case BFD_RELOC_HI16_S:
        case BFD_RELOC_16:
        case BFD_RELOC_GPREL16:
        case BFD_RELOC_16_GOT_PCREL:
        case BFD_RELOC_16:
        case BFD_RELOC_GPREL16:
        case BFD_RELOC_16_GOT_PCREL:
@@ -4702,18 +5008,38 @@ md_apply_fix3 (fixp, valuep, seg)
        case BFD_RELOC_PPC_EMB_RELSDA:
        case BFD_RELOC_PPC_TOC16:
          if (fixp->fx_pcrel)
        case BFD_RELOC_PPC_EMB_RELSDA:
        case BFD_RELOC_PPC_TOC16:
          if (fixp->fx_pcrel)
-           as_bad_where (fixp->fx_file, fixp->fx_line,
-                         "cannot emit PC relative %s relocation%s%s",
-                         bfd_get_reloc_code_name (fixp->fx_r_type),
-                         fixp->fx_addsy != NULL ? " against " : "",
-                         (fixp->fx_addsy != NULL
-                          ? S_GET_NAME (fixp->fx_addsy)
-                          : ""));
+           {
+             if (fixp->fx_addsy != NULL)
+               as_bad_where (fixp->fx_file, fixp->fx_line,
+                             _("cannot emit PC relative %s relocation against %s"),
+                             bfd_get_reloc_code_name (fixp->fx_r_type),
+                             S_GET_NAME (fixp->fx_addsy));
+             else
+               as_bad_where (fixp->fx_file, fixp->fx_line,
+                             _("cannot emit PC relative %s relocation"),
+                             bfd_get_reloc_code_name (fixp->fx_r_type));
+           }
 
          md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
                              value, 2);
          break;
 
 
          md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
                              value, 2);
          break;
 
+         /* This case happens when you write, for example,
+            lis %r3,(L1-L2)@ha
+            where L1 and L2 are defined later.  */
+       case BFD_RELOC_HI16:
+         if (fixp->fx_pcrel)
+           abort ();
+         md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+                             value >> 16, 2);
+         break;
+       case BFD_RELOC_HI16_S:
+         if (fixp->fx_pcrel)
+           abort ();
+         md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+                             (value + 0x8000) >> 16, 2);
+         break;
+
          /* Because SDA21 modifies the register field, the size is set to 4
             bytes, rather than 2, so offset it here appropriately */
        case BFD_RELOC_PPC_EMB_SDA21:
          /* Because SDA21 modifies the register field, the size is set to 4
             bytes, rather than 2, so offset it here appropriately */
        case BFD_RELOC_PPC_EMB_SDA21:
@@ -4733,15 +5059,54 @@ md_apply_fix3 (fixp, valuep, seg)
                              value, 1);
          break;
 
                              value, 1);
          break;
 
+       case BFD_RELOC_24_PLT_PCREL:
        case BFD_RELOC_PPC_LOCAL24PC:
        case BFD_RELOC_PPC_LOCAL24PC:
-         if (!fixp->fx_pcrel)
+         if (!fixp->fx_pcrel && !fixp->fx_done)
            abort ();
 
            abort ();
 
+         if (fixp->fx_done)
+         {
+           char *where;
+           unsigned long insn;
+
+           /* Fetch the instruction, insert the fully resolved operand
+              value, and stuff the instruction back again.  */
+           where = fixp->fx_frag->fr_literal + fixp->fx_where;
+           if (target_big_endian)
+             insn = bfd_getb32 ((unsigned char *) where);
+           else
+             insn = bfd_getl32 ((unsigned char *) where);
+           if ((value & 3) != 0)
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("must branch to an address a multiple of 4"));
+           if ((offsetT) value < -0x40000000
+               || (offsetT) value >= 0x40000000)
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("@local or @plt branch destination is too far away, %ld bytes"),
+                           value);
+           insn = insn | (value & 0x03fffffc);
+           if (target_big_endian)
+             bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
+           else
+             bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+         }
+         break;
+
+       case BFD_RELOC_VTABLE_INHERIT:
+         fixp->fx_done = 0;
+         if (fixp->fx_addsy
+             && !S_IS_DEFINED (fixp->fx_addsy)
+             && !S_IS_WEAK (fixp->fx_addsy))
+           S_SET_WEAK (fixp->fx_addsy);
+         break;
+
+       case BFD_RELOC_VTABLE_ENTRY:
+         fixp->fx_done = 0;
          break;
 
        default:
          break;
 
        default:
-         fprintf(stderr,
-                 "Gas failure, reloc value %d\n", fixp->fx_r_type);
+         fprintf (stderr,
+                 _("Gas failure, reloc value %d\n"), fixp->fx_r_type);
          fflush(stderr);
          abort ();
        }
          fflush(stderr);
          abort ();
        }
@@ -4772,20 +5137,21 @@ md_apply_fix3 (fixp, valuep, seg)
 
 arelent *
 tc_gen_reloc (seg, fixp)
 
 arelent *
 tc_gen_reloc (seg, fixp)
-     asection *seg;
+     asection *seg ATTRIBUTE_UNUSED;
      fixS *fixp;
 {
   arelent *reloc;
 
      fixS *fixp;
 {
   arelent *reloc;
 
-  reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
+  reloc = (arelent *) xmalloc (sizeof (arelent));
 
 
-  reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                   "reloc %d not supported by object file format", (int)fixp->fx_r_type);
+                   _("reloc %d not supported by object file format"), (int)fixp->fx_r_type);
       return NULL;
     }
   reloc->addend = fixp->fx_addnumber;
       return NULL;
     }
   reloc->addend = fixp->fx_addnumber;
This page took 0.072059 seconds and 4 git commands to generate.