2003-02-25 Alexandre Oliva <aoliva@redhat.com>
authorAlexandre Oliva <aoliva@redhat.com>
Thu, 10 Jul 2003 03:20:14 +0000 (03:20 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Thu, 10 Jul 2003 03:20:14 +0000 (03:20 +0000)
* config/tc-mn10300.c (mn10300_check_fixup): Set GOT_PCREL type
for subtracts from GLOBAL_OFFSET_TABLE that could not be
simplified.
2002-07-18  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.c (mn10300_check_fixup): Accept subtracts that
could not be simplified.
(tc_gen_reloc): Turn an absolute fx_subsy into part of fx_offset.
2001-11-04  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.h (TC_RELOC_RTSYM_LOC_FIXUP): Don't adjust
BDF_RELOC_MN10300_GOT32.
* config/tc-mn10300.c (mn10300_fix_adjustable): If
TC_RELOC_RTSYM_LOC_FIXUP doesn't hold, it's not adjustable.
2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.c (mn10300_parse_name): Don't return a
symbol if we know its value.
2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.h (GLOBAL_OFFSET_TABLE_NAME): Remove
duplicate underscore prefix.
2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.c (mn10300_parse_name): Store relocation
type in X_md, not X_add_number.  Zero X_add_number.
(mn10300_check_fixup): Extract relocation type from X_md.
* config/tc-mn10300.h: Update comment.
2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
* config/tc-mn10300.h (O_GOTOFF, O_PLT, O_GOT): Replace with...
(O_PIC_reloc): this.
* config/tc-mn10300.c (mn10300_PIC_related_p): Use it.
(mn10300_check_fixup): Likewise.
(mn10300_parse_name): Set X_add_number to relocation type.
* config/tc-mn10300.h (DIFF_EXPR_OK, GLOBAL_OFFSET_TABLE_NAME,
TC_RELOC_RTSYM_LOC_FIXUP, md_parse_name, TC_CONS_FIX_NEW,
O_GOTOFF, O_PLT, O_GOT): Define.
* config/tc-mn10300.c (mn10300_PIC_related_p): New fn.
(mn10300_check_fixup): New fn.
(md_assemble): Call it.  Check for PIC-related relocs.
(mn10300_cons_fix_new): Likewise.  New fn.
(mn10300_end_of_match): New fn.
(mn10300_md_parse_name_cont): New fn.

gas/ChangeLog
gas/config/tc-mn10300.c
gas/config/tc-mn10300.h

index d7ee712a3b73c5ce4075d5afecf0ca31b4fe1b01..ddfe1a50f6b6cf0e60d5d5415bc670752d7e52a5 100644 (file)
@@ -1,3 +1,45 @@
+2003-07-09  Alexandre Oliva  <aoliva@redhat.com>
+
+       2003-02-25  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.c (mn10300_check_fixup): Set GOT_PCREL type
+       for subtracts from GLOBAL_OFFSET_TABLE that could not be
+       simplified.
+       2002-07-18  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.c (mn10300_check_fixup): Accept subtracts that
+       could not be simplified.
+       (tc_gen_reloc): Turn an absolute fx_subsy into part of fx_offset.
+       2001-11-04  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.h (TC_RELOC_RTSYM_LOC_FIXUP): Don't adjust
+       BDF_RELOC_MN10300_GOT32.
+       * config/tc-mn10300.c (mn10300_fix_adjustable): If
+       TC_RELOC_RTSYM_LOC_FIXUP doesn't hold, it's not adjustable.
+       2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.c (mn10300_parse_name): Don't return a
+       symbol if we know its value.
+       2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.h (GLOBAL_OFFSET_TABLE_NAME): Remove
+       duplicate underscore prefix.
+       2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.c (mn10300_parse_name): Store relocation
+       type in X_md, not X_add_number.  Zero X_add_number.
+       (mn10300_check_fixup): Extract relocation type from X_md.
+       * config/tc-mn10300.h: Update comment.
+       2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/tc-mn10300.h (O_GOTOFF, O_PLT, O_GOT): Replace with...
+       (O_PIC_reloc): this.
+       * config/tc-mn10300.c (mn10300_PIC_related_p): Use it.
+       (mn10300_check_fixup): Likewise.
+       (mn10300_parse_name): Set X_add_number to relocation type.
+       * config/tc-mn10300.h (DIFF_EXPR_OK, GLOBAL_OFFSET_TABLE_NAME,
+       TC_RELOC_RTSYM_LOC_FIXUP, md_parse_name, TC_CONS_FIX_NEW,
+       O_GOTOFF, O_PLT, O_GOT): Define.
+       * config/tc-mn10300.c (mn10300_PIC_related_p): New fn.
+       (mn10300_check_fixup): New fn.
+       (md_assemble): Call it.  Check for PIC-related relocs.
+       (mn10300_cons_fix_new): Likewise.  New fn.
+       (mn10300_end_of_match): New fn.
+       (mn10300_md_parse_name_cont): New fn.
+
 2003-07-09  Alexandre Oliva  <aoliva@redhat.com>
 
        2000-05-25  Alexandre Oliva  <aoliva@cygnus.com>
index ff2fffa14836086628f03ea618fd7a217908e4aa..e36d0f9ada3cc873b89fc6aa61f93470381819ec 100644 (file)
@@ -1219,6 +1219,140 @@ md_begin ()
   current_machine = MN103;
 }
 
+static symbolS *GOT_symbol;
+
+static inline int mn10300_check_fixup PARAMS ((struct mn10300_fixup *));
+static inline int mn10300_PIC_related_p PARAMS ((symbolS *));
+
+static inline int
+mn10300_PIC_related_p (sym)
+     symbolS *sym;
+{
+  expressionS *exp;
+
+  if (! sym)
+    return 0;
+
+  if (sym == GOT_symbol)
+    return 1;
+
+  exp = symbol_get_value_expression (sym);
+
+  return (exp->X_op == O_PIC_reloc
+         || mn10300_PIC_related_p (exp->X_add_symbol)
+         || mn10300_PIC_related_p (exp->X_op_symbol));
+}
+
+static inline int
+mn10300_check_fixup (fixup)
+     struct mn10300_fixup *fixup;
+{
+  expressionS *exp = &fixup->exp;
+
+ repeat:
+  switch (exp->X_op)
+    {
+    case O_add:
+    case O_subtract: /* If we're sufficiently unlucky that the label
+                       and the expression that references it happen
+                       to end up in different frags, the subtract
+                       won't be simplified within expression().  */
+      /* The PIC-related operand must be the first operand of a sum.  */
+      if (exp != &fixup->exp || mn10300_PIC_related_p (exp->X_op_symbol))
+       return 1;
+
+      if (exp->X_add_symbol && exp->X_add_symbol == GOT_symbol)
+       fixup->reloc = BFD_RELOC_32_GOT_PCREL;
+
+      exp = symbol_get_value_expression (exp->X_add_symbol);
+      goto repeat;
+
+    case O_symbol:
+      if (exp->X_add_symbol && exp->X_add_symbol == GOT_symbol)
+       fixup->reloc = BFD_RELOC_32_GOT_PCREL;
+      break;
+
+    case O_PIC_reloc:
+      fixup->reloc = exp->X_md;
+      exp->X_op = O_symbol;
+      if (fixup->reloc == BFD_RELOC_32_PLT_PCREL
+         && fixup->opindex >= 0
+         && (mn10300_operands[fixup->opindex].flags
+             & MN10300_OPERAND_RELAX))
+       return 1;
+      break;
+
+    default:
+      return (mn10300_PIC_related_p (exp->X_add_symbol)
+             || mn10300_PIC_related_p (exp->X_op_symbol));
+    }
+
+  return 0;
+}
+
+void
+mn10300_cons_fix_new (frag, off, size, exp)
+     fragS *frag;
+     int off, size;
+     expressionS *exp;
+{
+  struct mn10300_fixup fixup;
+
+  fixup.opindex = -1;
+  fixup.exp = *exp;
+  fixup.reloc = BFD_RELOC_UNUSED;
+
+  mn10300_check_fixup (&fixup);
+
+  if (fixup.reloc == BFD_RELOC_MN10300_GOT32)
+    switch (size)
+      {
+      case 2:
+       fixup.reloc = BFD_RELOC_MN10300_GOT16;
+       break;
+
+      case 3:
+       fixup.reloc = BFD_RELOC_MN10300_GOT24;
+       break;
+
+      case 4:
+       break;
+
+      default:
+       goto error;
+      }
+  else if (fixup.reloc == BFD_RELOC_UNUSED)
+    switch (size)
+      {
+      case 1:
+       fixup.reloc = BFD_RELOC_8;
+       break;
+
+      case 2:
+       fixup.reloc = BFD_RELOC_16;
+       break;
+
+      case 3:
+       fixup.reloc = BFD_RELOC_24;
+       break;
+
+      case 4:
+       fixup.reloc = BFD_RELOC_32;
+       break;
+
+      default:
+       goto error;
+      }
+  else if (size != 4)
+    {
+    error:
+      as_bad (_("unsupported BFD relocation size %u"), size);
+      fixup.reloc = BFD_RELOC_UNUSED;
+    }
+    
+  fix_new_exp (frag, off, size, &fixup.exp, 0, fixup.reloc);
+}
+
 void
 md_assemble (str)
      char *str;
@@ -1748,6 +1882,8 @@ md_assemble (str)
              fixups[fc].exp = ex;
              fixups[fc].opindex = *opindex_ptr;
              fixups[fc].reloc = BFD_RELOC_UNUSED;
+             if (mn10300_check_fixup (& fixups[fc]))
+               goto error;
              ++fc;
              break;
            }
@@ -2042,7 +2178,11 @@ keep_going:
          const struct mn10300_operand *operand;
 
          operand = &mn10300_operands[fixups[i].opindex];
-         if (fixups[i].reloc != BFD_RELOC_UNUSED)
+         if (fixups[i].reloc != BFD_RELOC_UNUSED
+             && fixups[i].reloc != BFD_RELOC_32_GOT_PCREL
+             && fixups[i].reloc != BFD_RELOC_32_GOTOFF
+             && fixups[i].reloc != BFD_RELOC_32_PLT_PCREL
+             && fixups[i].reloc != BFD_RELOC_MN10300_GOT32)
            {
              reloc_howto_type *reloc_howto;
              int size;
@@ -2072,6 +2212,8 @@ keep_going:
              fixS *fixP;
 
              reloc = BFD_RELOC_NONE;
+             if (fixups[i].reloc != BFD_RELOC_UNUSED)
+               reloc = fixups[i].reloc;
              /* How big is the reloc?  Remember SPLIT relocs are
                 implicitly 32bits.  */
              if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
@@ -2083,11 +2225,15 @@ keep_going:
 
              /* Is the reloc pc-relative?  */
              pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0;
+             if (reloc != BFD_RELOC_NONE)
+               pcrel = bfd_reloc_type_lookup (stdoutput, reloc)->pc_relative;
 
              offset = size - (reloc_size + operand->shift) / 8;
 
              /* Choose a proper BFD relocation type.  */
-             if (pcrel)
+             if (reloc != BFD_RELOC_NONE)
+               ;
+             else if (pcrel)
                {
                  if (reloc_size == 32)
                    reloc = BFD_RELOC_32_PCREL;
@@ -2153,6 +2299,13 @@ tc_gen_reloc (seg, fixp)
     }
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 
+  if (fixp->fx_subsy
+      && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+    {
+      fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
+      fixp->fx_subsy = 0;
+    }
+
   if (fixp->fx_addsy && fixp->fx_subsy)
     {
       reloc->sym_ptr_ptr = NULL;
@@ -2368,6 +2521,9 @@ bfd_boolean
 mn10300_fix_adjustable (fixp)
      struct fix *fixp;
 {
+  if (! TC_RELOC_RTSYM_LOC_FIXUP (fixp))
+    return 0;
+
   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -2560,3 +2716,87 @@ set_arch_mach (mach)
 
   current_machine = mach;
 }
+
+static inline char * mn10300_end_of_match PARAMS ((char *, char *));
+
+static inline char *
+mn10300_end_of_match (cont, what)
+     char *cont, *what;
+{
+  int len = strlen (what);
+
+  if (strncmp (cont, what, strlen (what)) == 0
+      && ! is_part_of_name (cont[len]))
+    return cont + len;
+
+  return NULL;
+}  
+
+int
+mn10300_parse_name (name, exprP, nextcharP)
+     char const *name;
+     expressionS *exprP;
+     char *nextcharP;
+{
+  char *next = input_line_pointer;
+  char *next_end;
+  int reloc_type;
+  segT segment;
+
+  exprP->X_op_symbol = NULL;
+
+  if (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0)
+    {
+      if (! GOT_symbol)
+       GOT_symbol = symbol_find_or_make (name);
+
+      exprP->X_add_symbol = GOT_symbol;
+    no_suffix:
+      /* If we have an absolute symbol or a reg,
+        then we know its value now.  */
+      segment = S_GET_SEGMENT (exprP->X_add_symbol);
+      if (segment == absolute_section)
+       {
+         exprP->X_op = O_constant;
+         exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
+         exprP->X_add_symbol = NULL;
+       }
+      else if (segment == reg_section)
+       {
+         exprP->X_op = O_register;
+         exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
+         exprP->X_add_symbol = NULL;
+       }
+      else
+       {
+         exprP->X_op = O_symbol;
+         exprP->X_add_number = 0;
+       }
+
+      return 1;
+    }
+
+  exprP->X_add_symbol = symbol_find_or_make (name);
+  
+  if (*nextcharP != '@')
+    goto no_suffix;
+  else if ((next_end = mn10300_end_of_match (next + 1, "GOTOFF")))
+    reloc_type = BFD_RELOC_32_GOTOFF;
+  else if ((next_end = mn10300_end_of_match (next + 1, "GOT")))
+    reloc_type = BFD_RELOC_MN10300_GOT32;
+  else if ((next_end = mn10300_end_of_match (next + 1, "PLT")))
+    reloc_type = BFD_RELOC_32_PLT_PCREL;
+  else
+    goto no_suffix;
+
+  *input_line_pointer = *nextcharP;
+  input_line_pointer = next_end;
+  *nextcharP = *input_line_pointer;
+  *input_line_pointer = '\0';
+
+  exprP->X_op = O_PIC_reloc;
+  exprP->X_add_number = 0;
+  exprP->X_md = reloc_type;
+
+  return 1;
+}
index 736f93b29922821c011391eddc9f4c1ee3a0fc81..955165236d63333180f8cd93aff2cd7bf15e16f5 100644 (file)
  #error MN10300 support requires BFD_ASSEMBLER
 #endif
 
+#define DIFF_EXPR_OK
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX)                          \
+  ((FIX)->fx_r_type != BFD_RELOC_32_PLT_PCREL                  \
+   && (FIX)->fx_r_type != BFD_RELOC_MN10300_GOT32              \
+   && (FIX)->fx_r_type != BFD_RELOC_32_GOT_PCREL               \
+   && ((FIX)->fx_addsy == NULL                                 \
+       || (! S_IS_EXTERNAL ((FIX)->fx_addsy)                   \
+          && ! S_IS_WEAK ((FIX)->fx_addsy)                     \
+          && S_IS_DEFINED ((FIX)->fx_addsy)                    \
+          && ! S_IS_COMMON ((FIX)->fx_addsy))))
+
+#define md_parse_name(name, exprP, nextcharP) \
+    mn10300_parse_name ((name), (exprP), (nextcharP))
+int mn10300_parse_name PARAMS ((char const *, expressionS *, char *));
+
+#define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \
+     mn10300_cons_fix_new ((FRAG), (OFF), (LEN), (EXP))
+void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
+
+/* This is used to construct expressions out of @GOTOFF, @PLT and @GOT
+   symbols.  The relocation type is stored in X_md.  */
+#define O_PIC_reloc O_md1
+
 /* The target BFD architecture.  */
 #define TARGET_ARCH bfd_arch_mn10300