ChangeLog rotatation and copyright year update
[deliverable/binutils-gdb.git] / gas / config / tc-xstormy16.c
index 446ac389c564a36bbf78e79b5dacb52b5dc268a0..4cdb0ee8e098d6781a9bcb3e6a6d7551b37fa8e4 100644 (file)
@@ -1,11 +1,11 @@
 /* tc-xstormy16.c -- Assembler for the Sanyo XSTORMY16.
-   Copyright (C) 2000, 2001, 2002 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
-   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 "subsegs.h"     
+#include "subsegs.h"
 #include "symcat.h"
 #include "opcodes/xstormy16-desc.h"
 #include "opcodes/xstormy16-opc.h"
@@ -66,19 +65,17 @@ struct option md_longopts[] =
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (c, arg)
-     int    c ATTRIBUTE_UNUSED;
-     char * arg ATTRIBUTE_UNUSED;
+md_parse_option (int    c ATTRIBUTE_UNUSED,
+                char * arg ATTRIBUTE_UNUSED)
 {
   return 0;
 }
 
 void
-md_show_usage (stream)
-  FILE * stream;
+md_show_usage (FILE * stream)
 {
   fprintf (stream, _(" XSTORMY16 specific command line options:\n"));
-} 
+}
 
 /* The target specific pseudo-ops which we support.  */
 const pseudo_typeS md_pseudo_table[] =
@@ -89,10 +86,10 @@ const pseudo_typeS md_pseudo_table[] =
 
 \f
 void
-md_begin ()
+md_begin (void)
 {
   /* Initialize the `cgen' interface.  */
-  
+
   /* Set the machine number and endian.  */
   gas_cgen_cpu_desc = xstormy16_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
                                          CGEN_CPU_OPEN_ENDIAN,
@@ -104,22 +101,27 @@ md_begin ()
   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
 }
 
+static bfd_boolean skipping_fptr = FALSE;
+
 void
-md_assemble (str)
-     char * str;
+md_assemble (char * str)
 {
   xstormy16_insn insn;
   char *    errmsg;
 
+  /* Make sure that if we had an erroneous input line which triggered
+     the skipping_fptr boolean that it does not affect following lines.  */
+  skipping_fptr = FALSE;
+
   /* Initialize GAS's cgen interface for a new instruction.  */
   gas_cgen_init_parse ();
 
   insn.insn = xstormy16_cgen_assemble_insn
     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
-  
+
   if (!insn.insn)
     {
-      as_bad (errmsg);
+      as_bad ("%s", errmsg);
       return;
     }
 
@@ -128,20 +130,19 @@ md_assemble (str)
                        CGEN_FIELDS_BITSIZE (& insn.fields), 0, NULL);
 }
 
-void 
-md_operand (e)
-     expressionS * e;
+void
+md_operand (expressionS * e)
 {
   if (*input_line_pointer != '@')
     return;
 
-  if (strncmp (input_line_pointer+1, "fptr", 4) == 0)
+  if (strncmp (input_line_pointer + 1, "fptr", 4) == 0)
     {
       input_line_pointer += 5;
       SKIP_WHITESPACE ();
       if (*input_line_pointer != '(')
        {
-         as_bad ("Expected '('");
+         as_bad (_("Expected '('"));
          goto err;
        }
       input_line_pointer++;
@@ -150,13 +151,32 @@ md_operand (e)
 
       if (*input_line_pointer != ')')
        {
-         as_bad ("Missing ')'");
+         as_bad (_("Missing ')'"));
          goto err;
        }
       input_line_pointer++;
+      SKIP_WHITESPACE ();
 
       if (e->X_op != O_symbol)
-       as_bad ("Not a symbolic expression");
+       as_bad (_("Not a symbolic expression"));
+      else if (* input_line_pointer == '-')
+       /* We are computing the difference of two function pointers
+          like this:
+
+           .hword  @fptr (foo) - @fptr (bar)
+
+         In this situation we do not want to generate O_fptr_symbol
+         operands because the result is an absolute value, not a
+         function pointer.
+
+         We need to make the check here, rather than when the fixup
+         is generated as the function names (foo & bar in the above
+         example) might be local symbols and we want the expression
+         to be evaluated now.  This kind of thing can happen when
+         gcc is generating computed gotos.  */
+       skipping_fptr = TRUE;
+      else if (skipping_fptr)
+       skipping_fptr = FALSE;
       else
         e->X_op = O_fptr_symbol;
     }
@@ -170,24 +190,39 @@ md_operand (e)
    Create BFD_RELOC_XSTORMY16_FPTR16 relocations.  */
 
 void
-xstormy16_cons_fix_new (f, where, nbytes, exp)
-     fragS *f;
-     int where;
-     int nbytes;
-     expressionS *exp;
+xstormy16_cons_fix_new (fragS *f,
+                       int where,
+                       int nbytes,
+                       expressionS *exp,
+                       bfd_reloc_code_real_type code)
 {
-  bfd_reloc_code_real_type code;
-  fixS *fix;
-
   if (exp->X_op == O_fptr_symbol)
     {
-      if (nbytes != 2)
+      switch (nbytes)
        {
-         as_bad ("unsupported fptr fixup size %d", nbytes);
+       case 4:
+         /* This can happen when gcc is generating debug output.
+            For example it can create a stab with the address of
+            a function:
+            
+               .stabs  "foo:F(0,21)",36,0,0,@fptr(foo)
+            Since this does not involve switching code pages, we
+            just allow the reloc to be generated without any
+            @fptr behaviour.  */
+         exp->X_op = O_symbol;
+         code = BFD_RELOC_32;
+         break;
+
+       case 2:
+         exp->X_op = O_symbol;
+         code = BFD_RELOC_XSTORMY16_FPTR16;
+         break;
+
+       default:
+         as_bad (_("unsupported fptr fixup size %d"), nbytes);
          return;
        }
-      exp->X_op = O_symbol;
-      code = BFD_RELOC_XSTORMY16_FPTR16;
     }
   else if (nbytes == 1)
     code = BFD_RELOC_8;
@@ -197,29 +232,28 @@ xstormy16_cons_fix_new (f, where, nbytes, exp)
     code = BFD_RELOC_32;
   else
     {
-      as_bad ("unsupported fixup size %d", nbytes);
+      as_bad (_("unsupported fixup size %d"), nbytes);
       return;
     }
 
-  fix = fix_new_exp (f, where, nbytes, exp, 0, code);
+  fix_new_exp (f, where, nbytes, exp, 0, code);
 }
 
-/* Called while parsing an instruction to create a fixup. 
+/* Called while parsing an instruction to create a fixup.
    Create BFD_RELOC_XSTORMY16_FPTR16 relocations.  */
 
 fixS *
-xstormy16_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
-     fragS *              frag;
-     int                  where;
-     const CGEN_INSN *    insn;
-     int                  length;
-     const CGEN_OPERAND * operand;
-     int                  opinfo;
-     expressionS *        exp;
+xstormy16_cgen_record_fixup_exp (fragS *              frag,
+                                int                  where,
+                                const CGEN_INSN *    insn,
+                                int                  length,
+                                const CGEN_OPERAND * operand,
+                                int                  opinfo,
+                                expressionS *        exp)
 {
   fixS *fixP;
   operatorT op = exp->X_op;
-  
+
   if (op == O_fptr_symbol)
     exp->X_op = O_symbol;
 
@@ -229,7 +263,7 @@ xstormy16_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp
   if (op == O_fptr_symbol)
     {
       if (operand->type != XSTORMY16_OPERAND_IMM16)
-       as_bad ("unsupported fptr fixup");
+       as_bad (_("unsupported fptr fixup"));
       else
        {
          fixP->fx_r_type = BFD_RELOC_XSTORMY16_FPTR16;
@@ -241,17 +275,15 @@ xstormy16_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp
 }
 
 valueT
-md_section_align (segment, size)
-     segT   segment;
-     valueT size;
+md_section_align (segT segment, valueT size)
 {
   int align = bfd_get_section_alignment (stdoutput, segment);
+
   return ((size + (1 << align) - 1) & (-1 << align));
 }
 
 symbolS *
-md_undefined_symbol (name)
-  char * name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
@@ -268,13 +300,12 @@ md_undefined_symbol (name)
    0 value.  */
 
 int
-md_estimate_size_before_relax (fragP, segment)
-     fragS * fragP ATTRIBUTE_UNUSED;
-     segT    segment ATTRIBUTE_UNUSED;
+md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
+                              segT    segment ATTRIBUTE_UNUSED)
 {
   /* No assembler relaxation is defined (or necessary) for this port.  */
   abort ();
-} 
+}
 
 /* *fragP has been relaxed to its final size, and now needs to have
    the bytes inside it modified to conform to the new size.
@@ -284,10 +315,9 @@ md_estimate_size_before_relax (fragP, segment)
    fragP->fr_subtype is the subtype of what the address relaxed to.  */
 
 void
-md_convert_frag (abfd, sec, fragP)
-  bfd *   abfd ATTRIBUTE_UNUSED;
-  segT    sec ATTRIBUTE_UNUSED;
-  fragS * fragP ATTRIBUTE_UNUSED;
+md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
+                segT    sec ATTRIBUTE_UNUSED,
+                fragS * fragP ATTRIBUTE_UNUSED)
 {
   /* No assembler relaxation is defined (or necessary) for this port.  */
   abort ();
@@ -299,18 +329,17 @@ md_convert_frag (abfd, sec, fragP)
    given a PC relative reloc.  */
 
 long
-md_pcrel_from_section (fixP, sec)
-     fixS * fixP;
-     segT   sec;
+md_pcrel_from_section (fixS * fixP, segT sec)
 {
-  if (fixP->fx_addsy != (symbolS *) NULL
-      && (! S_IS_DEFINED (fixP->fx_addsy)
-         || S_GET_SEGMENT (fixP->fx_addsy) != sec))
-    {
-      /* The symbol is undefined (or is defined but not in this section).
-        Let the linker figure it out.  */
-      return 0;
-    }
+  if ((fixP->fx_addsy != (symbolS *) NULL
+       && (! S_IS_DEFINED (fixP->fx_addsy)
+          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+      || xstormy16_force_relocation (fixP))
+    /* The symbol is undefined,
+       or it is defined but not in this section,
+       or the relocation will be relative to this symbol not the section symbol.        
+       Let the linker figure it out.  */
+    return 0;
 
   return fixP->fx_frag->fr_address + fixP->fx_where;
 }
@@ -320,10 +349,9 @@ md_pcrel_from_section (fixP, sec)
    *FIXP may be modified if desired.  */
 
 bfd_reloc_code_real_type
-md_cgen_lookup_reloc (insn, operand, fixP)
-     const CGEN_INSN *    insn ATTRIBUTE_UNUSED;
-     const CGEN_OPERAND * operand;
-     fixS *               fixP;
+md_cgen_lookup_reloc (const CGEN_INSN *    insn ATTRIBUTE_UNUSED,
+                     const CGEN_OPERAND * operand,
+                     fixS *               fixP)
 {
   switch (operand->type)
     {
@@ -331,30 +359,39 @@ md_cgen_lookup_reloc (insn, operand, fixP)
     case XSTORMY16_OPERAND_IMM3:
     case XSTORMY16_OPERAND_IMM3B:
     case XSTORMY16_OPERAND_IMM4:
-    case XSTORMY16_OPERAND_IMM12:
     case XSTORMY16_OPERAND_HMEM8:
       return BFD_RELOC_NONE;
-      
+
+    case XSTORMY16_OPERAND_IMM12:
+      fixP->fx_where += 2;
+      return BFD_RELOC_XSTORMY16_12;
+
     case XSTORMY16_OPERAND_IMM8:
     case XSTORMY16_OPERAND_LMEM8:
       return fixP->fx_pcrel ? BFD_RELOC_8_PCREL : BFD_RELOC_8;
-      
+
     case XSTORMY16_OPERAND_IMM16:
+      /* This might have been processed at parse time.  */
       fixP->fx_where += 2;
+      if (fixP->fx_cgen.opinfo && fixP->fx_cgen.opinfo != BFD_RELOC_NONE)
+       return fixP->fx_cgen.opinfo;
       return fixP->fx_pcrel ? BFD_RELOC_16_PCREL : BFD_RELOC_16;
 
     case XSTORMY16_OPERAND_ABS24:
       return BFD_RELOC_XSTORMY16_24;
 
-    case XSTORMY16_OPERAND_REL8_2:
     case XSTORMY16_OPERAND_REL8_4:
+      fixP->fx_addnumber -= 2;
+    case XSTORMY16_OPERAND_REL8_2:
+      fixP->fx_addnumber -= 2;
       fixP->fx_pcrel = 1;
       return BFD_RELOC_8_PCREL;
 
     case XSTORMY16_OPERAND_REL12:
       fixP->fx_where += 2;
-      /* Fall through... */
+      /* Fall through...  */
     case XSTORMY16_OPERAND_REL12A:
+      fixP->fx_addnumber -= 2;
       fixP->fx_pcrel = 1;
       return BFD_RELOC_XSTORMY16_REL_12;
 
@@ -368,66 +405,55 @@ md_cgen_lookup_reloc (insn, operand, fixP)
    relaxing.  */
 
 int
-xstormy16_force_relocation (fix)
-     fixS * fix;
+xstormy16_force_relocation (fixS * fix)
 {
-  switch (fix->fx_r_type)
-    {
-    case BFD_RELOC_XSTORMY16_FPTR16:
-    case BFD_RELOC_VTABLE_INHERIT:
-    case BFD_RELOC_VTABLE_ENTRY:
-      return 1;
+  if (fix->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
+    return 1;
 
-    default:
-      return 0;
-    }
+  return generic_force_reloc (fix);
 }
 
 /* Return true if a relocation against a symbol may be replaced with
    a relocation against section+offset.  */
 
-boolean
-xstormy16_fix_adjustable (fixP)
-   fixS * fixP;
+bfd_boolean
+xstormy16_fix_adjustable (fixS * fixP)
 {
-  if (fixP->fx_addsy == NULL)
-    return 1;
-  
-  /* Prevent all adjustments to global symbols. */
-  if (S_IS_EXTERN (fixP->fx_addsy))
-    return 0;
-  
-  if (S_IS_WEAK (fixP->fx_addsy))
-    return 0;
-  
   /* We need the symbol name for the VTABLE entries.  */
-  if (   fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    return 0;
+    return FALSE;
+
+  if (fixP->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16)
+    return FALSE;
 
-  return ! xstormy16_force_relocation (fixP);
+  return TRUE;
 }
 
-/* This is a copy of gas_cgen_md_apply_fix3, with some enhancements to
+/* This is a copy of gas_cgen_md_apply_fix, with some enhancements to
    do various things that would not be valid for all ports.  */
 
 void
-xstormy16_md_apply_fix3 (fixP, valueP, seg)
-     fixS *   fixP;
-     valueT * valueP;
-     segT     seg ATTRIBUTE_UNUSED;
+xstormy16_md_apply_fix (fixS *   fixP,
+                        valueT * valueP,
+                        segT     seg ATTRIBUTE_UNUSED)
 {
   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
-  valueT value;
+  valueT value = *valueP;
   /* Canonical name, since used a lot.  */
   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
 
+  /* md_cgen_lookup_reloc() will adjust this to compensate for where
+     in the opcode the relocation happens, for pcrel relocations.  We
+     have no other way of keeping track of what this offset needs to
+     be.  */
+  fixP->fx_addnumber = 0;
+
   /* This port has pc-relative relocs and DIFF_EXPR_OK defined, so
      it must deal with turning a BFD_RELOC_{8,16,32,64} into a
      BFD_RELOC_*_PCREL for the case of
 
-       .word something-.
-  */
+       .word something-.  */
   if (fixP->fx_pcrel)
     switch (fixP->fx_r_type)
       {
@@ -446,40 +472,13 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
       default:
        break;
       }
-  
-  /* FIXME FIXME FIXME: 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.
-     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
-     is PC relative, we do want to use *valuep since it includes the
-     result of md_pcrel_from.  This is confusing.  */
 
   if (fixP->fx_addsy == (symbolS *) NULL)
-    {
-      value = *valueP;
-      fixP->fx_done = 1;
-    }
-  else if (fixP->fx_pcrel)
-    value = *valueP;
-  else
-    {
-      value = fixP->fx_offset;
-      if (fixP->fx_subsy != (symbolS *) NULL)
-       {
-         if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
-           value -= S_GET_VALUE (fixP->fx_subsy);
-         else
-           {
-             /* We don't actually support subtracting a symbol.  */
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("expression too complex"));
-           }
-       }
-    }
+    fixP->fx_done = 1;
+
+  /* We don't actually support subtracting a symbol.  */
+  if (fixP->fx_subsy != (symbolS *) NULL)
+    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
 
   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
@@ -500,17 +499,19 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
 #if CGEN_INT_INSN_P
          {
            CGEN_INSN_INT insn_value =
-             cgen_get_insn_value (cd, where, CGEN_INSN_BITSIZE (insn));
+             cgen_get_insn_value (cd, (unsigned char *) where,
+                                  CGEN_INSN_BITSIZE (insn));
 
            /* ??? 0 is passed for `pc'.  */
            errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
                                                   &insn_value, (bfd_vma) 0);
-           cgen_put_insn_value (cd, where, CGEN_INSN_BITSIZE (insn),
-                                insn_value);
+           cgen_put_insn_value (cd, (unsigned char *) where,
+                                CGEN_INSN_BITSIZE (insn), insn_value);
          }
 #else
          /* ??? 0 is passed for `pc'.  */
-         errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields, where,
+         errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
+                                                (unsigned char *) where,
                                                 (bfd_vma) 0);
 #endif
          if (errmsg)
@@ -523,13 +524,11 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
       /* The operand isn't fully resolved.  Determine a BFD reloc value
         based on the operand information and leave it to
         bfd_install_relocation.  Note that this doesn't work when
-        partial_inplace == false.  */
+        !partial_inplace.  */
 
       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
       if (reloc_type != BFD_RELOC_NONE)
-       {
-         fixP->fx_r_type = reloc_type;
-       }
+       fixP->fx_r_type = reloc_type;
       else
        {
          as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -571,9 +570,9 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
   /* This is a RELA port.  Thus, it does not need to store a
      value if it is going to make a reloc.  What's more, when
      assembling a line like
-     
+
      .byte global-0x7f00
-     
+
      we'll get a spurious error message if we try to stuff 0x7f00 into
      the byte.  */
   if (! fixP->fx_done)
@@ -582,72 +581,20 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg)
   /* Tuck `value' away for use by tc_gen_reloc.
      See the comment describing fx_addnumber in write.h.
      This field is misnamed (or misused :-).  */
-  fixP->fx_addnumber = value;
+  fixP->fx_addnumber += value;
 }
 
 \f
 /* Write a value out to the object file, using the appropriate endianness.  */
 
 void
-md_number_to_chars (buf, val, n)
-     char * buf;
-     valueT val;
-     int    n;
+md_number_to_chars (char * buf, valueT val, int n)
 {
   number_to_chars_littleendian (buf, val, n);
 }
 
-/* Turn a string in input_line_pointer into a floating point constant of type
-   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
-   emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
-*/
-
-/* Equal to MAX_PRECISION in atof-ieee.c */
-#define MAX_LITTLENUMS 6
-
 char *
-md_atof (type, litP, sizeP)
-     char   type;
-     char * litP;
-     int *  sizeP;
+md_atof (int type, char * litP, int * sizeP)
 {
-  int              prec;
-  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
-  LITTLENUM_TYPE   *wordP;
-  char *           t;
-
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-      prec = 2;
-      break;
-
-    case 'd':
-    case 'D':
-      prec = 4;
-      break;
-
-   /* FIXME: Some targets allow other format chars for bigger sizes here.  */
-
-    default:
-      * sizeP = 0;
-      return _("Bad call to md_atof()");
-    }
-
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-  * sizeP = prec * sizeof (LITTLENUM_TYPE);
-
-  *sizeP = prec * sizeof (LITTLENUM_TYPE);
-  /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
-     the littleendianness of the processor.  */
-  for (wordP = words + prec - 1; prec--;)
-    {
-      md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
-    }
-     
-  return 0;
+  return ieee_md_atof (type, litP, sizeP, FALSE);
 }
This page took 0.031848 seconds and 4 git commands to generate.