s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[deliverable/binutils-gdb.git] / gas / config / tc-mn10300.c
index 21e8e42938dbd73522094cfb861876a4b6a2cf6a..6749460e73d904486dab7969dbc712b1a53d114a 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-mn10300.c -- Assembler code for the Matsushita 10300
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -19,8 +20,8 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include "as.h"
+#include "safe-ctype.h"
 #include "subsegs.h"
 #include "opcode/mn10300.h"
 #include "dwarf2dbg.h"
@@ -88,10 +89,10 @@ static unsigned long check_operand PARAMS ((unsigned long,
                                            const struct mn10300_operand *,
                                            offsetT));
 static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
-static boolean data_register_name PARAMS ((expressionS *expressionP));
-static boolean address_register_name PARAMS ((expressionS *expressionP));
-static boolean other_register_name PARAMS ((expressionS *expressionP));
-static void set_arch_mach PARAMS ((int));
+static bfd_boolean data_register_name PARAMS ((expressionS *expressionP));
+static bfd_boolean address_register_name PARAMS ((expressionS *expressionP));
+static bfd_boolean other_register_name PARAMS ((expressionS *expressionP));
+static void set_arch_mach PARAMS ((unsigned int));
 
 /*  Set linkrelax here to avoid fixups in most sections.  */
 int linkrelax = 1;
@@ -122,7 +123,7 @@ size_t md_longopts_size = sizeof (md_longopts);
 /* The target specific pseudo-ops which we support.  */
 const pseudo_typeS md_pseudo_table[] =
 {
-  { "file",     dwarf2_directive_file,  0 },
+  { "file",     (void (*) PARAMS ((int))) dwarf2_directive_file,  0 },
   { "loc",      dwarf2_directive_loc,   0 },
   { "am30",    set_arch_mach,          AM30 },
   { "am33",    set_arch_mach,          AM33 },
@@ -233,9 +234,16 @@ static const struct reg_name xr_registers[] =
 #define XR_REG_NAME_CNT                                        \
   (sizeof (xr_registers) / sizeof (struct reg_name))
 
+/* We abuse the `value' field, that would be otherwise unused, to
+   encode the architecture on which (access to) the register was
+   introduced.  FIXME: we should probably warn when we encounter a
+   register name when assembling for an architecture that doesn't
+   support it, before parsing it as a symbol name.  */
 static const struct reg_name other_registers[] =
 {
+  { "epsw", AM33 },
   { "mdr", 0 },
+  { "pc", AM33 },
   { "psw", 0 },
   { "sp", 0 },
 };
@@ -278,14 +286,14 @@ reg_name_search (regs, regcount, name)
  *
  * in: Input_line_pointer points to 1st char of operand.
  *
- * out: A expressionS.
+ * out: An expressionS.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 
-static boolean
+static bfd_boolean
 r_register_name (expressionP)
      expressionS *expressionP;
 {
@@ -300,6 +308,9 @@ r_register_name (expressionP)
   c = get_symbol_end ();
   reg_number = reg_name_search (r_registers, R_REG_NAME_CNT, name);
 
+  /* Put back the delimiting char.  */
+  *input_line_pointer = c;
+
   /* Look to see if it's in the register table.  */
   if (reg_number >= 0)
     {
@@ -310,34 +321,26 @@ r_register_name (expressionP)
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
 
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-      return true;
+      return TRUE;
     }
-  else
-    {
-      /* Reset the line as if we had not done anything.  */
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
 
-      /* Reset input_line pointer.  */
-      input_line_pointer = start;
-      return false;
-    }
+  /* Reset the line as if we had not done anything.  */
+  input_line_pointer = start;
+  return FALSE;
 }
 
 /* Summary of register_name().
  *
  * in: Input_line_pointer points to 1st char of operand.
  *
- * out: A expressionS.
+ * out: An expressionS.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 
-static boolean
+static bfd_boolean
 xr_register_name (expressionP)
      expressionS *expressionP;
 {
@@ -352,6 +355,9 @@ xr_register_name (expressionP)
   c = get_symbol_end ();
   reg_number = reg_name_search (xr_registers, XR_REG_NAME_CNT, name);
 
+  /* Put back the delimiting char.  */
+  *input_line_pointer = c;
+
   /* Look to see if it's in the register table.  */
   if (reg_number >= 0)
     {
@@ -362,34 +368,26 @@ xr_register_name (expressionP)
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
 
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-      return true;
+      return TRUE;
     }
-  else
-    {
-      /* Reset the line as if we had not done anything.  */
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
 
-      /* Reset input_line pointer.  */
-      input_line_pointer = start;
-      return false;
-    }
+  /* Reset the line as if we had not done anything.  */
+  input_line_pointer = start;
+  return FALSE;
 }
 
 /* Summary of register_name().
  *
  * in: Input_line_pointer points to 1st char of operand.
  *
- * out: A expressionS.
+ * out: An expressionS.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 
-static boolean
+static bfd_boolean
 data_register_name (expressionP)
      expressionS *expressionP;
 {
@@ -404,6 +402,9 @@ data_register_name (expressionP)
   c = get_symbol_end ();
   reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
 
+  /* Put back the delimiting char.  */
+  *input_line_pointer = c;
+
   /* Look to see if it's in the register table.  */
   if (reg_number >= 0)
     {
@@ -414,34 +415,26 @@ data_register_name (expressionP)
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
 
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-      return true;
+      return TRUE;
     }
-  else
-    {
-      /* Reset the line as if we had not done anything.  */
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
 
-      /* Reset input_line pointer.  */
-      input_line_pointer = start;
-      return false;
-    }
+  /* Reset the line as if we had not done anything.  */
+  input_line_pointer = start;
+  return FALSE;
 }
 
 /* Summary of register_name().
  *
  * in: Input_line_pointer points to 1st char of operand.
  *
- * out: A expressionS.
+ * out: An expressionS.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 
-static boolean
+static bfd_boolean
 address_register_name (expressionP)
      expressionS *expressionP;
 {
@@ -456,6 +449,9 @@ address_register_name (expressionP)
   c = get_symbol_end ();
   reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
 
+  /* Put back the delimiting char.  */
+  *input_line_pointer = c;
+
   /* Look to see if it's in the register table.  */
   if (reg_number >= 0)
     {
@@ -466,35 +462,26 @@ address_register_name (expressionP)
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
 
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-      return true;
+      return TRUE;
     }
-  else
-    {
-      /* Reset the line as if we had not done anything.  */
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-
-      /* Reset input_line pointer.  */
-      input_line_pointer = start;
 
-      return false;
-    }
+  /* Reset the line as if we had not done anything.  */
+  input_line_pointer = start;
+  return FALSE;
 }
 
 /* Summary of register_name().
  *
  * in: Input_line_pointer points to 1st char of operand.
  *
- * out: A expressionS.
+ * out: An expressionS.
  *     The operand may have been a register: in this case, X_op == O_register,
  *     X_add_number is set to the register number, and truth is returned.
  *     Input_line_pointer->(next non-blank) char after operand, or is in
  *     its original state.
  */
 
-static boolean
+static bfd_boolean
 other_register_name (expressionP)
      expressionS *expressionP;
 {
@@ -509,30 +496,26 @@ other_register_name (expressionP)
   c = get_symbol_end ();
   reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
 
+  /* Put back the delimiting char.  */
+  *input_line_pointer = c;
+
   /* Look to see if it's in the register table.  */
-  if (reg_number >= 0)
+  if (reg_number == 0
+      || (reg_number == AM33 && HAVE_AM33))
     {
       expressionP->X_op = O_register;
-      expressionP->X_add_number = reg_number;
+      expressionP->X_add_number = 0;
 
       /* Make the rest nice.  */
       expressionP->X_add_symbol = NULL;
       expressionP->X_op_symbol = NULL;
 
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
-      return true;
+      return TRUE;
     }
-  else
-    {
-      /* Reset the line as if we had not done anything.  */
-      /* Put back the delimiting char.  */
-      *input_line_pointer = c;
 
-      /* Reset input_line pointer.  */
-      input_line_pointer = start;
-      return false;
-    }
+  /* Reset the line as if we had not done anything.  */
+  input_line_pointer = start;
+  return FALSE;
 }
 
 void
@@ -935,13 +918,13 @@ md_assemble (str)
   struct mn10300_opcode *next_opcode;
   const unsigned char *opindex_ptr;
   int next_opindex, relaxable;
-  unsigned long insn, extension, size = 0, real_size;
+  unsigned long insn, extension, size = 0;
   char *f;
   int i;
   int match;
 
   /* Get the opcode.  */
-  for (s = str; *s != '\0' && !isspace (*s); s++)
+  for (s = str; *s != '\0' && !ISSPACE (*s); s++)
     ;
   if (*s != '\0')
     *s++ = '\0';
@@ -955,7 +938,7 @@ md_assemble (str)
     }
 
   str = s;
-  while (isspace (*str))
+  while (ISSPACE (*str))
     ++str;
 
   input_line_pointer = str;
@@ -1469,7 +1452,7 @@ keep_going:
       break;
     }
 
-  while (isspace (*str))
+  while (ISSPACE (*str))
     ++str;
 
   if (*str != '\0')
@@ -1511,12 +1494,17 @@ keep_going:
   if (opcode->format == FMT_D4)
     size = 6;
 
-  real_size = size;
-
   if (relaxable && fc > 0)
     {
       int type;
 
+      /* We want to anchor the line info to the previous frag (if
+        there isn't one, create it), so that, when the insn is
+        resized, we still get the right address for the beginning of
+        the region.  */
+      f = frag_more (0);
+      dwarf2_emit_insn (0);
+
       /* bCC  */
       if (size == 2)
        {
@@ -1727,24 +1715,7 @@ keep_going:
              /* Is the reloc pc-relative?  */
              pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0;
 
-             /* Gross.  This disgusting hack is to make sure we
-                get the right offset for the 16/32 bit reloc in
-                "call" instructions.  Basically they're a pain
-                because the reloc isn't at the end of the instruction.  */
-             if ((size == 5 || size == 7)
-                 && (((insn >> 24) & 0xff) == 0xcd
-                     || ((insn >> 24) & 0xff) == 0xdd))
-               size -= 2;
-
-             /* Similarly for certain bit instructions which don't
-                hav their 32bit reloc at the tail of the instruction.  */
-             if (size == 7
-                 && (((insn >> 16) & 0xffff) == 0xfe00
-                     || ((insn >> 16) & 0xffff) == 0xfe01
-                     || ((insn >> 16) & 0xffff) == 0xfe02))
-               size -= 1;
-
-             offset = size - reloc_size / 8;
+             offset = size - (reloc_size + operand->shift) / 8;
 
              /* Choose a proper BFD relocation type.  */
              if (pcrel)
@@ -1787,9 +1758,9 @@ keep_going:
                fixP->fx_offset += offset;
            }
        }
-    }
 
-  dwarf2_emit_insn (real_size);
+      dwarf2_emit_insn (size);
+    }
 }
 
 /* If while processing a fixup, a reloc really needs to be created
@@ -1815,18 +1786,89 @@ tc_gen_reloc (seg, fixp)
 
   if (fixp->fx_addsy && fixp->fx_subsy)
     {
+      reloc->sym_ptr_ptr = NULL;
+
+      /* If we got a difference between two symbols, and the
+        subtracted symbol is in the current section, use a
+        PC-relative relocation.  If both symbols are in the same
+        section, the difference would have already been simplified
+        to a constant.  */
+      if (S_GET_SEGMENT (fixp->fx_subsy) == seg)
+       {
+         reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+         *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+         reloc->addend = (reloc->address - S_GET_VALUE (fixp->fx_subsy)
+                          + fixp->fx_offset);
+
+         switch (fixp->fx_r_type)
+           {
+           case BFD_RELOC_8:
+             reloc->howto = bfd_reloc_type_lookup (stdoutput,
+                                                   BFD_RELOC_8_PCREL);
+             return reloc;
+
+           case BFD_RELOC_16:
+             reloc->howto = bfd_reloc_type_lookup (stdoutput,
+                                                   BFD_RELOC_16_PCREL);
+             return reloc;
+
+           case BFD_RELOC_24:
+             reloc->howto = bfd_reloc_type_lookup (stdoutput,
+                                                   BFD_RELOC_24_PCREL);
+             return reloc;
+
+           case BFD_RELOC_32:
+             reloc->howto = bfd_reloc_type_lookup (stdoutput,
+                                                   BFD_RELOC_32_PCREL);
+             return reloc;
+
+           default:
+             /* Try to compute the absolute value below.  */
+             break;
+           }
+       }
 
       if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
          || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
        {
          as_bad_where (fixp->fx_file, fixp->fx_line,
                        "Difference of symbols in different sections is not supported");
-         return NULL;
+       }
+      else
+       {
+         char *fixpos = fixp->fx_where + fixp->fx_frag->fr_literal;
+
+         reloc->addend = (S_GET_VALUE (fixp->fx_addsy)
+                          - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset);
+
+         switch (fixp->fx_r_type)
+           {
+           case BFD_RELOC_8:
+             md_number_to_chars (fixpos, reloc->addend, 1);
+             break;
+
+           case BFD_RELOC_16:
+             md_number_to_chars (fixpos, reloc->addend, 2);
+             break;
+
+           case BFD_RELOC_24:
+             md_number_to_chars (fixpos, reloc->addend, 3);
+             break;
+
+           case BFD_RELOC_32:
+             md_number_to_chars (fixpos, reloc->addend, 4);
+             break;
+
+           default:
+             reloc->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+             return reloc;
+           }
        }
 
-      reloc->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
-      reloc->addend = (S_GET_VALUE (fixp->fx_addsy)
-                      - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset);
+      if (reloc->sym_ptr_ptr)
+       free (reloc->sym_ptr_ptr);
+      free (reloc);
+      return NULL;
     }
   else
     {
@@ -1842,44 +1884,23 @@ md_estimate_size_before_relax (fragp, seg)
      fragS *fragp;
      asection *seg;
 {
-  if (fragp->fr_subtype == 0)
-    return 2;
-  if (fragp->fr_subtype == 3)
-    return 3;
-  if (fragp->fr_subtype == 6)
-    {
-      if (!S_IS_DEFINED (fragp->fr_symbol)
-         || seg != S_GET_SEGMENT (fragp->fr_symbol))
-       {
-         fragp->fr_subtype = 7;
-         return 7;
-       }
-      else
-       return 5;
-    }
-  if (fragp->fr_subtype == 8)
-    {
-      if (!S_IS_DEFINED (fragp->fr_symbol)
-         || seg != S_GET_SEGMENT (fragp->fr_symbol))
-       {
-         fragp->fr_subtype = 9;
-         return 6;
-       }
-      else
-       return 4;
-    }
-  if (fragp->fr_subtype == 10)
-    {
-      if (!S_IS_DEFINED (fragp->fr_symbol)
-         || seg != S_GET_SEGMENT (fragp->fr_symbol))
-       {
-         fragp->fr_subtype = 12;
-         return 5;
-       }
-      else
-       return 2;
-    }
-  abort ();
+  if (fragp->fr_subtype == 6
+      && (!S_IS_DEFINED (fragp->fr_symbol)
+         || seg != S_GET_SEGMENT (fragp->fr_symbol)))
+    fragp->fr_subtype = 7;
+  else if (fragp->fr_subtype == 8
+          && (!S_IS_DEFINED (fragp->fr_symbol)
+              || seg != S_GET_SEGMENT (fragp->fr_symbol)))
+    fragp->fr_subtype = 9;
+  else if (fragp->fr_subtype == 10
+          &&  (!S_IS_DEFINED (fragp->fr_symbol)
+               || seg != S_GET_SEGMENT (fragp->fr_symbol)))
+    fragp->fr_subtype = 12;
+
+  if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
+    abort ();
+
+  return md_relax_table[fragp->fr_subtype].rlx_length;
 }
 
 long
@@ -1894,21 +1915,21 @@ md_pcrel_from (fixp)
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
-int
-md_apply_fix3 (fixp, valuep, seg)
-     fixS *fixp;
-     valueT *valuep;
+void
+md_apply_fix3 (fixP, valP, seg)
+     fixS * fixP;
+     valueT * valP;
      segT seg;
 {
-  char *fixpos = fixp->fx_where + fixp->fx_frag->fr_literal;
+  char * fixpos = fixP->fx_where + fixP->fx_frag->fr_literal;
   int size = 0;
-  int value;
+  int value = (int) * valP;
 
-  assert (fixp->fx_r_type < BFD_RELOC_UNUSED);
+  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
 
   /* This should never happen.  */
   if (seg->flags & SEC_ALLOC)
-      abort ();
+    abort ();
 
   /* The value we are passed in *valuep includes the symbol values.
      Since we are using BFD_ASSEMBLER, if we are doing this relocation
@@ -1921,53 +1942,52 @@ md_apply_fix3 (fixp, valuep, seg)
      *valuep, and must use fx_offset instead.  However, if the reloc
      is PC relative, we do want to use *valuep since it includes the
      result of md_pcrel_from.  */
-  if (fixp->fx_addsy == (symbolS *) NULL || fixp->fx_pcrel)
-    value = *valuep;
-  else
-    value = fixp->fx_offset;
+  if (fixP->fx_addsy != (symbolS *) NULL && ! fixP->fx_pcrel)
+    value = fixP->fx_offset;
 
   /* If the fix is relative to a symbol which is not defined, or not
      in the same segment as the fix, we cannot resolve it here.  */
-  if (fixp->fx_addsy != NULL
-      && (! S_IS_DEFINED (fixp->fx_addsy)
-         || (S_GET_SEGMENT (fixp->fx_addsy) != seg)))
+  if (fixP->fx_addsy != NULL
+      && (! S_IS_DEFINED (fixP->fx_addsy)
+         || (S_GET_SEGMENT (fixP->fx_addsy) != seg)))
     {
-      fixp->fx_done = 0;
-      return 0;
+      fixP->fx_done = 0;
+      return;
     }
 
-  switch (fixp->fx_r_type)
+  switch (fixP->fx_r_type)
     {
     case BFD_RELOC_8:
+    case BFD_RELOC_8_PCREL:
       size = 1;
       break;
 
     case BFD_RELOC_16:
+    case BFD_RELOC_16_PCREL:
       size = 2;
       break;
 
     case BFD_RELOC_32:
+    case BFD_RELOC_32_PCREL:
       size = 4;
       break;
 
     case BFD_RELOC_VTABLE_INHERIT:
     case BFD_RELOC_VTABLE_ENTRY:
-      fixp->fx_done = 0;
-      return 1;
+      fixP->fx_done = 0;
+      return;
 
     case BFD_RELOC_NONE:
     default:
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("Bad relocation fixup type (%d)"), fixp->fx_r_type);
+      as_bad_where (fixP->fx_file, fixP->fx_line,
+                   _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
     }
 
   md_number_to_chars (fixpos, value, size);
 
   /* If a symbol remains, pass the fixup, as a reloc, onto the linker.  */
-  if (fixp->fx_addsy == NULL)
-    fixp->fx_done = 1;
-
-  return 0;
+  if (fixP->fx_addsy == NULL)
+    fixP->fx_done = 1;
 }
 
 /* Return nonzero if the fixup in FIXP will require a relocation,
@@ -1982,24 +2002,27 @@ mn10300_force_relocation (fixp)
       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 1;
 
-  return 0;
+  return S_FORCE_RELOC (fixp->fx_addsy);
 }
 
 /* Return zero if the fixup in fixp should be left alone and not
    adjusted.  */
 
-boolean
+bfd_boolean
 mn10300_fix_adjustable (fixp)
      struct fix *fixp;
 {
-  /* Prevent all adjustments to global symbols.  */
-  if (S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
-    return 0;
-
   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
 
+  /* Do not adjust relocations involving symbols in code sections,
+     because it breaks linker relaxations.  This could be fixed in the
+     linker, but this fix is simpler, and it pretty much only affects
+     object size a little bit.  */
+  if (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE)
+    return 0;
+
   return 1;
 }
 
@@ -2129,7 +2152,7 @@ check_operand (insn, operand, val)
 
 static void
 set_arch_mach (mach)
-     int mach;
+     unsigned int mach;
 {
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, mach))
     as_warn (_("could not set architecture and machine"));
This page took 0.032637 seconds and 4 git commands to generate.