* config/tc-ppc.c (md_apply_fix): Hoist code common to insn
authorAlan Modra <amodra@gmail.com>
Mon, 20 May 2013 10:16:31 +0000 (10:16 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 20 May 2013 10:16:31 +0000 (10:16 +0000)
and data fixups performing shift/high adjust/sign extension on
fieldval.  Sink fx_pcrel handling and checks.  Use fixP->fx_size
when writing data fixups rather than recalculating size.

gas/ChangeLog
gas/config/tc-ppc.c

index de64c90e34c64298d70ac762a76b85a251628198..a6440a8ba57bc3b0a1139f3243acf00b69b1d8a7 100644 (file)
@@ -1,3 +1,10 @@
+2013-05-20  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (md_apply_fix): Hoist code common to insn
+       and data fixups performing shift/high adjust/sign extension on
+       fieldval.  Sink fx_pcrel handling and checks.  Use fixP->fx_size
+       when writing data fixups rather than recalculating size.
+
 2013-05-16  Jan-Benedict Glaw  <jbglaw@lug-owl.de>
 
        * doc/c-msp430.texi: Fix typo.
index a76416857884e216f81c174707d9e10971b43f0d..c9a773227898e3ba97987093c9c4ec225b145bbb 100644 (file)
@@ -6287,6 +6287,8 @@ void
 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   valueT value = * valP;
+  offsetT fieldval;
+  const struct powerpc_operand *operand;
 
 #ifdef OBJ_ELF
   if (fixP->fx_addsy != NULL)
@@ -6325,16 +6327,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
     }
 
+  operand = NULL;
   if (fixP->fx_pcrel_adjust != 0)
     {
-      /* Handle relocs in an insn.  */
-
+      /* This is a fixup on an instruction.  */
       int opindex = fixP->fx_pcrel_adjust & 0xff;
-      const struct powerpc_operand *operand = &powerpc_operands[opindex];
-      char *where;
-      unsigned long insn;
-      offsetT fieldval;
 
+      operand = &powerpc_operands[opindex];
 #ifdef OBJ_XCOFF
       /* An instruction like `lwz 9,sym(30)' when `sym' is not a TOC symbol
         does not generate a reloc.  It uses the offset of `sym' within its
@@ -6354,74 +6353,75 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
          fixP->fx_done = 1;
        }
 #endif
-      fieldval = value;
-      switch (fixP->fx_r_type)
-       {
+    }
+
+  /* Calculate value to be stored in field.  */
+  fieldval = value;
+  switch (fixP->fx_r_type)
+    {
 #ifdef OBJ_ELF
-       case BFD_RELOC_PPC64_ADDR16_LO_DS:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         /* fall through */
+    case BFD_RELOC_PPC64_ADDR16_LO_DS:
+    case BFD_RELOC_PPC_VLE_LO16A:
+    case BFD_RELOC_PPC_VLE_LO16D:
 #endif
-       case BFD_RELOC_LO16:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
-         /* fall through */
-       case BFD_RELOC_LO16_PCREL:
-       case BFD_RELOC_PPC_VLE_LO16A:
-       case BFD_RELOC_PPC_VLE_LO16D:
-         fieldval = value & 0xffff;
-       sign_extend_16:
-         if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-           fieldval = (fieldval ^ 0x8000) - 0x8000;
-         fixP->fx_no_overflow = 1;
-         break;
+    case BFD_RELOC_LO16:
+    case BFD_RELOC_LO16_PCREL:
+      fieldval = value & 0xffff;
+    sign_extend_16:
+      if (operand != NULL && (operand->flags & PPC_OPERAND_SIGNED) != 0)
+       fieldval = (fieldval ^ 0x8000) - 0x8000;
+      fixP->fx_no_overflow = 1;
+      break;
 
-       case BFD_RELOC_HI16:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
-         /* fall through */
-       case BFD_RELOC_HI16_PCREL:
-       case BFD_RELOC_PPC_VLE_HI16A:
-       case BFD_RELOC_PPC_VLE_HI16D:
-         fieldval = PPC_HI (value);
-         goto sign_extend_16;
+#ifdef OBJ_ELF
+    case BFD_RELOC_PPC_VLE_HI16A:
+    case BFD_RELOC_PPC_VLE_HI16D:
+#endif
+    case BFD_RELOC_HI16:
+    case BFD_RELOC_HI16_PCREL:
+      fieldval = PPC_HI (value);
+      goto sign_extend_16;
 
-       case BFD_RELOC_HI16_S:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
-         /* fall through */
-       case BFD_RELOC_HI16_S_PCREL:
-       case BFD_RELOC_PPC_VLE_HA16A:
-       case BFD_RELOC_PPC_VLE_HA16D:
-         fieldval = PPC_HA (value);
-         goto sign_extend_16;
+#ifdef OBJ_ELF
+    case BFD_RELOC_PPC_VLE_HA16A:
+    case BFD_RELOC_PPC_VLE_HA16D:
+#endif
+    case BFD_RELOC_HI16_S:
+    case BFD_RELOC_HI16_S_PCREL:
+      fieldval = PPC_HA (value);
+      goto sign_extend_16;
 
 #ifdef OBJ_ELF
-       case BFD_RELOC_PPC64_HIGHER:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         fieldval = PPC_HIGHER (value);
-         goto sign_extend_16;
+    case BFD_RELOC_PPC64_HIGHER:
+      fieldval = PPC_HIGHER (value);
+      goto sign_extend_16;
 
-       case BFD_RELOC_PPC64_HIGHER_S:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         fieldval = PPC_HIGHERA (value);
-         goto sign_extend_16;
+    case BFD_RELOC_PPC64_HIGHER_S:
+      fieldval = PPC_HIGHERA (value);
+      goto sign_extend_16;
 
-       case BFD_RELOC_PPC64_HIGHEST:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         fieldval = PPC_HIGHEST (value);
-         goto sign_extend_16;
+    case BFD_RELOC_PPC64_HIGHEST:
+      fieldval = PPC_HIGHEST (value);
+      goto sign_extend_16;
 
-       case BFD_RELOC_PPC64_HIGHEST_S:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         fieldval = PPC_HIGHESTA (value);
-         goto sign_extend_16;
+    case BFD_RELOC_PPC64_HIGHEST_S:
+      fieldval = PPC_HIGHESTA (value);
+      goto sign_extend_16;
+#endif
+
+    default:
+      break;
+    }
+
+  if (operand != NULL)
+    {
+      /* Handle relocs in an insn.  */
+      char *where;
+      unsigned long insn;
 
+#ifdef OBJ_ELF
+      switch (fixP->fx_r_type)
+       {
          /* The following relocs can't be calculated by the assembler.
             Leave the field zero.  */
        case BFD_RELOC_PPC_TPREL16:
@@ -6463,8 +6463,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
          gas_assert (fixP->fx_addsy != NULL);
          S_SET_THREAD_LOCAL (fixP->fx_addsy);
          fieldval = 0;
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
          break;
 
          /* These also should leave the field zero for the same
@@ -6531,14 +6529,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        case BFD_RELOC_PPC_TLSGD:
        case BFD_RELOC_PPC_TLSLD:
          fieldval = 0;
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
          break;
-#endif
 
        default:
          break;
        }
+#endif
 
 #ifdef OBJ_ELF
 /* powerpc uses RELA style relocs, so if emitting a reloc the field
@@ -6610,79 +6606,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     }
   else
     {
-      int size = 0;
-      offsetT fieldval = value;
-
       /* Handle relocs in data.  */
       switch (fixP->fx_r_type)
        {
-       case BFD_RELOC_CTOR:
-         if (ppc_obj64)
-           goto ctor64;
-         /* fall through */
-
-       case BFD_RELOC_32:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_32_PCREL;
-         /* fall through */
-
-       case BFD_RELOC_32_PCREL:
-       case BFD_RELOC_RVA:
-         size = 4;
-         break;
-
-       case BFD_RELOC_64:
-       ctor64:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_64_PCREL;
-         /* fall through */
-
-       case BFD_RELOC_64_PCREL:
-         size = 8;
-         break;
-
-       case BFD_RELOC_16:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_16_PCREL;
-         /* fall through */
-
-       case BFD_RELOC_16_PCREL:
-         size = 2;
-         break;
-
-       case BFD_RELOC_8:
-         if (fixP->fx_pcrel)
-           {
-#ifdef OBJ_ELF
-           bad_pcrel:
-#endif
-             if (fixP->fx_addsy)
-               {
-                 char *sfile;
-                 unsigned int sline;
-
-                 /* Use expr_symbol_where to see if this is an
-                    expression symbol.  */
-                 if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
-                   as_bad_where (fixP->fx_file, fixP->fx_line,
-                                 _("unresolved expression that must"
-                                   " be resolved"));
-                 else
-                   as_bad_where (fixP->fx_file, fixP->fx_line,
-                                 _("cannot emit PC relative %s relocation"
-                                   " against %s"),
-                                 bfd_get_reloc_code_name (fixP->fx_r_type),
-                                 S_GET_NAME (fixP->fx_addsy));
-               }
-             else
-               as_bad_where (fixP->fx_file, fixP->fx_line,
-                             _("unable to resolve expression"));
-             fixP->fx_done = 1;
-           }
-         else
-           size = 1;
-         break;
-
        case BFD_RELOC_VTABLE_INHERIT:
          if (fixP->fx_addsy
              && !S_IS_DEFINED (fixP->fx_addsy)
@@ -6697,54 +6623,15 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 #ifdef OBJ_ELF
          /* These can appear with @l etc. in data.  */
        case BFD_RELOC_LO16:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
        case BFD_RELOC_LO16_PCREL:
-         size = 2;
-         break;
-
        case BFD_RELOC_HI16:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
        case BFD_RELOC_HI16_PCREL:
-         size = 2;
-         fieldval = PPC_HI (value);
-         break;
-
        case BFD_RELOC_HI16_S:
-         if (fixP->fx_pcrel)
-           fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
        case BFD_RELOC_HI16_S_PCREL:
-         size = 2;
-         fieldval = PPC_HA (value);
-         break;
-
        case BFD_RELOC_PPC64_HIGHER:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         size = 2;
-         fieldval = PPC_HIGHER (value);
-         break;
-
        case BFD_RELOC_PPC64_HIGHER_S:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         size = 2;
-         fieldval = PPC_HIGHERA (value);
-         break;
-
        case BFD_RELOC_PPC64_HIGHEST:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         size = 2;
-         fieldval = PPC_HIGHEST (value);
-         break;
-
        case BFD_RELOC_PPC64_HIGHEST_S:
-         if (fixP->fx_pcrel)
-           goto bad_pcrel;
-         size = 2;
-         fieldval = PPC_HIGHESTA (value);
          break;
 
        case BFD_RELOC_PPC_DTPMOD:
@@ -6835,8 +6722,17 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 
 #ifdef OBJ_XCOFF
        case BFD_RELOC_NONE:
-         break;
 #endif
+       case BFD_RELOC_CTOR:
+       case BFD_RELOC_32:
+       case BFD_RELOC_32_PCREL:
+       case BFD_RELOC_RVA:
+       case BFD_RELOC_64:
+       case BFD_RELOC_64_PCREL:
+       case BFD_RELOC_16:
+       case BFD_RELOC_16_PCREL:
+       case BFD_RELOC_8:
+         break;
 
        default:
          fprintf (stderr,
@@ -6845,9 +6741,85 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
          abort ();
        }
 
-      if (size && APPLY_RELOC)
+      if (fixP->fx_size && APPLY_RELOC)
        md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
-                           fieldval, size);
+                           fieldval, fixP->fx_size);
+    }
+
+  /* We are only able to convert some relocs to pc-relative.  */
+  if (!fixP->fx_done && fixP->fx_pcrel)
+    {
+      switch (fixP->fx_r_type)
+       {
+       case BFD_RELOC_LO16:
+         fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16:
+         fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16_S:
+         fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+         break;
+
+       case BFD_RELOC_64:
+         fixP->fx_r_type = BFD_RELOC_64_PCREL;
+         break;
+
+       case BFD_RELOC_32:
+         fixP->fx_r_type = BFD_RELOC_32_PCREL;
+         break;
+
+       case BFD_RELOC_16:
+         fixP->fx_r_type = BFD_RELOC_16_PCREL;
+         break;
+
+         /* Some of course are already pc-relative.  */
+       case BFD_RELOC_LO16_PCREL:
+       case BFD_RELOC_HI16_PCREL:
+       case BFD_RELOC_HI16_S_PCREL:
+       case BFD_RELOC_64_PCREL:
+       case BFD_RELOC_32_PCREL:
+       case BFD_RELOC_16_PCREL:
+       case BFD_RELOC_PPC_B16:
+       case BFD_RELOC_PPC_B16_BRTAKEN:
+       case BFD_RELOC_PPC_B16_BRNTAKEN:
+       case BFD_RELOC_PPC_B26:
+       case BFD_RELOC_PPC_LOCAL24PC:
+       case BFD_RELOC_24_PLT_PCREL:
+       case BFD_RELOC_32_PLT_PCREL:
+       case BFD_RELOC_64_PLT_PCREL:
+       case BFD_RELOC_PPC_VLE_REL8:
+       case BFD_RELOC_PPC_VLE_REL15:
+       case BFD_RELOC_PPC_VLE_REL24:
+         break;
+
+       default:
+         if (fixP->fx_addsy)
+           {
+             char *sfile;
+             unsigned int sline;
+
+             /* Use expr_symbol_where to see if this is an
+                expression symbol.  */
+             if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
+               as_bad_where (fixP->fx_file, fixP->fx_line,
+                             _("unresolved expression that must"
+                               " be resolved"));
+             else
+               as_bad_where (fixP->fx_file, fixP->fx_line,
+                             _("cannot emit PC relative %s relocation"
+                               " against %s"),
+                             bfd_get_reloc_code_name (fixP->fx_r_type),
+                             S_GET_NAME (fixP->fx_addsy));
+           }
+         else
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("unable to resolve expression"));
+         fixP->fx_done = 1;
+         break;
+       }
     }
 
 #ifdef OBJ_ELF
This page took 0.034427 seconds and 4 git commands to generate.