Fix PR 8255
authorMichael Meissner <gnu@the-meissners.org>
Tue, 24 Oct 1995 18:59:05 +0000 (18:59 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Tue, 24 Oct 1995 18:59:05 +0000 (18:59 +0000)
gas/ChangeLog
gas/config/tc-ppc.c
gas/config/tc-ppc.h
gas/write.c

index 523d6ef27ab0d0683019ef4dfc1cd3656d0fe399..1e598110e16c39845a177383a6046541cdc56915 100644 (file)
@@ -1,3 +1,22 @@
+Tue Oct 24 14:50:38 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * config/tc-ppc.h (TC_FORCE_RELOCATION_SECTION): Rename from
+       TC_FORCE_RELOCATION, taking an additional section argument.  If
+       the section of the target symbol is not the same as the current
+       section, always force the relocation to be used.
+       (MD_PCREL_FROM_SECTION): New macro to call md_pcrel_from_section.
+
+       * config/tc-ppc.c (md_pcrel_from_section): Rename from the
+       md_pcrel_from function, taking an additional section argument.
+       Invoke TC_FORCE_RELOCATION_SECTION instead of TC_FORCE_RELOCATION.
+
+       * write.c (TC_FORCE_RELOCATION_SECTION): Define in terms of the
+       older TC_FORCE_RELOCATION if not defined.
+       (MD_PCREL_FROM_SECTION): If not defined, invoke md_pcrel_from.
+       (fixup_segment): Use MD_PCREL_FROM_SECTION instead of
+       md_pcrel_from, and TC_FORCE_RELOCATION_SECTION instead of
+       TC_FORCE_RELOCATION.
+       
 Mon Oct 23 16:20:04 1995  Ken Raeburn  <raeburn@cygnus.com>
 
        * input-scrub.c (as_where): Set name to null pointer if we don't
index 59405bc7f40349d55ef2018df7b9718729f4ed50..f7cf199ad16719636db2aa4f6cb5830eaccc5af2 100644 (file)
@@ -561,10 +561,8 @@ md_parse_option (c, arg)
       /* -mpwr means to assemble for the IBM POWER (RIOS1).  */
       else if (strcmp (arg, "pwr") == 0)
        ppc_cpu = PPC_OPCODE_POWER;
-      /* -m601 means to assemble for the Motorola PowerPC 601.  FIXME: We
-        ignore the option for now, but we should really use it to permit
-        instructions defined on the 601 that are not part of the standard
-        PowerPC architecture (mostly holdovers from the POWER).  */
+      /* -m601 means to assemble for the Motorola PowerPC 601, which includes
+         instructions that are holdovers from the Power. */
       else if (strcmp (arg, "601") == 0)
        ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601;
       /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
@@ -586,10 +584,10 @@ md_parse_option (c, arg)
         and PowerPC.  At present, we just allow the union, rather
         than the intersection.  */
       else if (strcmp (arg, "com") == 0)
-       ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_PPC;
+       ppc_cpu = PPC_OPCODE_COMMON;
       /* -many means to assemble for any architecture (PWR/PWRX/PPC).  */
       else if (strcmp (arg, "any") == 0)
-       ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_PPC;
+       ppc_cpu = PPC_OPCODE_ANY;
 
 #ifdef OBJ_ELF
       /* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */
@@ -700,17 +698,24 @@ ppc_set_cpu ()
 enum bfd_architecture
 ppc_arch ()
 {
+  const char *default_cpu = TARGET_CPU;
   ppc_set_cpu ();
 
   if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
     return bfd_arch_powerpc;
   else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
     return bfd_arch_rs6000;
-  else
+  else if ((ppc_cpu & (PPC_OPCODE_COMMON | PPC_OPCODE_ANY)) != 0)
     {
-      as_fatal ("Neither Power nor PowerPC opcodes were selected.");
-      return bfd_arch_unknown;
+      if (strcmp (default_cpu, "rs6000") == 0)
+       return bfd_arch_rs6000;
+      else if (strcmp (default_cpu, "powerpc") == 0
+              || strcmp (default_cpu, "powerpcle") == 0)
+       return bfd_arch_powerpc;
     }
+
+  as_fatal ("Neither Power nor PowerPC opcodes were selected.");
+  return bfd_arch_unknown;
 }
 
 /* This function is called when the assembler starts up.  It is called
@@ -724,6 +729,7 @@ md_begin ()
   const struct powerpc_opcode *op_end;
   const struct powerpc_macro *macro;
   const struct powerpc_macro *macro_end;
+  boolean dup_insn = false;
 
   ppc_set_cpu ();
 
@@ -750,28 +756,13 @@ md_begin ()
          retval = hash_insert (ppc_hash, op->name, (PTR) op);
          if (retval != (const char *) NULL)
            {
-             /* We permit a duplication of the mfdec instruction on
-                the 601, because it seems to have one value on the
-                601 and a different value on other PowerPC
-                processors.  It's easier to permit a duplication than
-                to define a new instruction type flag.  When using
-                -many/-mcom, the comparison instructions are a harmless
-                special case.  */
-             if (strcmp (retval, "exists") != 0
-                 || ((((ppc_cpu & PPC_OPCODE_601) == 0
-                       && ((ppc_cpu & ~PPC_OPCODE_POWER2)
-                           == (PPC_OPCODE_POWER | PPC_OPCODE_PPC)))
-                      || strcmp (op->name, "mfdec") != 0)
-                     && (((ppc_cpu & ~PPC_OPCODE_POWER2)
-                         != (PPC_OPCODE_POWER | PPC_OPCODE_PPC))
-                         || (strcmp (op->name, "cmpli") != 0
-                             && strcmp (op->name, "cmpi") != 0
-                             && strcmp (op->name, "cmp") != 0
-                             && strcmp (op->name, "cmpl") != 0))))
-               {
-                 as_bad ("Internal assembler error for instruction %s", op->name);
-                 abort ();
-               }
+             /* Ignore Power duplicates for -m601 */
+             if ((ppc_cpu & PPC_OPCODE_601) != 0
+                 && (op->flags & PPC_OPCODE_POWER) != 0)
+               continue;
+
+             as_bad ("Internal assembler error for instruction %s", op->name);
+             dup_insn = true;
            }
        }
     }
@@ -788,10 +779,16 @@ md_begin ()
 
          retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
          if (retval != (const char *) NULL)
-           abort ();
+           {
+             as_bad ("Internal assembler error for macro %s", macro->name);
+             dup_insn = true;
+           }
        }
     }
 
+  if (dup_insn)
+    abort ();
+
   /* Tell the main code what the endianness is if it is not overidden by the user.  */
   if (!set_target_endian)
     {
@@ -3756,13 +3753,14 @@ md_undefined_symbol (name)
    given a PC relative reloc.  */
 
 long
-md_pcrel_from (fixp)
+md_pcrel_from_section (fixp, sec)
      fixS *fixp;
+     segT sec;
 {
 #ifdef OBJ_ELF
   if (fixp->fx_addsy != (symbolS *) NULL
       && (! S_IS_DEFINED (fixp->fx_addsy)
-         || TC_FORCE_RELOCATION (fixp)))
+         || TC_FORCE_RELOCATION_SECTION (fixp, sec)))
     return 0;
 #endif
 
index 1a456aed9ced55ecfd1f89b4bf44772cfd9d1e5a..cbedae4863189ed209bb40a0b7bc41690ebd4fba 100644 (file)
@@ -102,6 +102,10 @@ extern int target_big_endian;
 /* Question marks are permitted in symbol names.  */
 #define LEX_QM 1
 
+/* Don't adjust TOC relocs.  */
+#define tc_fix_adjustable(fixp) ppc_pe_fix_adjustable (fixp)
+extern int ppc_pe_fix_adjustable PARAMS ((struct fix *));
+
 #endif
 
 #ifdef OBJ_XCOFF
@@ -187,15 +191,20 @@ extern void ppc_frob_file PARAMS ((void));
 #endif
 
 /* Branch prediction relocations must force relocation */
-#define TC_FORCE_RELOCATION(FIXP)                                      \
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEC)                          \
 ((FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRTAKEN                                \
  || (FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRNTAKEN                    \
  || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRTAKEN                    \
- || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN)
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN                   \
+ || ((FIXP)->fx_addsy && !(FIXP)->fx_subsy && (FIXP)->fx_addsy->bsym   \
+     && (FIXP)->fx_addsy->bsym->section != SEC))
 
 #endif /* OBJ_ELF */
 
 /* call md_apply_fix3 with segment instead of md_apply_fix */
 #define MD_APPLY_FIX3
 
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+
 #define md_operand(x)
index 6dd4ff1e725d93453f2b6dd797af6bcf07424a3a..91871da548ee4ee06766e22e1b8afc4b3eea4e05 100644 (file)
 #define TC_FORCE_RELOCATION(FIXP) 0
 #endif
 
+#ifndef TC_FORCE_RELOCATION_SECTION
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEG) TC_FORCE_RELOCATION(FIXP)
+#endif
+
+#ifndef        MD_PCREL_FROM_SECTION
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from(FIXP)
+#endif
+
 #ifndef WORKING_DOT_WORD
 extern CONST int md_short_jump_size;
 extern CONST int md_long_jump_size;
@@ -235,7 +243,7 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type)
   symbolS *add = NULL;
   symbolS *sub = NULL;
   offsetT off = 0;
-  
+
   switch (exp->X_op)
     {
     case O_absent:
@@ -254,6 +262,19 @@ fix_new_exp (frag, where, size, exp, pcrel, r_type)
        return fix_new_exp (frag, where, size, exp, pcrel, r_type);
       }
 
+    case O_symbol_rva:
+      add = exp->X_add_symbol;
+      off = exp->X_add_number;
+
+#if defined(BFD_ASSEMBLER)
+      r_type = BFD_RELOC_RVA;
+#elif defined(TC_RVA_RELOC)
+      r_type = TC_RVA_RELOC;
+#else
+      as_fatal("rva not supported");
+#endif
+      break;
+
     case O_uminus:
       sub = exp->X_add_symbol;
       off = exp->X_add_number;
@@ -355,6 +376,7 @@ chain_frchains_together_1 (section, frchp)
     {
       prev_frag->fr_next = frchp->frch_root;
       prev_frag = frchp->frch_last;
+      assert (prev_frag->fr_type != 0);
 #ifdef BFD_ASSEMBLER
       if (frchp->fix_root != (fixS *) NULL)
        {
@@ -366,6 +388,7 @@ chain_frchains_together_1 (section, frchp)
        }
 #endif
     }
+  assert (prev_frag->fr_type != 0);
   prev_frag->fr_next = 0;
   return prev_frag;
 }
@@ -2183,11 +2206,21 @@ fixup_segment (fixP, this_segment_type)
       if (sub_symbolP)
        {
          resolve_symbol_value (sub_symbolP);
-         if (!add_symbolP)
+         if (add_symbolP == NULL || add_symbol_segment == absolute_section)
            {
-             /* Its just -sym */
+             if (add_symbolP != NULL)
+               {
+                 add_number += S_GET_VALUE (add_symbolP);
+                 add_symbolP = NULL;
+                 fixP->fx_addsy = NULL;
+               }
+
+             /* It's just -sym */
              if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
-               add_number -= S_GET_VALUE (sub_symbolP);
+               {
+                 add_number -= S_GET_VALUE (sub_symbolP);
+                 fixP->fx_subsy = NULL;
+               }
              else if (pcrel
                       && S_GET_SEGMENT (sub_symbolP) == this_segment_type)
                {
@@ -2200,9 +2233,8 @@ fixup_segment (fixP, this_segment_type)
                              "Negative of non-absolute symbol %s",
                              S_GET_NAME (sub_symbolP));
            }
-         else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment)
-                  && (SEG_NORMAL (add_symbol_segment)
-                      || (add_symbol_segment == absolute_section)))
+         else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
+                  && SEG_NORMAL (add_symbol_segment))
            {
              /* Difference of 2 symbols from same segment.
                 Can't make difference of 2 undefineds: 'value' means
@@ -2223,10 +2255,11 @@ fixup_segment (fixP, this_segment_type)
              /* Let the target machine make the final determination
                 as to whether or not a relocation will be needed to
                 handle this fixup.  */
-             if (!TC_FORCE_RELOCATION (fixP))
+             if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment_type))
                {
                  fixP->fx_pcrel = 0;
                  fixP->fx_addsy = NULL;
+                 fixP->fx_subsy = NULL;
                }
            }
          else
@@ -2248,7 +2281,7 @@ fixup_segment (fixP, this_segment_type)
                       )
                {
                  /* Make it pc-relative.  */
-                 add_number += (md_pcrel_from (fixP)
+                 add_number += (MD_PCREL_FROM_SECTION (fixP, this_segment_type)
                                 - S_GET_VALUE (sub_symbolP));
                  pcrel = 1;
                  fixP->fx_pcrel = 1;
@@ -2304,7 +2337,7 @@ fixup_segment (fixP, this_segment_type)
 #endif /* TC_I960 */
 
              add_number += S_GET_VALUE (add_symbolP);
-             add_number -= md_pcrel_from (fixP);
+             add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
              pcrel = 0;        /* Lie. Don't want further pcrel processing. */
              
              /* Let the target machine make the final determination
@@ -2378,7 +2411,7 @@ fixup_segment (fixP, this_segment_type)
 
       if (pcrel)
        {
-         add_number -= md_pcrel_from (fixP);
+         add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
          if (add_symbolP == 0)
            {
 #ifndef BFD_ASSEMBLER