Use CXXCOMPILE in gold/testsuite/Makefile for c++ testcases
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index d7090102a29bbc0e7d5b26d1eef0571a7f32d8e3..aa989e7d1c2cad6851f7da6e35f7d8f7eb600f07 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
-   Copyright (C) 1994-2019 Free Software Foundation, Inc.
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
@@ -346,6 +346,16 @@ struct pd_reg
 
 static const struct pd_reg pre_defined_registers[] =
 {
+  /* VSX accumulators.  */
+  { "a0", 0, PPC_OPERAND_ACC },
+  { "a1", 1, PPC_OPERAND_ACC },
+  { "a2", 2, PPC_OPERAND_ACC },
+  { "a3", 3, PPC_OPERAND_ACC },
+  { "a4", 4, PPC_OPERAND_ACC },
+  { "a5", 5, PPC_OPERAND_ACC },
+  { "a6", 6, PPC_OPERAND_ACC },
+  { "a7", 7, PPC_OPERAND_ACC },
+
   /* Condition Registers */
   { "cr.0", 0, PPC_OPERAND_CR_REG },
   { "cr.1", 1, PPC_OPERAND_CR_REG },
@@ -1400,6 +1410,8 @@ PowerPC options:\n"));
   fprintf (stream, _("\
 -mpower9, -mpwr9        generate code for Power9 architecture\n"));
   fprintf (stream, _("\
+-mpower10, -mpwr10      generate code for Power10 architecture\n"));
+  fprintf (stream, _("\
 -mcell                  generate code for Cell Broadband Engine architecture\n"));
   fprintf (stream, _("\
 -mcom                   generate code for Power/PowerPC common instructions\n"));
@@ -1975,9 +1987,7 @@ ppc_cleanup (void)
 
     /* Create the .PPC.EMB.apuinfo section.  */
     apuinfo_secp = subseg_new (APUINFO_SECTION_NAME, 0);
-    bfd_set_section_flags (stdoutput,
-                          apuinfo_secp,
-                          SEC_HAS_CONTENTS | SEC_READONLY);
+    bfd_set_section_flags (apuinfo_secp, SEC_HAS_CONTENTS | SEC_READONLY);
 
     p = frag_more (4);
     md_number_to_chars (p, (valueT) 8, 4);
@@ -2224,6 +2234,11 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
     MAP64 ("pcrel",            BFD_RELOC_PPC64_PCREL34),
     MAP64 ("got@pcrel",                BFD_RELOC_PPC64_GOT_PCREL34),
     MAP64 ("plt@pcrel",                BFD_RELOC_PPC64_PLT_PCREL34),
+    MAP64 ("tls@pcrel",                BFD_RELOC_PPC64_TLS_PCREL),
+    MAP64 ("got@tlsgd@pcrel",  BFD_RELOC_PPC64_GOT_TLSGD_PCREL34),
+    MAP64 ("got@tlsld@pcrel",  BFD_RELOC_PPC64_GOT_TLSLD_PCREL34),
+    MAP64 ("got@tprel@pcrel",  BFD_RELOC_PPC64_GOT_TPREL_PCREL34),
+    MAP64 ("got@dtprel@pcrel", BFD_RELOC_PPC64_GOT_DTPREL_PCREL34),
     MAP64 ("higher34",         BFD_RELOC_PPC64_ADDR16_HIGHER34),
     MAP64 ("highera34",                BFD_RELOC_PPC64_ADDR16_HIGHERA34),
     MAP64 ("highest34",                BFD_RELOC_PPC64_ADDR16_HIGHEST34),
@@ -2262,8 +2277,8 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
              case BFD_RELOC_LO16_GOTOFF:
              case BFD_RELOC_HI16_GOTOFF:
              case BFD_RELOC_HI16_S_GOTOFF:
-               as_warn (_("identifier+constant@got means "
-                          "identifier@got+constant"));
+               as_warn (_("symbol+offset@%s means symbol@%s+offset"),
+                        ptr->string, ptr->string);
                break;
 
              case BFD_RELOC_PPC_GOT_TLSGD16:
@@ -2282,7 +2297,7 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
              case BFD_RELOC_PPC_GOT_TPREL16_LO:
              case BFD_RELOC_PPC_GOT_TPREL16_HI:
              case BFD_RELOC_PPC_GOT_TPREL16_HA:
-               as_bad (_("symbol+offset not supported for got tls"));
+               as_bad (_("symbol+offset@%s not supported"), ptr->string);
                break;
              }
          }
@@ -2608,6 +2623,12 @@ ppc_elf_end (void)
       elf_elfheader (stdoutput)->e_flags &= ~EF_PPC64_ABI;
       elf_elfheader (stdoutput)->e_flags |= ppc_abiversion & EF_PPC64_ABI;
     }
+  /* Any selection of opcodes based on ppc_cpu after gas has finished
+     parsing the file is invalid.  md_apply_fix and ppc_handle_align
+     must select opcodes based on the machine in force at the point
+     where the fixup or alignment frag was created, not the machine in
+     force at the end of file.  */
+  ppc_cpu = 0;
 }
 
 /* Validate any relocations emitted for -mrelocatable, possibly adding
@@ -2692,7 +2713,7 @@ ppc_frob_file_before_adjust (void)
   toc = bfd_get_section_by_name (stdoutput, ".toc");
   if (toc != NULL
       && toc_reloc_types != has_large_toc_reloc
-      && bfd_section_size (stdoutput, toc) > 0x10000)
+      && bfd_section_size (toc) > 0x10000)
     as_warn (_("TOC section size exceeds 64k"));
 }
 
@@ -3149,6 +3170,7 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
     case BFD_RELOC_PPC_VLE_SDAREL_LO16A:
     case BFD_RELOC_PPC_VLE_SDAREL_LO16D:
+    case BFD_RELOC_PPC64_TLS_PCREL:
     case BFD_RELOC_RVA:
       size = 4;
       break;
@@ -3190,6 +3212,8 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_PPC64_D34_LO:
     case BFD_RELOC_PPC64_D34_HI30:
     case BFD_RELOC_PPC64_D34_HA30:
+    case BFD_RELOC_PPC64_TPREL34:
+    case BFD_RELOC_PPC64_DTPREL34:
     case BFD_RELOC_PPC64_TOC:
       size = 8;
       break;
@@ -3197,6 +3221,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative)
     case BFD_RELOC_64_PCREL:
     case BFD_RELOC_64_PLT_PCREL:
     case BFD_RELOC_PPC64_GOT_PCREL34:
+    case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34:
+    case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34:
+    case BFD_RELOC_PPC64_GOT_TPREL_PCREL34:
+    case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34:
     case BFD_RELOC_PPC64_PCREL28:
     case BFD_RELOC_PPC64_PCREL34:
     case BFD_RELOC_PPC64_PLT_PCREL34:
@@ -3239,7 +3267,10 @@ parse_tls_arg (char **str, const expressionS *exp, struct ppc_fixup *tls_fix)
     ++sym_name;
 
   tls_fix->reloc = BFD_RELOC_NONE;
-  if (strcasecmp (sym_name, "__tls_get_addr") == 0)
+  if (strncasecmp (sym_name, "__tls_get_addr", 14) == 0
+      && (sym_name[14] == 0
+         || strcasecmp (sym_name + 14, "_desc") == 0
+         || strcasecmp (sym_name + 14, "_opt") == 0))
     {
       char *hold = input_line_pointer;
       input_line_pointer = *str + 1;
@@ -3550,7 +3581,7 @@ md_assemble (char *str)
               & ~operand->flags
               & (PPC_OPERAND_GPR | PPC_OPERAND_FPR | PPC_OPERAND_VR
                  | PPC_OPERAND_VSR | PPC_OPERAND_CR_BIT | PPC_OPERAND_CR_REG
-                 | PPC_OPERAND_SPR | PPC_OPERAND_GQR)) != 0
+                 | PPC_OPERAND_SPR | PPC_OPERAND_GQR | PPC_OPERAND_ACC)) != 0
              && !((ex.X_md & PPC_OPERAND_GPR) != 0
                   && ex.X_add_number != 0
                   && (operand->flags & PPC_OPERAND_GPR_0) != 0))
@@ -3738,6 +3769,7 @@ md_assemble (char *str)
                  break;
 
                case BFD_RELOC_PPC_TLS:
+               case BFD_RELOC_PPC64_TLS_PCREL:
                  if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
                    as_bad (_("@tls may not be used with \"%s\" operands"),
                            opcode->name);
@@ -3750,13 +3782,19 @@ md_assemble (char *str)
                  break;
 
                  /* We'll only use the 32 (or 64) bit form of these relocations
-                    in constants.  Instructions get the 16 bit form.  */
+                    in constants.  Instructions get the 16 or 34 bit form.  */
                case BFD_RELOC_PPC_DTPREL:
-                 reloc = BFD_RELOC_PPC_DTPREL16;
+                 if (operand->bitm == 0x3ffffffffULL)
+                   reloc = BFD_RELOC_PPC64_DTPREL34;
+                 else
+                   reloc = BFD_RELOC_PPC_DTPREL16;
                  break;
 
                case BFD_RELOC_PPC_TPREL:
-                 reloc = BFD_RELOC_PPC_TPREL16;
+                 if (operand->bitm == 0x3ffffffffULL)
+                   reloc = BFD_RELOC_PPC64_TPREL34;
+                 else
+                   reloc = BFD_RELOC_PPC_TPREL16;
                  break;
 
                case BFD_RELOC_PPC64_PCREL34:
@@ -3768,6 +3806,10 @@ md_assemble (char *str)
                  /* Fall through.  */
                case BFD_RELOC_PPC64_GOT_PCREL34:
                case BFD_RELOC_PPC64_PLT_PCREL34:
+               case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34:
+               case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34:
+               case BFD_RELOC_PPC64_GOT_TPREL_PCREL34:
+               case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34:
                  if (operand->bitm != 0x3ffffffffULL
                      || (operand->flags & PPC_OPERAND_NEGATIVE) != 0)
                    as_warn (_("%s unsupported on this instruction"), "@pcrel");
@@ -4101,7 +4143,7 @@ md_assemble (char *str)
   insn_length = 4;
   if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && PPC_OP_SE_VLE (insn))
     insn_length = 2;
-  else if ((opcode->flags & PPC_OPCODE_POWERXX) != 0
+  else if ((opcode->flags & PPC_OPCODE_POWER10) != 0
           && PPC_PREFIX_P (insn))
     {
       struct insn_label_list *l;
@@ -4652,14 +4694,14 @@ ppc_change_debug_section (unsigned int idx, subsegT subseg)
   const struct xcoff_dwsect_name *dw = &xcoff_dwsect_names[idx];
 
   sec = subseg_new (dw->name, subseg);
-  oldflags = bfd_get_section_flags (stdoutput, sec);
+  oldflags = bfd_section_flags (sec);
   if (oldflags == SEC_NO_FLAGS)
     {
       /* Just created section.  */
       gas_assert (dw_sections[idx].sect == NULL);
 
-      bfd_set_section_flags (stdoutput, sec, SEC_DEBUGGING);
-      bfd_set_section_alignment (stdoutput, sec, 0);
+      bfd_set_section_flags (sec, SEC_DEBUGGING);
+      bfd_set_section_alignment (sec, 0);
       dw_sections[idx].sect = sec;
     }
 
@@ -5562,6 +5604,7 @@ ppc_xcoff_end (void)
             symbol_set_value_now (dwss->end_exp.X_add_symbol);
           }
     }
+  ppc_cpu = 0;
 }
 
 #endif /* OBJ_XCOFF */
@@ -5774,11 +5817,10 @@ ppc_pdata (int ignore ATTRIBUTE_UNUSED)
     {
       pdata_section = subseg_new (".pdata", 0);
 
-      bfd_set_section_flags (stdoutput, pdata_section,
-                            (SEC_ALLOC | SEC_LOAD | SEC_RELOC
-                             | SEC_READONLY | SEC_DATA ));
+      bfd_set_section_flags (pdata_section, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                            | SEC_READONLY | SEC_DATA));
 
-      bfd_set_section_alignment (stdoutput, pdata_section, 2);
+      bfd_set_section_alignment (pdata_section, 2);
     }
   else
     {
@@ -5807,11 +5849,10 @@ ppc_ydata (int ignore ATTRIBUTE_UNUSED)
   if (ydata_section == 0)
     {
       ydata_section = subseg_new (".ydata", 0);
-      bfd_set_section_flags (stdoutput, ydata_section,
-                            (SEC_ALLOC | SEC_LOAD | SEC_RELOC
-                             | SEC_READONLY | SEC_DATA ));
+      bfd_set_section_flags (ydata_section, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                            | SEC_READONLY | SEC_DATA ));
 
-      bfd_set_section_alignment (stdoutput, ydata_section, 3);
+      bfd_set_section_alignment (ydata_section, 3);
     }
   else
     {
@@ -5844,11 +5885,10 @@ ppc_reldata (int ignore ATTRIBUTE_UNUSED)
     {
       reldata_section = subseg_new (".reldata", 0);
 
-      bfd_set_section_flags (stdoutput, reldata_section,
-                            (SEC_ALLOC | SEC_LOAD | SEC_RELOC
-                             | SEC_DATA));
+      bfd_set_section_flags (reldata_section, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                              | SEC_DATA));
 
-      bfd_set_section_alignment (stdoutput, reldata_section, 2);
+      bfd_set_section_alignment (reldata_section, 2);
     }
   else
     {
@@ -5873,11 +5913,10 @@ ppc_rdata (int ignore ATTRIBUTE_UNUSED)
   if (rdata_section == 0)
     {
       rdata_section = subseg_new (".rdata", 0);
-      bfd_set_section_flags (stdoutput, rdata_section,
-                            (SEC_ALLOC | SEC_LOAD | SEC_RELOC
-                             | SEC_READONLY | SEC_DATA ));
+      bfd_set_section_flags (rdata_section, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                            | SEC_READONLY | SEC_DATA ));
 
-      bfd_set_section_alignment (stdoutput, rdata_section, 2);
+      bfd_set_section_alignment (rdata_section, 2);
     }
   else
     {
@@ -6231,13 +6270,13 @@ ppc_pe_section (int ignore ATTRIBUTE_UNUSED)
 
   if (flags != SEC_NO_FLAGS)
     {
-      if (! bfd_set_section_flags (stdoutput, sec, flags))
+      if (!bfd_set_section_flags (sec, flags))
        as_bad (_("error setting flags for \"%s\": %s"),
-               bfd_section_name (stdoutput, sec),
+               bfd_section_name (sec),
                bfd_errmsg (bfd_get_error ()));
     }
 
-  bfd_set_section_alignment (stdoutput, sec, align);
+  bfd_set_section_alignment (sec, align);
 }
 
 static void
@@ -6268,11 +6307,10 @@ ppc_pe_tocd (int ignore ATTRIBUTE_UNUSED)
     {
       tocdata_section = subseg_new (".tocd", 0);
       /* FIXME: section flags won't work.  */
-      bfd_set_section_flags (stdoutput, tocdata_section,
-                            (SEC_ALLOC | SEC_LOAD | SEC_RELOC
-                             | SEC_READONLY | SEC_DATA));
+      bfd_set_section_flags (tocdata_section, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                              | SEC_READONLY | SEC_DATA));
 
-      bfd_set_section_alignment (stdoutput, tocdata_section, 2);
+      bfd_set_section_alignment (tocdata_section, 2);
     }
   else
     {
@@ -6543,8 +6581,7 @@ ppc_frob_symbol (symbolS *sym)
          /* This is a csect symbol.  x_scnlen is the size of the
             csect.  */
          if (symbol_get_tc (sym)->next == (symbolS *) NULL)
-           a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
-                                                      S_GET_SEGMENT (sym))
+           a->x_csect.x_scnlen.l = (bfd_section_size (S_GET_SEGMENT (sym))
                                     - S_GET_VALUE (sym));
          else
            {
@@ -6592,8 +6629,7 @@ ppc_frob_symbol (symbolS *sym)
              || symbol_get_tc (next)->symbol_class != XMC_TC)
            {
              if (ppc_after_toc_frag == (fragS *) NULL)
-               a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
-                                                          data_section)
+               a->x_csect.x_scnlen.l = (bfd_section_size (data_section)
                                         - S_GET_VALUE (sym));
              else
                a->x_csect.x_scnlen.l = (ppc_after_toc_frag->fr_address
@@ -6757,12 +6793,12 @@ ppc_frob_section (asection *sec)
   static bfd_vma vma = 0;
 
   /* Dwarf sections start at 0.  */
-  if (bfd_get_section_flags (NULL, sec) & SEC_DEBUGGING)
+  if (bfd_section_flags (sec) & SEC_DEBUGGING)
     return;
 
   vma = md_section_align (sec, vma);
-  bfd_set_section_vma (stdoutput, sec, vma);
-  vma += bfd_section_size (stdoutput, sec);
+  bfd_set_section_vma (sec, vma);
+  vma += bfd_section_size (sec);
 }
 
 #endif /* OBJ_XCOFF */
@@ -6793,7 +6829,7 @@ md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr)
 #ifdef OBJ_ELF
   return addr;
 #else
-  int align = bfd_get_section_alignment (stdoutput, seg);
+  int align = bfd_section_alignment (seg);
 
   return ((addr + (1 << align) - 1) & -(1 << align));
 #endif
@@ -6856,7 +6892,7 @@ ppc_fix_adjustable (fixS *fix)
     return 0;
 
   /* Always adjust symbols in debugging sections.  */
-  if (bfd_get_section_flags (stdoutput, symseg) & SEC_DEBUGGING)
+  if (bfd_section_flags (symseg) & SEC_DEBUGGING)
     return 1;
 
   if (ppc_toc_csect != (symbolS *) NULL
@@ -6996,7 +7032,7 @@ ppc_force_relocation (fixS *fix)
     }
 
   if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
-      && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
+      && fix->fx_r_type <= BFD_RELOC_PPC64_TLS_PCREL)
     return 1;
 
   return generic_force_reloc (fix);
@@ -7064,7 +7100,7 @@ ppc_fix_adjustable (fixS *fix)
          && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
          && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
          && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
-              && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA));
+              && fix->fx_r_type <= BFD_RELOC_PPC64_TLS_PCREL));
 }
 #endif
 
@@ -7077,26 +7113,58 @@ ppc_frag_check (struct frag *fragP)
                  fragP->insn_addr + 1);
 }
 
-/* Implement HANDLE_ALIGN.  This writes the NOP pattern into an
-   rs_align_code frag.  */
+/* rs_align_code frag handling.  */
+
+enum ppc_nop_encoding_for_rs_align_code
+{
+  PPC_NOP_VANILLA,
+  PPC_NOP_VLE,
+  PPC_NOP_GROUP_P6,
+  PPC_NOP_GROUP_P7
+};
+
+unsigned int
+ppc_nop_select (void)
+{
+  if ((ppc_cpu & PPC_OPCODE_VLE) != 0)
+    return PPC_NOP_VLE;
+  if ((ppc_cpu & (PPC_OPCODE_POWER9 | PPC_OPCODE_E500MC)) == 0)
+    {
+      if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
+       return PPC_NOP_GROUP_P7;
+      if ((ppc_cpu & PPC_OPCODE_POWER6) != 0)
+       return PPC_NOP_GROUP_P6;
+    }
+  return PPC_NOP_VANILLA;
+}
 
 void
 ppc_handle_align (struct frag *fragP)
 {
   valueT count = (fragP->fr_next->fr_address
                  - (fragP->fr_address + fragP->fr_fix));
+  char *dest = fragP->fr_literal + fragP->fr_fix;
+  enum ppc_nop_encoding_for_rs_align_code nop_select = *dest & 0xff;
+
+  /* Pad with zeros if not inserting a whole number of instructions.
+     We could pad with zeros up to an instruction boundary then follow
+     with nops but odd counts indicate data in an executable section
+     so padding with zeros is most appropriate.  */
+  if (count == 0
+      || (nop_select == PPC_NOP_VLE ? (count & 1) != 0 : (count & 3) != 0))
+    {
+      *dest = 0;
+      return;
+    }
 
-  if ((ppc_cpu & PPC_OPCODE_VLE) != 0 && count != 0 && (count & 1) == 0)
+  if (nop_select == PPC_NOP_VLE)
     {
-      char *dest = fragP->fr_literal + fragP->fr_fix;
 
       fragP->fr_var = 2;
       md_number_to_chars (dest, 0x4400, 2);
     }
-  else if (count != 0 && (count & 3) == 0)
+  else
     {
-      char *dest = fragP->fr_literal + fragP->fr_fix;
-
       fragP->fr_var = 4;
 
       if (count > 4 * nop_limit && count < 0x2000000)
@@ -7125,8 +7193,7 @@ ppc_handle_align (struct frag *fragP)
 
       md_number_to_chars (dest, 0x60000000, 4);
 
-      if ((ppc_cpu & PPC_OPCODE_POWER6) != 0
-         && (ppc_cpu & PPC_OPCODE_POWER9) == 0)
+      if (nop_select >= PPC_NOP_GROUP_P6)
        {
          /* For power6, power7, and power8, we want the last nop to
             be a group terminating one.  Do this by inserting an
@@ -7146,18 +7213,12 @@ ppc_handle_align (struct frag *fragP)
              dest = group_nop->fr_literal;
            }
 
-         if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
-           {
-             if (ppc_cpu & PPC_OPCODE_E500MC)
-               /* e500mc group terminating nop: "ori 0,0,0".  */
-               md_number_to_chars (dest, 0x60000000, 4);
-             else
-               /* power7/power8 group terminating nop: "ori 2,2,0".  */
-               md_number_to_chars (dest, 0x60420000, 4);
-           }
-         else
+         if (nop_select == PPC_NOP_GROUP_P6)
            /* power6 group terminating nop: "ori 1,1,0".  */
            md_number_to_chars (dest, 0x60210000, 4);
+         else
+           /* power7/power8 group terminating nop: "ori 2,2,0".  */
+           md_number_to_chars (dest, 0x60420000, 4);
        }
     }
 }
@@ -7471,6 +7532,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
        case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
        case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+       case BFD_RELOC_PPC64_TPREL34:
+       case BFD_RELOC_PPC64_DTPREL34:
+       case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34:
+       case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34:
+       case BFD_RELOC_PPC64_GOT_TPREL_PCREL34:
+       case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34:
          gas_assert (fixP->fx_addsy != NULL);
          S_SET_THREAD_LOCAL (fixP->fx_addsy);
          fieldval = 0;
@@ -7541,6 +7608,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC_TLS:
        case BFD_RELOC_PPC_TLSGD:
        case BFD_RELOC_PPC_TLSLD:
+       case BFD_RELOC_PPC64_TLS_PCREL:
          fieldval = 0;
          break;
 #endif
@@ -7794,6 +7862,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
        case BFD_RELOC_PPC64_TPREL16_HIGHERA:
        case BFD_RELOC_PPC64_TPREL16_HIGHEST:
        case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+       case BFD_RELOC_PPC64_TLS_PCREL:
          fixP->fx_done = 0;
          break;
 #endif
@@ -7864,9 +7933,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 #else
       /* 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))
-       - S_GET_VALUE (ppc_toc_csect);
+      fixP->fx_addnumber = (- bfd_section_vma (S_GET_SEGMENT (fixP->fx_addsy))
+                           - S_GET_VALUE (ppc_toc_csect));
       /* Set *valP to avoid errors.  */
       *valP = value;
 #endif
@@ -7886,6 +7954,9 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
   reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+  /* BFD_RELOC_PPC64_TLS_PCREL generates R_PPC64_TLS with an odd r_offset.  */
+  if (fixp->fx_r_type == BFD_RELOC_PPC64_TLS_PCREL)
+    reloc->address++;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
This page took 0.030982 seconds and 4 git commands to generate.