Add support for using the ADR alias in Thumb mode against nearby symbols.
[deliverable/binutils-gdb.git] / gas / config / tc-sh64.c
index fe82b4632cc5115d9d58c9fe9ae5d32c82b20cd2..780052bb77a82a6f0d363b85d17ee3c6d5c2e2ea 100644 (file)
@@ -1,11 +1,11 @@
 /* tc-sh64.c -- Assemble code for the SuperH SH SHcompact and SHmedia.
 /* tc-sh64.c -- Assemble code for the SuperH SH SHcompact and SHmedia.
-   Copyright 2000, 2001, 2002, 2003 Free Software Foundation.
+   Copyright (C) 2000-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* This file defines SHmedia ISA-specific functions and includes tc-sh.c.
    The SHcompact ISA is in all useful aspects the "old" sh4 as implemented
 
 /* This file defines SHmedia ISA-specific functions and includes tc-sh.c.
    The SHcompact ISA is in all useful aspects the "old" sh4 as implemented
@@ -25,7 +25,6 @@
 
 #define HAVE_SH64
 
 
 #define HAVE_SH64
 
-#include <stdio.h>
 #include "as.h"
 #include "safe-ctype.h"
 #include "opcodes/sh64-opc.h"
 #include "as.h"
 #include "safe-ctype.h"
 #include "opcodes/sh64-opc.h"
@@ -39,7 +38,7 @@
    symbol" or local symbol.  */
 #define DATALABEL_SUFFIX " DL"
 
    symbol" or local symbol.  */
 #define DATALABEL_SUFFIX " DL"
 
-/* See shmedia_md_apply_fix3 and shmedia_md_pcrel_from_section for usage.  */
+/* See shmedia_md_apply_fix and shmedia_md_pcrel_from_section for usage.  */
 #define SHMEDIA_MD_PCREL_FROM_FIX(FIXP) \
  ((FIXP)->fx_size + (FIXP)->fx_where + (FIXP)->fx_frag->fr_address - 4)
 
 #define SHMEDIA_MD_PCREL_FROM_FIX(FIXP) \
  ((FIXP)->fx_size + (FIXP)->fx_where + (FIXP)->fx_frag->fr_address - 4)
 
@@ -136,7 +135,7 @@ static const unsigned char shmedia_little_nop_pattern[4] =
 static void shmedia_md_begin (void);
 static int shmedia_parse_reg (char *, int *, int *, shmedia_arg_type);
 static void shmedia_md_assemble (char *);
 static void shmedia_md_begin (void);
 static int shmedia_parse_reg (char *, int *, int *, shmedia_arg_type);
 static void shmedia_md_assemble (char *);
-static void shmedia_md_apply_fix3 (fixS *, valueT *);
+static void shmedia_md_apply_fix (fixS *, valueT *);
 static int shmedia_md_estimate_size_before_relax (fragS *, segT);
 static int shmedia_init_reloc (arelent *, fixS *);
 static char *shmedia_get_operands (shmedia_opcode_info *, char *,
 static int shmedia_md_estimate_size_before_relax (fragS *, segT);
 static int shmedia_init_reloc (arelent *, fixS *);
 static char *shmedia_get_operands (shmedia_opcode_info *, char *,
@@ -284,7 +283,7 @@ shmedia_frob_file_before_adjust (void)
 
       if (mainsym != NULL
          && S_GET_OTHER (mainsym) != STO_SH5_ISA32
 
       if (mainsym != NULL
          && S_GET_OTHER (mainsym) != STO_SH5_ISA32
-         && (S_IS_EXTERN (mainsym) || S_IS_WEAK (mainsym)))
+         && (S_IS_EXTERNAL (mainsym) || S_IS_WEAK (mainsym)))
        {
          symp->sy_value.X_op = O_symbol;
          symp->sy_value.X_add_symbol = mainsym;
        {
          symp->sy_value.X_op = O_symbol;
          symp->sy_value.X_add_symbol = mainsym;
@@ -577,10 +576,10 @@ shmedia_init_reloc (arelent *rel, fixS *fixP)
   return 0;
 }
 
   return 0;
 }
 
-/* Hook called from md_apply_fix3 in tc-sh.c.  */
+/* Hook called from md_apply_fix in tc-sh.c.  */
 
 static void
 
 static void
-shmedia_md_apply_fix3 (fixS *fixP, valueT *valp)
+shmedia_md_apply_fix (fixS *fixP, valueT *valp)
 {
   offsetT val = *valp;
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 {
   offsetT val = *valp;
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
@@ -602,7 +601,7 @@ shmedia_md_apply_fix3 (fixS *fixP, valueT *valp)
          /* Because write.c calls MD_PCREL_FROM_SECTION twice, we need to
             undo one of the adjustments, if the relocation is not
             actually for a symbol within the same segment (which we
          /* Because write.c calls MD_PCREL_FROM_SECTION twice, we need to
             undo one of the adjustments, if the relocation is not
             actually for a symbol within the same segment (which we
-            cannot check, because we're not called from md_apply_fix3, so
+            cannot check, because we're not called from md_apply_fix, so
             we have to keep the reloc).  FIXME: This is a bug in
             write.c:fixup_segment affecting most targets that change
             ordinary relocs to pcrel relocs in md_apply_fix.  */
             we have to keep the reloc).  FIXME: This is a bug in
             write.c:fixup_segment affecting most targets that change
             ordinary relocs to pcrel relocs in md_apply_fix.  */
@@ -691,7 +690,7 @@ shmedia_md_apply_fix3 (fixS *fixP, valueT *valp)
   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
     {
       /* Emit error for an out-of-range value.  */
   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
     {
       /* Emit error for an out-of-range value.  */
-      shmedia_check_limits (valp, fixP->fx_r_type, fixP);
+      shmedia_check_limits ((offsetT *) valp, fixP->fx_r_type, fixP);
 
       switch (fixP->fx_r_type)
        {
 
       switch (fixP->fx_r_type)
        {
@@ -823,7 +822,7 @@ shmedia_md_convert_frag (bfd *output_bfd ATTRIBUTE_UNUSED,
        || sh_relax
        || symbolP == NULL
        || ! S_IS_DEFINED (symbolP)
        || sh_relax
        || symbolP == NULL
        || ! S_IS_DEFINED (symbolP)
-       || S_IS_EXTERN (symbolP)
+       || S_IS_EXTERNAL (symbolP)
        || S_IS_WEAK (symbolP)
        || (S_GET_SEGMENT (fragP->fr_symbol) != absolute_section
           && S_GET_SEGMENT (fragP->fr_symbol) != seg));
        || S_IS_WEAK (symbolP)
        || (S_GET_SEGMENT (fragP->fr_symbol) != absolute_section
           && S_GET_SEGMENT (fragP->fr_symbol) != seg));
@@ -1533,7 +1532,7 @@ shmedia_check_limits (offsetT *valp, bfd_reloc_code_real_type reloc,
 
     case BFD_RELOC_SH_IMMU16:
       if (val < 0 || val > (1 << 16) - 1)
 
     case BFD_RELOC_SH_IMMU16:
       if (val < 0 || val > (1 << 16) - 1)
-       msg = _("invalid operand, not an 16-bit unsigned value: %d");
+       msg = _("invalid operand, not a 16-bit unsigned value: %d");
       break;
 
     case BFD_RELOC_SH_PT_16:
       break;
 
     case BFD_RELOC_SH_PT_16:
@@ -2204,16 +2203,16 @@ static char *
 shmedia_parse_exp (char *s, shmedia_operand_info *op)
 {
   char *save;
 shmedia_parse_exp (char *s, shmedia_operand_info *op)
 {
   char *save;
-  char *new;
+  char *new_pointer;
 
   save = input_line_pointer;
   input_line_pointer = s;
   expression (&op->immediate);
   if (op->immediate.X_op == O_absent)
     as_bad (_("missing operand"));
 
   save = input_line_pointer;
   input_line_pointer = s;
   expression (&op->immediate);
   if (op->immediate.X_op == O_absent)
     as_bad (_("missing operand"));
-  new = input_line_pointer;
+  new_pointer = input_line_pointer;
   input_line_pointer = save;
   input_line_pointer = save;
-  return new;
+  return new_pointer;
 }
 
 /* Parse an operand.  Store pointer to next character in *PTR.  */
 }
 
 /* Parse an operand.  Store pointer to next character in *PTR.  */
@@ -2677,7 +2676,10 @@ shmedia_build_Mytes (shmedia_opcode_info *opcode,
 
            /* Don't allow complex expressions here.  */
            if (opjp->immediate.X_op_symbol != NULL)
 
            /* Don't allow complex expressions here.  */
            if (opjp->immediate.X_op_symbol != NULL)
-             return 0;
+             {
+               as_bad (_("invalid operand: expression in PT target"));
+               return 0;
+             }
 
            if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL)
              init = max = min = SH64PCRELPLT;
 
            if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL)
              init = max = min = SH64PCRELPLT;
@@ -2714,7 +2716,10 @@ shmedia_build_Mytes (shmedia_opcode_info *opcode,
 
            /* Don't allow complex expressions here.  */
            if (opjp->immediate.X_op_symbol != NULL)
 
            /* Don't allow complex expressions here.  */
            if (opjp->immediate.X_op_symbol != NULL)
-             return 0;
+             {
+               as_bad (_("invalid operand: expression in PT target"));
+               return 0;
+             }
 
            if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL)
              init = max = min = SH64PCRELPLT;
 
            if (opjp->reloctype == BFD_RELOC_32_PLT_PCREL)
              init = max = min = SH64PCRELPLT;
@@ -2730,7 +2735,7 @@ shmedia_build_Mytes (shmedia_opcode_info *opcode,
                        insn_loc);
            else
              /* This reloc-type is just temporary, so we can distinguish
                        insn_loc);
            else
              /* This reloc-type is just temporary, so we can distinguish
-                PTA from PT.  It is changed in shmedia_md_apply_fix3 to
+                PTA from PT.  It is changed in shmedia_md_apply_fix to
                 BFD_RELOC_SH_PT_16.  */
              insn |= shmedia_immediate_op (insn_loc, opjp, 1,
                                            opjp->reloctype == BFD_RELOC_NONE
                 BFD_RELOC_SH_PT_16.  */
              insn |= shmedia_immediate_op (insn_loc, opjp, 1,
                                            opjp->reloctype == BFD_RELOC_NONE
@@ -2922,14 +2927,14 @@ sh64_target_format (void)
 {
 #ifdef TE_NetBSD
   /* For NetBSD, if the ISA is unspecified, always use SHmedia.  */
 {
 #ifdef TE_NetBSD
   /* For NetBSD, if the ISA is unspecified, always use SHmedia.  */
-  if (sh64_isa_mode == sh64_isa_unspecified)
+  if (preset_target_arch == 0 && sh64_isa_mode == sh64_isa_unspecified)
     sh64_isa_mode = sh64_isa_shmedia;
 
   /* If the ABI is unspecified, select a default: based on how
      we were configured: sh64 == sh64_abi_64, else sh64_abi_32.  */
   if (sh64_abi == sh64_abi_unspecified)
     {
     sh64_isa_mode = sh64_isa_shmedia;
 
   /* If the ABI is unspecified, select a default: based on how
      we were configured: sh64 == sh64_abi_64, else sh64_abi_32.  */
   if (sh64_abi == sh64_abi_unspecified)
     {
-      if (sh64_isa_mode == sh64_isa_shcompact)
+      if (preset_target_arch != 0 || sh64_isa_mode == sh64_isa_shcompact)
        sh64_abi = sh64_abi_32;
       else if (strncmp (TARGET_CPU, "sh64", 4) == 0)
         sh64_abi = sh64_abi_64;
        sh64_abi = sh64_abi_32;
       else if (strncmp (TARGET_CPU, "sh64", 4) == 0)
         sh64_abi = sh64_abi_64;
@@ -2939,7 +2944,7 @@ sh64_target_format (void)
 #endif
 
 #ifdef TE_LINUX
 #endif
 
 #ifdef TE_LINUX
-  if (sh64_isa_mode == sh64_isa_unspecified)
+  if (preset_target_arch == 0 && sh64_isa_mode == sh64_isa_unspecified)
     sh64_isa_mode = sh64_isa_shmedia;
 
   if (sh64_abi == sh64_abi_unspecified)
     sh64_isa_mode = sh64_isa_shmedia;
 
   if (sh64_abi == sh64_abi_unspecified)
@@ -3029,8 +3034,6 @@ sh64_target_mach (void)
 valueT
 shmedia_md_pcrel_from_section (struct fix *fixP, segT sec ATTRIBUTE_UNUSED)
 {
 valueT
 shmedia_md_pcrel_from_section (struct fix *fixP, segT sec ATTRIBUTE_UNUSED)
 {
-  know (fixP->fx_frag->fr_type == rs_machine_dependent);
-
   /* Use the ISA for the instruction to decide which offset to use.  We
      can glean it from the fisup type.  */
   switch (fixP->fx_r_type)
   /* Use the ISA for the instruction to decide which offset to use.  We
      can glean it from the fisup type.  */
   switch (fixP->fx_r_type)
@@ -3060,8 +3063,7 @@ shmedia_md_pcrel_from_section (struct fix *fixP, segT sec ATTRIBUTE_UNUSED)
 
     case BFD_RELOC_64:
     case BFD_RELOC_64_PCREL:
 
     case BFD_RELOC_64:
     case BFD_RELOC_64_PCREL:
-      know (0 /* Shouldn't get here.  */);
-      break;
+      /* Fall through.  */
 
     default:
       /* If section was SHcompact, use its function.  */
 
     default:
       /* If section was SHcompact, use its function.  */
@@ -3238,8 +3240,9 @@ sh64_frob_label (symbolS *symp)
    symbol hook.  */
 
 int
    symbol hook.  */
 
 int
-sh64_consume_datalabel (const char *name, expressionS *exp, char *cp,
-                       segT (*operandf) (expressionS *))
+sh64_consume_datalabel (const char *name, expressionS *exp,
+                       enum expr_mode mode, char *cp,
+                       segT (*operandf) (expressionS *, enum expr_mode))
 {
   static int parsing_datalabel = 0;
 
 {
   static int parsing_datalabel = 0;
 
@@ -3252,7 +3255,7 @@ sh64_consume_datalabel (const char *name, expressionS *exp, char *cp,
 
       *input_line_pointer = *cp;
       parsing_datalabel = 1;
 
       *input_line_pointer = *cp;
       parsing_datalabel = 1;
-      (*operandf) (exp);
+      (*operandf) (exp, expr_normal);
       parsing_datalabel = save_parsing_datalabel;
 
       if (exp->X_op == O_symbol || exp->X_op == O_PIC_reloc)
       parsing_datalabel = save_parsing_datalabel;
 
       if (exp->X_op == O_symbol || exp->X_op == O_PIC_reloc)
@@ -3269,9 +3272,9 @@ sh64_consume_datalabel (const char *name, expressionS *exp, char *cp,
          else
            {
              symbolS *dl_symp;
          else
            {
              symbolS *dl_symp;
-             const char *name = S_GET_NAME (symp);
+             const char * sname = S_GET_NAME (symp);
              char *dl_name
              char *dl_name
-               = xmalloc (strlen (name) + sizeof (DATALABEL_SUFFIX));
+               = xmalloc (strlen (sname) + sizeof (DATALABEL_SUFFIX));
 
              /* Now we copy the datalabel-qualified symbol into a symbol
                 with the same name, but with " DL" appended.  We mark the
 
              /* Now we copy the datalabel-qualified symbol into a symbol
                 with the same name, but with " DL" appended.  We mark the
@@ -3279,13 +3282,13 @@ sh64_consume_datalabel (const char *name, expressionS *exp, char *cp,
                 the main symbol, so we don't have to inspect all symbol
                 names.  Note that use of "datalabel" is not expected to
                 be a common case.  */
                 the main symbol, so we don't have to inspect all symbol
                 names.  Note that use of "datalabel" is not expected to
                 be a common case.  */
-             strcpy (dl_name, name);
+             strcpy (dl_name, sname);
              strcat (dl_name, DATALABEL_SUFFIX);
 
              /* A FAKE_LABEL_NAME marks "$" or ".".  There can be any
                 number of them and all have the same (faked) name; we
                 must make a new one each time.  */
              strcat (dl_name, DATALABEL_SUFFIX);
 
              /* A FAKE_LABEL_NAME marks "$" or ".".  There can be any
                 number of them and all have the same (faked) name; we
                 must make a new one each time.  */
-             if (strcmp (name, FAKE_LABEL_NAME) == 0)
+             if (strcmp (sname, FAKE_LABEL_NAME) == 0)
                dl_symp = symbol_make (dl_name);
              else
                dl_symp = symbol_find_or_make (dl_name);
                dl_symp = symbol_make (dl_name);
              else
                dl_symp = symbol_find_or_make (dl_name);
@@ -3325,7 +3328,7 @@ sh64_consume_datalabel (const char *name, expressionS *exp, char *cp,
       return 1;
     }
 
       return 1;
     }
 
-  return sh_parse_name (name, exp, cp);
+  return sh_parse_name (name, exp, mode, cp);
 }
 
 /* This function is called just before symbols are being output.  It
 }
 
 /* This function is called just before symbols are being output.  It
@@ -3507,3 +3510,18 @@ sh64_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
   input_line_pointer = eol;
 }
 
   input_line_pointer = eol;
 }
 
+int
+sh64_fake_label (const char *name)
+{
+  size_t len;
+
+  if (strcmp (name, FAKE_LABEL_NAME) == 0)
+    return 1;
+
+  len = strlen (name);
+  if (len >= (sizeof (DATALABEL_SUFFIX) - 1))
+    return strcmp (&name [len - sizeof (DATALABEL_SUFFIX) + 1],
+                  DATALABEL_SUFFIX) == 0;
+
+  return 0;
+}
This page took 0.027388 seconds and 4 git commands to generate.