(obj_coff_section [BEF_ASSEMBLER]): Make 'r' mean readonly data.
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index b19e04d46b0c10a6f30544a51c974339d11e7548..5849654837a318f3b8a8b89323d4404219f9acc4 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
@@ -24,7 +24,7 @@
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
-
+#include "dw2gencfi.h"
 #include "opcode/ppc.h"
 
 #ifdef OBJ_ELF
@@ -47,9 +47,9 @@ static int set_target_endian = 0;
 /* Whether to use user friendly register names.  */
 #ifndef TARGET_REG_NAMES_P
 #ifdef TE_PE
-#define TARGET_REG_NAMES_P true
+#define TARGET_REG_NAMES_P TRUE
 #else
-#define TARGET_REG_NAMES_P false
+#define TARGET_REG_NAMES_P FALSE
 #endif
 #endif
 
@@ -68,14 +68,14 @@ static int set_target_endian = 0;
 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
 
 /* #higher(value) denotes bits 32 through 47 of the indicated value.  */
-#define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
+#define PPC_HIGHER(v) (((v) >> 16 >> 16) & 0xffff)
 
 /* #highera(value) denotes bits 32 through 47 of the indicated value,
    compensating for #lo() being treated as a signed number.  */
 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
 
 /* #highest(value) denotes bits 48 through 63 of the indicated value.  */
-#define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
+#define PPC_HIGHEST(v) (((v) >> 24 >> 24) & 0xffff)
 
 /* #highesta(value) denotes bits 48 through 63 of the indicated value,
    compensating for #lo being treated as a signed number.  */
@@ -83,9 +83,9 @@ static int set_target_endian = 0;
 
 #define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000)
 
-static boolean reg_names_p = TARGET_REG_NAMES_P;
+static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
 
-static boolean register_name PARAMS ((expressionS *));
+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,
@@ -111,7 +111,7 @@ 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 *));
+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));
@@ -182,6 +182,13 @@ const char EXP_CHARS[] = "eE";
 /* Characters which mean that a number is a floating point constant,
    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.  */
+const char ppc_symbol_chars[] = "+-";
+
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
+int ppc_cie_data_alignment;
 \f
 /* The target specific pseudo-ops which we support.  */
 
@@ -233,8 +240,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "rdata",   ppc_elf_rdata,  0 },
   { "rodata",  ppc_elf_rdata,  0 },
   { "lcomm",   ppc_elf_lcomm,  0 },
-  { "file",    (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
-  { "loc",     dwarf2_directive_loc, 0 },
 #endif
 
 #ifdef TE_PE
@@ -603,7 +608,7 @@ reg_name_search (regs, regcount, name)
  *      original state.
  */
 
-static boolean
+static bfd_boolean
 register_name (expressionP)
      expressionS *expressionP;
 {
@@ -618,7 +623,7 @@ register_name (expressionP)
     name = ++input_line_pointer;
 
   else if (!reg_names_p || !ISALPHA (name[0]))
-    return false;
+    return FALSE;
 
   c = get_symbol_end ();
   reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
@@ -635,12 +640,12 @@ register_name (expressionP)
       /* Make the rest nice.  */
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
-      return true;
+      return TRUE;
     }
 
   /* Reset the line as if we had not done anything.  */
   input_line_pointer = start;
-  return false;
+  return FALSE;
 }
 \f
 /* This function is called for each symbol seen in an expression.  It
@@ -648,7 +653,7 @@ register_name (expressionP)
    to use for condition codes.  */
 
 /* Whether to do the special parsing.  */
-static boolean cr_operand;
+static bfd_boolean cr_operand;
 
 /* Names to recognize in a condition code.  This table is sorted.  */
 static const struct pd_reg cr_names[] =
@@ -716,12 +721,12 @@ static flagword ppc_flags = 0;
 
 /* Whether this is Solaris or not.  */
 #ifdef TARGET_SOLARIS_COMMENT
-#define SOLARIS_P true
+#define SOLARIS_P TRUE
 #else
-#define SOLARIS_P false
+#define SOLARIS_P FALSE
 #endif
 
-static boolean msolaris = SOLARIS_P;
+static bfd_boolean msolaris = SOLARIS_P;
 #endif
 
 #ifdef OBJ_XCOFF
@@ -796,8 +801,8 @@ symbolS *GOT_symbol;                /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
 #define PPC_APUINFO_EFS                0x101
 #define PPC_APUINFO_BRLOCK     0x102
 
-/* 
- * We keep a list of APUinfo 
+/*
+ * We keep a list of APUinfo
  */
 unsigned long *ppc_apuinfo_list;
 unsigned int ppc_apuinfo_num;
@@ -867,7 +872,13 @@ md_parse_option (c, arg)
       /* a64 and a32 determine whether to use XCOFF64 or XCOFF32.  */
     case 'a':
       if (strcmp (arg, "64") == 0)
-       ppc_obj64 = 1;
+       {
+#ifdef BFD64
+         ppc_obj64 = 1;
+#else
+         as_fatal (_("%s unsupported"), "-a64");
+#endif
+       }
       else if (strcmp (arg, "32") == 0)
        ppc_obj64 = 0;
       else
@@ -885,8 +896,8 @@ md_parse_option (c, arg)
       /* -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;
+       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
@@ -896,28 +907,32 @@ md_parse_option (c, arg)
        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;
+              || 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;
+              || 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, "altivec") == 0)
-        {
-          if (ppc_cpu == 0)
-            ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
-          else
-            ppc_cpu |= PPC_OPCODE_ALTIVEC;
-        }
+       {
+         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;
-        }
+         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)
@@ -933,8 +948,8 @@ md_parse_option (c, arg)
        }
       else if (strcmp (arg, "ppc64bridge") == 0)
        {
-         ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
-                    | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64;
+         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)
@@ -944,13 +959,13 @@ md_parse_option (c, arg)
       /* -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;
+         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;
+         ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+                    | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
        }
       /* -mcom means assemble for the common intersection between Power
         and PowerPC.  At present, we just allow the union, rather
@@ -959,13 +974,13 @@ md_parse_option (c, arg)
        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 | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_ANY;
 
       else if (strcmp (arg, "regnames") == 0)
-       reg_names_p = true;
+       reg_names_p = TRUE;
 
       else if (strcmp (arg, "no-regnames") == 0)
-       reg_names_p = false;
+       reg_names_p = FALSE;
 
 #ifdef OBJ_ELF
       /* -mrelocatable/-mrelocatable-lib -- warn about initializations
@@ -1002,13 +1017,13 @@ md_parse_option (c, arg)
 
       else if (strcmp (arg, "solaris") == 0)
        {
-         msolaris = true;
+         msolaris = TRUE;
          ppc_comment_chars = ppc_solaris_comment_chars;
        }
 
       else if (strcmp (arg, "no-solaris") == 0)
        {
-         msolaris = false;
+         msolaris = FALSE;
          ppc_comment_chars = ppc_eabi_comment_chars;
        }
 #endif
@@ -1053,36 +1068,41 @@ md_show_usage (stream)
 {
   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\
 -mppc, -mppc32, -m603, -m604\n\
                        generate code for PowerPC 603/604\n\
--m403, -m405            generate code for PowerPC 403/405\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"));
+  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\
--maltivec              generate code for AltiVec\n\
 -mcom                  generate code Power/PowerPC common instructions\n\
--many                  generate code for any architecture (PWR/PWRX/PPC)\n\
--mregnames             Allow symbolic names for registers\n\
--mno-regnames          Do not allow symbolic names for registers\n"));
+-many                  generate code for any architecture (PWR/PWRX/PPC)\n"));
   fprintf (stream, _("\
+-maltivec              generate code for AltiVec\n\
 -me500, -me500x2       generate code for Motorola e500 core complex\n\
--mspe                  generate code for Motorola SPE instructions\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"));
 #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\
--mlittle, -mlittle-endian\n\
+-mlittle, -mlittle-endian, -l, -le\n\
                        generate code for a little endian machine\n\
--mbig, -mbig-endian    generate code for a big endian machine\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\
@@ -1098,22 +1118,24 @@ ppc_set_cpu ()
   const char *default_os  = TARGET_OS;
   const char *default_cpu = TARGET_CPU;
 
-  if (ppc_cpu == 0)
+  if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
     {
-      if (strncmp (default_os, "aix", 3) == 0
-         && default_os[3] >= '4' && default_os[3] <= '9')
-       ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
+      if (ppc_obj64)
+       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+      else if (strncmp (default_os, "aix", 3) == 0
+              && default_os[3] >= '4' && default_os[3] <= '9')
+       ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
       else if (strncmp (default_os, "aix3", 4) == 0)
-       ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
       else if (strcmp (default_cpu, "rs6000") == 0)
-       ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+       ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
       else if (strncmp (default_cpu, "powerpc", 7) == 0)
-        {
-          if (default_cpu[7] == '6' && default_cpu[8] == '4')
-            ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
-          else
-            ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
-        }
+       {
+         if (default_cpu[7] == '6' && default_cpu[8] == '4')
+           ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+         else
+           ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+       }
       else
        as_fatal (_("Unknown default cpu = %s, os = %s"),
                  default_cpu, default_os);
@@ -1147,7 +1169,12 @@ ppc_arch ()
 unsigned long
 ppc_mach ()
 {
-  return ppc_obj64 ? bfd_mach_ppc64 : bfd_mach_ppc;
+  if (ppc_obj64)
+    return bfd_mach_ppc64;
+  else if (ppc_arch () == bfd_arch_rs6000)
+    return bfd_mach_rs6k;
+  else
+    return bfd_mach_ppc;
 }
 
 extern char*
@@ -1184,10 +1211,12 @@ md_begin ()
   const struct powerpc_opcode *op_end;
   const struct powerpc_macro *macro;
   const struct powerpc_macro *macro_end;
-  boolean dup_insn = false;
+  bfd_boolean dup_insn = FALSE;
 
   ppc_set_cpu ();
 
+  ppc_cie_data_alignment = ppc_obj64 ? -8 : -4;
+
 #ifdef OBJ_ELF
   /* Set the ELF flags if desired.  */
   if (ppc_flags && !msolaris)
@@ -1207,6 +1236,14 @@ md_begin ()
              || ((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))))
@@ -1223,11 +1260,15 @@ md_begin ()
 
              as_bad (_("Internal assembler error for instruction %s"),
                      op->name);
-             dup_insn = true;
+             dup_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);
+
   /* Insert the macros into a hash table.  */
   ppc_macro_hash = hash_new ();
 
@@ -1242,7 +1283,7 @@ md_begin ()
          if (retval != (const char *) NULL)
            {
              as_bad (_("Internal assembler error for macro %s"), macro->name);
-             dup_insn = true;
+             dup_insn = TRUE;
            }
        }
     }
@@ -1302,19 +1343,19 @@ ppc_cleanup ()
     asection *seg = now_seg;
     subsegT subseg = now_subseg;
     asection *apuinfo_secp = (asection *) NULL;
-    int i;
+    unsigned int i;
 
     /* Create the .PPC.EMB.apuinfo section.  */
     apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
     bfd_set_section_flags (stdoutput,
                           apuinfo_secp,
-                          SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE);
+                          SEC_HAS_CONTENTS | SEC_READONLY);
 
     p = frag_more (4);
     md_number_to_chars (p, (valueT) 8, 4);
 
     p = frag_more (4);
-    md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4);
+    md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4);
 
     p = frag_more (4);
     md_number_to_chars (p, (valueT) 2, 4);
@@ -1324,8 +1365,8 @@ ppc_cleanup ()
 
     for (i = 0; i < ppc_apuinfo_num; i++)
       {
-        p = frag_more (4);
-        md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
+       p = frag_more (4);
+       md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
       }
 
     frag_align (2, 0, 0);
@@ -1438,60 +1479,94 @@ ppc_elf_suffix (str_p, exp_p)
 #define MAP(str,reloc) { str, sizeof (str)-1, reloc }
 
   static const struct map_bfd mapping[] = {
-    MAP ("l",          (int) BFD_RELOC_LO16),
-    MAP ("h",          (int) BFD_RELOC_HI16),
-    MAP ("ha",         (int) BFD_RELOC_HI16_S),
-    MAP ("brtaken",    (int) BFD_RELOC_PPC_B16_BRTAKEN),
-    MAP ("brntaken",   (int) BFD_RELOC_PPC_B16_BRNTAKEN),
-    MAP ("got",                (int) BFD_RELOC_16_GOTOFF),
-    MAP ("got@l",      (int) BFD_RELOC_LO16_GOTOFF),
-    MAP ("got@h",      (int) BFD_RELOC_HI16_GOTOFF),
-    MAP ("got@ha",     (int) BFD_RELOC_HI16_S_GOTOFF),
-    MAP ("fixup",      (int) BFD_RELOC_CTOR), /* warning with -mrelocatable */
-    MAP ("plt",                (int) BFD_RELOC_24_PLT_PCREL),
-    MAP ("pltrel24",   (int) BFD_RELOC_24_PLT_PCREL),
-    MAP ("copy",       (int) BFD_RELOC_PPC_COPY),
-    MAP ("globdat",    (int) BFD_RELOC_PPC_GLOB_DAT),
-    MAP ("local24pc",  (int) BFD_RELOC_PPC_LOCAL24PC),
-    MAP ("local",      (int) BFD_RELOC_PPC_LOCAL24PC),
-    MAP ("pltrel",     (int) BFD_RELOC_32_PLT_PCREL),
-    MAP ("plt@l",      (int) BFD_RELOC_LO16_PLTOFF),
-    MAP ("plt@h",      (int) BFD_RELOC_HI16_PLTOFF),
-    MAP ("plt@ha",     (int) BFD_RELOC_HI16_S_PLTOFF),
-    MAP ("sdarel",     (int) BFD_RELOC_GPREL16),
-    MAP ("sectoff",    (int) BFD_RELOC_16_BASEREL),
-    MAP ("sectoff@l",  (int) BFD_RELOC_LO16_BASEREL),
-    MAP ("sectoff@h",  (int) BFD_RELOC_HI16_BASEREL),
-    MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
-    MAP ("naddr",      (int) BFD_RELOC_PPC_EMB_NADDR32),
-    MAP ("naddr16",    (int) BFD_RELOC_PPC_EMB_NADDR16),
-    MAP ("naddr@l",    (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
-    MAP ("naddr@h",    (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
-    MAP ("naddr@ha",   (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
-    MAP ("sdai16",     (int) BFD_RELOC_PPC_EMB_SDAI16),
-    MAP ("sda2rel",    (int) BFD_RELOC_PPC_EMB_SDA2REL),
-    MAP ("sda2i16",    (int) BFD_RELOC_PPC_EMB_SDA2I16),
-    MAP ("sda21",      (int) BFD_RELOC_PPC_EMB_SDA21),
-    MAP ("mrkref",     (int) BFD_RELOC_PPC_EMB_MRKREF),
-    MAP ("relsect",    (int) BFD_RELOC_PPC_EMB_RELSEC16),
-    MAP ("relsect@l",  (int) BFD_RELOC_PPC_EMB_RELST_LO),
-    MAP ("relsect@h",  (int) BFD_RELOC_PPC_EMB_RELST_HI),
-    MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
-    MAP ("bitfld",     (int) BFD_RELOC_PPC_EMB_BIT_FLD),
-    MAP ("relsda",     (int) BFD_RELOC_PPC_EMB_RELSDA),
-    MAP ("xgot",       (int) BFD_RELOC_PPC_TOC16),
+    MAP ("l",                  (int) BFD_RELOC_LO16),
+    MAP ("h",                  (int) BFD_RELOC_HI16),
+    MAP ("ha",                 (int) BFD_RELOC_HI16_S),
+    MAP ("brtaken",            (int) BFD_RELOC_PPC_B16_BRTAKEN),
+    MAP ("brntaken",           (int) BFD_RELOC_PPC_B16_BRNTAKEN),
+    MAP ("got",                        (int) BFD_RELOC_16_GOTOFF),
+    MAP ("got@l",              (int) BFD_RELOC_LO16_GOTOFF),
+    MAP ("got@h",              (int) BFD_RELOC_HI16_GOTOFF),
+    MAP ("got@ha",             (int) BFD_RELOC_HI16_S_GOTOFF),
+    MAP ("fixup",              (int) BFD_RELOC_CTOR),
+    MAP ("plt",                        (int) BFD_RELOC_24_PLT_PCREL),
+    MAP ("pltrel24",           (int) BFD_RELOC_24_PLT_PCREL),
+    MAP ("copy",               (int) BFD_RELOC_PPC_COPY),
+    MAP ("globdat",            (int) BFD_RELOC_PPC_GLOB_DAT),
+    MAP ("local24pc",          (int) BFD_RELOC_PPC_LOCAL24PC),
+    MAP ("local",              (int) BFD_RELOC_PPC_LOCAL24PC),
+    MAP ("pltrel",             (int) BFD_RELOC_32_PLT_PCREL),
+    MAP ("plt@l",              (int) BFD_RELOC_LO16_PLTOFF),
+    MAP ("plt@h",              (int) BFD_RELOC_HI16_PLTOFF),
+    MAP ("plt@ha",             (int) BFD_RELOC_HI16_S_PLTOFF),
+    MAP ("sdarel",             (int) BFD_RELOC_GPREL16),
+    MAP ("sectoff",            (int) BFD_RELOC_16_BASEREL),
+    MAP ("sectoff@l",          (int) BFD_RELOC_LO16_BASEREL),
+    MAP ("sectoff@h",          (int) BFD_RELOC_HI16_BASEREL),
+    MAP ("sectoff@ha",         (int) BFD_RELOC_HI16_S_BASEREL),
+    MAP ("naddr",              (int) BFD_RELOC_PPC_EMB_NADDR32),
+    MAP ("naddr16",            (int) BFD_RELOC_PPC_EMB_NADDR16),
+    MAP ("naddr@l",            (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
+    MAP ("naddr@h",            (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
+    MAP ("naddr@ha",           (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
+    MAP ("sdai16",             (int) BFD_RELOC_PPC_EMB_SDAI16),
+    MAP ("sda2rel",            (int) BFD_RELOC_PPC_EMB_SDA2REL),
+    MAP ("sda2i16",            (int) BFD_RELOC_PPC_EMB_SDA2I16),
+    MAP ("sda21",              (int) BFD_RELOC_PPC_EMB_SDA21),
+    MAP ("mrkref",             (int) BFD_RELOC_PPC_EMB_MRKREF),
+    MAP ("relsect",            (int) BFD_RELOC_PPC_EMB_RELSEC16),
+    MAP ("relsect@l",          (int) BFD_RELOC_PPC_EMB_RELST_LO),
+    MAP ("relsect@h",          (int) BFD_RELOC_PPC_EMB_RELST_HI),
+    MAP ("relsect@ha",         (int) BFD_RELOC_PPC_EMB_RELST_HA),
+    MAP ("bitfld",             (int) BFD_RELOC_PPC_EMB_BIT_FLD),
+    MAP ("relsda",             (int) BFD_RELOC_PPC_EMB_RELSDA),
+    MAP ("xgot",               (int) BFD_RELOC_PPC_TOC16),
+    MAP ("tls",                        (int) BFD_RELOC_PPC_TLS),
+    MAP ("dtpmod",             (int) BFD_RELOC_PPC_DTPMOD),
+    MAP ("dtprel",             (int) BFD_RELOC_PPC_DTPREL),
+    MAP ("dtprel@l",           (int) BFD_RELOC_PPC_DTPREL16_LO),
+    MAP ("dtprel@h",           (int) BFD_RELOC_PPC_DTPREL16_HI),
+    MAP ("dtprel@ha",          (int) BFD_RELOC_PPC_DTPREL16_HA),
+    MAP ("tprel",              (int) BFD_RELOC_PPC_TPREL),
+    MAP ("tprel@l",            (int) BFD_RELOC_PPC_TPREL16_LO),
+    MAP ("tprel@h",            (int) BFD_RELOC_PPC_TPREL16_HI),
+    MAP ("tprel@ha",           (int) BFD_RELOC_PPC_TPREL16_HA),
+    MAP ("got@tlsgd",          (int) BFD_RELOC_PPC_GOT_TLSGD16),
+    MAP ("got@tlsgd@l",                (int) BFD_RELOC_PPC_GOT_TLSGD16_LO),
+    MAP ("got@tlsgd@h",                (int) BFD_RELOC_PPC_GOT_TLSGD16_HI),
+    MAP ("got@tlsgd@ha",       (int) BFD_RELOC_PPC_GOT_TLSGD16_HA),
+    MAP ("got@tlsld",          (int) BFD_RELOC_PPC_GOT_TLSLD16),
+    MAP ("got@tlsld@l",                (int) BFD_RELOC_PPC_GOT_TLSLD16_LO),
+    MAP ("got@tlsld@h",                (int) BFD_RELOC_PPC_GOT_TLSLD16_HI),
+    MAP ("got@tlsld@ha",       (int) BFD_RELOC_PPC_GOT_TLSLD16_HA),
+    MAP ("got@dtprel",         (int) BFD_RELOC_PPC_GOT_DTPREL16),
+    MAP ("got@dtprel@l",       (int) BFD_RELOC_PPC_GOT_DTPREL16_LO),
+    MAP ("got@dtprel@h",       (int) BFD_RELOC_PPC_GOT_DTPREL16_HI),
+    MAP ("got@dtprel@ha",      (int) BFD_RELOC_PPC_GOT_DTPREL16_HA),
+    MAP ("got@tprel",          (int) BFD_RELOC_PPC_GOT_TPREL16),
+    MAP ("got@tprel@l",                (int) BFD_RELOC_PPC_GOT_TPREL16_LO),
+    MAP ("got@tprel@h",                (int) BFD_RELOC_PPC_GOT_TPREL16_HI),
+    MAP ("got@tprel@ha",       (int) BFD_RELOC_PPC_GOT_TPREL16_HA),
     /* The following are only valid for ppc64.  Negative values are
        used instead of a flag.  */
-    MAP ("higher",     - (int) BFD_RELOC_PPC64_HIGHER),
-    MAP ("highera",    - (int) BFD_RELOC_PPC64_HIGHER_S),
-    MAP ("highest",    - (int) BFD_RELOC_PPC64_HIGHEST),
-    MAP ("highesta",   - (int) BFD_RELOC_PPC64_HIGHEST_S),
-    MAP ("tocbase",    - (int) BFD_RELOC_PPC64_TOC),
-    MAP ("toc",                - (int) BFD_RELOC_PPC_TOC16),
-    MAP ("toc@l",      - (int) BFD_RELOC_PPC64_TOC16_LO),
-    MAP ("toc@h",      - (int) BFD_RELOC_PPC64_TOC16_HI),
-    MAP ("toc@ha",     - (int) BFD_RELOC_PPC64_TOC16_HA),
-    { (char *) 0, 0,   (int) BFD_RELOC_UNUSED }
+    MAP ("higher",             - (int) BFD_RELOC_PPC64_HIGHER),
+    MAP ("highera",            - (int) BFD_RELOC_PPC64_HIGHER_S),
+    MAP ("highest",            - (int) BFD_RELOC_PPC64_HIGHEST),
+    MAP ("highesta",           - (int) BFD_RELOC_PPC64_HIGHEST_S),
+    MAP ("tocbase",            - (int) BFD_RELOC_PPC64_TOC),
+    MAP ("toc",                        - (int) BFD_RELOC_PPC_TOC16),
+    MAP ("toc@l",              - (int) BFD_RELOC_PPC64_TOC16_LO),
+    MAP ("toc@h",              - (int) BFD_RELOC_PPC64_TOC16_HI),
+    MAP ("toc@ha",             - (int) BFD_RELOC_PPC64_TOC16_HA),
+    MAP ("dtprel@higher",      - (int) BFD_RELOC_PPC64_DTPREL16_HIGHER),
+    MAP ("dtprel@highera",     - (int) BFD_RELOC_PPC64_DTPREL16_HIGHERA),
+    MAP ("dtprel@highest",     - (int) BFD_RELOC_PPC64_DTPREL16_HIGHEST),
+    MAP ("dtprel@highesta",    - (int) BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
+    MAP ("tprel@higher",       - (int) BFD_RELOC_PPC64_TPREL16_HIGHER),
+    MAP ("tprel@highera",      - (int) BFD_RELOC_PPC64_TPREL16_HIGHERA),
+    MAP ("tprel@highest",      - (int) BFD_RELOC_PPC64_TPREL16_HIGHEST),
+    MAP ("tprel@highesta",     - (int) BFD_RELOC_PPC64_TPREL16_HIGHESTA),
+    { (char *) 0, 0,           (int) BFD_RELOC_UNUSED }
   };
 
   if (*str++ != '@')
@@ -1523,12 +1598,13 @@ ppc_elf_suffix (str_p, exp_p)
            reloc = -reloc;
          }
 
-       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)
+         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"));
 
        /* Now check for identifier@suffix+constant.  */
        if (*str == '-' || *str == '+')
@@ -1550,11 +1626,11 @@ ppc_elf_suffix (str_p, exp_p)
        *str_p = str;
 
        if (reloc == (int) BFD_RELOC_PPC64_TOC
-           && exp_p->X_op == O_symbol)
+           && exp_p->X_op == O_symbol
+           && strcmp (S_GET_NAME (exp_p->X_add_symbol), ".TOC.") == 0)
          {
-           /* This reloc type ignores the symbol.  Change the symbol
-              so that the dummy .TOC. symbol can be omitted from the
-              object file.  */
+           /* Change the symbol so that the dummy .TOC. symbol can be
+              omitted from the object file.  */
            exp_p->X_add_symbol = &abs_symbol;
          }
 
@@ -1947,7 +2023,7 @@ ppc_apuinfo_section_add (apu, version)
   for (i = 0; i < ppc_apuinfo_num; i++)
     if (ppc_apuinfo_list[i] == APUID (apu, version))
       return;
-    
+
   if (ppc_apuinfo_num == ppc_apuinfo_num_alloc)
     {
       if (ppc_apuinfo_num_alloc == 0)
@@ -2048,6 +2124,8 @@ md_assemble (str)
       if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
        {
          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.  */
@@ -2064,10 +2142,16 @@ md_assemble (str)
                }
            }
 
+         /* Compute the number of expected operands.
+            Do not count fake operands.  */
+         for (num_operands_expected = 0, i = 0; opcode->operands[i]; i ++)
+           if ((powerpc_operands [opcode->operands[i]].flags & PPC_OPERAND_FAKE) == 0)
+             ++ num_operands_expected;
+
          /* If there are fewer operands in the line then are called
             for by the instruction, we want to skip the optional
             operand.  */
-         if (opcount < strlen (opcode->operands))
+         if (opcount < num_operands_expected)
            skip_optional = 1;
 
          break;
@@ -2243,9 +2327,9 @@ md_assemble (str)
          if (! register_name (&ex))
            {
              if ((operand->flags & PPC_OPERAND_CR) != 0)
-               cr_operand = true;
+               cr_operand = TRUE;
              expression (&ex);
-             cr_operand = false;
+             cr_operand = FALSE;
            }
        }
 
@@ -2333,6 +2417,25 @@ md_assemble (str)
 #ifdef OBJ_ELF
       else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
        {
+         /* Some TLS tweaks.  */
+         switch (reloc)
+           {
+           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;
+           }
+
          /* For the absolute forms of branches, convert the PC
             relative form back into the absolute.  */
          if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
@@ -2357,7 +2460,7 @@ md_assemble (str)
            }
 
          if (ppc_obj64
-             && (operand->flags & PPC_OPERAND_DS) != 0)
+             && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
            {
              switch (reloc)
                {
@@ -2394,6 +2497,23 @@ md_assemble (str)
                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;
@@ -2462,19 +2582,19 @@ md_assemble (str)
     {
       /* These are all version "1".  */
       if (opcode->flags & PPC_OPCODE_SPE)
-        ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
       if (opcode->flags & PPC_OPCODE_ISEL)
-        ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
       if (opcode->flags & PPC_OPCODE_EFS)
-        ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
       if (opcode->flags & PPC_OPCODE_BRLOCK)
-        ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
       if (opcode->flags & PPC_OPCODE_PMR)
-        ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
       if (opcode->flags & PPC_OPCODE_CACHELCK)
-        ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
       if (opcode->flags & PPC_OPCODE_RFMCI)
-        ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
+       ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
     }
 #endif
 
@@ -2645,7 +2765,7 @@ ppc_section_letter (letter, ptr_msg)
     return SHF_EXCLUDE;
 
   *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
-  return 0;
+  return -1;
 }
 
 int
@@ -2730,7 +2850,7 @@ ppc_byte (ignore)
 
 /* This is set if we are creating a .stabx symbol, since we don't want
    to handle symbol suffixes for such symbols.  */
-static boolean ppc_stab_symbol;
+static bfd_boolean ppc_stab_symbol;
 
 /* The .comm and .lcomm pseudo-ops for XCOFF.  XCOFF puts common
    symbols in the .bss segment as though they were local common
@@ -2899,6 +3019,7 @@ ppc_csect (ignore)
   char *name;
   char endc;
   symbolS *sym;
+  offsetT align;
 
   name = input_line_pointer;
   endc = get_symbol_end ();
@@ -2913,22 +3034,24 @@ ppc_csect (ignore)
       symbol_get_tc (sym)->class = XMC_PR;
     }
 
-  ppc_change_csect (sym);
-
+  align = 2;
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
-      symbol_get_tc (sym)->align = get_absolute_expression ();
+      align = get_absolute_expression ();
     }
 
+  ppc_change_csect (sym, align);
+
   demand_empty_rest_of_line ();
 }
 
 /* Change to a different csect.  */
 
 static void
-ppc_change_csect (sym)
+ppc_change_csect (sym, align)
      symbolS *sym;
+     offsetT align;
 {
   if (S_IS_DEFINED (sym))
     subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
@@ -2938,11 +3061,14 @@ ppc_change_csect (sym)
       int after_toc;
       int hold_chunksize;
       symbolS *list;
+      int is_code;
+      segT sec;
 
       /* This is a new csect.  We need to look at the symbol class to
         figure out whether it should go in the text section or the
         data section.  */
       after_toc = 0;
+      is_code = 0;
       switch (symbol_get_tc (sym)->class)
        {
        case XMC_PR:
@@ -2957,6 +3083,7 @@ ppc_change_csect (sym)
          symbol_get_tc (sym)->subseg = ppc_text_subsegment;
          ++ppc_text_subsegment;
          list_ptr = &ppc_text_csects;
+         is_code = 1;
          break;
        case XMC_RW:
        case XMC_TC0:
@@ -2984,18 +3111,24 @@ ppc_change_csect (sym)
       hold_chunksize = chunksize;
       chunksize = 64;
 
-      subseg_new (segment_name (S_GET_SEGMENT (sym)),
-                 symbol_get_tc (sym)->subseg);
+      sec = subseg_new (segment_name (S_GET_SEGMENT (sym)),
+                       symbol_get_tc (sym)->subseg);
 
       chunksize = hold_chunksize;
 
       if (after_toc)
        ppc_after_toc_frag = frag_now;
 
+      record_alignment (sec, align);
+      if (is_code)
+       frag_align_code (align, 0);
+      else
+       frag_align (align, 0, 0);
+
       symbol_set_frag (sym, frag_now);
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
 
-      symbol_get_tc (sym)->align = 2;
+      symbol_get_tc (sym)->align = align;
       symbol_get_tc (sym)->output = 1;
       symbol_get_tc (sym)->within = sym;
 
@@ -3033,7 +3166,7 @@ ppc_section (type)
 
   sym = symbol_find_or_make (name);
 
-  ppc_change_csect (sym);
+  ppc_change_csect (sym, 2);
 
   demand_empty_rest_of_line ();
 }
@@ -3070,7 +3203,7 @@ ppc_named_section (ignore)
 
   sym = symbol_find_or_make (real_name);
 
-  ppc_change_csect (sym);
+  ppc_change_csect (sym, 2);
 
   demand_empty_rest_of_line ();
 }
@@ -3173,9 +3306,9 @@ ppc_stabx (ignore)
     }
   ++input_line_pointer;
 
-  ppc_stab_symbol = true;
+  ppc_stab_symbol = TRUE;
   sym = symbol_make (name);
-  ppc_stab_symbol = false;
+  ppc_stab_symbol = FALSE;
 
   symbol_get_tc (sym)->real_name = name;
 
@@ -3741,7 +3874,7 @@ ppc_vbyte (dummy)
    give to this location in the toc; this will be a symbol with class
    TC.  The rest of the arguments are N-byte values to actually put at
    this location in the TOC; often there is just one more argument, a
-   relocateable symbol reference.  The size of the value to store
+   relocatable symbol reference.  The size of the value to store
    depends on target word size.  A 32-bit target uses 4-byte values, a
    64-bit target uses 8-byte values.
 
@@ -3904,11 +4037,11 @@ ppc_previous (ignore)
 
 /* pseudo-op: .pdata
    behaviour: predefined read only data section
-              double word aligned
+             double word aligned
    errors:    None
    warnings:  None
    initial:   .section .pdata "adr3"
-              a - don't know -- maybe a misprint
+             a - don't know -- maybe a misprint
              d - initialized data
              r - readable
              3 - double word aligned (that would be 4 byte boundary)
@@ -3940,11 +4073,11 @@ ppc_pdata (ignore)
 
 /* pseudo-op: .ydata
    behaviour: predefined read only data section
-              double word aligned
+             double word aligned
    errors:    None
    warnings:  None
    initial:   .section .ydata "drw3"
-              a - don't know -- maybe a misprint
+             a - don't know -- maybe a misprint
              d - initialized data
              r - readable
              3 - double word aligned (that would be 4 byte boundary)
@@ -3974,7 +4107,7 @@ ppc_ydata (ignore)
 
 /* pseudo-op: .reldata
    behaviour: predefined read write data section
-              double word aligned (4-byte)
+             double word aligned (4-byte)
              FIXME: relocation is applied to it
              FIXME: what's the difference between this and .data?
    errors:    None
@@ -4012,7 +4145,7 @@ ppc_reldata (ignore)
 
 /* pseudo-op: .rdata
    behaviour: predefined read only data section
-              double word aligned
+             double word aligned
    errors:    None
    warnings:  None
    initial:   .section .rdata "dr3"
@@ -4042,7 +4175,7 @@ ppc_rdata (ignore)
 
 /* pseudo-op: .ualong
    behaviour: much like .int, with the exception that no alignment is
-              performed.
+             performed.
              FIXME: test the alignment statement
    errors:    None
    warnings:  None  */
@@ -4057,7 +4190,7 @@ ppc_ualong (ignore)
 
 /* pseudo-op: .znop  <symbol name>
    behaviour: Issue a nop instruction
-              Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
+             Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
              the supplied symbol name.
    errors:    None
    warnings:  Missing symbol name  */
@@ -4619,7 +4752,7 @@ ppc_frob_label (sym)
    seen.  It tells ppc_adjust_symtab whether it needs to look through
    the symbols.  */
 
-static boolean ppc_saw_abs;
+static bfd_boolean ppc_saw_abs;
 
 /* Change the name of a symbol just before writing it out.  Set the
    real name if the .rename pseudo-op was used.  Otherwise, remove any
@@ -4642,6 +4775,10 @@ ppc_frob_symbol (sym)
              && S_GET_STORAGE_CLASS (sym) != C_FILE)))
     return 1;
 
+  /* This one will disappear anyway.  Don't make a csect sym for it.  */
+  if (sym == abs_section_sym)
+    return 1;
+
   if (symbol_get_tc (sym)->real_name != (char *) NULL)
     S_SET_NAME (sym, symbol_get_tc (sym)->real_name);
   else
@@ -4758,7 +4895,7 @@ ppc_frob_symbol (sym)
        {
          /* This is an absolute symbol.  The csect will be created by
             ppc_adjust_symtab.  */
-         ppc_saw_abs = true;
+         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;
@@ -4854,10 +4991,10 @@ ppc_frob_symbol (sym)
       /* We want the value to be the symbol index of the referenced
         csect symbol.  BFD will do that for us if we set the right
         flags.  */
-      S_SET_VALUE (sym,
-                  ((valueT)
-                   coffsymbol (symbol_get_bfdsym
-                               (symbol_get_tc (sym)->within))->native));
+      asymbol *bsym = symbol_get_bfdsym (symbol_get_tc (sym)->within);
+      combined_entry_type *c = coffsymbol (bsym)->native;
+
+      S_SET_VALUE (sym, (valueT) (size_t) c);
       coffsymbol (symbol_get_bfdsym (sym))->native->fix_value = 1;
     }
   else if (S_GET_STORAGE_CLASS (sym) == C_STSYM)
@@ -4926,7 +5063,7 @@ ppc_adjust_symtab ()
       coffsymbol (symbol_get_bfdsym (sym))->native[i].fix_scnlen = 1;
     }
 
-  ppc_saw_abs = false;
+  ppc_saw_abs = FALSE;
 }
 
 /* Set the VMA for a section.  This is called on all the sections in
@@ -4936,8 +5073,9 @@ void
 ppc_frob_section (sec)
      asection *sec;
 {
-  static bfd_size_type vma = 0;
+  static bfd_vma vma = 0;
 
+  vma = md_section_align (sec, vma);
   bfd_set_section_vma (stdoutput, sec, vma);
   vma += bfd_section_size (stdoutput, sec);
 }
@@ -5083,14 +5221,16 @@ int
 ppc_fix_adjustable (fix)
      fixS *fix;
 {
-  valueT val;
+  valueT val = resolve_symbol_value (fix->fx_addsy);
+  segT symseg = S_GET_SEGMENT (fix->fx_addsy);
+  TC_SYMFIELD_TYPE *tc;
+
+  if (symseg == absolute_section)
+    return 0;
 
-  resolve_symbol_value (fix->fx_addsy);
-  val = S_GET_VALUE (fix->fx_addsy);
   if (ppc_toc_csect != (symbolS *) NULL
-      && fix->fx_addsy != (symbolS *) NULL
       && fix->fx_addsy != ppc_toc_csect
-      && S_GET_SEGMENT (fix->fx_addsy) == data_section
+      && symseg == data_section
       && val >= ppc_toc_frag->fr_address
       && (ppc_after_toc_frag == (fragS *) NULL
          || val < ppc_after_toc_frag->fr_address))
@@ -5101,12 +5241,13 @@ ppc_fix_adjustable (fix)
           sy != (symbolS *) NULL;
           sy = symbol_next (sy))
        {
-         if (symbol_get_tc (sy)->class == XMC_TC0)
+         TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy);
+
+         if (sy_tc->class == XMC_TC0)
            continue;
-         if (symbol_get_tc (sy)->class != XMC_TC)
+         if (sy_tc->class != XMC_TC)
            break;
-         resolve_symbol_value (sy);
-         if (val == S_GET_VALUE (sy))
+         if (val == resolve_symbol_value (sy))
            {
              fix->fx_addsy = sy;
              fix->fx_addnumber = val - ppc_toc_frag->fr_address;
@@ -5119,23 +5260,24 @@ ppc_fix_adjustable (fix)
     }
 
   /* Possibly adjust the reloc to be against the csect.  */
-  if (fix->fx_addsy != (symbolS *) NULL
-      && symbol_get_tc (fix->fx_addsy)->subseg == 0
-      && symbol_get_tc (fix->fx_addsy)->class != XMC_TC0
-      && symbol_get_tc (fix->fx_addsy)->class != XMC_TC
-      && S_GET_SEGMENT (fix->fx_addsy) != bss_section
+  tc = symbol_get_tc (fix->fx_addsy);
+  if (tc->subseg == 0
+      && tc->class != XMC_TC0
+      && tc->class != XMC_TC
+      && symseg != bss_section
       /* Don't adjust if this is a reloc in the toc section.  */
-      && (S_GET_SEGMENT (fix->fx_addsy) != data_section
+      && (symseg != data_section
          || ppc_toc_csect == NULL
          || val < ppc_toc_frag->fr_address
          || (ppc_after_toc_frag != NULL
              && val >= ppc_after_toc_frag->fr_address)))
     {
       symbolS *csect;
+      symbolS *next_csect;
 
-      if (S_GET_SEGMENT (fix->fx_addsy) == text_section)
+      if (symseg == text_section)
        csect = ppc_text_csects;
-      else if (S_GET_SEGMENT (fix->fx_addsy) == data_section)
+      else if (symseg == data_section)
        csect = ppc_data_csects;
       else
        abort ();
@@ -5145,16 +5287,15 @@ ppc_fix_adjustable (fix)
 
       if (csect != (symbolS *) NULL)
        {
-         while (symbol_get_tc (csect)->next != (symbolS *) NULL
-                && (symbol_get_frag (symbol_get_tc (csect)->next)->fr_address
-                    <= val))
+         while ((next_csect = symbol_get_tc (csect)->next) != (symbolS *) NULL
+                && (symbol_get_frag (next_csect)->fr_address <= val))
            {
              /* If the csect address equals the symbol value, then we
                 have to look through the full symbol table to see
                 whether this is the csect we want.  Note that we will
                 only get here if the csect has zero length.  */
-             if ((symbol_get_frag (csect)->fr_address == val)
-                 && S_GET_VALUE (csect) == S_GET_VALUE (fix->fx_addsy))
+             if (symbol_get_frag (csect)->fr_address == val
+                 && S_GET_VALUE (csect) == val)
                {
                  symbolS *scan;
 
@@ -5174,26 +5315,24 @@ ppc_fix_adjustable (fix)
                    break;
                }
 
-             csect = symbol_get_tc (csect)->next;
+             csect = next_csect;
            }
 
-         fix->fx_offset += (S_GET_VALUE (fix->fx_addsy)
-                            - symbol_get_frag (csect)->fr_address);
+         fix->fx_offset += val - symbol_get_frag (csect)->fr_address;
          fix->fx_addsy = csect;
        }
+      return 0;
     }
 
   /* Adjust a reloc against a .lcomm symbol to be against the base
      .lcomm.  */
-  if (fix->fx_addsy != (symbolS *) NULL
-      && S_GET_SEGMENT (fix->fx_addsy) == bss_section
+  if (symseg == bss_section
       && ! S_IS_EXTERNAL (fix->fx_addsy))
     {
-      resolve_symbol_value (symbol_get_frag (fix->fx_addsy)->fr_symbol);
-      fix->fx_offset +=
-       (S_GET_VALUE (fix->fx_addsy)
-        - S_GET_VALUE (symbol_get_frag (fix->fx_addsy)->fr_symbol));
-      fix->fx_addsy = symbol_get_frag (fix->fx_addsy)->fr_symbol;
+      symbolS *sy = symbol_get_frag (fix->fx_addsy)->fr_symbol;
+
+      fix->fx_offset += val - resolve_symbol_value (sy);
+      fix->fx_addsy = sy;
     }
 
   return 0;
@@ -5221,12 +5360,40 @@ ppc_force_relocation (fix)
                  <= fix->fx_frag->fr_address))))
     return 1;
 
-  return 0;
+  return generic_force_reloc (fix);
 }
 
 #endif /* OBJ_XCOFF */
 
 #ifdef OBJ_ELF
+/* If this function returns non-zero, it guarantees that a relocation
+   will be emitted for a fixup.  */
+
+int
+ppc_force_relocation (fix)
+     fixS *fix;
+{
+  /* Branch prediction relocations must force a relocation, as must
+     the vtable description relocs.  */
+  switch (fix->fx_r_type)
+    {
+    case BFD_RELOC_PPC_B16_BRTAKEN:
+    case BFD_RELOC_PPC_B16_BRNTAKEN:
+    case BFD_RELOC_PPC_BA16_BRTAKEN:
+    case BFD_RELOC_PPC_BA16_BRNTAKEN:
+    case BFD_RELOC_PPC64_TOC:
+      return 1;
+    default:
+      break;
+    }
+
+  if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
+      && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
+    return 1;
+
+  return generic_force_reloc (fix);
+}
+
 int
 ppc_fix_adjustable (fix)
      fixS *fix;
@@ -5238,8 +5405,8 @@ ppc_fix_adjustable (fix)
          && fix->fx_r_type != BFD_RELOC_GPREL16
          && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
          && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
-         && ! S_IS_EXTERNAL (fix->fx_addsy)
-         && ! S_IS_WEAK (fix->fx_addsy)
+         && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
+              && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
          && (fix->fx_pcrel
              || (fix->fx_subsy != NULL
                  && (S_GET_SEGMENT (fix->fx_subsy)
@@ -5268,32 +5435,22 @@ md_apply_fix3 (fixP, valP, seg)
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL)
     {
-      /* `*valuep' may contain the value of the symbol on which the reloc
-        will be based; we have to remove it.  */
-      if (symbol_used_in_reloc_p (fixP->fx_addsy)
-         && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
-         && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
-         && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
-       value -= S_GET_VALUE (fixP->fx_addsy);
-
-      /* FIXME: Why '+'?  Better yet, what exactly is '*valuep'
-        supposed to be?  I think this is related to various similar
-        FIXMEs in tc-i386.c and tc-sparc.c.  */
+      /* Hack around bfd_install_relocation brain damage.  */
       if (fixP->fx_pcrel)
        value += fixP->fx_frag->fr_address + fixP->fx_where;
     }
   else
     fixP->fx_done = 1;
 #else
-  /* FIXME FIXME FIXME: The value we are passed in *valuep includes
+  /* FIXME FIXME FIXME: The value we are passed in *valP includes
      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
      doing this relocation the code in write.c is going to call
      bfd_install_relocation, which is also going to use the symbol
      value.  That means that if the reloc is fully resolved we want to
-     use *valuep since bfd_install_relocation is not being used.
+     use *valP since bfd_install_relocation is not being used.
      However, if the reloc is not fully resolved we do not want to use
-     *valuep, and must use fx_offset instead.  However, if the reloc
-     is PC relative, we do want to use *valuep since it includes the
+     *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.  */
   if (fixP->fx_addsy == (symbolS *) NULL)
     fixP->fx_done = 1;
@@ -5302,21 +5459,14 @@ md_apply_fix3 (fixP, valP, seg)
     ;
 
   else
+    value = fixP->fx_offset;
+#endif
+
+  if (fixP->fx_subsy != (symbolS *) NULL)
     {
-      value = fixP->fx_offset;
-      if (fixP->fx_subsy != (symbolS *) NULL)
-       {
-         if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
-           value -= S_GET_VALUE (fixP->fx_subsy);
-         else
-           {
-             /* We can't actually support subtracting a symbol.  */
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("expression too complex"));
-           }
-       }
+      /* We can't actually support subtracting a symbol.  */
+      as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
     }
-#endif
 
   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
@@ -5405,15 +5555,26 @@ md_apply_fix3 (fixP, valP, seg)
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
               && operand->bits == 16
-              && operand->shift == 0
-              && ppc_is_toc_sym (fixP->fx_addsy))
+              && operand->shift == 0)
        {
-         fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
+         if (ppc_is_toc_sym (fixP->fx_addsy))
+           {
+             fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
 #ifdef OBJ_ELF
-         if (ppc_obj64
-             && (operand->flags & PPC_OPERAND_DS) != 0)
-           fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
+             if (ppc_obj64
+                 && (operand->flags & PPC_OPERAND_DS) != 0)
+               fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
+#endif
+           }
+         else
+           {
+             fixP->fx_r_type = BFD_RELOC_16;
+#ifdef OBJ_ELF
+             if (ppc_obj64
+                 && (operand->flags & PPC_OPERAND_DS) != 0)
+               fixP->fx_r_type = BFD_RELOC_PPC64_ADDR16_DS;
 #endif
+           }
          fixP->fx_size = 2;
          if (target_big_endian)
            fixP->fx_where += 2;
@@ -5580,19 +5741,72 @@ md_apply_fix3 (fixP, valP, seg)
            abort ();
          {
            unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
-           unsigned long val;
+           unsigned long val, mask;
 
            if (target_big_endian)
-             val = bfd_getb16 (where);
+             val = bfd_getb32 (where - 2);
            else
-             val = bfd_getl16 (where);
-           val |= (value & 0xfffc);
+             val = bfd_getl32 (where);
+           mask = 0xfffc;
+           /* lq insns reserve the four lsbs.  */
+           if ((ppc_cpu & PPC_OPCODE_POWER4) != 0
+               && (val & (0x3f << 26)) == (56u << 26))
+             mask = 0xfff0;
+           val |= value & mask;
            if (target_big_endian)
              bfd_putb16 ((bfd_vma) val, where);
            else
              bfd_putl16 ((bfd_vma) val, where);
          }
          break;
+
+       case BFD_RELOC_PPC_B16_BRTAKEN:
+       case BFD_RELOC_PPC_B16_BRNTAKEN:
+       case BFD_RELOC_PPC_BA16_BRTAKEN:
+       case BFD_RELOC_PPC_BA16_BRNTAKEN:
+         break;
+
+       case BFD_RELOC_PPC_TLS:
+       case BFD_RELOC_PPC_DTPMOD:
+       case BFD_RELOC_PPC_TPREL16:
+       case BFD_RELOC_PPC_TPREL16_LO:
+       case BFD_RELOC_PPC_TPREL16_HI:
+       case BFD_RELOC_PPC_TPREL16_HA:
+       case BFD_RELOC_PPC_TPREL:
+       case BFD_RELOC_PPC_DTPREL16:
+       case BFD_RELOC_PPC_DTPREL16_LO:
+       case BFD_RELOC_PPC_DTPREL16_HI:
+       case BFD_RELOC_PPC_DTPREL16_HA:
+       case BFD_RELOC_PPC_DTPREL:
+       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_TPREL16:
+       case BFD_RELOC_PPC_GOT_TPREL16_LO:
+       case BFD_RELOC_PPC_GOT_TPREL16_HI:
+       case BFD_RELOC_PPC_GOT_TPREL16_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_PPC64_TPREL16_DS:
+       case BFD_RELOC_PPC64_TPREL16_LO_DS:
+       case BFD_RELOC_PPC64_TPREL16_HIGHER:
+       case BFD_RELOC_PPC64_TPREL16_HIGHERA:
+       case BFD_RELOC_PPC64_TPREL16_HIGHEST:
+       case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+       case BFD_RELOC_PPC64_DTPREL16_DS:
+       case BFD_RELOC_PPC64_DTPREL16_LO_DS:
+       case BFD_RELOC_PPC64_DTPREL16_HIGHER:
+       case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
+       case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
+       case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+         break;
 #endif
          /* Because SDA21 modifies the register field, the size is set to 4
             bytes, rather than 2, so offset it here appropriately.  */
@@ -5718,3 +5932,49 @@ tc_gen_reloc (seg, fixp)
 
   return reloc;
 }
+
+void
+ppc_cfi_frame_initial_instructions ()
+{
+  cfi_add_CFA_def_cfa (1, 0);
+}
+
+int
+tc_ppc_regname_to_dw2regnum (const char *regname)
+{
+  unsigned int regnum = -1;
+  unsigned int i;
+  const char *p;
+  char *q;
+  static struct { char *name; int dw2regnum; } regnames[] =
+    {
+      { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
+      { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },
+      { "cc", 68 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 },
+      { "spe_acc", 111 }, { "spefscr", 112 }
+    };
+
+  for (i = 0; i < ARRAY_SIZE (regnames); ++i)
+    if (strcmp (regnames[i].name, regname) == 0)
+      return regnames[i].dw2regnum;
+
+  if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
+    {
+      p = regname + 1 + (regname[1] == '.');
+      regnum = strtoul (p, &q, 10);
+      if (p == q || *q || regnum >= 32)
+       return -1;
+      if (regname[0] == 'f')
+        regnum += 32;
+      else if (regname[0] == 'v')
+        regnum += 77;
+    }
+  else if (regname[0] == 'c' && regname[1] == 'r')
+    {
+      p = regname + 2 + (regname[2] == '.');
+      if (p[0] < '0' || p[0] > '7' || p[1])
+        return -1;
+      regnum = p[0] - '0' + 68;
+    }
+  return regnum;
+}
This page took 0.044863 seconds and 4 git commands to generate.