ppc e500mc support
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index 8b59f3fa4b18487454722e9b3a6750f39d67790c..ef54165bb94be9558c21bd7bbca2db48abc19c9f 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,
-   2004, 2005, 2006 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008 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
-   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,
@@ -20,7 +20,6 @@
    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"
@@ -85,67 +84,57 @@ static int set_target_endian = 0;
 
 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)
-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
-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_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
-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
-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
@@ -183,14 +172,16 @@ const char EXP_CHARS[] = "eE";
    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.  */
-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 type of processor we are assembling for.  This is one or more
+   of the PPC_OPCODE flags defined in opcode/ppc.h.  */
+unsigned long ppc_cpu = 0;
 \f
 /* The target specific pseudo-ops which we support.  */
 
@@ -409,6 +400,24 @@ static const struct pd_reg pre_defined_registers[] =
 
   { "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 },
@@ -567,14 +576,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.  */
 
-static int reg_name_search
-  PARAMS ((const struct pd_reg *, int, const char * name));
-
 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;
@@ -611,8 +614,7 @@ reg_name_search (regs, regcount, name)
  */
 
 static bfd_boolean
-register_name (expressionP)
-     expressionS *expressionP;
+register_name (expressionS *expressionP)
 {
   int reg_number;
   char *name;
@@ -679,15 +681,15 @@ static const struct pd_reg cr_names[] =
    expression.  */
 
 int
-ppc_parse_name (name, expr)
-     const char *name;
-     expressionS *expr;
+ppc_parse_name (const char *name, expressionS *expr)
 {
   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)
@@ -701,10 +703,6 @@ ppc_parse_name (name, expr)
 \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;
 
@@ -827,6 +825,8 @@ const size_t md_longopts_size = sizeof (md_longopts);
 static int
 parse_cpu (const char *arg)
 {
+  unsigned long altivec_or_spe = ppc_cpu & (PPC_OPCODE_ALTIVEC | PPC_OPCODE_SPE);
+
   /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
      (RIOS2).  */
   if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
@@ -846,6 +846,9 @@ parse_cpu (const char *arg)
           || strcmp (arg, "603") == 0
           || strcmp (arg, "604") == 0)
     ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+  /* Do all PPC750s have paired single ops?  */
+  else if (strcmp (arg, "750cl") == 0)
+    ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_PPCPS;
   /* -m403 and -m405 mean to assemble for the PowerPC 403/405.  */
   else if (strcmp (arg, "403") == 0
           || strcmp (arg, "405") == 0)
@@ -866,23 +869,29 @@ parse_cpu (const char *arg)
   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;
+       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC;
+
+      altivec_or_spe |= 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);
+                | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
+    }
+  else if (strcmp (arg, "e500mc") == 0)
+    {
+      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
+                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+                | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
     }
   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;
+       ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_EFS;
+
+      altivec_or_spe |= PPC_OPCODE_SPE;
     }
   /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
      620.  */
@@ -923,6 +932,12 @@ parse_cpu (const char *arg)
                 | PPC_OPCODE_64 | PPC_OPCODE_POWER4
                 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
     }
+  else if (strcmp (arg, "cell") == 0)
+    {
+      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
+                | PPC_OPCODE_CELL);
+    }
   /* -mcom means assemble for the common intersection between Power
      and PowerPC.  At present, we just allow the union, rather
      than the intersection.  */
@@ -934,13 +949,13 @@ parse_cpu (const char *arg)
   else
     return 0;
 
+  /* Make sure the the Altivec and SPE bits are not lost.  */
+  ppc_cpu |= altivec_or_spe;
   return 1;
 }
 
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg;
+md_parse_option (int c, char *arg)
 {
   switch (c)
     {
@@ -1094,8 +1109,7 @@ md_parse_option (c, arg)
 }
 
 void
-md_show_usage (stream)
-     FILE *stream;
+md_show_usage (FILE *stream)
 {
   fprintf (stream, _("\
 PowerPC options:\n\
@@ -1110,7 +1124,8 @@ PowerPC options:\n\
 -m403, -m405           generate code for PowerPC 403/405\n\
 -m440                  generate code for PowerPC 440\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, _("\
 -mppc64, -m620         generate code for PowerPC 620/625/630\n\
 -mppc64bridge          generate code for PowerPC 64, including bridge insns\n\
@@ -1119,12 +1134,14 @@ PowerPC options:\n\
 -mpower4               generate code for Power4 architecture\n\
 -mpower5               generate code for Power5 architecture\n\
 -mpower6               generate code for Power6 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, _("\
 -maltivec              generate code for AltiVec\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\
 -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"));
@@ -1147,7 +1164,7 @@ PowerPC options:\n\
 /* 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;
@@ -1175,7 +1192,7 @@ ppc_set_cpu ()
    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 ();
@@ -1197,7 +1214,7 @@ ppc_arch ()
 }
 
 unsigned long
-ppc_mach ()
+ppc_mach (void)
 {
   if (ppc_obj64)
     return bfd_mach_ppc64;
@@ -1208,7 +1225,7 @@ ppc_mach ()
 }
 
 extern char*
-ppc_target_format ()
+ppc_target_format (void)
 {
 #ifdef OBJ_COFF
 #ifdef TE_PE
@@ -1240,11 +1257,11 @@ ppc_target_format ()
 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;
-  bfd_boolean dup_insn = FALSE;
+  bfd_boolean bad_insn = FALSE;
 
   if (ppc_hash != NULL)
     hash_die (ppc_hash);
@@ -1254,10 +1271,127 @@ ppc_setup_opcodes (void)
   /* 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++)
     {
-      know ((op->opcode & op->mask) == op->opcode);
+      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.  eg. "lhae" booke64 insn must be
+                found before "ld" ppc64 insn.  */
+             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 ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0
          && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
@@ -1284,7 +1418,7 @@ ppc_setup_opcodes (void)
        {
          const char *retval;
 
-         retval = hash_insert (ppc_hash, op->name, (PTR) op);
+         retval = hash_insert (ppc_hash, op->name, (void *) op);
          if (retval != NULL)
            {
              /* Ignore Power duplicates for -m601.  */
@@ -1292,16 +1426,16 @@ ppc_setup_opcodes (void)
                  && (op->flags & PPC_OPCODE_POWER) != 0)
                continue;
 
-             as_bad (_("Internal assembler error for instruction %s"),
+             as_bad (_("duplicate instruction %s"),
                      op->name);
-             dup_insn = TRUE;
+             bad_insn = TRUE;
            }
        }
     }
 
   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 ();
@@ -1313,16 +1447,16 @@ ppc_setup_opcodes (void)
        {
          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)
            {
-             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 ();
 }
 
@@ -1331,7 +1465,7 @@ ppc_setup_opcodes (void)
    opened.  */
 
 void
-md_begin ()
+md_begin (void)
 {
   ppc_set_cpu ();
 
@@ -1374,7 +1508,7 @@ md_begin ()
 }
 
 void
-ppc_cleanup ()
+ppc_cleanup (void)
 {
 #ifdef OBJ_ELF
   if (ppc_apuinfo_list == NULL)
@@ -1436,54 +1570,61 @@ ppc_cleanup ()
 /* 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,
+                   unsigned long ppc_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;
+
+      /* 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;
 
-      if (test < (offsetT) min || test > (offsetT) max)
-       as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
+      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)
@@ -1496,8 +1637,7 @@ ppc_insert_operand (insn, operand, val, file, line)
        as_bad_where (file, line, errmsg);
     }
   else
-    insn |= (((long) val & ((1 << operand->bits) - 1))
-            << operand->shift);
+    insn |= ((long) val & operand->bitm) << operand->shift;
 
   return insn;
 }
@@ -1506,9 +1646,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
-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;
@@ -1686,8 +1824,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
-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;
@@ -1742,8 +1879,7 @@ ppc_elf_cons (nbytes)
 
 /* 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";
@@ -1757,14 +1893,13 @@ ppc_elf_rdata (xxx)
 
 /* 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;
-  register symbolS *symbolP;
+  symbolS *symbolP;
   offsetT align;
   segT old_sec;
   int old_subsec;
@@ -1867,9 +2002,7 @@ ppc_elf_lcomm (xxx)
    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;
@@ -1914,7 +2047,7 @@ ppc_elf_validate_fix (fixp, seg)
    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;
@@ -1997,8 +2130,7 @@ enum toc_size_qualifier
 };
 
 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;
@@ -2062,8 +2194,7 @@ parse_toc_entry (toc_kind)
 #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;
 
@@ -2109,8 +2240,7 @@ struct ppc_fixup
 /* 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;
@@ -2374,12 +2504,19 @@ md_assemble (str)
       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)
-               cr_operand = TRUE;
+               {
+                 cr_operand = TRUE;
+                 lex_type['%'] |= LEX_BEGIN_NAME;
+               }
              expression (&ex);
              cr_operand = FALSE;
+             lex_type['%'] = save_lex;
            }
        }
 
@@ -2393,7 +2530,7 @@ md_assemble (str)
       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)
        {
@@ -2462,7 +2599,7 @@ md_assemble (str)
              }
 #endif /* OBJ_ELF */
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
-                                    (char *) NULL, 0);
+                                    ppc_cpu, (char *) NULL, 0);
        }
 #ifdef OBJ_ELF
       else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
@@ -2474,7 +2611,7 @@ md_assemble (str)
              break;
            case BFD_RELOC_PPC_TLS:
              insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
-                                        (char *) NULL, 0);
+                                        ppc_cpu, (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.  */
@@ -2595,6 +2732,14 @@ md_assemble (str)
        {
          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)
        {
@@ -2734,16 +2879,14 @@ md_assemble (str)
    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;
-  int arg;
+  unsigned int arg;
   char *send;
   char *complete;
 
@@ -2781,7 +2924,7 @@ ppc_macro (str, macro)
       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;
        }
@@ -2812,9 +2955,7 @@ ppc_macro (str, macro)
 /* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED.  */
 
 int
-ppc_section_letter (letter, ptr_msg)
-     int letter;
-     char **ptr_msg;
+ppc_section_letter (int letter, char **ptr_msg)
 {
   if (letter == 'e')
     return SHF_EXCLUDE;
@@ -2824,9 +2965,7 @@ ppc_section_letter (letter, ptr_msg)
 }
 
 int
-ppc_section_word (str, len)
-     char *str;
-     size_t len;
+ppc_section_word (char *str, size_t len)
 {
   if (len == 7 && strncmp (str, "exclude", 7) == 0)
     return SHF_EXCLUDE;
@@ -2835,9 +2974,7 @@ ppc_section_word (str, len)
 }
 
 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;
@@ -2846,10 +2983,7 @@ ppc_section_type (str, len)
 }
 
 int
-ppc_section_flags (flags, attr, type)
-     int flags;
-     int attr;
-     int type;
+ppc_section_flags (int flags, int attr, int type)
 {
   if (type == SHT_ORDERED)
     flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
@@ -2868,8 +3002,7 @@ ppc_section_flags (flags, attr, type)
    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 != '\"')
     {
@@ -2913,8 +3046,7 @@ static bfd_boolean ppc_stab_symbol;
    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;
@@ -3068,8 +3200,7 @@ ppc_comm (lcomm)
    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;
@@ -3104,9 +3235,7 @@ ppc_csect (ignore)
 /* 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);
@@ -3206,8 +3335,7 @@ ppc_change_csect (sym, align)
    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;
@@ -3231,8 +3359,7 @@ ppc_section (type)
    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;
@@ -3266,8 +3393,7 @@ ppc_named_section (ignore)
 /* 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;
@@ -3285,8 +3411,7 @@ ppc_extern (ignore)
 /* 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;
@@ -3308,8 +3433,7 @@ ppc_lglobl (ignore)
    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;
@@ -3344,8 +3468,7 @@ ppc_rename (ignore)
    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;
@@ -3471,8 +3594,7 @@ ppc_stabx (ignore)
    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;
@@ -3565,8 +3687,7 @@ ppc_function (ignore)
 static symbolS *saved_bi_sym = 0;
 
 static void
-ppc_bf (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bf (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
@@ -3601,8 +3722,7 @@ ppc_bf (ignore)
    most recent ".bf" symbol.  */
 
 static void
-ppc_ef (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ef (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
@@ -3626,8 +3746,7 @@ ppc_ef (ignore)
    is encountered.  */
 
 static void
-ppc_biei (ei)
-     int ei;
+ppc_biei (int ei)
 {
   static symbolS *last_biei;
 
@@ -3681,8 +3800,7 @@ ppc_biei (ei)
    .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;
@@ -3717,8 +3835,7 @@ ppc_bs (ignore)
 /* 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;
 
@@ -3742,8 +3859,7 @@ ppc_es (ignore)
    line number.  */
 
 static void
-ppc_bb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bb (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
@@ -3769,8 +3885,7 @@ ppc_bb (ignore)
    line number.  */
 
 static void
-ppc_eb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_eb (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *sym;
 
@@ -3794,8 +3909,7 @@ ppc_eb (ignore)
    specified name.  */
 
 static void
-ppc_bc (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_bc (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   int len;
@@ -3817,8 +3931,7 @@ ppc_bc (ignore)
 /* 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;
 
@@ -3837,8 +3950,7 @@ ppc_ec (ignore)
 /* 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);
@@ -3884,8 +3996,7 @@ ppc_toc (ignore)
    .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);
@@ -3893,8 +4004,7 @@ ppc_xcoff_cons (log_size)
 }
 
 static void
-ppc_vbyte (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+ppc_vbyte (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS exp;
   int byte_count;
@@ -3937,8 +4047,7 @@ ppc_vbyte (dummy)
    the first argument is simply ignored.  */
 
 static void
-ppc_tc (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_tc (int ignore ATTRIBUTE_UNUSED)
 {
 #ifdef OBJ_XCOFF
 
@@ -4000,6 +4109,7 @@ ppc_tc (ignore)
 
   /* 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 == '{'
@@ -4024,8 +4134,7 @@ ppc_tc (ignore)
 /* 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
@@ -4088,8 +4197,7 @@ ppc_machine (ignore)
 /* 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
   return symbol_get_tc (sym)->class == XMC_TC;
@@ -4110,8 +4218,7 @@ ppc_is_toc_sym (sym)
 
 /* 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;
@@ -4123,8 +4230,7 @@ ppc_set_current_section (new)
    warnings:  "No previous section"  */
 
 static void
-ppc_previous (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_previous (int ignore ATTRIBUTE_UNUSED)
 {
   symbolS *tmp;
 
@@ -4155,8 +4261,7 @@ ppc_previous (ignore)
    handling, debugging, etc.  */
 
 static void
-ppc_pdata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pdata (int ignore ATTRIBUTE_UNUSED)
 {
   if (pdata_section == 0)
     {
@@ -4190,8 +4295,7 @@ ppc_pdata (ignore)
    debugging, etc.  */
 
 static void
-ppc_ydata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ydata (int ignore ATTRIBUTE_UNUSED)
 {
   if (ydata_section == 0)
     {
@@ -4227,8 +4331,7 @@ ppc_ydata (ignore)
    function descriptors, etc.  */
 
 static void
-ppc_reldata (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_reldata (int ignore ATTRIBUTE_UNUSED)
 {
   if (reldata_section == 0)
     {
@@ -4258,8 +4361,7 @@ ppc_reldata (ignore)
              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)
     {
@@ -4285,8 +4387,7 @@ ppc_rdata (ignore)
    warnings:  None  */
 
 static void
-ppc_ualong (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_ualong (int ignore ATTRIBUTE_UNUSED)
 {
   /* Try for long.  */
   cons (4);
@@ -4300,8 +4401,7 @@ ppc_ualong (ignore)
    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;
@@ -4353,14 +4453,13 @@ ppc_znop (ignore)
    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;
-  register symbolS *symbolP;
+  symbolS *symbolP;
   offsetT align;
 
   name = input_line_pointer;
@@ -4483,8 +4582,7 @@ ppc_pe_comm (lcomm)
  */
 
 void
-ppc_pe_section (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_section (int ignore ATTRIBUTE_UNUSED)
 {
   /* Strip out the section name.  */
   char *section_name;
@@ -4572,7 +4670,7 @@ ppc_pe_section (ignore)
                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;
@@ -4616,7 +4714,7 @@ ppc_pe_section (ignore)
                  flags |= IMAGE_SCN_ALIGN_64BYTES;
                  align = 6;
                  break;
-
+#endif
                default:
                  as_bad (_("unknown section attribute '%c'"),
                          *input_line_pointer);
@@ -4642,12 +4740,10 @@ ppc_pe_section (ignore)
     }
 
   bfd_set_section_alignment (stdoutput, sec, align);
-
 }
 
 static void
-ppc_pe_function (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_function (int ignore ATTRIBUTE_UNUSED)
 {
   char *name;
   char endc;
@@ -4669,8 +4765,7 @@ ppc_pe_function (ignore)
 }
 
 static void
-ppc_pe_tocd (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+ppc_pe_tocd (int ignore ATTRIBUTE_UNUSED)
 {
   if (tocdata_section == 0)
     {
@@ -4695,8 +4790,7 @@ ppc_pe_tocd (ignore)
 /* 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;
 }
@@ -4711,8 +4805,7 @@ ppc_pe_fix_adjustable (fix)
    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;
 
@@ -4749,8 +4842,7 @@ ppc_canonicalize_symbol_name (name)
    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;
@@ -4838,8 +4930,7 @@ ppc_symbol_new_hook (sym)
    follows the csect symbol.  */
 
 void
-ppc_frob_label (sym)
-     symbolS *sym;
+ppc_frob_label (symbolS *sym)
 {
   if (ppc_current_csect != (symbolS *) NULL)
     {
@@ -4869,8 +4960,7 @@ static bfd_boolean ppc_saw_abs;
    symbol table.  */
 
 int
-ppc_frob_symbol (sym)
-     symbolS *sym;
+ppc_frob_symbol (symbolS *sym)
 {
   static symbolS *ppc_last_function;
   static symbolS *set_end;
@@ -5133,7 +5223,7 @@ ppc_frob_symbol (sym)
    absolute symbols.  */
 
 void
-ppc_adjust_symtab ()
+ppc_adjust_symtab (void)
 {
   symbolS *sym;
 
@@ -5179,8 +5269,7 @@ ppc_adjust_symtab ()
    turn.  */
 
 void
-ppc_frob_section (sec)
-     asection *sec;
+ppc_frob_section (asection *sec)
 {
   static bfd_vma vma = 0;
 
@@ -5191,71 +5280,17 @@ ppc_frob_section (sec)
 
 #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 *
-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
-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);
@@ -5266,21 +5301,22 @@ md_number_to_chars (buf, val, n)
 /* 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));
+#endif
 }
 
 /* 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;
@@ -5289,10 +5325,9 @@ md_estimate_size_before_relax (fragp, seg)
 /* 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 ();
 }
@@ -5300,8 +5335,7 @@ md_convert_frag (abfd, sec, fragp)
 /* 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;
 }
@@ -5312,9 +5346,7 @@ md_undefined_symbol (name)
    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;
 }
@@ -5327,8 +5359,7 @@ md_pcrel_from_section (fixp, sec)
    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);
@@ -5453,8 +5484,7 @@ ppc_fix_adjustable (fix)
    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
@@ -5479,8 +5509,7 @@ ppc_force_relocation (fix)
    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.  */
@@ -5505,8 +5534,7 @@ ppc_force_relocation (fix)
 }
 
 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
@@ -5520,6 +5548,47 @@ ppc_fix_adjustable (fix)
 }
 #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)
+       {
+         /* For power6, we want the last nop to be a group terminating
+            one, "ori 1,1,0".  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;
+           }
+
+         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
@@ -5530,10 +5599,7 @@ ppc_fix_adjustable (fix)
    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;
 
@@ -5590,7 +5656,7 @@ 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
-         && operand->bits == 16
+         && (operand->bitm & 0xfff0) == 0xfff0
          && operand->shift == 0
          && (operand->insert == NULL || ppc_obj64)
          && fixP->fx_addsy != NULL
@@ -5612,6 +5678,7 @@ md_apply_fix (fixP, valP, seg)
       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);
@@ -5628,11 +5695,11 @@ md_apply_fix (fixP, valP, seg)
         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->bits == 16
+         && operand->bitm == 0xfffc
          && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_B16;
@@ -5643,11 +5710,11 @@ md_apply_fix (fixP, valP, seg)
 #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->bits == 16
+              && operand->bitm == 0xfffc
               && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_BA16;
@@ -5659,7 +5726,7 @@ md_apply_fix (fixP, valP, seg)
        }
 #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))
@@ -6045,10 +6112,11 @@ md_apply_fix (fixP, valP, seg)
 #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 =
-       - 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
@@ -6057,9 +6125,7 @@ md_apply_fix (fixP, valP, seg)
 /* 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;
 
@@ -6082,7 +6148,7 @@ tc_gen_reloc (seg, fixp)
 }
 
 void
-ppc_cfi_frame_initial_instructions ()
+ppc_cfi_frame_initial_instructions (void)
 {
   cfi_add_CFA_def_cfa (1, 0);
 }
This page took 0.044346 seconds and 4 git commands to generate.