* read.c (potable): Add string8, string16, string32 and string64. Add bit size for...
[binutils-gdb.git] / gas / config / tc-mn10300.c
index e36d0f9ada3cc873b89fc6aa61f93470381819ec..64d1f6dd38d5766b7997f809201a5c0644a0cbf7 100644 (file)
@@ -1,12 +1,12 @@
 /* tc-mn10300.c -- Assembler code for the Matsushita 10300
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007 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
-   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,
 
    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.  */
 
-#include <stdio.h>
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
@@ -54,15 +53,20 @@ const char EXP_CHARS[] = "eE";
    as in 0d1.0.  */
 const char FLT_CHARS[] = "dD";
 \f
-const relax_typeS md_relax_table[] = {
+const relax_typeS md_relax_table[] =
+{
+  /* The plus values for the bCC and fBCC instructions in the table below
+     are because the branch instruction is translated into a jump
+     instruction that is now +2 or +3 bytes further on in memory, and the
+     correct size of jump instruction must be selected.  */
   /* bCC relaxing  */
   {0x7f, -0x80, 2, 1},
-  {0x7fff, -0x8000, 5, 2},
+  {0x7fff + 2, -0x8000 + 2, 5, 2},
   {0x7fffffff, -0x80000000, 7, 0},
 
-  /* bCC relaxing (uncommon cases)  */
+  /* bCC relaxing (uncommon cases for 3byte length instructions)  */
   {0x7f, -0x80, 3, 4},
-  {0x7fff, -0x8000, 6, 5},
+  {0x7fff + 3, -0x8000 + 3, 6, 5},
   {0x7fffffff, -0x80000000, 8, 0},
 
   /* call relaxing  */
@@ -80,7 +84,7 @@ const relax_typeS md_relax_table[] = {
 
   /* fbCC relaxing  */
   {0x7f, -0x80, 3, 14},
-  {0x7fff, -0x8000, 6, 15},
+  {0x7fff + 3, -0x8000 + 3, 6, 15},
   {0x7fffffff, -0x80000000, 8, 0},
 
 };
@@ -687,7 +691,7 @@ void
 md_show_usage (stream)
      FILE *stream;
 {
-  fprintf (stream, _("MN10300 options:\n\
+  fprintf (stream, _("MN10300 assembler options:\n\
 none yet\n"));
 }
 
@@ -1015,7 +1019,7 @@ md_convert_frag (abfd, sec, fragP)
       int offset = fragP->fr_fix;
       fragP->fr_literal[offset] = 0xcc;
 
-      fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+      fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
               fragP->fr_offset + 1, 1, BFD_RELOC_16_PCREL);
       fragP->fr_var = 0;
       fragP->fr_fix += 3;
@@ -1213,10 +1217,17 @@ md_begin ()
     }
 
   /* Set the default machine type.  */
+#ifdef TE_LINUX
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, AM33_2))
+    as_warn (_("could not set architecture and machine"));
+
+  current_machine = AM33_2;
+#else  
   if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, MN103))
     as_warn (_("could not set architecture and machine"));
 
   current_machine = MN103;
+#endif
 }
 
 static symbolS *GOT_symbol;
@@ -1993,6 +2004,18 @@ keep_going:
 
   if (relaxable && fc > 0)
     {
+      /* On a 64-bit host the size of an 'int' is not the same
+        as the size of a pointer, so we need a union to convert
+        the opindex field of the fr_cgen structure into a char *
+        so that it can be stored in the frag.  We do not have
+        to worry about loosing accuracy as we are not going to
+        be even close to the 32bit limit of the int.  */
+      union
+      {
+       int opindex;
+       char * ptr;
+      }
+      opindex_converter;
       int type;
 
       /* We want to anchor the line info to the previous frag (if
@@ -2032,10 +2055,11 @@ keep_going:
       else
        type = 3;
 
+      opindex_converter.opindex = fixups[0].opindex;
       f = frag_var (rs_machine_dependent, 8, 8 - size, type,
                    fixups[0].exp.X_add_symbol,
                    fixups[0].exp.X_add_number,
-                   (char *)fixups[0].opindex);
+                   opindex_converter.ptr);
 
       /* This is pretty hokey.  We basically just care about the
         opcode, so we have to write out the first word big endian.
@@ -2256,17 +2280,8 @@ keep_going:
                    abort ();
                }
 
-             /* Convert the size of the reloc into what fix_new_exp wants.  */
-             reloc_size = reloc_size / 8;
-             if (reloc_size == 8)
-               reloc_size = 0;
-             else if (reloc_size == 16)
-               reloc_size = 1;
-             else if (reloc_size == 32)
-               reloc_size = 2;
-
              fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
-                                 reloc_size, &fixups[i].exp, pcrel,
+                                 reloc_size / 8, &fixups[i].exp, pcrel,
                                  ((bfd_reloc_code_real_type) reloc));
 
              if (pcrel)
@@ -2382,7 +2397,8 @@ tc_gen_reloc (seg, fixp)
              break;
 
            default:
-             reloc->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+             reloc->sym_ptr_ptr
+               = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
              return reloc;
            }
        }
@@ -2440,7 +2456,7 @@ md_pcrel_from (fixp)
 }
 
 void
-md_apply_fix3 (fixP, valP, seg)
+md_apply_fix (fixP, valP, seg)
      fixS * fixP;
      valueT * valP;
      segT seg;
@@ -2456,11 +2472,10 @@ md_apply_fix3 (fixP, valP, seg)
     abort ();
 
   /* The value we are passed in *valuep includes the symbol values.
-     Since we are using BFD_ASSEMBLER, if we are doing this relocation
-     the code in write.c is going to call bfd_install_relocation, which
-     is also going to use the symbol value.  That means that if the
-     reloc is fully resolved we want to use *valuep since
-     bfd_install_relocation is not being used.
+     If we are doing this relocation the code in write.c is going to
+     call bfd_install_relocation, which is also going to use the symbol
+     value.  That means that if the reloc is fully resolved we want to
+     use *valuep since bfd_install_relocation is not being used.
 
      However, if the reloc is not fully resolved we do not want to use
      *valuep, and must use fx_offset instead.  However, if the reloc
@@ -2521,7 +2536,7 @@ bfd_boolean
 mn10300_fix_adjustable (fixp)
      struct fix *fixp;
 {
-  if (! TC_RELOC_RTSYM_LOC_FIXUP (fixp))
+  if (TC_FORCE_RELOCATION_LOCAL (fixp))
     return 0;
 
   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
@@ -2535,6 +2550,15 @@ mn10300_fix_adjustable (fixp)
   if (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE)
     return 0;
 
+  /* Likewise, do not adjust symbols that won't be merged, or debug
+     symbols, because they too break relaxation.  We do want to adjust
+     other mergable symbols, like .rodata, because code relaxations
+     need section-relative symbols to properly relax them.  */
+  if (! (S_GET_SEGMENT(fixp->fx_addsy)->flags & SEC_MERGE))
+    return 0;
+  if (strncmp (S_GET_SEGMENT (fixp->fx_addsy)->name, ".debug", 6) == 0)
+    return 0;
+
   return 1;
 }
 
@@ -2577,17 +2601,7 @@ mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
       test = val;
 
       if (test < (offsetT) min || test > (offsetT) max)
-       {
-         const char *err =
-           _("operand out of range (%s not between %ld and %ld)");
-         char buf[100];
-
-         sprint_value (buf, test);
-         if (file == (char *) NULL)
-           as_warn (err, buf, min, max);
-         else
-           as_warn_where (file, line, err, buf, min, max);
-       }
+       as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
     }
 
   if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
@@ -2733,9 +2747,10 @@ mn10300_end_of_match (cont, what)
 }  
 
 int
-mn10300_parse_name (name, exprP, nextcharP)
+mn10300_parse_name (name, exprP, mode, nextcharP)
      char const *name;
      expressionS *exprP;
+     enum expr_mode mode;
      char *nextcharP;
 {
   char *next = input_line_pointer;
@@ -2755,13 +2770,13 @@ mn10300_parse_name (name, exprP, nextcharP)
       /* 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)
+      if (mode != expr_defer && 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)
+      else if (mode != expr_defer && segment == reg_section)
        {
          exprP->X_op = O_register;
          exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);