Add binutils support for v850e1 processor
[deliverable/binutils-gdb.git] / gas / config / tc-ia64.c
index 13ff8a0b1733d8a2acb214b63e9bfad1255573d7..24e33c0662648347dae5c46e5274cfb78ee2a4c9 100644 (file)
@@ -24,7 +24,6 @@
 
   - optional operands
   - directives:
-       .alias
        .eb
        .estate
        .lb
@@ -156,6 +155,20 @@ struct label_fix
 
 extern int target_big_endian;
 
+void (*ia64_number_to_chars) PARAMS ((char *, valueT, int));
+
+static void ia64_float_to_chars_bigendian
+  PARAMS ((char *, LITTLENUM_TYPE *, int));
+static void ia64_float_to_chars_littleendian
+  PARAMS ((char *, LITTLENUM_TYPE *, int));
+static void (*ia64_float_to_chars)
+  PARAMS ((char *, LITTLENUM_TYPE *, int));
+
+static struct hash_control *alias_hash;
+static struct hash_control *alias_name_hash;
+static struct hash_control *secalias_hash;
+static struct hash_control *secalias_name_hash;
+
 /* Characters which always start a comment.  */
 const char comment_chars[] = "";
 
@@ -525,9 +538,13 @@ pseudo_func[] =
     { "pause", PSEUDO_FUNC_CONST, { 0x0 } },
 
     /* unwind-related constants:  */
-    { "svr4",  PSEUDO_FUNC_CONST, { 0 } },
-    { "hpux",  PSEUDO_FUNC_CONST, { 1 } },
-    { "nt",    PSEUDO_FUNC_CONST, { 2 } },
+    { "svr4",  PSEUDO_FUNC_CONST,      { ELFOSABI_NONE } },
+    { "hpux",  PSEUDO_FUNC_CONST,      { ELFOSABI_HPUX } },
+    { "nt",    PSEUDO_FUNC_CONST,      { 2 } },                /* conflicts w/ELFOSABI_NETBSD */
+    { "linux", PSEUDO_FUNC_CONST,      { ELFOSABI_LINUX } },
+    { "freebsd", PSEUDO_FUNC_CONST,    { ELFOSABI_FREEBSD } },
+    { "openvms", PSEUDO_FUNC_CONST,    { ELFOSABI_OPENVMS } },
+    { "nsk",   PSEUDO_FUNC_CONST,      { ELFOSABI_NSK } },
 
     /* unwind-related registers:  */
     { "priunat",PSEUDO_FUNC_REG, { REG_PRIUNAT } }
@@ -959,9 +976,11 @@ ia64_elf_section_letter (letter, ptr_msg)
 {
   if (letter == 's')
     return SHF_IA_64_SHORT;
+  else if (letter == 'o')
+    return SHF_LINK_ORDER;
 
-  *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
-  return 0;
+  *ptr_msg = _("Bad .section directive: want a,o,s,w,x,M,S,G,T in string");
+  return -1;
 }
 
 /* Map SHF_IA_64_SHORT to SEC_SMALL_DATA.  */
@@ -995,6 +1014,9 @@ ia64_elf_section_type (str, len)
   if (STREQ (ELF_STRING_ia64_unwind_once))
     return SHT_IA_64_UNWIND;
 
+  if (STREQ ("unwind"))
+    return SHT_IA_64_UNWIND;
+
   if (STREQ ("init_array"))
     return SHT_INIT_ARRAY;
 
@@ -4308,7 +4330,32 @@ static void
 dot_byteorder (byteorder)
      int byteorder;
 {
-  target_big_endian = byteorder;
+  segment_info_type *seginfo = seg_info (now_seg);
+
+  if (byteorder == -1)
+    {
+      if (seginfo->tc_segment_info_data.endian == 0)
+       seginfo->tc_segment_info_data.endian
+         = TARGET_BYTES_BIG_ENDIAN ? 1 : 2;
+      byteorder = seginfo->tc_segment_info_data.endian == 1;
+    }
+  else
+    seginfo->tc_segment_info_data.endian = byteorder ? 1 : 2;
+
+  if (target_big_endian != byteorder)
+    {
+      target_big_endian = byteorder;
+      if (target_big_endian)
+       {
+         ia64_number_to_chars = number_to_chars_bigendian;
+         ia64_float_to_chars = ia64_float_to_chars_bigendian;
+       }
+      else
+       {
+         ia64_number_to_chars = number_to_chars_littleendian;
+         ia64_float_to_chars = ia64_float_to_chars_littleendian;
+       }
+    }
 }
 
 static void
@@ -4344,13 +4391,6 @@ dot_psr (dummy)
   demand_empty_rest_of_line ();
 }
 
-static void
-dot_alias (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  as_bad (".alias not implemented yet");
-}
-
 static void
 dot_ln (dummy)
      int dummy ATTRIBUTE_UNUSED;
@@ -4838,8 +4878,6 @@ const pseudo_typeS md_pseudo_table[] =
     { "body", dot_body, 0 },
     { "prologue", dot_prologue, 0 },
     { "endp", dot_endp, 0 },
-    { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
-    { "loc", dwarf2_directive_loc, 0 },
 
     { "fframe", dot_fframe, 0 },
     { "vframe", dot_vframe, 0 },
@@ -4896,6 +4934,7 @@ const pseudo_typeS md_pseudo_table[] =
     { "msb", dot_byteorder, 1 },
     { "psr", dot_psr, 0 },
     { "alias", dot_alias, 0 },
+    { "secalias", dot_alias, 1 },
     { "ln", dot_ln, 0 },               /* source line info (for debugging) */
 
     { "xdata1", dot_xdata, 1 },
@@ -6535,7 +6574,15 @@ md_begin ()
 
   bfd_set_section_alignment (stdoutput, text_section, 4);
 
-  target_big_endian = TARGET_BYTES_BIG_ENDIAN;
+  /* Make sure fucntion pointers get initialized.  */
+  target_big_endian = -1;
+  dot_byteorder (TARGET_BYTES_BIG_ENDIAN);
+
+  alias_hash = hash_new ();
+  alias_name_hash = hash_new ();
+  secalias_hash = hash_new ();
+  secalias_name_hash = hash_new ();
+
   pseudo_func[FUNC_DTP_MODULE].u.sym =
     symbol_new (".<dtpmod>", undefined_section, FUNC_DTP_MODULE,
                &zero_address_frag);
@@ -8893,7 +8940,7 @@ note_register_values (idesc)
       else if (idesc->operands[i] == IA64_OPND_PR_ROT)
        {
          if (idesc->operands[1] & ((valueT) 1 << 43))
-           qp_changemask = ~(valueT) 0xFFFFFFFFFFF | idesc->operands[1];
+           qp_changemask = -((valueT) 1 << 44) | idesc->operands[1];
          else
            qp_changemask = idesc->operands[1];
          qp_changemask &= ~(valueT) 0xFFFF;
@@ -10554,7 +10601,6 @@ md_atof (type, lit, size)
      int *size;
 {
   LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *word;
   char *t;
   int prec;
 
@@ -10589,32 +10635,19 @@ md_atof (type, lit, size)
   t = atof_ieee (input_line_pointer, type, words);
   if (t)
     input_line_pointer = t;
-  *size = prec * sizeof (LITTLENUM_TYPE);
 
-  for (word = words + prec - 1; prec--;)
-    {
-      md_number_to_chars (lit, (long) (*word--), sizeof (LITTLENUM_TYPE));
-      lit += sizeof (LITTLENUM_TYPE);
-    }
+  (*ia64_float_to_chars) (lit, words, prec);
+
   if (type == 'X')
     {
       /* It is 10 byte floating point with 6 byte padding.  */
-      memset (lit, 0, 6);
+      memset (&lit [10], 0, 6);
       *size = 8 * sizeof (LITTLENUM_TYPE);
     }
-  return 0;
-}
-
-/* Round up a section's size to the appropriate boundary.  */
-valueT
-md_section_align (seg, size)
-     segT seg;
-     valueT size;
-{
-  int align = bfd_get_section_alignment (stdoutput, seg);
-  valueT mask = ((valueT) 1 << align) - 1;
+  else
+    *size = prec * sizeof (LITTLENUM_TYPE);
 
-  return (size + mask) & ~mask;
+  return 0;
 }
 
 /* Handle ia64 specific semantics of the align directive.  */
@@ -10668,3 +10701,210 @@ ia64_handle_align (fragp)
   memcpy (p, (target_big_endian ? be_nop : le_nop), 16);
   fragp->fr_var = 16;
 }
+
+static void
+ia64_float_to_chars_bigendian (char *lit, LITTLENUM_TYPE *words,
+                              int prec)
+{
+  while (prec--)
+    {
+      number_to_chars_bigendian (lit, (long) (*words++),
+                                sizeof (LITTLENUM_TYPE));
+      lit += sizeof (LITTLENUM_TYPE);
+    }
+}
+
+static void
+ia64_float_to_chars_littleendian (char *lit, LITTLENUM_TYPE *words,
+                                 int prec)
+{
+  while (prec--)
+    {
+      number_to_chars_littleendian (lit, (long) (words[prec]),
+                                   sizeof (LITTLENUM_TYPE));
+      lit += sizeof (LITTLENUM_TYPE);
+    }
+}
+
+void
+ia64_elf_section_change_hook  (void)
+{
+  dot_byteorder (-1);
+}
+
+/* Check if a label should be made global.  */
+void
+ia64_check_label (symbolS *label)
+{
+  if (*input_line_pointer == ':')
+    {
+      S_SET_EXTERNAL (label);
+      input_line_pointer++;
+    }
+}
+
+/* Used to remember where .alias and .secalias directives are seen. We
+   will rename symbol and section names when we are about to output
+   the relocatable file.  */
+struct alias
+{
+  char *file;          /* The file where the directive is seen.  */
+  unsigned int line;   /* The line number the directive is at.  */
+  const char *name;    /* The orignale name of the symbol.  */
+};
+
+/* Called for .alias and .secalias directives. If SECTION is 1, it is
+   .secalias. Otherwise, it is .alias.  */
+static void
+dot_alias (int section)
+{
+  char *name, *alias;
+  char delim;
+  char *end_name;
+  int len;
+  const char *error_string;
+  struct alias *h;
+  const char *a;
+  struct hash_control *ahash, *nhash;
+  const char *kind;
+
+  name = input_line_pointer;
+  delim = get_symbol_end ();
+  end_name = input_line_pointer;
+  *end_name = delim;
+
+  if (name == end_name)
+    {
+      as_bad (_("expected symbol name"));
+      discard_rest_of_line ();
+      return;
+    }
+
+  SKIP_WHITESPACE ();
+
+  if (*input_line_pointer != ',')
+    {
+      *end_name = 0;
+      as_bad (_("expected comma after \"%s\""), name);
+      *end_name = delim;
+      ignore_rest_of_line ();
+      return;
+    }
+
+  input_line_pointer++;
+  *end_name = 0;
+
+  /* We call demand_copy_C_string to check if alias string is valid.
+     There should be a closing `"' and no `\0' in the string.  */
+  alias = demand_copy_C_string (&len);
+  if (alias == NULL)
+    {
+      ignore_rest_of_line ();
+      return;
+    }
+
+  /* Make a copy of name string.  */
+  len = strlen (name) + 1;
+  obstack_grow (&notes, name, len);
+  name = obstack_finish (&notes);
+
+  if (section)
+    {
+      kind = "section";
+      ahash = secalias_hash;
+      nhash = secalias_name_hash;
+    }
+  else
+    {
+      kind = "symbol";
+      ahash = alias_hash;
+      nhash = alias_name_hash;
+    }
+
+  /* Check if alias has been used before.  */
+  h = (struct alias *) hash_find (ahash, alias);
+  if (h)
+    {
+      if (strcmp (h->name, name))
+       as_bad (_("`%s' is already the alias of %s `%s'"),
+               alias, kind, h->name);
+      goto out;
+    }
+
+  /* Check if name already has an alias.  */
+  a = (const char *) hash_find (nhash, name);
+  if (a)
+    {
+      if (strcmp (a, alias))
+       as_bad (_("%s `%s' already has an alias `%s'"), kind, name, a);
+      goto out;
+    }
+
+  h = (struct alias *) xmalloc (sizeof (struct alias));
+  as_where (&h->file, &h->line);
+  h->name = name;
+  
+  error_string = hash_jam (ahash, alias, (PTR) h);
+  if (error_string)
+    {
+      as_fatal (_("inserting \"%s\" into %s alias hash table failed: %s"),
+               alias, kind, error_string);
+      goto out;
+    }
+
+  error_string = hash_jam (nhash, name, (PTR) alias);
+  if (error_string)
+    {
+      as_fatal (_("inserting \"%s\" into %s name hash table failed: %s"),
+               alias, kind, error_string);
+out:
+      obstack_free (&notes, name);
+      obstack_free (&notes, alias);
+    }
+
+  demand_empty_rest_of_line ();
+}
+
+/* It renames the original symbol name to its alias.  */
+static void
+do_alias (const char *alias, PTR value)
+{
+  struct alias *h = (struct alias *) value;
+  symbolS *sym = symbol_find (h->name);
+
+  if (sym == NULL)
+    as_warn_where (h->file, h->line,
+                  _("symbol `%s' aliased to `%s' is not used"),
+                  h->name, alias);
+    else
+      S_SET_NAME (sym, (char *) alias);
+}
+
+/* Called from write_object_file.  */
+void
+ia64_adjust_symtab (void)
+{
+  hash_traverse (alias_hash, do_alias);
+}
+
+/* It renames the original section name to its alias.  */
+static void
+do_secalias (const char *alias, PTR value)
+{
+  struct alias *h = (struct alias *) value;
+  segT sec = bfd_get_section_by_name (stdoutput, h->name);
+
+  if (sec == NULL)
+    as_warn_where (h->file, h->line,
+                  _("section `%s' aliased to `%s' is not used"),
+                  h->name, alias);
+  else
+    sec->name = alias;
+}
+
+/* Called from write_object_file.  */
+void
+ia64_frob_file (void)
+{
+  hash_traverse (secalias_hash, do_secalias);
+}
This page took 0.02813 seconds and 4 git commands to generate.