gas/:
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index 8b59f3fa4b18487454722e9b3a6750f39d67790c..1321cd446265c307c54467f49412f7675c32a5cd 100644 (file)
@@ -1,13 +1,13 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -20,7 +20,6 @@
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-#include <stdio.h>
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
@@ -85,67 +84,58 @@ static int set_target_endian = 0;
 
 static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
 
 
 static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
 
-static bfd_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,
-          offsetT val, char *file, unsigned int line));
-static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro));
-static void ppc_byte PARAMS ((int));
+static void ppc_macro (char *, const struct powerpc_macro *);
+static void ppc_byte (int);
 
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
 
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
-static int ppc_is_toc_sym PARAMS ((symbolS *sym));
-static void ppc_tc PARAMS ((int));
-static void ppc_machine PARAMS ((int));
+static void ppc_tc (int);
+static void ppc_machine (int);
 #endif
 
 #ifdef OBJ_XCOFF
 #endif
 
 #ifdef OBJ_XCOFF
-static void ppc_comm PARAMS ((int));
-static void ppc_bb PARAMS ((int));
-static void ppc_bc PARAMS ((int));
-static void ppc_bf PARAMS ((int));
-static void ppc_biei PARAMS ((int));
-static void ppc_bs PARAMS ((int));
-static void ppc_eb PARAMS ((int));
-static void ppc_ec PARAMS ((int));
-static void ppc_ef PARAMS ((int));
-static void ppc_es PARAMS ((int));
-static void ppc_csect PARAMS ((int));
-static void ppc_change_csect PARAMS ((symbolS *, offsetT));
-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_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_xcoff_cons PARAMS ((int));
-static void ppc_vbyte PARAMS ((int));
+static void ppc_comm (int);
+static void ppc_bb (int);
+static void ppc_bc (int);
+static void ppc_bf (int);
+static void ppc_biei (int);
+static void ppc_bs (int);
+static void ppc_eb (int);
+static void ppc_ec (int);
+static void ppc_ef (int);
+static void ppc_es (int);
+static void ppc_csect (int);
+static void ppc_change_csect (symbolS *, offsetT);
+static void ppc_function (int);
+static void ppc_extern (int);
+static void ppc_lglobl (int);
+static void ppc_ref (int);
+static void ppc_section (int);
+static void ppc_named_section (int);
+static void ppc_stabx (int);
+static void ppc_rename (int);
+static void ppc_toc (int);
+static void ppc_xcoff_cons (int);
+static void ppc_vbyte (int);
 #endif
 
 #ifdef OBJ_ELF
 #endif
 
 #ifdef OBJ_ELF
-static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *));
-static void ppc_elf_cons PARAMS ((int));
-static void ppc_elf_rdata PARAMS ((int));
-static void ppc_elf_lcomm PARAMS ((int));
-static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
-static void ppc_apuinfo_section_add PARAMS ((unsigned int apu, unsigned int version));
+static void ppc_elf_cons (int);
+static void ppc_elf_rdata (int);
+static void ppc_elf_lcomm (int);
 #endif
 
 #ifdef TE_PE
 #endif
 
 #ifdef TE_PE
-static void ppc_set_current_section PARAMS ((segT));
-static void ppc_previous PARAMS ((int));
-static void ppc_pdata PARAMS ((int));
-static void ppc_ydata PARAMS ((int));
-static void ppc_reldata PARAMS ((int));
-static void ppc_rdata PARAMS ((int));
-static void ppc_ualong PARAMS ((int));
-static void ppc_znop PARAMS ((int));
-static void ppc_pe_comm PARAMS ((int));
-static void ppc_pe_section PARAMS ((int));
-static void ppc_pe_function PARAMS ((int));
-static void ppc_pe_tocd PARAMS ((int));
+static void ppc_previous (int);
+static void ppc_pdata (int);
+static void ppc_ydata (int);
+static void ppc_reldata (int);
+static void ppc_rdata (int);
+static void ppc_ualong (int);
+static void ppc_znop (int);
+static void ppc_pe_comm (int);
+static void ppc_pe_section (int);
+static void ppc_pe_function (int);
+static void ppc_pe_tocd (int);
 #endif
 \f
 /* Generic assembler global variables which must be defined by all
 #endif
 \f
 /* Generic assembler global variables which must be defined by all
@@ -183,14 +173,22 @@ const char EXP_CHARS[] = "eE";
    as in 0d1.0.  */
 const char FLT_CHARS[] = "dD";
 
    as in 0d1.0.  */
 const char FLT_CHARS[] = "dD";
 
-/* '+' and '-' can be used as postfix predicate predictors for conditional
-   branches.  So they need to be accepted as symbol characters.
-   Also, anything that can start an operand needs to be mentioned here,
+/* Anything that can start an operand needs to be mentioned here,
    to stop the input scrubber eating whitespace.  */
    to stop the input scrubber eating whitespace.  */
-const char ppc_symbol_chars[] = "+-%[";
+const char ppc_symbol_chars[] = "%[";
 
 /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
 int ppc_cie_data_alignment;
 
 /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
 int ppc_cie_data_alignment;
+
+/* The type of processor we are assembling for.  This is one or more
+   of the PPC_OPCODE flags defined in opcode/ppc.h.  */
+ppc_cpu_t ppc_cpu = 0;
+
+/* Flags set on encountering toc relocs.  */
+enum {
+  has_large_toc_reloc = 1,
+  has_small_toc_reloc = 2
+} toc_reloc_types;
 \f
 /* The target specific pseudo-ops which we support.  */
 
 \f
 /* The target specific pseudo-ops which we support.  */
 
@@ -221,6 +219,7 @@ const pseudo_typeS md_pseudo_table[] =
   { "extern",  ppc_extern,     0 },
   { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
   { "extern",  ppc_extern,     0 },
   { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
+  { "ref",     ppc_ref,        0 },
   { "rename",  ppc_rename,     0 },
   { "section", ppc_named_section, 0 },
   { "stabx",   ppc_stabx,      0 },
   { "rename",  ppc_rename,     0 },
   { "section", ppc_named_section, 0 },
   { "stabx",   ppc_stabx,      0 },
@@ -367,9 +366,42 @@ static const struct pd_reg pre_defined_registers[] =
   { "f.3", 3 },
   { "f.30", 30 },
   { "f.31", 31 },
   { "f.3", 3 },
   { "f.30", 30 },
   { "f.31", 31 },
+
+  { "f.32", 32 },    /* Extended floating point scalar registers (ISA 2.06).  */
+  { "f.33", 33 },
+  { "f.34", 34 },
+  { "f.35", 35 },
+  { "f.36", 36 },
+  { "f.37", 37 },
+  { "f.38", 38 },
+  { "f.39", 39 },
   { "f.4", 4 },
   { "f.4", 4 },
+  { "f.40", 40 },
+  { "f.41", 41 },
+  { "f.42", 42 },
+  { "f.43", 43 },
+  { "f.44", 44 },
+  { "f.45", 45 },
+  { "f.46", 46 },
+  { "f.47", 47 },
+  { "f.48", 48 },
+  { "f.49", 49 },
   { "f.5", 5 },
   { "f.5", 5 },
+  { "f.50", 50 },
+  { "f.51", 51 },
+  { "f.52", 52 },
+  { "f.53", 53 },
+  { "f.54", 54 },
+  { "f.55", 55 },
+  { "f.56", 56 },
+  { "f.57", 57 },
+  { "f.58", 58 },
+  { "f.59", 59 },
   { "f.6", 6 },
   { "f.6", 6 },
+  { "f.60", 60 },
+  { "f.61", 61 },
+  { "f.62", 62 },
+  { "f.63", 63 },
   { "f.7", 7 },
   { "f.8", 8 },
   { "f.9", 9 },
   { "f.7", 7 },
   { "f.8", 8 },
   { "f.9", 9 },
@@ -400,15 +432,66 @@ static const struct pd_reg pre_defined_registers[] =
   { "f3", 3 },
   { "f30", 30 },
   { "f31", 31 },
   { "f3", 3 },
   { "f30", 30 },
   { "f31", 31 },
+
+  { "f32", 32 },    /* Extended floating point scalar registers (ISA 2.06).  */
+  { "f33", 33 },
+  { "f34", 34 },
+  { "f35", 35 },
+  { "f36", 36 },
+  { "f37", 37 },
+  { "f38", 38 },
+  { "f39", 39 },
   { "f4", 4 },
   { "f4", 4 },
+  { "f40", 40 },
+  { "f41", 41 },
+  { "f42", 42 },
+  { "f43", 43 },
+  { "f44", 44 },
+  { "f45", 45 },
+  { "f46", 46 },
+  { "f47", 47 },
+  { "f48", 48 },
+  { "f49", 49 },
   { "f5", 5 },
   { "f5", 5 },
+  { "f50", 50 },
+  { "f51", 51 },
+  { "f52", 52 },
+  { "f53", 53 },
+  { "f54", 54 },
+  { "f55", 55 },
+  { "f56", 56 },
+  { "f57", 57 },
+  { "f58", 58 },
+  { "f59", 59 },
   { "f6", 6 },
   { "f6", 6 },
+  { "f60", 60 },
+  { "f61", 61 },
+  { "f62", 62 },
+  { "f63", 63 },
   { "f7", 7 },
   { "f8", 8 },
   { "f9", 9 },
 
   { "fpscr", 0 },
 
   { "f7", 7 },
   { "f8", 8 },
   { "f9", 9 },
 
   { "fpscr", 0 },
 
+  /* Quantization registers used with pair single instructions.  */
+  { "gqr.0", 0 },
+  { "gqr.1", 1 },
+  { "gqr.2", 2 },
+  { "gqr.3", 3 },
+  { "gqr.4", 4 },
+  { "gqr.5", 5 },
+  { "gqr.6", 6 },
+  { "gqr.7", 7 },
+  { "gqr0", 0 },
+  { "gqr1", 1 },
+  { "gqr2", 2 },
+  { "gqr3", 3 },
+  { "gqr4", 4 },
+  { "gqr5", 5 },
+  { "gqr6", 6 },
+  { "gqr7", 7 },
+
   { "lr", 8 },     /* Link Register */
 
   { "pmr", 0 },
   { "lr", 8 },     /* Link Register */
 
   { "pmr", 0 },
@@ -492,7 +575,7 @@ 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.0", 0 },     /* Vector (Altivec/VMX) registers */
   { "v.1", 1 },
   { "v.10", 10 },
   { "v.11", 11 },
   { "v.1", 1 },
   { "v.10", 10 },
   { "v.11", 11 },
@@ -558,6 +641,136 @@ static const struct pd_reg pre_defined_registers[] =
   { "v8", 8 },
   { "v9", 9 },
 
   { "v8", 8 },
   { "v9", 9 },
 
+  { "vs.0", 0 },     /* Vector Scalar (VSX) registers (ISA 2.06).  */
+  { "vs.1", 1 },
+  { "vs.10", 10 },
+  { "vs.11", 11 },
+  { "vs.12", 12 },
+  { "vs.13", 13 },
+  { "vs.14", 14 },
+  { "vs.15", 15 },
+  { "vs.16", 16 },
+  { "vs.17", 17 },
+  { "vs.18", 18 },
+  { "vs.19", 19 },
+  { "vs.2", 2 },
+  { "vs.20", 20 },
+  { "vs.21", 21 },
+  { "vs.22", 22 },
+  { "vs.23", 23 },
+  { "vs.24", 24 },
+  { "vs.25", 25 },
+  { "vs.26", 26 },
+  { "vs.27", 27 },
+  { "vs.28", 28 },
+  { "vs.29", 29 },
+  { "vs.3", 3 },
+  { "vs.30", 30 },
+  { "vs.31", 31 },
+  { "vs.32", 32 },
+  { "vs.33", 33 },
+  { "vs.34", 34 },
+  { "vs.35", 35 },
+  { "vs.36", 36 },
+  { "vs.37", 37 },
+  { "vs.38", 38 },
+  { "vs.39", 39 },
+  { "vs.4", 4 },
+  { "vs.40", 40 },
+  { "vs.41", 41 },
+  { "vs.42", 42 },
+  { "vs.43", 43 },
+  { "vs.44", 44 },
+  { "vs.45", 45 },
+  { "vs.46", 46 },
+  { "vs.47", 47 },
+  { "vs.48", 48 },
+  { "vs.49", 49 },
+  { "vs.5", 5 },
+  { "vs.50", 50 },
+  { "vs.51", 51 },
+  { "vs.52", 52 },
+  { "vs.53", 53 },
+  { "vs.54", 54 },
+  { "vs.55", 55 },
+  { "vs.56", 56 },
+  { "vs.57", 57 },
+  { "vs.58", 58 },
+  { "vs.59", 59 },
+  { "vs.6", 6 },
+  { "vs.60", 60 },
+  { "vs.61", 61 },
+  { "vs.62", 62 },
+  { "vs.63", 63 },
+  { "vs.7", 7 },
+  { "vs.8", 8 },
+  { "vs.9", 9 },
+
+  { "vs0", 0 },
+  { "vs1", 1 },
+  { "vs10", 10 },
+  { "vs11", 11 },
+  { "vs12", 12 },
+  { "vs13", 13 },
+  { "vs14", 14 },
+  { "vs15", 15 },
+  { "vs16", 16 },
+  { "vs17", 17 },
+  { "vs18", 18 },
+  { "vs19", 19 },
+  { "vs2", 2 },
+  { "vs20", 20 },
+  { "vs21", 21 },
+  { "vs22", 22 },
+  { "vs23", 23 },
+  { "vs24", 24 },
+  { "vs25", 25 },
+  { "vs26", 26 },
+  { "vs27", 27 },
+  { "vs28", 28 },
+  { "vs29", 29 },
+  { "vs3", 3 },
+  { "vs30", 30 },
+  { "vs31", 31 },
+  { "vs32", 32 },
+  { "vs33", 33 },
+  { "vs34", 34 },
+  { "vs35", 35 },
+  { "vs36", 36 },
+  { "vs37", 37 },
+  { "vs38", 38 },
+  { "vs39", 39 },
+  { "vs4", 4 },
+  { "vs40", 40 },
+  { "vs41", 41 },
+  { "vs42", 42 },
+  { "vs43", 43 },
+  { "vs44", 44 },
+  { "vs45", 45 },
+  { "vs46", 46 },
+  { "vs47", 47 },
+  { "vs48", 48 },
+  { "vs49", 49 },
+  { "vs5", 5 },
+  { "vs50", 50 },
+  { "vs51", 51 },
+  { "vs52", 52 },
+  { "vs53", 53 },
+  { "vs54", 54 },
+  { "vs55", 55 },
+  { "vs56", 56 },
+  { "vs57", 57 },
+  { "vs58", 58 },
+  { "vs59", 59 },
+  { "vs6", 6 },
+  { "vs60", 60 },
+  { "vs61", 61 },
+  { "vs62", 62 },
+  { "vs63", 63 },
+  { "vs7", 7 },
+  { "vs8", 8 },
+  { "vs9", 9 },
+
   { "xer", 1 },
 
 };
   { "xer", 1 },
 
 };
@@ -567,14 +780,8 @@ static const struct pd_reg pre_defined_registers[] =
 /* 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.  */
 
-static int reg_name_search
-  PARAMS ((const struct pd_reg *, int, const char * name));
-
 static int
 static int
-reg_name_search (regs, regcount, name)
-     const struct pd_reg *regs;
-     int regcount;
-     const char *name;
+reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
 {
   int middle, low, high;
   int cmp;
 {
   int middle, low, high;
   int cmp;
@@ -611,8 +818,7 @@ reg_name_search (regs, regcount, name)
  */
 
 static bfd_boolean
  */
 
 static bfd_boolean
-register_name (expressionP)
-     expressionS *expressionP;
+register_name (expressionS *expressionP)
 {
   int reg_number;
   char *name;
 {
   int reg_number;
   char *name;
@@ -679,32 +885,28 @@ static const struct pd_reg cr_names[] =
    expression.  */
 
 int
    expression.  */
 
 int
-ppc_parse_name (name, expr)
-     const char *name;
-     expressionS *expr;
+ppc_parse_name (const char *name, expressionS *exp)
 {
   int val;
 
   if (! cr_operand)
     return 0;
 
 {
   int val;
 
   if (! cr_operand)
     return 0;
 
+  if (*name == '%')
+    ++name;
   val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
                         name);
   if (val < 0)
     return 0;
 
   val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
                         name);
   if (val < 0)
     return 0;
 
-  expr->X_op = O_constant;
-  expr->X_add_number = val;
+  exp->X_op = O_constant;
+  exp->X_add_number = val;
 
   return 1;
 }
 \f
 /* Local variables.  */
 
 
   return 1;
 }
 \f
 /* Local variables.  */
 
-/* The type of processor we are assembling for.  This is one or more
-   of the PPC_OPCODE flags defined in opcode/ppc.h.  */
-static unsigned long ppc_cpu = 0;
-
 /* Whether to target xcoff64/elf64.  */
 static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64;
 
 /* Whether to target xcoff64/elf64.  */
 static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64;
 
@@ -821,127 +1023,11 @@ const struct option md_longopts[] = {
 };
 const size_t md_longopts_size = sizeof (md_longopts);
 
 };
 const size_t md_longopts_size = sizeof (md_longopts);
 
-
-/* Handle -m options that set cpu type, and .machine arg.  */
-
-static int
-parse_cpu (const char *arg)
-{
-  /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
-     (RIOS2).  */
-  if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
-    ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32;
-  /* -mpwr means to assemble for the IBM POWER (RIOS1).  */
-  else if (strcmp (arg, "pwr") == 0)
-    ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
-  /* -m601 means to assemble for the PowerPC 601, which includes
-     instructions that are holdovers from the Power.  */
-  else if (strcmp (arg, "601") == 0)
-    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-              | PPC_OPCODE_601 | PPC_OPCODE_32);
-  /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
-     PowerPC 603/604.  */
-  else if (strcmp (arg, "ppc") == 0
-          || strcmp (arg, "ppc32") == 0
-          || strcmp (arg, "603") == 0
-          || strcmp (arg, "604") == 0)
-    ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
-  /* -m403 and -m405 mean to assemble for the PowerPC 403/405.  */
-  else if (strcmp (arg, "403") == 0
-          || strcmp (arg, "405") == 0)
-    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-              | PPC_OPCODE_403 | PPC_OPCODE_32);
-  else if (strcmp (arg, "440") == 0)
-    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
-              | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI);
-  else if (strcmp (arg, "7400") == 0
-          || strcmp (arg, "7410") == 0
-          || strcmp (arg, "7450") == 0
-          || strcmp (arg, "7455") == 0)
-    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-              | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
-  else if (strcmp (arg, "e300") == 0)
-    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32
-              | PPC_OPCODE_E300);
-  else if (strcmp (arg, "altivec") == 0)
-    {
-      if (ppc_cpu == 0)
-       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
-      else
-       ppc_cpu |= PPC_OPCODE_ALTIVEC;
-    }
-  else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
-                | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
-                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
-                | PPC_OPCODE_RFMCI);
-    }
-  else if (strcmp (arg, "spe") == 0)
-    {
-      if (ppc_cpu == 0)
-       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS;
-      else
-       ppc_cpu |= PPC_OPCODE_SPE;
-    }
-  /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
-     620.  */
-  else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
-    {
-      ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
-    }
-  else if (strcmp (arg, "ppc64bridge") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-                | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64);
-    }
-  /* -mbooke/-mbooke32 mean enable 32-bit BookE support.  */
-  else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0)
-    {
-      ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32;
-    }
-  /* -mbooke64 means enable 64-bit BookE support.  */
-  else if (strcmp (arg, "booke64") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE
-                | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64);
-    }
-  else if (strcmp (arg, "power4") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-                | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
-    }
-  else if (strcmp (arg, "power5") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
-                | PPC_OPCODE_POWER5);
-    }
-  else if (strcmp (arg, "power6") == 0)
-    {
-      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
-                | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
-    }
-  /* -mcom means assemble for the common intersection between Power
-     and PowerPC.  At present, we just allow the union, rather
-     than the intersection.  */
-  else if (strcmp (arg, "com") == 0)
-    ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
-  /* -many means to assemble for any architecture (PWR/PWRX/PPC).  */
-  else if (strcmp (arg, "any") == 0)
-    ppc_cpu |= PPC_OPCODE_ANY;
-  else
-    return 0;
-
-  return 1;
-}
-
 int
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg;
+md_parse_option (int c, char *arg)
 {
 {
+  ppc_cpu_t new_cpu;
+
   switch (c)
     {
     case 'u':
   switch (c)
     {
     case 'u':
@@ -1004,8 +1090,8 @@ md_parse_option (c, arg)
       break;
 
     case 'm':
       break;
 
     case 'm':
-      if (parse_cpu (arg))
-       ;
+      if ((new_cpu = ppc_parse_cpu (ppc_cpu, arg)) != 0)
+       ppc_cpu = new_cpu;
 
       else if (strcmp (arg, "regnames") == 0)
        reg_names_p = TRUE;
 
       else if (strcmp (arg, "regnames") == 0)
        reg_names_p = TRUE;
@@ -1094,77 +1180,87 @@ md_parse_option (c, arg)
 }
 
 void
 }
 
 void
-md_show_usage (stream)
-     FILE *stream;
+md_show_usage (FILE *stream)
 {
   fprintf (stream, _("\
 PowerPC options:\n\
 {
   fprintf (stream, _("\
 PowerPC options:\n\
--a32                   generate ELF32/XCOFF32\n\
--a64                   generate ELF64/XCOFF64\n\
--u                     ignored\n\
--mpwrx, -mpwr2         generate code for POWER/2 (RIOS2)\n\
--mpwr                  generate code for POWER (RIOS1)\n\
--m601                  generate code for PowerPC 601\n\
+-a32                    generate ELF32/XCOFF32\n\
+-a64                    generate ELF64/XCOFF64\n\
+-u                      ignored\n\
+-mpwrx, -mpwr2          generate code for POWER/2 (RIOS2)\n\
+-mpwr                   generate code for POWER (RIOS1)\n\
+-m601                   generate code for PowerPC 601\n\
 -mppc, -mppc32, -m603, -m604\n\
 -mppc, -mppc32, -m603, -m604\n\
-                       generate code for PowerPC 603/604\n\
--m403, -m405           generate code for PowerPC 403/405\n\
--m440                  generate code for PowerPC 440\n\
+                        generate code for PowerPC 603/604\n\
+-m403                   generate code for PowerPC 403\n\
+-m405                   generate code for PowerPC 405\n\
+-m440                   generate code for PowerPC 440\n\
+-m464                   generate code for PowerPC 464\n\
+-m476                   generate code for PowerPC 476\n\
 -m7400, -m7410, -m7450, -m7455\n\
 -m7400, -m7410, -m7450, -m7455\n\
-                       generate code For PowerPC 7400/7410/7450/7455\n"));
+                        generate code for PowerPC 7400/7410/7450/7455\n\
+-m750cl                 generate code for PowerPC 750cl\n"));
   fprintf (stream, _("\
   fprintf (stream, _("\
--mppc64, -m620         generate code for PowerPC 620/625/630\n\
--mppc64bridge          generate code for PowerPC 64, including bridge insns\n\
--mbooke64              generate code for 64-bit PowerPC BookE\n\
--mbooke, mbooke32      generate code for 32-bit PowerPC BookE\n\
--mpower4               generate code for Power4 architecture\n\
--mpower5               generate code for Power5 architecture\n\
--mpower6               generate code for Power6 architecture\n\
--mcom                  generate code Power/PowerPC common instructions\n\
--many                  generate code for any architecture (PWR/PWRX/PPC)\n"));
+-mppc64, -m620          generate code for PowerPC 620/625/630\n\
+-mppc64bridge           generate code for PowerPC 64, including bridge insns\n\
+-mbooke                 generate code for 32-bit PowerPC BookE\n\
+-ma2                    generate code for A2 architecture\n\
+-mpower4, -mpwr4        generate code for Power4 architecture\n\
+-mpower5, -mpwr5, -mpwr5x\n\
+                        generate code for Power5 architecture\n\
+-mpower6, -mpwr6        generate code for Power6 architecture\n\
+-mpower7, -mpwr7        generate code for Power7 architecture\n\
+-mcell                  generate code for Cell Broadband Engine architecture\n\
+-mcom                   generate code Power/PowerPC common instructions\n\
+-many                   generate code for any architecture (PWR/PWRX/PPC)\n"));
   fprintf (stream, _("\
   fprintf (stream, _("\
--maltivec              generate code for AltiVec\n\
--me300                 generate code for PowerPC e300 family\n\
--me500, -me500x2       generate code for Motorola e500 core complex\n\
--mspe                  generate code for Motorola SPE instructions\n\
--mregnames             Allow symbolic names for registers\n\
--mno-regnames          Do not allow symbolic names for registers\n"));
+-maltivec               generate code for AltiVec\n\
+-mvsx                   generate code for Vector-Scalar (VSX) instructions\n\
+-me300                  generate code for PowerPC e300 family\n\
+-me500, -me500x2        generate code for Motorola e500 core complex\n\
+-me500mc,               generate code for Freescale e500mc core complex\n\
+-me500mc64,             generate code for Freescale e500mc64 core complex\n\
+-mspe                   generate code for Motorola SPE instructions\n\
+-mtitan                 generate code for AppliedMicro Titan core complex\n\
+-mregnames              Allow symbolic names for registers\n\
+-mno-regnames           Do not allow symbolic names for registers\n"));
 #ifdef OBJ_ELF
   fprintf (stream, _("\
 #ifdef OBJ_ELF
   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\
 -mlittle, -mlittle-endian, -l, -le\n\
 -mlittle, -mlittle-endian, -l, -le\n\
-                       generate code for a little endian machine\n\
+                        generate code for a little endian machine\n\
 -mbig, -mbig-endian, -b, -be\n\
 -mbig, -mbig-endian, -b, -be\n\
-                       generate code for a big endian machine\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"));
+                        generate code for a big endian machine\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"));
 #endif
 }
 \f
 /* Set ppc_cpu if it is not already set.  */
 
 static void
 #endif
 }
 \f
 /* Set ppc_cpu if it is not already set.  */
 
 static void
-ppc_set_cpu ()
+ppc_set_cpu (void)
 {
   const char *default_os  = TARGET_OS;
   const char *default_cpu = TARGET_CPU;
 
 {
   const char *default_os  = TARGET_OS;
   const char *default_cpu = TARGET_CPU;
 
-  if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
+  if ((ppc_cpu & ~(ppc_cpu_t) PPC_OPCODE_ANY) == 0)
     {
       if (ppc_obj64)
     {
       if (ppc_obj64)
-       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_64;
       else if (strncmp (default_os, "aix", 3) == 0
               && default_os[3] >= '4' && default_os[3] <= '9')
       else if (strncmp (default_os, "aix", 3) == 0
               && default_os[3] >= '4' && default_os[3] <= '9')
-       ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_COMMON;
       else if (strncmp (default_os, "aix3", 4) == 0)
       else if (strncmp (default_os, "aix3", 4) == 0)
-       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_POWER;
       else if (strcmp (default_cpu, "rs6000") == 0)
       else if (strcmp (default_cpu, "rs6000") == 0)
-       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_POWER;
       else if (strncmp (default_cpu, "powerpc", 7) == 0)
       else if (strncmp (default_cpu, "powerpc", 7) == 0)
-       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_PPC;
       else
        as_fatal (_("Unknown default cpu = %s, os = %s"),
                  default_cpu, default_os);
       else
        as_fatal (_("Unknown default cpu = %s, os = %s"),
                  default_cpu, default_os);
@@ -1175,7 +1271,7 @@ ppc_set_cpu ()
    are called well before md_begin, when the output file is opened.  */
 
 enum bfd_architecture
    are called well before md_begin, when the output file is opened.  */
 
 enum bfd_architecture
-ppc_arch ()
+ppc_arch (void)
 {
   const char *default_cpu = TARGET_CPU;
   ppc_set_cpu ();
 {
   const char *default_cpu = TARGET_CPU;
   ppc_set_cpu ();
@@ -1197,18 +1293,20 @@ ppc_arch ()
 }
 
 unsigned long
 }
 
 unsigned long
-ppc_mach ()
+ppc_mach (void)
 {
   if (ppc_obj64)
     return bfd_mach_ppc64;
   else if (ppc_arch () == bfd_arch_rs6000)
     return bfd_mach_rs6k;
 {
   if (ppc_obj64)
     return bfd_mach_ppc64;
   else if (ppc_arch () == bfd_arch_rs6000)
     return bfd_mach_rs6k;
+  else if (ppc_cpu & PPC_OPCODE_TITAN)
+    return bfd_mach_ppc_titan;
   else
     return bfd_mach_ppc;
 }
 
 extern char*
   else
     return bfd_mach_ppc;
 }
 
 extern char*
-ppc_target_format ()
+ppc_target_format (void)
 {
 #ifdef OBJ_COFF
 #ifdef TE_PE
 {
 #ifdef OBJ_COFF
 #ifdef TE_PE
@@ -1240,11 +1338,11 @@ ppc_target_format ()
 static void
 ppc_setup_opcodes (void)
 {
 static void
 ppc_setup_opcodes (void)
 {
-  register const struct powerpc_opcode *op;
+  const struct powerpc_opcode *op;
   const struct powerpc_opcode *op_end;
   const struct powerpc_macro *macro;
   const struct powerpc_macro *macro_end;
   const struct powerpc_opcode *op_end;
   const struct powerpc_macro *macro;
   const struct powerpc_macro *macro_end;
-  bfd_boolean dup_insn = FALSE;
+  bfd_boolean bad_insn = FALSE;
 
   if (ppc_hash != NULL)
     hash_die (ppc_hash);
 
   if (ppc_hash != NULL)
     hash_die (ppc_hash);
@@ -1254,54 +1352,145 @@ ppc_setup_opcodes (void)
   /* Insert the opcodes into a hash table.  */
   ppc_hash = hash_new ();
 
   /* Insert the opcodes into a hash table.  */
   ppc_hash = hash_new ();
 
+  if (ENABLE_CHECKING)
+    {
+      unsigned int i;
+
+      /* Check operand masks.  Code here and in the disassembler assumes
+        all the 1's in the mask are contiguous.  */
+      for (i = 0; i < num_powerpc_operands; ++i)
+       {
+         unsigned long mask = powerpc_operands[i].bitm;
+         unsigned long right_bit;
+         unsigned int j;
+
+         right_bit = mask & -mask;
+         mask += right_bit;
+         right_bit = mask & -mask;
+         if (mask != right_bit)
+           {
+             as_bad (_("powerpc_operands[%d].bitm invalid"), i);
+             bad_insn = TRUE;
+           }
+         for (j = i + 1; j < num_powerpc_operands; ++j)
+           if (memcmp (&powerpc_operands[i], &powerpc_operands[j],
+                       sizeof (powerpc_operands[0])) == 0)
+             {
+               as_bad (_("powerpc_operands[%d] duplicates powerpc_operands[%d]"),
+                       j, i);
+               bad_insn = TRUE;
+             }
+       }
+    }
+
   op_end = powerpc_opcodes + powerpc_num_opcodes;
   for (op = powerpc_opcodes; op < op_end; op++)
     {
   op_end = powerpc_opcodes + powerpc_num_opcodes;
   for (op = powerpc_opcodes; op < op_end; op++)
     {
-      know ((op->opcode & op->mask) == op->opcode);
-
-      if ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0
-         && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
-             || ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64))
-                 == (ppc_cpu & (PPC_OPCODE_32 | PPC_OPCODE_64)))
-             || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)
-         /* Certain instructions (eg: extsw) do not exist in the
-            32-bit BookE instruction set, but they do exist in the
-            64-bit BookE instruction set, and other PPC instruction
-            sets.  Check to see if the opcode has the BOOKE64 flag set.
-            If it does make sure that the target CPU is not the BookE32.  */
-         && ((op->flags & PPC_OPCODE_BOOKE64) == 0
-             || (ppc_cpu & PPC_OPCODE_BOOKE64) == PPC_OPCODE_BOOKE64
-             || (ppc_cpu & PPC_OPCODE_BOOKE) == 0)
-         && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
-             || ((op->flags & PPC_OPCODE_POWER4)
-                 == (ppc_cpu & PPC_OPCODE_POWER4)))
-         && ((op->flags & PPC_OPCODE_POWER5) == 0
-             || ((op->flags & PPC_OPCODE_POWER5)
-                 == (ppc_cpu & PPC_OPCODE_POWER5)))
-         && ((op->flags & PPC_OPCODE_POWER6) == 0
-             || ((op->flags & PPC_OPCODE_POWER6)
-                 == (ppc_cpu & PPC_OPCODE_POWER6))))
+      if (ENABLE_CHECKING)
+       {
+         const unsigned char *o;
+         unsigned long omask = op->mask;
+
+         if (op != powerpc_opcodes)
+           {
+             /* The major opcodes had better be sorted.  Code in the
+                disassembler assumes the insns are sorted according to
+                major opcode.  */
+             if (PPC_OP (op[0].opcode) < PPC_OP (op[-1].opcode))
+               {
+                 as_bad (_("major opcode is not sorted for %s"),
+                         op->name);
+                 bad_insn = TRUE;
+               }
+
+             /* Warn if the table isn't more strictly ordered.
+                Unfortunately it doesn't seem possible to order the
+                table on much more than the major opcode, which makes
+                it difficult to implement a binary search in the
+                disassembler.  The problem is that we have multiple
+                ways to disassemble instructions, and we usually want
+                to choose a more specific form (with more bits set in
+                the opcode) than a more general form.  eg. all of the
+                following are equivalent:
+                bne label      # opcode = 0x40820000, mask = 0xff830003
+                bf  2,label    # opcode = 0x40800000, mask = 0xff800003
+                bc  4,2,label  # opcode = 0x40000000, mask = 0xfc000003
+
+                There are also cases where the table needs to be out
+                of order to disassemble the correct instruction for
+                processor variants.  */
+             else if (0)
+               {
+                 unsigned long t1 = op[0].opcode;
+                 unsigned long t2 = op[-1].opcode;
+
+                 if (((t1 ^ t2) & 0xfc0007ff) == 0
+                     && (t1 & 0xfc0006df) == 0x7c000286)
+                   {
+                     /* spr field is split.  */
+                     t1 = ((t1 & ~0x1ff800)
+                           | ((t1 & 0xf800) << 5) | ((t1 & 0x1f0000) >> 5));
+                     t2 = ((t2 & ~0x1ff800)
+                           | ((t2 & 0xf800) << 5) | ((t2 & 0x1f0000) >> 5));
+                   }
+                 if (t1 < t2)
+                   as_warn (_("%s (%08lx %08lx) after %s (%08lx %08lx)"),
+                            op[0].name, op[0].opcode, op[0].mask,
+                            op[-1].name, op[-1].opcode, op[-1].mask);
+               }
+           }
+
+         /* The mask had better not trim off opcode bits.  */
+         if ((op->opcode & omask) != op->opcode)
+           {
+             as_bad (_("mask trims opcode bits for %s"),
+                     op->name);
+             bad_insn = TRUE;
+           }
+
+         /* The operands must not overlap the opcode or each other.  */
+         for (o = op->operands; *o; ++o)
+           if (*o >= num_powerpc_operands)
+             {
+               as_bad (_("operand index error for %s"),
+                       op->name);
+               bad_insn = TRUE;
+             }
+           else
+             {
+               const struct powerpc_operand *operand = &powerpc_operands[*o];
+               if (operand->shift >= 0)
+                 {
+                   unsigned long mask = operand->bitm << operand->shift;
+                   if (omask & mask)
+                     {
+                       as_bad (_("operand %d overlap in %s"),
+                               (int) (o - op->operands), op->name);
+                       bad_insn = TRUE;
+                     }
+                   omask |= mask;
+                 }
+             }
+       }
+
+      if ((ppc_cpu & op->flags) != 0
+         && !(ppc_cpu & op->deprecated))
        {
          const char *retval;
 
        {
          const char *retval;
 
-         retval = hash_insert (ppc_hash, op->name, (PTR) op);
+         retval = hash_insert (ppc_hash, op->name, (void *) op);
          if (retval != NULL)
            {
          if (retval != NULL)
            {
-             /* Ignore Power duplicates for -m601.  */
-             if ((ppc_cpu & PPC_OPCODE_601) != 0
-                 && (op->flags & PPC_OPCODE_POWER) != 0)
-               continue;
-
-             as_bad (_("Internal assembler error for instruction %s"),
+             as_bad (_("duplicate instruction %s"),
                      op->name);
                      op->name);
-             dup_insn = TRUE;
+             bad_insn = TRUE;
            }
        }
     }
 
   if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
     for (op = powerpc_opcodes; op < op_end; op++)
            }
        }
     }
 
   if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
     for (op = powerpc_opcodes; op < op_end; op++)
-      hash_insert (ppc_hash, op->name, (PTR) op);
+      hash_insert (ppc_hash, op->name, (void *) op);
 
   /* Insert the macros into a hash table.  */
   ppc_macro_hash = hash_new ();
 
   /* Insert the macros into a hash table.  */
   ppc_macro_hash = hash_new ();
@@ -1313,16 +1502,16 @@ ppc_setup_opcodes (void)
        {
          const char *retval;
 
        {
          const char *retval;
 
-         retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
+         retval = hash_insert (ppc_macro_hash, macro->name, (void *) macro);
          if (retval != (const char *) NULL)
            {
          if (retval != (const char *) NULL)
            {
-             as_bad (_("Internal assembler error for macro %s"), macro->name);
-             dup_insn = TRUE;
+             as_bad (_("duplicate macro %s"), macro->name);
+             bad_insn = TRUE;
            }
        }
     }
 
            }
        }
     }
 
-  if (dup_insn)
+  if (bad_insn)
     abort ();
 }
 
     abort ();
 }
 
@@ -1331,7 +1520,7 @@ ppc_setup_opcodes (void)
    opened.  */
 
 void
    opened.  */
 
 void
-md_begin ()
+md_begin (void)
 {
   ppc_set_cpu ();
 
 {
   ppc_set_cpu ();
 
@@ -1374,7 +1563,7 @@ md_begin ()
 }
 
 void
 }
 
 void
-ppc_cleanup ()
+ppc_cleanup (void)
 {
 #ifdef OBJ_ELF
   if (ppc_apuinfo_list == NULL)
 {
 #ifdef OBJ_ELF
   if (ppc_apuinfo_list == NULL)
@@ -1436,54 +1625,61 @@ ppc_cleanup ()
 /* Insert an operand value into an instruction.  */
 
 static unsigned long
 /* Insert an operand value into an instruction.  */
 
 static unsigned long
-ppc_insert_operand (insn, operand, val, file, line)
-     unsigned long insn;
-     const struct powerpc_operand *operand;
-     offsetT val;
-     char *file;
-     unsigned int line;
+ppc_insert_operand (unsigned long insn,
+                   const struct powerpc_operand *operand,
+                   offsetT val,
+                   ppc_cpu_t cpu,
+                   char *file,
+                   unsigned int line)
 {
 {
-  if (operand->bits != 32)
+  long min, max, right;
+
+  max = operand->bitm;
+  right = max & -max;
+  min = 0;
+
+  if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
     {
     {
-      long min, max;
-      offsetT test;
+      if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0)
+       max = (max >> 1) & -right;
+      min = ~max & -right;
+    }
 
 
-      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-       {
-         if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
-           max = (1 << operand->bits) - 1;
-         else
-           max = (1 << (operand->bits - 1)) - 1;
-         min = - (1 << (operand->bits - 1));
+  if ((operand->flags & PPC_OPERAND_PLUS1) != 0)
+    max++;
 
 
-         if (!ppc_obj64)
-           {
-             /* 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
-       {
-         max = (1 << operand->bits) - 1;
-         min = 0;
-       }
+  if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+    {
+      long tmp = min;
+      min = -max;
+      max = -tmp;
+    }
 
 
-      if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
-       test = - val;
-      else
-       test = val;
+  if (min <= max)
+    {
+      /* Some people write constants with the sign extension done by
+        hand but only up to 32 bits.  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 to 64 bits if so doing makes the
+        value valid.  */
+      if (val > max
+         && (offsetT) (val - 0x80000000 - 0x80000000) >= min
+         && (offsetT) (val - 0x80000000 - 0x80000000) <= max
+         && ((val - 0x80000000 - 0x80000000) & (right - 1)) == 0)
+       val = val - 0x80000000 - 0x80000000;
 
 
-      if (test < (offsetT) min || test > (offsetT) max)
-       as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
+      /* Similarly, people write expressions like ~(1<<15), and expect
+        this to be OK for a 32-bit unsigned value.  */
+      else if (val < min
+              && (offsetT) (val + 0x80000000 + 0x80000000) >= min
+              && (offsetT) (val + 0x80000000 + 0x80000000) <= max
+              && ((val + 0x80000000 + 0x80000000) & (right - 1)) == 0)
+       val = val + 0x80000000 + 0x80000000;
+
+      else if (val < min
+              || val > max
+              || (val & (right - 1)) != 0)
+       as_bad_value_out_of_range (_("operand"), val, min, max, file, line);
     }
 
   if (operand->insert)
     }
 
   if (operand->insert)
@@ -1491,13 +1687,12 @@ ppc_insert_operand (insn, operand, val, file, line)
       const char *errmsg;
 
       errmsg = NULL;
       const char *errmsg;
 
       errmsg = NULL;
-      insn = (*operand->insert) (insn, (long) val, ppc_cpu, &errmsg);
+      insn = (*operand->insert) (insn, (long) val, cpu, &errmsg);
       if (errmsg != (const char *) NULL)
       if (errmsg != (const char *) NULL)
-       as_bad_where (file, line, errmsg);
+       as_bad_where (file, line, "%s", errmsg);
     }
   else
     }
   else
-    insn |= (((long) val & ((1 << operand->bits) - 1))
-            << operand->shift);
+    insn |= ((long) val & operand->bitm) << operand->shift;
 
   return insn;
 }
 
   return insn;
 }
@@ -1506,9 +1701,7 @@ ppc_insert_operand (insn, operand, val, file, line)
 #ifdef OBJ_ELF
 /* Parse @got, etc. and return the desired relocation.  */
 static bfd_reloc_code_real_type
 #ifdef OBJ_ELF
 /* Parse @got, etc. and return the desired relocation.  */
 static bfd_reloc_code_real_type
-ppc_elf_suffix (str_p, exp_p)
-     char **str_p;
-     expressionS *exp_p;
+ppc_elf_suffix (char **str_p, expressionS *exp_p)
 {
   struct map_bfd {
     char *string;
 {
   struct map_bfd {
     char *string;
@@ -1641,13 +1834,38 @@ ppc_elf_suffix (str_p, exp_p)
       {
        int reloc = ptr->reloc;
 
       {
        int reloc = ptr->reloc;
 
-       if (!ppc_obj64)
-         if (exp_p->X_add_number != 0
-             && (reloc == (int) BFD_RELOC_16_GOTOFF
-                 || reloc == (int) BFD_RELOC_LO16_GOTOFF
-                 || reloc == (int) BFD_RELOC_HI16_GOTOFF
-                 || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
-           as_warn (_("identifier+constant@got means identifier@got+constant"));
+       if (!ppc_obj64 && exp_p->X_add_number != 0)
+         {
+           switch (reloc)
+             {
+             case BFD_RELOC_16_GOTOFF:
+             case BFD_RELOC_LO16_GOTOFF:
+             case BFD_RELOC_HI16_GOTOFF:
+             case BFD_RELOC_HI16_S_GOTOFF:
+               as_warn (_("identifier+constant@got means "
+                          "identifier@got+constant"));
+               break;
+
+             case BFD_RELOC_PPC_GOT_TLSGD16:
+             case BFD_RELOC_PPC_GOT_TLSGD16_LO:
+             case BFD_RELOC_PPC_GOT_TLSGD16_HI:
+             case BFD_RELOC_PPC_GOT_TLSGD16_HA:
+             case BFD_RELOC_PPC_GOT_TLSLD16:
+             case BFD_RELOC_PPC_GOT_TLSLD16_LO:
+             case BFD_RELOC_PPC_GOT_TLSLD16_HI:
+             case BFD_RELOC_PPC_GOT_TLSLD16_HA:
+             case BFD_RELOC_PPC_GOT_DTPREL16:
+             case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+             case BFD_RELOC_PPC_GOT_DTPREL16_HI:
+             case BFD_RELOC_PPC_GOT_DTPREL16_HA:
+             case BFD_RELOC_PPC_GOT_TPREL16:
+             case BFD_RELOC_PPC_GOT_TPREL16_LO:
+             case BFD_RELOC_PPC_GOT_TPREL16_HI:
+             case BFD_RELOC_PPC_GOT_TPREL16_HA:
+               as_bad (_("symbol+offset not supported for got tls"));
+               break;
+             }
+         }
 
        /* Now check for identifier@suffix+constant.  */
        if (*str == '-' || *str == '+')
 
        /* Now check for identifier@suffix+constant.  */
        if (*str == '-' || *str == '+')
@@ -1686,8 +1904,7 @@ ppc_elf_suffix (str_p, exp_p)
 /* Like normal .long/.short/.word, except support @got, etc.
    Clobbers input_line_pointer, checks end-of-line.  */
 static void
 /* Like normal .long/.short/.word, except support @got, etc.
    Clobbers input_line_pointer, checks end-of-line.  */
 static void
-ppc_elf_cons (nbytes)
-     register int nbytes;      /* 1=.byte, 2=.word, 4=.long, 8=.llong.  */
+ppc_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long, 8=.llong */)
 {
   expressionS exp;
   bfd_reloc_code_real_type reloc;
 {
   expressionS exp;
   bfd_reloc_code_real_type reloc;
@@ -1723,6 +1940,7 @@ ppc_elf_cons (nbytes)
              int offset;
 
              p = frag_more (nbytes);
              int offset;
 
              p = frag_more (nbytes);
+             memset (p, 0, nbytes);
              offset = 0;
              if (target_big_endian)
                offset = nbytes - size;
              offset = 0;
              if (target_big_endian)
                offset = nbytes - size;
@@ -1742,8 +1960,7 @@ ppc_elf_cons (nbytes)
 
 /* Solaris pseduo op to change to the .rodata section.  */
 static void
 
 /* Solaris pseduo op to change to the .rodata section.  */
 static void
-ppc_elf_rdata (xxx)
-     int xxx;
+ppc_elf_rdata (int xxx)
 {
   char *save_line = input_line_pointer;
   static char section[] = ".rodata\n";
 {
   char *save_line = input_line_pointer;
   static char section[] = ".rodata\n";
@@ -1757,14 +1974,13 @@ ppc_elf_rdata (xxx)
 
 /* Pseudo op to make file scope bss items.  */
 static void
 
 /* Pseudo op to make file scope bss items.  */
 static void
-ppc_elf_lcomm (xxx)
-     int xxx ATTRIBUTE_UNUSED;
+ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED)
 {
 {
-  register char *name;
-  register char c;
-  register char *p;
+  char *name;
+  char c;
+  char *p;
   offsetT size;
   offsetT size;
-  register symbolS *symbolP;
+  symbolS *symbolP;
   offsetT align;
   segT old_sec;
   int old_subsec;
   offsetT align;
   segT old_sec;
   int old_subsec;
@@ -1867,9 +2083,7 @@ ppc_elf_lcomm (xxx)
    fixups for word relocations in writable segments, so we can adjust
    them at runtime.  */
 static void
    fixups for word relocations in writable segments, so we can adjust
    them at runtime.  */
 static void
-ppc_elf_validate_fix (fixp, seg)
-     fixS *fixp;
-     segT seg;
+ppc_elf_validate_fix (fixS *fixp, segT seg)
 {
   if (fixp->fx_done || fixp->fx_pcrel)
     return;
 {
   if (fixp->fx_done || fixp->fx_pcrel)
     return;
@@ -1914,7 +2128,7 @@ ppc_elf_validate_fix (fixp, seg)
    function descriptor sym if the corresponding code sym is used.  */
 
 void
    function descriptor sym if the corresponding code sym is used.  */
 
 void
-ppc_frob_file_before_adjust ()
+ppc_frob_file_before_adjust (void)
 {
   symbolS *symp;
   asection *toc;
 {
   symbolS *symp;
   asection *toc;
@@ -1951,6 +2165,7 @@ ppc_frob_file_before_adjust ()
 
   toc = bfd_get_section_by_name (stdoutput, ".toc");
   if (toc != NULL
 
   toc = bfd_get_section_by_name (stdoutput, ".toc");
   if (toc != NULL
+      && toc_reloc_types != has_large_toc_reloc
       && bfd_section_size (stdoutput, toc) > 0x10000)
     as_warn (_("TOC section size exceeds 64k"));
 
       && bfd_section_size (stdoutput, toc) > 0x10000)
     as_warn (_("TOC section size exceeds 64k"));
 
@@ -1997,8 +2212,7 @@ enum toc_size_qualifier
 };
 
 static int
 };
 
 static int
-parse_toc_entry (toc_kind)
-     enum toc_size_qualifier *toc_kind;
+parse_toc_entry (enum toc_size_qualifier *toc_kind)
 {
   char *start;
   char *toc_spec;
 {
   char *start;
   char *toc_spec;
@@ -2062,8 +2276,7 @@ parse_toc_entry (toc_kind)
 #ifdef OBJ_ELF
 #define APUID(a,v)     ((((a) & 0xffff) << 16) | ((v) & 0xffff))
 static void
 #ifdef OBJ_ELF
 #define APUID(a,v)     ((((a) & 0xffff) << 16) | ((v) & 0xffff))
 static void
-ppc_apuinfo_section_add (apu, version)
-      unsigned int apu, version;
+ppc_apuinfo_section_add (unsigned int apu, unsigned int version)
 {
   unsigned int i;
 
 {
   unsigned int i;
 
@@ -2109,8 +2322,7 @@ struct ppc_fixup
 /* This routine is called for each instruction to be assembled.  */
 
 void
 /* This routine is called for each instruction to be assembled.  */
 
 void
-md_assemble (str)
-     char *str;
+md_assemble (char *str)
 {
   char *s;
   const struct powerpc_opcode *opcode;
 {
   char *s;
   const struct powerpc_opcode *opcode;
@@ -2175,7 +2387,6 @@ md_assemble (str)
        {
          unsigned int opcount;
          unsigned int num_operands_expected;
        {
          unsigned int opcount;
          unsigned int num_operands_expected;
-         unsigned int i;
 
          /* There is an optional operand.  Count the number of
             commas in the input line.  */
 
          /* There is an optional operand.  Count the number of
             commas in the input line.  */
@@ -2235,7 +2446,7 @@ md_assemble (str)
        {
          insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
          if (errmsg != (const char *) NULL)
        {
          insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
          if (errmsg != (const char *) NULL)
-           as_bad (errmsg);
+           as_bad ("%s", errmsg);
          continue;
        }
 
          continue;
        }
 
@@ -2248,7 +2459,7 @@ md_assemble (str)
            {
              insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
              if (errmsg != (const char *) NULL)
            {
              insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
              if (errmsg != (const char *) NULL)
-               as_bad (errmsg);
+               as_bad ("%s", errmsg);
            }
          if ((operand->flags & PPC_OPERAND_NEXT) != 0)
            next_opindex = *opindex_ptr + 1;
            }
          if ((operand->flags & PPC_OPERAND_NEXT) != 0)
            next_opindex = *opindex_ptr + 1;
@@ -2323,7 +2534,7 @@ md_assemble (str)
                 explain.  */
              if (ex.X_op == O_symbol)
                {
                 explain.  */
              if (ex.X_op == O_symbol)
                {
-                 assert (ex.X_add_symbol != NULL);
+                 gas_assert (ex.X_add_symbol != NULL);
                  if (symbol_get_bfdsym (ex.X_add_symbol)->section
                      != tocdata_section)
                    {
                  if (symbol_get_bfdsym (ex.X_add_symbol)->section
                      != tocdata_section)
                    {
@@ -2374,12 +2585,19 @@ md_assemble (str)
       else
 #endif         /* TE_PE */
        {
       else
 #endif         /* TE_PE */
        {
-         if (! register_name (&ex))
+         if ((reg_names_p && (operand->flags & PPC_OPERAND_CR) != 0)
+             || !register_name (&ex))
            {
            {
+             char save_lex = lex_type['%'];
+
              if ((operand->flags & PPC_OPERAND_CR) != 0)
              if ((operand->flags & PPC_OPERAND_CR) != 0)
-               cr_operand = TRUE;
+               {
+                 cr_operand = TRUE;
+                 lex_type['%'] |= LEX_BEGIN_NAME;
+               }
              expression (&ex);
              cr_operand = FALSE;
              expression (&ex);
              cr_operand = FALSE;
+             lex_type['%'] = save_lex;
            }
        }
 
            }
        }
 
@@ -2393,7 +2611,7 @@ md_assemble (str)
       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,
-                                    (char *) NULL, 0);
+                                    ppc_cpu, (char *) NULL, 0);
        }
       else if (ex.X_op == O_constant)
        {
        }
       else if (ex.X_op == O_constant)
        {
@@ -2462,124 +2680,192 @@ md_assemble (str)
              }
 #endif /* OBJ_ELF */
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
              }
 #endif /* OBJ_ELF */
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
-                                    (char *) NULL, 0);
+                                    ppc_cpu, (char *) NULL, 0);
        }
 #ifdef OBJ_ELF
        }
 #ifdef OBJ_ELF
-      else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
+      else
        {
        {
-         /* Some TLS tweaks.  */
-         switch (reloc)
+         if (ex.X_op == O_symbol && str[0] == '(')
            {
            {
-           default:
-             break;
-           case BFD_RELOC_PPC_TLS:
-             insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
-                                        (char *) NULL, 0);
-             break;
-         /* We'll only use the 32 (or 64) bit form of these relocations
-            in constants.  Instructions get the 16 bit form.  */
-           case BFD_RELOC_PPC_DTPREL:
-             reloc = BFD_RELOC_PPC_DTPREL16;
-             break;
-           case BFD_RELOC_PPC_TPREL:
-             reloc = BFD_RELOC_PPC_TPREL16;
-             break;
+             const char *sym_name = S_GET_NAME (ex.X_add_symbol);
+             if (sym_name[0] == '.')
+               ++sym_name;
+
+             if (strcasecmp (sym_name, "__tls_get_addr") == 0)
+               {
+                 expressionS tls_exp;
+
+                 hold = input_line_pointer;
+                 input_line_pointer = str + 1;
+                 expression (&tls_exp);
+                 if (tls_exp.X_op == O_symbol)
+                   {
+                     reloc = BFD_RELOC_UNUSED;
+                     if (strncasecmp (input_line_pointer, "@tlsgd)", 7) == 0)
+                       {
+                         reloc = BFD_RELOC_PPC_TLSGD;
+                         input_line_pointer += 7;
+                       }
+                     else if (strncasecmp (input_line_pointer, "@tlsld)", 7) == 0)
+                       {
+                         reloc = BFD_RELOC_PPC_TLSLD;
+                         input_line_pointer += 7;
+                       }
+                     if (reloc != BFD_RELOC_UNUSED)
+                       {
+                         SKIP_WHITESPACE ();
+                         str = input_line_pointer;
+
+                         if (fc >= MAX_INSN_FIXUPS)
+                           as_fatal (_("too many fixups"));
+                         fixups[fc].exp = tls_exp;
+                         fixups[fc].opindex = *opindex_ptr;
+                         fixups[fc].reloc = reloc;
+                         ++fc;
+                       }
+                   }
+                 input_line_pointer = hold;
+               }
            }
 
            }
 
-         /* For the absolute forms of branches, convert the PC
-            relative form back into the absolute.  */
-         if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+         if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
            {
            {
+             /* Some TLS tweaks.  */
              switch (reloc)
                {
              switch (reloc)
                {
-               case BFD_RELOC_PPC_B26:
-                 reloc = BFD_RELOC_PPC_BA26;
-                 break;
-               case BFD_RELOC_PPC_B16:
-                 reloc = BFD_RELOC_PPC_BA16;
+               default:
                  break;
                  break;
-               case BFD_RELOC_PPC_B16_BRTAKEN:
-                 reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+
+               case BFD_RELOC_PPC_TLS:
+                 if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
+                   as_bad (_("@tls may not be used with \"%s\" operands"),
+                           opcode->name);
+                 else if (operand->shift != 11)
+                   as_bad (_("@tls may only be used in last operand"));
+                 else
+                   insn = ppc_insert_operand (insn, operand,
+                                              ppc_obj64 ? 13 : 2,
+                                              ppc_cpu, (char *) NULL, 0);
                  break;
                  break;
-               case BFD_RELOC_PPC_B16_BRNTAKEN:
-                 reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+
+                 /* We'll only use the 32 (or 64) bit form of these relocations
+                    in constants.  Instructions get the 16 bit form.  */
+               case BFD_RELOC_PPC_DTPREL:
+                 reloc = BFD_RELOC_PPC_DTPREL16;
                  break;
                  break;
-               default:
+               case BFD_RELOC_PPC_TPREL:
+                 reloc = BFD_RELOC_PPC_TPREL16;
                  break;
                }
                  break;
                }
-           }
 
 
-         if (ppc_obj64
-             && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
-           {
+             /* For the absolute forms of branches, convert the PC
+                relative form back into the absolute.  */
+             if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+               {
+                 switch (reloc)
+                   {
+                   case BFD_RELOC_PPC_B26:
+                     reloc = BFD_RELOC_PPC_BA26;
+                     break;
+                   case BFD_RELOC_PPC_B16:
+                     reloc = BFD_RELOC_PPC_BA16;
+                     break;
+                   case BFD_RELOC_PPC_B16_BRTAKEN:
+                     reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+                     break;
+                   case BFD_RELOC_PPC_B16_BRNTAKEN:
+                     reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+                     break;
+                   default:
+                     break;
+                   }
+               }
+
              switch (reloc)
                {
              switch (reloc)
                {
-               case BFD_RELOC_16:
-                 reloc = BFD_RELOC_PPC64_ADDR16_DS;
-                 break;
-               case BFD_RELOC_LO16:
-                 reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
-                 break;
-               case BFD_RELOC_16_GOTOFF:
-                 reloc = BFD_RELOC_PPC64_GOT16_DS;
-                 break;
-               case BFD_RELOC_LO16_GOTOFF:
-                 reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
-                 break;
-               case BFD_RELOC_LO16_PLTOFF:
-                 reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
-                 break;
-               case BFD_RELOC_16_BASEREL:
-                 reloc = BFD_RELOC_PPC64_SECTOFF_DS;
-                 break;
-               case BFD_RELOC_LO16_BASEREL:
-                 reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
-                 break;
                case BFD_RELOC_PPC_TOC16:
                case BFD_RELOC_PPC_TOC16:
-                 reloc = BFD_RELOC_PPC64_TOC16_DS;
+                 toc_reloc_types |= has_small_toc_reloc;
                  break;
                case BFD_RELOC_PPC64_TOC16_LO:
                  break;
                case BFD_RELOC_PPC64_TOC16_LO:
-                 reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
-                 break;
-               case BFD_RELOC_PPC64_PLTGOT16:
-                 reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
-                 break;
-               case BFD_RELOC_PPC64_PLTGOT16_LO:
-                 reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
-                 break;
-               case BFD_RELOC_PPC_DTPREL16:
-                 reloc = BFD_RELOC_PPC64_DTPREL16_DS;
-                 break;
-               case BFD_RELOC_PPC_DTPREL16_LO:
-                 reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
-                 break;
-               case BFD_RELOC_PPC_TPREL16:
-                 reloc = BFD_RELOC_PPC64_TPREL16_DS;
-                 break;
-               case BFD_RELOC_PPC_TPREL16_LO:
-                 reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
-                 break;
-               case BFD_RELOC_PPC_GOT_DTPREL16:
-               case BFD_RELOC_PPC_GOT_DTPREL16_LO:
-               case BFD_RELOC_PPC_GOT_TPREL16:
-               case BFD_RELOC_PPC_GOT_TPREL16_LO:
+               case BFD_RELOC_PPC64_TOC16_HI:
+               case BFD_RELOC_PPC64_TOC16_HA:
+                 toc_reloc_types |= has_large_toc_reloc;
                  break;
                default:
                  break;
                default:
-                 as_bad (_("unsupported relocation for DS offset field"));
                  break;
                }
                  break;
                }
+
+             if (ppc_obj64
+                 && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
+               {
+                 switch (reloc)
+                   {
+                   case BFD_RELOC_16:
+                     reloc = BFD_RELOC_PPC64_ADDR16_DS;
+                     break;
+                   case BFD_RELOC_LO16:
+                     reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
+                     break;
+                   case BFD_RELOC_16_GOTOFF:
+                     reloc = BFD_RELOC_PPC64_GOT16_DS;
+                     break;
+                   case BFD_RELOC_LO16_GOTOFF:
+                     reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
+                     break;
+                   case BFD_RELOC_LO16_PLTOFF:
+                     reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
+                     break;
+                   case BFD_RELOC_16_BASEREL:
+                     reloc = BFD_RELOC_PPC64_SECTOFF_DS;
+                     break;
+                   case BFD_RELOC_LO16_BASEREL:
+                     reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
+                     break;
+                   case BFD_RELOC_PPC_TOC16:
+                     reloc = BFD_RELOC_PPC64_TOC16_DS;
+                     break;
+                   case BFD_RELOC_PPC64_TOC16_LO:
+                     reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
+                     break;
+                   case BFD_RELOC_PPC64_PLTGOT16:
+                     reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
+                     break;
+                   case BFD_RELOC_PPC64_PLTGOT16_LO:
+                     reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
+                     break;
+                   case BFD_RELOC_PPC_DTPREL16:
+                     reloc = BFD_RELOC_PPC64_DTPREL16_DS;
+                     break;
+                   case BFD_RELOC_PPC_DTPREL16_LO:
+                     reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
+                     break;
+                   case BFD_RELOC_PPC_TPREL16:
+                     reloc = BFD_RELOC_PPC64_TPREL16_DS;
+                     break;
+                   case BFD_RELOC_PPC_TPREL16_LO:
+                     reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+                     break;
+                   case BFD_RELOC_PPC_GOT_DTPREL16:
+                   case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+                   case BFD_RELOC_PPC_GOT_TPREL16:
+                   case BFD_RELOC_PPC_GOT_TPREL16_LO:
+                     break;
+                   default:
+                     as_bad (_("unsupported relocation for DS offset field"));
+                     break;
+                   }
+               }
            }
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
            as_fatal (_("too many fixups"));
          fixups[fc].exp = ex;
            }
 
          /* We need to generate a fixup for this expression.  */
          if (fc >= MAX_INSN_FIXUPS)
            as_fatal (_("too many fixups"));
          fixups[fc].exp = ex;
-         fixups[fc].opindex = 0;
+         fixups[fc].opindex = *opindex_ptr;
          fixups[fc].reloc = reloc;
          ++fc;
        }
          fixups[fc].reloc = reloc;
          ++fc;
        }
-#endif /* OBJ_ELF */
-
+#else /* OBJ_ELF */
       else
        {
          /* We need to generate a fixup for this expression.  */
       else
        {
          /* We need to generate a fixup for this expression.  */
@@ -2590,11 +2876,20 @@ md_assemble (str)
          fixups[fc].reloc = BFD_RELOC_UNUSED;
          ++fc;
        }
          fixups[fc].reloc = BFD_RELOC_UNUSED;
          ++fc;
        }
+#endif /* OBJ_ELF */
 
       if (need_paren)
        {
          endc = ')';
          need_paren = 0;
 
       if (need_paren)
        {
          endc = ')';
          need_paren = 0;
+         /* If expecting more operands, then we want to see "),".  */
+         if (*str == endc && opindex_ptr[1] != 0)
+           {
+             do
+               ++str;
+             while (ISSPACE (*str));
+             endc = ',';
+           }
        }
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
        {
        }
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
        {
@@ -2625,10 +2920,7 @@ md_assemble (str)
 
 #ifdef OBJ_ELF
   /* Do we need/want a APUinfo section? */
 
 #ifdef OBJ_ELF
   /* Do we need/want a APUinfo section? */
-  if (ppc_cpu & (PPC_OPCODE_SPE
-              | PPC_OPCODE_ISEL | PPC_OPCODE_EFS
-              | PPC_OPCODE_BRLOCK | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
-              | PPC_OPCODE_RFMCI))
+  if ((ppc_cpu & (PPC_OPCODE_E500 | PPC_OPCODE_E500MC)) != 0)
     {
       /* These are all version "1".  */
       if (opcode->flags & PPC_OPCODE_SPE)
     {
       /* These are all version "1".  */
       if (opcode->flags & PPC_OPCODE_SPE)
@@ -2669,9 +2961,6 @@ md_assemble (str)
      md_apply_fix.  */
   for (i = 0; i < fc; i++)
     {
      md_apply_fix.  */
   for (i = 0; i < fc; i++)
     {
-      const struct powerpc_operand *operand;
-
-      operand = &powerpc_operands[fixups[i].opindex];
       if (fixups[i].reloc != BFD_RELOC_UNUSED)
        {
          reloc_howto_type *reloc_howto;
       if (fixups[i].reloc != BFD_RELOC_UNUSED)
        {
          reloc_howto_type *reloc_howto;
@@ -2718,13 +3007,18 @@ md_assemble (str)
            }
        }
       else
            }
        }
       else
-       fix_new_exp (frag_now,
-                    f - frag_now->fr_literal,
-                    4,
-                    &fixups[i].exp,
-                    (operand->flags & PPC_OPERAND_RELATIVE) != 0,
-                    ((bfd_reloc_code_real_type)
-                     (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+       {
+         const struct powerpc_operand *operand;
+
+         operand = &powerpc_operands[fixups[i].opindex];
+         fix_new_exp (frag_now,
+                      f - frag_now->fr_literal,
+                      4,
+                      &fixups[i].exp,
+                      (operand->flags & PPC_OPERAND_RELATIVE) != 0,
+                      ((bfd_reloc_code_real_type)
+                       (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+       }
     }
 }
 
     }
 }
 
@@ -2734,16 +3028,14 @@ md_assemble (str)
    around operands here.  */
 
 static void
    around operands here.  */
 
 static void
-ppc_macro (str, macro)
-     char *str;
-     const struct powerpc_macro *macro;
+ppc_macro (char *str, const struct powerpc_macro *macro)
 {
   char *operands[10];
   unsigned int count;
   char *s;
   unsigned int len;
   const char *format;
 {
   char *operands[10];
   unsigned int count;
   char *s;
   unsigned int len;
   const char *format;
-  int arg;
+  unsigned int arg;
   char *send;
   char *complete;
 
   char *send;
   char *complete;
 
@@ -2781,7 +3073,7 @@ ppc_macro (str, macro)
       else
        {
          arg = strtol (format + 1, &send, 10);
       else
        {
          arg = strtol (format + 1, &send, 10);
-         know (send != format && arg >= 0 && arg < count);
+         know (send != format && arg < count);
          len += strlen (operands[arg]);
          format = send;
        }
          len += strlen (operands[arg]);
          format = send;
        }
@@ -2809,35 +3101,10 @@ ppc_macro (str, macro)
 }
 \f
 #ifdef OBJ_ELF
 }
 \f
 #ifdef OBJ_ELF
-/* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED.  */
+/* For ELF, add support for SHT_ORDERED.  */
 
 int
 
 int
-ppc_section_letter (letter, ptr_msg)
-     int letter;
-     char **ptr_msg;
-{
-  if (letter == 'e')
-    return SHF_EXCLUDE;
-
-  *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
-  return -1;
-}
-
-int
-ppc_section_word (str, len)
-     char *str;
-     size_t len;
-{
-  if (len == 7 && strncmp (str, "exclude", 7) == 0)
-    return SHF_EXCLUDE;
-
-  return -1;
-}
-
-int
-ppc_section_type (str, len)
-     char *str;
-     size_t len;
+ppc_section_type (char *str, size_t len)
 {
   if (len == 7 && strncmp (str, "ordered", 7) == 0)
     return SHT_ORDERED;
 {
   if (len == 7 && strncmp (str, "ordered", 7) == 0)
     return SHT_ORDERED;
@@ -2846,17 +3113,11 @@ ppc_section_type (str, len)
 }
 
 int
 }
 
 int
-ppc_section_flags (flags, attr, type)
-     int flags;
-     int attr;
-     int type;
+ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type)
 {
   if (type == SHT_ORDERED)
     flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
 
 {
   if (type == SHT_ORDERED)
     flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
 
-  if (attr & SHF_EXCLUDE)
-    flags |= SEC_EXCLUDE;
-
   return flags;
 }
 #endif /* OBJ_ELF */
   return flags;
 }
 #endif /* OBJ_ELF */
@@ -2868,8 +3129,7 @@ ppc_section_flags (flags, attr, type)
    pseudo-op, but it can also take a single ASCII string.  */
 
 static void
    pseudo-op, but it can also take a single ASCII string.  */
 
 static void
-ppc_byte (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_byte (int ignore ATTRIBUTE_UNUSED)
 {
   if (*input_line_pointer != '\"')
     {
 {
   if (*input_line_pointer != '\"')
     {
@@ -2913,8 +3173,7 @@ static bfd_boolean ppc_stab_symbol;
    aligns .comm and .lcomm to 4 bytes.  */
 
 static void
    aligns .comm and .lcomm to 4 bytes.  */
 
 static void
-ppc_comm (lcomm)
-     int lcomm;
+ppc_comm (int lcomm)
 {
   asection *current_seg = now_seg;
   subsegT current_subseg = now_subseg;
 {
   asection *current_seg = now_seg;
   subsegT current_subseg = now_subseg;
@@ -3068,8 +3327,7 @@ ppc_comm (lcomm)
    optional second argument is the alignment (the default is 2).  */
 
 static void
    optional second argument is the alignment (the default is 2).  */
 
 static void
-ppc_csect (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_csect (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3086,7 +3344,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].  */
-      symbol_get_tc (sym)->class = XMC_PR;
+      symbol_get_tc (sym)->symbol_class = XMC_PR;
     }
 
   align = 2;
     }
 
   align = 2;
@@ -3104,9 +3362,7 @@ ppc_csect (ignore)
 /* Change to a different csect.  */
 
 static void
 /* Change to a different csect.  */
 
 static void
-ppc_change_csect (sym, align)
-     symbolS *sym;
-     offsetT align;
+ppc_change_csect (symbolS *sym, offsetT align)
 {
   if (S_IS_DEFINED (sym))
     subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
 {
   if (S_IS_DEFINED (sym))
     subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
@@ -3124,7 +3380,7 @@ ppc_change_csect (sym, align)
         data section.  */
       after_toc = 0;
       is_code = 0;
         data section.  */
       after_toc = 0;
       is_code = 0;
-      switch (symbol_get_tc (sym)->class)
+      switch (symbol_get_tc (sym)->symbol_class)
        {
        case XMC_PR:
        case XMC_RO:
        {
        case XMC_PR:
        case XMC_RO:
@@ -3206,8 +3462,7 @@ ppc_change_csect (sym, align)
    convenience of people who aren't used to XCOFF.  */
 
 static void
    convenience of people who aren't used to XCOFF.  */
 
 static void
-ppc_section (type)
-     int type;
+ppc_section (int type)
 {
   const char *name;
   symbolS *sym;
 {
   const char *name;
   symbolS *sym;
@@ -3231,8 +3486,7 @@ ppc_section (type)
    we do permit the user to name the text or data section.  */
 
 static void
    we do permit the user to name the text or data section.  */
 
 static void
-ppc_named_section (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_named_section (int ignore ATTRIBUTE_UNUSED)
 {
   char *user_name;
   const char *real_name;
 {
   char *user_name;
   const char *real_name;
@@ -3266,8 +3520,7 @@ ppc_named_section (ignore)
 /* The .extern pseudo-op.  We create an undefined symbol.  */
 
 static void
 /* The .extern pseudo-op.  We create an undefined symbol.  */
 
 static void
-ppc_extern (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_extern (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3285,8 +3538,7 @@ ppc_extern (ignore)
 /* The .lglobl pseudo-op.  Keep the symbol in the symbol table.  */
 
 static void
 /* The .lglobl pseudo-op.  Keep the symbol in the symbol table.  */
 
 static void
-ppc_lglobl (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_lglobl (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3304,12 +3556,63 @@ ppc_lglobl (ignore)
   demand_empty_rest_of_line ();
 }
 
   demand_empty_rest_of_line ();
 }
 
+/* The .ref pseudo-op.  It takes a list of symbol names and inserts R_REF
+   relocations at the beginning of the current csect.
+
+   (In principle, there's no reason why the relocations _have_ to be at
+   the beginning.  Anywhere in the csect would do.  However, inserting
+   at the beginning is what the native assmebler does, and it helps to
+   deal with cases where the .ref statements follow the section contents.)
+
+   ??? .refs don't work for empty .csects.  However, the native assembler
+   doesn't report an error in this case, and neither yet do we.  */
+
+static void
+ppc_ref (int ignore ATTRIBUTE_UNUSED)
+{
+  char *name;
+  char c;
+
+  if (ppc_current_csect == NULL)
+    {
+      as_bad (_(".ref outside .csect"));
+      ignore_rest_of_line ();
+      return;
+    }
+
+  do
+    {
+      name = input_line_pointer;
+      c = get_symbol_end ();
+
+      fix_at_start (symbol_get_frag (ppc_current_csect), 0,
+                   symbol_find_or_make (name), 0, FALSE, BFD_RELOC_NONE);
+
+      *input_line_pointer = c;
+      SKIP_WHITESPACE ();
+      c = *input_line_pointer;
+      if (c == ',')
+       {
+         input_line_pointer++;
+         SKIP_WHITESPACE ();
+         if (is_end_of_line[(unsigned char) *input_line_pointer])
+           {
+             as_bad (_("missing symbol name"));
+             ignore_rest_of_line ();
+             return;
+           }
+       }
+    }
+  while (c == ',');
+
+  demand_empty_rest_of_line ();
+}
+
 /* The .rename pseudo-op.  The RS/6000 assembler can rename symbols,
    although I don't know why it bothers.  */
 
 static void
 /* The .rename pseudo-op.  The RS/6000 assembler can rename symbols,
    although I don't know why it bothers.  */
 
 static void
-ppc_rename (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_rename (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3344,8 +3647,7 @@ ppc_rename (ignore)
    always zero, and I am assuming it is the type.  */
 
 static void
    always zero, and I am assuming it is the type.  */
 
 static void
-ppc_stabx (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_stabx (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   int len;
 {
   char *name;
   int len;
@@ -3471,8 +3773,7 @@ ppc_stabx (ignore)
    gets an aux entry like that used for a csect.  */
 
 static void
    gets an aux entry like that used for a csect.  */
 
 static void
-ppc_function (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_function (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3521,22 +3822,22 @@ ppc_function (ignore)
       symbol_set_value_expression (ext_sym, &exp);
     }
 
       symbol_set_value_expression (ext_sym, &exp);
     }
 
-  if (symbol_get_tc (ext_sym)->class == -1)
-    symbol_get_tc (ext_sym)->class = XMC_PR;
+  if (symbol_get_tc (ext_sym)->symbol_class == -1)
+    symbol_get_tc (ext_sym)->symbol_class = XMC_PR;
   symbol_get_tc (ext_sym)->output = 1;
 
   if (*input_line_pointer == ',')
     {
   symbol_get_tc (ext_sym)->output = 1;
 
   if (*input_line_pointer == ',')
     {
-      expressionS ignore;
+      expressionS exp;
 
       /* Ignore the third argument.  */
       ++input_line_pointer;
 
       /* Ignore the third argument.  */
       ++input_line_pointer;
-      expression (&ignore);
+      expression (& exp);
       if (*input_line_pointer == ',')
        {
          /* Ignore the fourth argument.  */
          ++input_line_pointer;
       if (*input_line_pointer == ',')
        {
          /* Ignore the fourth argument.  */
          ++input_line_pointer;
-         expression (&ignore);
+         expression (& exp);
          if (*input_line_pointer == ',')
            {
              /* The fifth argument is the function size.  */
          if (*input_line_pointer == ',')
            {
              /* The fifth argument is the function size.  */
@@ -3565,8 +3866,7 @@ ppc_function (ignore)
 static symbolS *saved_bi_sym = 0;
 
 static void
 static symbolS *saved_bi_sym = 0;
 
 static void
-ppc_bf (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bf (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3601,8 +3901,7 @@ ppc_bf (ignore)
    most recent ".bf" symbol.  */
 
 static void
    most recent ".bf" symbol.  */
 
 static void
-ppc_ef (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ef (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3626,8 +3925,7 @@ ppc_ef (ignore)
    is encountered.  */
 
 static void
    is encountered.  */
 
 static void
-ppc_biei (ei)
-     int ei;
+ppc_biei (int ei)
 {
   static symbolS *last_biei;
 
 {
   static symbolS *last_biei;
 
@@ -3681,8 +3979,7 @@ ppc_biei (ei)
    .bs symbol is the index of this csect symbol.  */
 
 static void
    .bs symbol is the index of this csect symbol.  */
 
 static void
-ppc_bs (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bs (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -3717,8 +4014,7 @@ ppc_bs (ignore)
 /* The .es pseudo-op.  Generate a C_ESTART symbol named .es.  */
 
 static void
 /* The .es pseudo-op.  Generate a C_ESTART symbol named .es.  */
 
 static void
-ppc_es (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_es (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3742,8 +4038,7 @@ ppc_es (ignore)
    line number.  */
 
 static void
    line number.  */
 
 static void
-ppc_bb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bb (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3769,8 +4064,7 @@ ppc_bb (ignore)
    line number.  */
 
 static void
    line number.  */
 
 static void
-ppc_eb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_eb (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3794,8 +4088,7 @@ ppc_eb (ignore)
    specified name.  */
 
 static void
    specified name.  */
 
 static void
-ppc_bc (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bc (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   int len;
 {
   char *name;
   int len;
@@ -3817,8 +4110,7 @@ ppc_bc (ignore)
 /* The .ec pseudo-op.  This just creates a C_ECOMM symbol.  */
 
 static void
 /* The .ec pseudo-op.  This just creates a C_ECOMM symbol.  */
 
 static void
-ppc_ec (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ec (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -3837,8 +4129,7 @@ ppc_ec (ignore)
 /* The .toc pseudo-op.  Switch to the .toc subsegment.  */
 
 static void
 /* The .toc pseudo-op.  Switch to the .toc subsegment.  */
 
 static void
-ppc_toc (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_toc (int ignore ATTRIBUTE_UNUSED)
 {
   if (ppc_toc_csect != (symbolS *) NULL)
     subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg);
 {
   if (ppc_toc_csect != (symbolS *) NULL)
     subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg);
@@ -3884,8 +4175,7 @@ ppc_toc (ignore)
    .short pseudo-op, and we want to be compatible.  */
 
 static void
    .short pseudo-op, and we want to be compatible.  */
 
 static void
-ppc_xcoff_cons (log_size)
-     int log_size;
+ppc_xcoff_cons (int log_size)
 {
   frag_align (log_size, 0, 0);
   record_alignment (now_seg, log_size);
 {
   frag_align (log_size, 0, 0);
   record_alignment (now_seg, log_size);
@@ -3893,8 +4183,7 @@ ppc_xcoff_cons (log_size)
 }
 
 static void
 }
 
 static void
-ppc_vbyte (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+ppc_vbyte (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS exp;
   int byte_count;
 {
   expressionS exp;
   int byte_count;
@@ -3937,8 +4226,7 @@ ppc_vbyte (dummy)
    the first argument is simply ignored.  */
 
 static void
    the first argument is simply ignored.  */
 
 static void
-ppc_tc (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_tc (int ignore ATTRIBUTE_UNUSED)
 {
 #ifdef OBJ_XCOFF
 
 {
 #ifdef OBJ_XCOFF
 
@@ -3968,7 +4256,7 @@ ppc_tc (ignore)
        symbolS *label;
 
        label = symbol_get_tc (ppc_current_csect)->within;
        symbolS *label;
 
        label = symbol_get_tc (ppc_current_csect)->within;
-       if (symbol_get_tc (label)->class != XMC_TC0)
+       if (symbol_get_tc (label)->symbol_class != XMC_TC0)
          {
            as_bad (_(".tc with no label"));
            ignore_rest_of_line ();
          {
            as_bad (_(".tc with no label"));
            ignore_rest_of_line ();
@@ -3988,7 +4276,7 @@ ppc_tc (ignore)
     S_SET_SEGMENT (sym, now_seg);
     symbol_set_frag (sym, frag_now);
     S_SET_VALUE (sym, (valueT) frag_now_fix ());
     S_SET_SEGMENT (sym, now_seg);
     symbol_set_frag (sym, frag_now);
     S_SET_VALUE (sym, (valueT) frag_now_fix ());
-    symbol_get_tc (sym)->class = XMC_TC;
+    symbol_get_tc (sym)->symbol_class = XMC_TC;
     symbol_get_tc (sym)->output = 1;
 
     ppc_frob_label (sym);
     symbol_get_tc (sym)->output = 1;
 
     ppc_frob_label (sym);
@@ -4000,6 +4288,7 @@ ppc_tc (ignore)
 
   /* Skip the TOC symbol name.  */
   while (is_part_of_name (*input_line_pointer)
 
   /* Skip the TOC symbol name.  */
   while (is_part_of_name (*input_line_pointer)
+        || *input_line_pointer == ' '
         || *input_line_pointer == '['
         || *input_line_pointer == ']'
         || *input_line_pointer == '{'
         || *input_line_pointer == '['
         || *input_line_pointer == ']'
         || *input_line_pointer == '{'
@@ -4024,12 +4313,11 @@ ppc_tc (ignore)
 /* Pseudo-op .machine.  */
 
 static void
 /* Pseudo-op .machine.  */
 
 static void
-ppc_machine (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_machine (int ignore ATTRIBUTE_UNUSED)
 {
   char *cpu_string;
 #define MAX_HISTORY 100
 {
   char *cpu_string;
 #define MAX_HISTORY 100
-  static unsigned long *cpu_history;
+  static ppc_cpu_t *cpu_history;
   static int curr_hist;
 
   SKIP_WHITESPACE ();
   static int curr_hist;
 
   SKIP_WHITESPACE ();
@@ -4050,7 +4338,8 @@ ppc_machine (ignore)
 
   if (cpu_string != NULL)
     {
 
   if (cpu_string != NULL)
     {
-      unsigned long old_cpu = ppc_cpu;
+      ppc_cpu_t old_cpu = ppc_cpu;
+      ppc_cpu_t new_cpu;
       char *p;
 
       for (p = cpu_string; *p != 0; p++)
       char *p;
 
       for (p = cpu_string; *p != 0; p++)
@@ -4073,8 +4362,8 @@ ppc_machine (ignore)
          else
            ppc_cpu = cpu_history[--curr_hist];
        }
          else
            ppc_cpu = cpu_history[--curr_hist];
        }
-      else if (parse_cpu (cpu_string))
-       ;
+      else if ((new_cpu = ppc_parse_cpu (ppc_cpu, cpu_string)) != 0)
+       ppc_cpu = new_cpu;
       else
        as_bad (_("invalid machine `%s'"), cpu_string);
 
       else
        as_bad (_("invalid machine `%s'"), cpu_string);
 
@@ -4088,11 +4377,10 @@ ppc_machine (ignore)
 /* See whether a symbol is in the TOC section.  */
 
 static int
 /* See whether a symbol is in the TOC section.  */
 
 static int
-ppc_is_toc_sym (sym)
-     symbolS *sym;
+ppc_is_toc_sym (symbolS *sym)
 {
 #ifdef OBJ_XCOFF
 {
 #ifdef OBJ_XCOFF
-  return symbol_get_tc (sym)->class == XMC_TC;
+  return symbol_get_tc (sym)->symbol_class == XMC_TC;
 #endif
 #ifdef OBJ_ELF
   const char *sname = segment_name (S_GET_SEGMENT (sym));
 #endif
 #ifdef OBJ_ELF
   const char *sname = segment_name (S_GET_SEGMENT (sym));
@@ -4110,8 +4398,7 @@ ppc_is_toc_sym (sym)
 
 /* Set the current section.  */
 static void
 
 /* Set the current section.  */
 static void
-ppc_set_current_section (new)
-     segT new;
+ppc_set_current_section (segT new)
 {
   ppc_previous_section = ppc_current_section;
   ppc_current_section = new;
 {
   ppc_previous_section = ppc_current_section;
   ppc_current_section = new;
@@ -4123,8 +4410,7 @@ ppc_set_current_section (new)
    warnings:  "No previous section"  */
 
 static void
    warnings:  "No previous section"  */
 
 static void
-ppc_previous (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_previous (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *tmp;
 
 {
   symbolS *tmp;
 
@@ -4155,8 +4441,7 @@ ppc_previous (ignore)
    handling, debugging, etc.  */
 
 static void
    handling, debugging, etc.  */
 
 static void
-ppc_pdata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pdata (int ignore ATTRIBUTE_UNUSED)
 {
   if (pdata_section == 0)
     {
 {
   if (pdata_section == 0)
     {
@@ -4190,8 +4475,7 @@ ppc_pdata (ignore)
    debugging, etc.  */
 
 static void
    debugging, etc.  */
 
 static void
-ppc_ydata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ydata (int ignore ATTRIBUTE_UNUSED)
 {
   if (ydata_section == 0)
     {
 {
   if (ydata_section == 0)
     {
@@ -4227,8 +4511,7 @@ ppc_ydata (ignore)
    function descriptors, etc.  */
 
 static void
    function descriptors, etc.  */
 
 static void
-ppc_reldata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_reldata (int ignore ATTRIBUTE_UNUSED)
 {
   if (reldata_section == 0)
     {
 {
   if (reldata_section == 0)
     {
@@ -4258,8 +4541,7 @@ ppc_reldata (ignore)
              3 - double word aligned (that would be 4 byte boundary)  */
 
 static void
              3 - double word aligned (that would be 4 byte boundary)  */
 
 static void
-ppc_rdata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_rdata (int ignore ATTRIBUTE_UNUSED)
 {
   if (rdata_section == 0)
     {
 {
   if (rdata_section == 0)
     {
@@ -4285,8 +4567,7 @@ ppc_rdata (ignore)
    warnings:  None  */
 
 static void
    warnings:  None  */
 
 static void
-ppc_ualong (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ualong (int ignore ATTRIBUTE_UNUSED)
 {
   /* Try for long.  */
   cons (4);
 {
   /* Try for long.  */
   cons (4);
@@ -4300,8 +4581,7 @@ ppc_ualong (ignore)
    warnings:  Missing symbol name  */
 
 static void
    warnings:  Missing symbol name  */
 
 static void
-ppc_znop (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_znop (int ignore ATTRIBUTE_UNUSED)
 {
   unsigned long insn;
   const struct powerpc_opcode *opcode;
 {
   unsigned long insn;
   const struct powerpc_opcode *opcode;
@@ -4353,14 +4633,13 @@ ppc_znop (ignore)
    warnings:  */
 
 static void
    warnings:  */
 
 static void
-ppc_pe_comm (lcomm)
-     int lcomm;
+ppc_pe_comm (int lcomm)
 {
 {
-  register char *name;
-  register char c;
-  register char *p;
+  char *name;
+  char c;
+  char *p;
   offsetT temp;
   offsetT temp;
-  register symbolS *symbolP;
+  symbolS *symbolP;
   offsetT align;
 
   name = input_line_pointer;
   offsetT align;
 
   name = input_line_pointer;
@@ -4483,8 +4762,7 @@ ppc_pe_comm (lcomm)
  */
 
 void
  */
 
 void
-ppc_pe_section (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_section (int ignore ATTRIBUTE_UNUSED)
 {
   /* Strip out the section name.  */
   char *section_name;
 {
   /* Strip out the section name.  */
   char *section_name;
@@ -4572,7 +4850,7 @@ ppc_pe_section (ignore)
                case 'R': /* Remove section at link time */
                  flags |= SEC_NEVER_LOAD;
                  break;
                case 'R': /* Remove section at link time */
                  flags |= SEC_NEVER_LOAD;
                  break;
-
+#if IFLICT_BRAIN_DAMAGE
                  /* Section Protection */
                case 'r': /* section is readable */
                  flags |= IMAGE_SCN_MEM_READ;
                  /* Section Protection */
                case 'r': /* section is readable */
                  flags |= IMAGE_SCN_MEM_READ;
@@ -4616,7 +4894,7 @@ ppc_pe_section (ignore)
                  flags |= IMAGE_SCN_ALIGN_64BYTES;
                  align = 6;
                  break;
                  flags |= IMAGE_SCN_ALIGN_64BYTES;
                  align = 6;
                  break;
-
+#endif
                default:
                  as_bad (_("unknown section attribute '%c'"),
                          *input_line_pointer);
                default:
                  as_bad (_("unknown section attribute '%c'"),
                          *input_line_pointer);
@@ -4642,12 +4920,10 @@ ppc_pe_section (ignore)
     }
 
   bfd_set_section_alignment (stdoutput, sec, align);
     }
 
   bfd_set_section_alignment (stdoutput, sec, align);
-
 }
 
 static void
 }
 
 static void
-ppc_pe_function (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_function (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
 {
   char *name;
   char endc;
@@ -4669,8 +4945,7 @@ ppc_pe_function (ignore)
 }
 
 static void
 }
 
 static void
-ppc_pe_tocd (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_tocd (int ignore ATTRIBUTE_UNUSED)
 {
   if (tocdata_section == 0)
     {
 {
   if (tocdata_section == 0)
     {
@@ -4695,8 +4970,7 @@ ppc_pe_tocd (ignore)
 /* Don't adjust TOC relocs to use the section symbol.  */
 
 int
 /* Don't adjust TOC relocs to use the section symbol.  */
 
 int
-ppc_pe_fix_adjustable (fix)
-     fixS *fix;
+ppc_pe_fix_adjustable (fixS *fix)
 {
   return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
 }
 {
   return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
 }
@@ -4711,8 +4985,7 @@ ppc_pe_fix_adjustable (fix)
    any, to use square brackets, and to be in upper case.  */
 
 char *
    any, to use square brackets, and to be in upper case.  */
 
 char *
-ppc_canonicalize_symbol_name (name)
-     char *name;
+ppc_canonicalize_symbol_name (char *name)
 {
   char *s;
 
 {
   char *s;
 
@@ -4749,8 +5022,7 @@ ppc_canonicalize_symbol_name (name)
    called whenever a new symbol is created.  */
 
 void
    called whenever a new symbol is created.  */
 
 void
-ppc_symbol_new_hook (sym)
-     symbolS *sym;
+ppc_symbol_new_hook (symbolS *sym)
 {
   struct ppc_tc_sy *tc;
   const char *s;
 {
   struct ppc_tc_sy *tc;
   const char *s;
@@ -4758,7 +5030,7 @@ ppc_symbol_new_hook (sym)
   tc = symbol_get_tc (sym);
   tc->next = NULL;
   tc->output = 0;
   tc = symbol_get_tc (sym);
   tc->next = NULL;
   tc->output = 0;
-  tc->class = -1;
+  tc->symbol_class = -1;
   tc->real_name = NULL;
   tc->subseg = 0;
   tc->align = 0;
   tc->real_name = NULL;
   tc->subseg = 0;
   tc->align = 0;
@@ -4781,55 +5053,55 @@ ppc_symbol_new_hook (sym)
     {
     case 'B':
       if (strcmp (s, "BS]") == 0)
     {
     case 'B':
       if (strcmp (s, "BS]") == 0)
-       tc->class = XMC_BS;
+       tc->symbol_class = XMC_BS;
       break;
     case 'D':
       if (strcmp (s, "DB]") == 0)
       break;
     case 'D':
       if (strcmp (s, "DB]") == 0)
-       tc->class = XMC_DB;
+       tc->symbol_class = XMC_DB;
       else if (strcmp (s, "DS]") == 0)
       else if (strcmp (s, "DS]") == 0)
-       tc->class = XMC_DS;
+       tc->symbol_class = XMC_DS;
       break;
     case 'G':
       if (strcmp (s, "GL]") == 0)
       break;
     case 'G':
       if (strcmp (s, "GL]") == 0)
-       tc->class = XMC_GL;
+       tc->symbol_class = XMC_GL;
       break;
     case 'P':
       if (strcmp (s, "PR]") == 0)
       break;
     case 'P':
       if (strcmp (s, "PR]") == 0)
-       tc->class = XMC_PR;
+       tc->symbol_class = XMC_PR;
       break;
     case 'R':
       if (strcmp (s, "RO]") == 0)
       break;
     case 'R':
       if (strcmp (s, "RO]") == 0)
-       tc->class = XMC_RO;
+       tc->symbol_class = XMC_RO;
       else if (strcmp (s, "RW]") == 0)
       else if (strcmp (s, "RW]") == 0)
-       tc->class = XMC_RW;
+       tc->symbol_class = XMC_RW;
       break;
     case 'S':
       if (strcmp (s, "SV]") == 0)
       break;
     case 'S':
       if (strcmp (s, "SV]") == 0)
-       tc->class = XMC_SV;
+       tc->symbol_class = XMC_SV;
       break;
     case 'T':
       if (strcmp (s, "TC]") == 0)
       break;
     case 'T':
       if (strcmp (s, "TC]") == 0)
-       tc->class = XMC_TC;
+       tc->symbol_class = XMC_TC;
       else if (strcmp (s, "TI]") == 0)
       else if (strcmp (s, "TI]") == 0)
-       tc->class = XMC_TI;
+       tc->symbol_class = XMC_TI;
       else if (strcmp (s, "TB]") == 0)
       else if (strcmp (s, "TB]") == 0)
-       tc->class = XMC_TB;
+       tc->symbol_class = XMC_TB;
       else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
       else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
-       tc->class = XMC_TC0;
+       tc->symbol_class = XMC_TC0;
       break;
     case 'U':
       if (strcmp (s, "UA]") == 0)
       break;
     case 'U':
       if (strcmp (s, "UA]") == 0)
-       tc->class = XMC_UA;
+       tc->symbol_class = XMC_UA;
       else if (strcmp (s, "UC]") == 0)
       else if (strcmp (s, "UC]") == 0)
-       tc->class = XMC_UC;
+       tc->symbol_class = XMC_UC;
       break;
     case 'X':
       if (strcmp (s, "XO]") == 0)
       break;
     case 'X':
       if (strcmp (s, "XO]") == 0)
-       tc->class = XMC_XO;
+       tc->symbol_class = XMC_XO;
       break;
     }
 
       break;
     }
 
-  if (tc->class == -1)
+  if (tc->symbol_class == -1)
     as_bad (_("Unrecognized symbol suffix"));
 }
 
     as_bad (_("Unrecognized symbol suffix"));
 }
 
@@ -4838,13 +5110,12 @@ ppc_symbol_new_hook (sym)
    follows the csect symbol.  */
 
 void
    follows the csect symbol.  */
 
 void
-ppc_frob_label (sym)
-     symbolS *sym;
+ppc_frob_label (symbolS *sym)
 {
   if (ppc_current_csect != (symbolS *) NULL)
     {
 {
   if (ppc_current_csect != (symbolS *) NULL)
     {
-      if (symbol_get_tc (sym)->class == -1)
-       symbol_get_tc (sym)->class = symbol_get_tc (ppc_current_csect)->class;
+      if (symbol_get_tc (sym)->symbol_class == -1)
+       symbol_get_tc (sym)->symbol_class = symbol_get_tc (ppc_current_csect)->symbol_class;
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
 
       symbol_remove (sym, &symbol_rootP, &symbol_lastP);
       symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
@@ -4869,8 +5140,7 @@ static bfd_boolean ppc_saw_abs;
    symbol table.  */
 
 int
    symbol table.  */
 
 int
-ppc_frob_symbol (sym)
-     symbolS *sym;
+ppc_frob_symbol (symbolS *sym)
 {
   static symbolS *ppc_last_function;
   static symbolS *set_end;
 {
   static symbolS *ppc_last_function;
   static symbolS *set_end;
@@ -4958,6 +5228,7 @@ ppc_frob_symbol (sym)
     S_SET_STORAGE_CLASS (sym, C_HIDEXT);
 
   if (S_GET_STORAGE_CLASS (sym) == C_EXT
     S_SET_STORAGE_CLASS (sym, C_HIDEXT);
 
   if (S_GET_STORAGE_CLASS (sym) == C_EXT
+      || S_GET_STORAGE_CLASS (sym) == C_AIX_WEAKEXT
       || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
     {
       int i;
       || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
     {
       int i;
@@ -4967,7 +5238,7 @@ ppc_frob_symbol (sym)
       i = S_GET_NUMBER_AUXILIARY (sym);
       S_SET_NUMBER_AUXILIARY (sym, i + 1);
       a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent;
       i = S_GET_NUMBER_AUXILIARY (sym);
       S_SET_NUMBER_AUXILIARY (sym, i + 1);
       a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent;
-      if (symbol_get_tc (sym)->class == XMC_TC0)
+      if (symbol_get_tc (sym)->symbol_class == XMC_TC0)
        {
          /* This is the TOC table.  */
          know (strcmp (S_GET_NAME (sym), "TOC") == 0);
        {
          /* This is the TOC table.  */
          know (strcmp (S_GET_NAME (sym), "TOC") == 0);
@@ -4996,9 +5267,9 @@ ppc_frob_symbol (sym)
          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))
          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))
-           symbol_get_tc (sym)->class = XMC_RW;
+           symbol_get_tc (sym)->symbol_class = XMC_RW;
          else
          else
-           symbol_get_tc (sym)->class = XMC_BS;
+           symbol_get_tc (sym)->symbol_class = XMC_BS;
        }
       else if (S_GET_SEGMENT (sym) == absolute_section)
        {
        }
       else if (S_GET_SEGMENT (sym) == absolute_section)
        {
@@ -5006,8 +5277,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 (symbol_get_tc (sym)->class == -1)
-           symbol_get_tc (sym)->class = XMC_XO;
+         if (symbol_get_tc (sym)->symbol_class == -1)
+           symbol_get_tc (sym)->symbol_class = XMC_XO;
        }
       else if (! S_IS_DEFINED (sym))
        {
        }
       else if (! S_IS_DEFINED (sym))
        {
@@ -5015,17 +5286,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 (symbol_get_tc (sym)->class == XMC_TC)
+      else if (symbol_get_tc (sym)->symbol_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 (symbol_get_tc (next)->class == XMC_TC0)
+         while (symbol_get_tc (next)->symbol_class == XMC_TC0)
            next = symbol_next (next);
          if (next == (symbolS *) NULL
            next = symbol_next (next);
          if (next == (symbolS *) NULL
-             || symbol_get_tc (next)->class != XMC_TC)
+             || symbol_get_tc (next)->symbol_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,
@@ -5085,10 +5356,10 @@ ppc_frob_symbol (sym)
 
       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 (symbol_get_tc (sym)->class == -1)
+      if (symbol_get_tc (sym)->symbol_class == -1)
        a->x_csect.x_smclas = XMC_PR;
       else
        a->x_csect.x_smclas = XMC_PR;
       else
-       a->x_csect.x_smclas = symbol_get_tc (sym)->class;
+       a->x_csect.x_smclas = symbol_get_tc (sym)->symbol_class;
       a->x_csect.x_stab = 0;
       a->x_csect.x_snstab = 0;
 
       a->x_csect.x_stab = 0;
       a->x_csect.x_snstab = 0;
 
@@ -5133,7 +5404,7 @@ ppc_frob_symbol (sym)
    absolute symbols.  */
 
 void
    absolute symbols.  */
 
 void
-ppc_adjust_symtab ()
+ppc_adjust_symtab (void)
 {
   symbolS *sym;
 
 {
   symbolS *sym;
 
@@ -5179,8 +5450,7 @@ ppc_adjust_symtab ()
    turn.  */
 
 void
    turn.  */
 
 void
-ppc_frob_section (sec)
-     asection *sec;
+ppc_frob_section (asection *sec)
 {
   static bfd_vma vma = 0;
 
 {
   static bfd_vma vma = 0;
 
@@ -5191,71 +5461,17 @@ ppc_frob_section (sec)
 
 #endif /* OBJ_XCOFF */
 \f
 
 #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
-   returned, or NULL on OK.  */
-
 char *
 char *
-md_atof (type, litp, sizep)
-     int type;
-     char *litp;
-     int *sizep;
+md_atof (int type, char *litp, int *sizep)
 {
 {
-  int prec;
-  LITTLENUM_TYPE words[4];
-  char *t;
-  int i;
-
-  switch (type)
-    {
-    case 'f':
-      prec = 2;
-      break;
-
-    case 'd':
-      prec = 4;
-      break;
-
-    default:
-      *sizep = 0;
-      return _("bad call to md_atof");
-    }
-
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-
-  *sizep = prec * 2;
-
-  if (target_big_endian)
-    {
-      for (i = 0; i < prec; i++)
-       {
-         md_number_to_chars (litp, (valueT) words[i], 2);
-         litp += 2;
-       }
-    }
-  else
-    {
-      for (i = prec - 1; i >= 0; i--)
-       {
-         md_number_to_chars (litp, (valueT) words[i], 2);
-         litp += 2;
-       }
-    }
-
-  return NULL;
+  return ieee_md_atof (type, litp, sizep, target_big_endian);
 }
 
 /* Write a value out to the object file, using the appropriate
    endianness.  */
 
 void
 }
 
 /* Write a value out to the object file, using the appropriate
    endianness.  */
 
 void
-md_number_to_chars (buf, val, n)
-     char *buf;
-     valueT val;
-     int n;
+md_number_to_chars (char *buf, valueT val, int n)
 {
   if (target_big_endian)
     number_to_chars_bigendian (buf, val, n);
 {
   if (target_big_endian)
     number_to_chars_bigendian (buf, val, n);
@@ -5266,21 +5482,22 @@ md_number_to_chars (buf, val, n)
 /* Align a section (I don't know why this is machine dependent).  */
 
 valueT
 /* Align a section (I don't know why this is machine dependent).  */
 
 valueT
-md_section_align (seg, addr)
-     asection *seg;
-     valueT addr;
+md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr)
 {
 {
+#ifdef OBJ_ELF
+  return addr;
+#else
   int align = bfd_get_section_alignment (stdoutput, seg);
 
   return ((addr + (1 << align) - 1) & (-1 << align));
   int align = bfd_get_section_alignment (stdoutput, seg);
 
   return ((addr + (1 << align) - 1) & (-1 << align));
+#endif
 }
 
 /* We don't have any form of relaxing.  */
 
 int
 }
 
 /* We don't have any form of relaxing.  */
 
 int
-md_estimate_size_before_relax (fragp, seg)
-     fragS *fragp ATTRIBUTE_UNUSED;
-     asection *seg ATTRIBUTE_UNUSED;
+md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
+                              asection *seg ATTRIBUTE_UNUSED)
 {
   abort ();
   return 0;
 {
   abort ();
   return 0;
@@ -5289,10 +5506,9 @@ md_estimate_size_before_relax (fragp, seg)
 /* Convert a machine dependent frag.  We never generate these.  */
 
 void
 /* Convert a machine dependent frag.  We never generate these.  */
 
 void
-md_convert_frag (abfd, sec, fragp)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
-     fragS *fragp ATTRIBUTE_UNUSED;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+                asection *sec ATTRIBUTE_UNUSED,
+                fragS *fragp ATTRIBUTE_UNUSED)
 {
   abort ();
 }
 {
   abort ();
 }
@@ -5300,8 +5516,7 @@ md_convert_frag (abfd, sec, fragp)
 /* We have no need to default values of symbols.  */
 
 symbolS *
 /* We have no need to default values of symbols.  */
 
 symbolS *
-md_undefined_symbol (name)
-     char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 {
   return 0;
 }
@@ -5312,9 +5527,7 @@ md_undefined_symbol (name)
    given a PC relative reloc.  */
 
 long
    given a PC relative reloc.  */
 
 long
-md_pcrel_from_section (fixp, sec)
-     fixS *fixp;
-     segT sec ATTRIBUTE_UNUSED;
+md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
 {
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 {
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
@@ -5327,8 +5540,7 @@ md_pcrel_from_section (fixp, sec)
    corresponding .tc symbol.  */
 
 int
    corresponding .tc symbol.  */
 
 int
-ppc_fix_adjustable (fix)
-     fixS *fix;
+ppc_fix_adjustable (fixS *fix)
 {
   valueT val = resolve_symbol_value (fix->fx_addsy);
   segT symseg = S_GET_SEGMENT (fix->fx_addsy);
 {
   valueT val = resolve_symbol_value (fix->fx_addsy);
   segT symseg = S_GET_SEGMENT (fix->fx_addsy);
@@ -5352,9 +5564,9 @@ ppc_fix_adjustable (fix)
        {
          TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy);
 
        {
          TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy);
 
-         if (sy_tc->class == XMC_TC0)
+         if (sy_tc->symbol_class == XMC_TC0)
            continue;
            continue;
-         if (sy_tc->class != XMC_TC)
+         if (sy_tc->symbol_class != XMC_TC)
            break;
          if (val == resolve_symbol_value (sy))
            {
            break;
          if (val == resolve_symbol_value (sy))
            {
@@ -5371,8 +5583,8 @@ ppc_fix_adjustable (fix)
   /* Possibly adjust the reloc to be against the csect.  */
   tc = symbol_get_tc (fix->fx_addsy);
   if (tc->subseg == 0
   /* Possibly adjust the reloc to be against the csect.  */
   tc = symbol_get_tc (fix->fx_addsy);
   if (tc->subseg == 0
-      && tc->class != XMC_TC0
-      && tc->class != XMC_TC
+      && tc->symbol_class != XMC_TC0
+      && tc->symbol_class != XMC_TC
       && symseg != bss_section
       /* Don't adjust if this is a reloc in the toc section.  */
       && (symseg != data_section
       && symseg != bss_section
       /* Don't adjust if this is a reloc in the toc section.  */
       && (symseg != data_section
@@ -5453,8 +5665,7 @@ ppc_fix_adjustable (fix)
    between two csects in the same section.  */
 
 int
    between two csects in the same section.  */
 
 int
-ppc_force_relocation (fix)
-     fixS *fix;
+ppc_force_relocation (fixS *fix)
 {
   /* At this point fix->fx_addsy should already have been converted to
      a csect symbol.  If the csect does not include the fragment, then
 {
   /* At this point fix->fx_addsy should already have been converted to
      a csect symbol.  If the csect does not include the fragment, then
@@ -5479,8 +5690,7 @@ ppc_force_relocation (fix)
    will be emitted for a fixup.  */
 
 int
    will be emitted for a fixup.  */
 
 int
-ppc_force_relocation (fix)
-     fixS *fix;
+ppc_force_relocation (fixS *fix)
 {
   /* Branch prediction relocations must force a relocation, as must
      the vtable description relocs.  */
 {
   /* Branch prediction relocations must force a relocation, as must
      the vtable description relocs.  */
@@ -5505,8 +5715,7 @@ ppc_force_relocation (fix)
 }
 
 int
 }
 
 int
-ppc_fix_adjustable (fix)
-     fixS *fix;
+ppc_fix_adjustable (fixS *fix)
 {
   return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
          && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
 {
   return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
          && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
@@ -5520,6 +5729,53 @@ ppc_fix_adjustable (fix)
 }
 #endif
 
 }
 #endif
 
+/* Implement HANDLE_ALIGN.  This writes the NOP pattern into an
+   rs_align_code frag.  */
+
+void
+ppc_handle_align (struct frag *fragP)
+{
+  valueT count = (fragP->fr_next->fr_address
+                 - (fragP->fr_address + fragP->fr_fix));
+
+  if (count != 0 && (count & 3) == 0)
+    {
+      char *dest = fragP->fr_literal + fragP->fr_fix;
+
+      fragP->fr_var = 4;
+      md_number_to_chars (dest, 0x60000000, 4);
+
+      if ((ppc_cpu & PPC_OPCODE_POWER6) != 0
+         || (ppc_cpu & PPC_OPCODE_POWER7) != 0)
+       {
+         /* For power6 and power7, we want the last nop to be a group
+            terminating one.  Do this by inserting an rs_fill frag immediately
+            after this one, with its address set to the last nop location.
+            This will automatically reduce the number of nops in the current
+            frag by one.  */
+         if (count > 4)
+           {
+             struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4);
+
+             memcpy (group_nop, fragP, SIZEOF_STRUCT_FRAG);
+             group_nop->fr_address = group_nop->fr_next->fr_address - 4;
+             group_nop->fr_fix = 0;
+             group_nop->fr_offset = 1;
+             group_nop->fr_type = rs_fill;
+             fragP->fr_next = group_nop;
+             dest = group_nop->fr_literal;
+           }
+
+         if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
+           /* power7 group terminating nop: "ori 2,2,0".  */
+           md_number_to_chars (dest, 0x60420000, 4);
+         else
+           /* power6 group terminating nop: "ori 1,1,0".  */
+           md_number_to_chars (dest, 0x60210000, 4);
+       }
+    }
+}
+
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the call to fix_new_exp, above.  In the call
    above we used a reloc code which was the largest legal reloc code
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the call to fix_new_exp, above.  In the call
    above we used a reloc code which was the largest legal reloc code
@@ -5530,10 +5786,7 @@ ppc_fix_adjustable (fix)
    fixup.  */
 
 void
    fixup.  */
 
 void
-md_apply_fix (fixP, valP, seg)
-     fixS *fixP;
-     valueT * valP;
-     segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   valueT value = * valP;
 
 {
   valueT value = * valP;
 
@@ -5553,18 +5806,19 @@ md_apply_fix (fixP, valP, seg)
      going to use the symbol value.  That means that if the reloc is
      fully resolved we want to use *valP since bfd_install_relocation is
      not being used.
      going to use the symbol value.  That means that if the reloc is
      fully resolved we want to use *valP since bfd_install_relocation is
      not being used.
-     However, if the reloc is not fully resolved we do not want to use
-     *valP, and must use fx_offset instead.  However, if the reloc
-     is PC relative, we do want to use *valP 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 *valP, and must use fx_offset instead.  If the relocation
+     is PC-relative, we then need to re-apply md_pcrel_from_section
+     to this new relocation value.  */
   if (fixP->fx_addsy == (symbolS *) NULL)
     fixP->fx_done = 1;
 
   if (fixP->fx_addsy == (symbolS *) NULL)
     fixP->fx_done = 1;
 
-  else if (fixP->fx_pcrel)
-    ;
-
   else
   else
-    value = fixP->fx_offset;
+    {
+      value = fixP->fx_offset;
+      if (fixP->fx_pcrel)
+       value -= md_pcrel_from_section (fixP, seg);
+    }
 #endif
 
   if (fixP->fx_subsy != (symbolS *) NULL)
 #endif
 
   if (fixP->fx_subsy != (symbolS *) NULL)
@@ -5590,13 +5844,13 @@ md_apply_fix (fixP, valP, seg)
         csect.  Other usages, such as `.long sym', generate relocs.  This
         is the documented behaviour of non-TOC symbols.  */
       if ((operand->flags & PPC_OPERAND_PARENS) != 0
         csect.  Other usages, such as `.long sym', generate relocs.  This
         is the documented behaviour of non-TOC symbols.  */
       if ((operand->flags & PPC_OPERAND_PARENS) != 0
-         && operand->bits == 16
+         && (operand->bitm & 0xfff0) == 0xfff0
          && operand->shift == 0
          && (operand->insert == NULL || ppc_obj64)
          && fixP->fx_addsy != NULL
          && symbol_get_tc (fixP->fx_addsy)->subseg != 0
          && operand->shift == 0
          && (operand->insert == NULL || ppc_obj64)
          && fixP->fx_addsy != NULL
          && 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
+         && symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC
+         && symbol_get_tc (fixP->fx_addsy)->symbol_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;
@@ -5612,6 +5866,7 @@ md_apply_fix (fixP, valP, seg)
       else
        insn = bfd_getl32 ((unsigned char *) where);
       insn = ppc_insert_operand (insn, operand, (offsetT) value,
       else
        insn = bfd_getl32 ((unsigned char *) where);
       insn = ppc_insert_operand (insn, operand, (offsetT) value,
+                                fixP->tc_fix_data.ppc_cpu,
                                 fixP->fx_file, fixP->fx_line);
       if (target_big_endian)
        bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
                                 fixP->fx_file, fixP->fx_line);
       if (target_big_endian)
        bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
@@ -5622,17 +5877,17 @@ md_apply_fix (fixP, valP, seg)
        /* Nothing else to do here.  */
        return;
 
        /* Nothing else to do here.  */
        return;
 
-      assert (fixP->fx_addsy != NULL);
+      gas_assert (fixP->fx_addsy != NULL);
 
       /* Determine a BFD reloc value based on the operand information.
         We are only prepared to turn a few of the operands into
         relocs.  */
       if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
 
       /* Determine a BFD reloc value based on the operand information.
         We are only prepared to turn a few of the operands into
         relocs.  */
       if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
-         && operand->bits == 26
+         && operand->bitm == 0x3fffffc
          && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_B26;
       else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
          && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_B26;
       else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
-         && operand->bits == 16
+         && operand->bitm == 0xfffc
          && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_B16;
          && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_B16;
@@ -5643,11 +5898,11 @@ md_apply_fix (fixP, valP, seg)
 #endif
        }
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
 #endif
        }
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
-              && operand->bits == 26
+              && operand->bitm == 0x3fffffc
               && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_BA26;
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
               && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_BA26;
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
-              && operand->bits == 16
+              && operand->bitm == 0xfffc
               && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_BA16;
               && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_BA16;
@@ -5659,7 +5914,7 @@ md_apply_fix (fixP, valP, seg)
        }
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
        }
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
-              && operand->bits == 16
+              && (operand->bitm & 0xfff0) == 0xfff0
               && operand->shift == 0)
        {
          if (ppc_is_toc_sym (fixP->fx_addsy))
               && operand->shift == 0)
        {
          if (ppc_is_toc_sym (fixP->fx_addsy))
@@ -5826,6 +6081,11 @@ md_apply_fix (fixP, valP, seg)
                              PPC_HA (value), 2);
          break;
 
                              PPC_HA (value), 2);
          break;
 
+#ifdef OBJ_XCOFF
+       case BFD_RELOC_NONE:
+         break;
+#endif
+
 #ifdef OBJ_ELF
        case BFD_RELOC_PPC64_HIGHER:
          if (fixP->fx_pcrel)
 #ifdef OBJ_ELF
        case BFD_RELOC_PPC64_HIGHER:
          if (fixP->fx_pcrel)
@@ -5896,6 +6156,8 @@ md_apply_fix (fixP, valP, seg)
          break;
 
        case BFD_RELOC_PPC_TLS:
          break;
 
        case BFD_RELOC_PPC_TLS:
+       case BFD_RELOC_PPC_TLSGD:
+       case BFD_RELOC_PPC_TLSLD:
          break;
 
        case BFD_RELOC_PPC_DTPMOD:
          break;
 
        case BFD_RELOC_PPC_DTPMOD:
@@ -6045,10 +6307,11 @@ md_apply_fix (fixP, valP, seg)
 #ifdef TE_PE
       fixP->fx_addnumber = 0;
 #else
 #ifdef TE_PE
       fixP->fx_addnumber = 0;
 #else
-      /* We want to use the offset within the data segment of the
-        symbol, not the actual VMA of the symbol.  */
+      /* We want to use the offset within the toc, not the actual VMA
+        of the symbol.  */
       fixP->fx_addnumber =
       fixP->fx_addnumber =
-       - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy));
+       - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy))
+       - S_GET_VALUE (ppc_toc_csect);
 #endif
     }
 #endif
 #endif
     }
 #endif
@@ -6057,9 +6320,7 @@ md_apply_fix (fixP, valP, seg)
 /* Generate a reloc for a fixup.  */
 
 arelent *
 /* Generate a reloc for a fixup.  */
 
 arelent *
-tc_gen_reloc (seg, fixp)
-     asection *seg ATTRIBUTE_UNUSED;
-     fixS *fixp;
+tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
 
 {
   arelent *reloc;
 
@@ -6082,7 +6343,7 @@ tc_gen_reloc (seg, fixp)
 }
 
 void
 }
 
 void
-ppc_cfi_frame_initial_instructions ()
+ppc_cfi_frame_initial_instructions (void)
 {
   cfi_add_CFA_def_cfa (1, 0);
 }
 {
   cfi_add_CFA_def_cfa (1, 0);
 }
This page took 0.068725 seconds and 4 git commands to generate.