This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] [ARC] Object attributes.


Hi,

Please find attached a patch that adds object attributes support to
ARC backend. The object attributes are according to ARC's ABI
addendum[1], hence, they should be shared among ARC toolchains
proprietary or not.

Proposed NEWS entry for LD/GAS:
 * Add support for object attributes for ARC CPUs.

Ok to apply?
Claudiu

Reference:
[1] https://github.com/foss-for-synopsys-dwc-arc-processors/arc-ABI-manual

P.S. Apologize if you received this email multiple time.

gas/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* testsuite/gas/arc/attr-arc600.d: New file.
	* testsuite/gas/arc/attr-arc600_mul32x16.d: Likewise.
	* testsuite/gas/arc/attr-arc600_norm.d: Likewise.
	* testsuite/gas/arc/attr-arc601.d: Likewise.
	* testsuite/gas/arc/attr-arc601_mul32x16.d: Likewise.
	* testsuite/gas/arc/attr-arc601_mul64.d: Likewise.
	* testsuite/gas/arc/attr-arc601_norm.d: Likewise.
	* testsuite/gas/arc/attr-arc700.d: Likewise.
	* testsuite/gas/arc/attr-arcem.d: Likewise.
	* testsuite/gas/arc/attr-archs.d: Likewise.
	* testsuite/gas/arc/attr-autodetect-1.d: Likewise.
	* testsuite/gas/arc/attr-autodetect-1.s: Likewise.
	* testsuite/gas/arc/attr-cpu-a601.d: Likewise.
	* testsuite/gas/arc/attr-cpu-a601.s: Likewise.
	* testsuite/gas/arc/attr-cpu-a700.d: Likewise.
	* testsuite/gas/arc/attr-cpu-a700.s: Likewise.
	* testsuite/gas/arc/attr-cpu-em.d: Likewise.
	* testsuite/gas/arc/attr-cpu-em.s: Likewise.
	* testsuite/gas/arc/attr-cpu-hs.d: Likewise.
	* testsuite/gas/arc/attr-cpu-hs.s: Likewise.
	* testsuite/gas/arc/attr-em.d: Likewise.
	* testsuite/gas/arc/attr-em4.d: Likewise.
	* testsuite/gas/arc/attr-em4_dmips.d: Likewise.
	* testsuite/gas/arc/attr-em4_fpuda.d: Likewise.
	* testsuite/gas/arc/attr-em4_fpus.d: Likewise.
	* testsuite/gas/arc/attr-hs.d: Likewise.
	* testsuite/gas/arc/attr-hs34.d: Likewise.
	* testsuite/gas/arc/attr-hs38.d: Likewise.
	* testsuite/gas/arc/attr-hs38_linux.d: Likewise.
	* testsuite/gas/arc/attr-mul64.d: Likewise.
	* testsuite/gas/arc/attr-name.d: Likewise.
	* testsuite/gas/arc/attr-name.s: Likewise.
	* testsuite/gas/arc/attr-nps400.d: Likewise.
	* testsuite/gas/arc/attr-override-mcpu.d: Likewise.
	* testsuite/gas/arc/attr-override-mcpu.s
	* testsuite/gas/arc/attr-quarkse_em.d: Likewise.
	* testsuite/gas/arc/blank.s: Likewise.
	* testsuite/gas/elf/section2.e-arc: Likewise.
	* testsuite/gas/arc/cpu-pseudop-1.d: Update test.
	* testsuite/gas/arc/cpu-pseudop-2.d: Likewise.
	* testsuite/gas/arc/nps400-0.d: Likewise.
	* testsuite/gas/elf/elf.exp: Set target_machine for ARC.
	* config/tc-arc.c (opcode/arc-attrs.h): Include.
	(ARC_GET_FLAG, ARC_SET_FLAG, streq): Define.
	(arc_attribute): Declare new function.
	(md_pseudo_table): Add arc_attribute.
	(cpu_types): Rename default cpu features.
	(selected_cpu): Set the default OSABI flag.
	(mpy_option): New variable.
	(pic_option): Likewise.
	(sda_option): Likewise.
	(tls_option): Likewise.
	(feature_type, feature_list): Remove.
	(arc_initial_eflag): Likewise.
	(attributes_set_explicitly): New variable.
	(arc_check_feature): Check also for the conflicting features.
	(arc_select_cpu): Refactor assignment of selected_cpu.eflags.
	(arc_option): Remove setting of private flags and architecture.
	(check_cpu_feature): Refactor feature names.
	(autodetect_attributes): New function.
	(assemble_tokens): Use above function.
	(md_parse_option): Refactor feature names.
	(arc_attribute): New function.
	(arc_set_attribute_int): Likewise.
	(arc_set_attribute_string): Likewise.
	(arc_stralloc): Likewise.
	(arc_set_public_attributes): Likewise.
	(arc_md_end): Likewise.
	(arc_copy_symbol_attributes): Likewise.
	(rc_convert_symbolic_attribute): Likewise.
	* config/tc-arc.h (md_end): Define.
	(CONVERT_SYMBOLIC_ATTRIBUTE): Likewise.
	(TC_COPY_SYMBOL_ATTRIBUTES): Likewise.
	* doc/c-arc.texi: Document ARC object attributes.

binutils/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* readelf.c (decode_ARC_machine_flags): Recognize OSABI v4.
	(get_arc_section_type_name): New function.
	(get_section_type_name): Use the above function.
	(display_arc_attribute): New function.
	(process_arc_specific): Likewise.
	(process_arch_specific): Handle ARC specific information.

include/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* elf/arc.h (SHT_ARC_ATTRIBUTES): Define.
	(Tag_ARC_*): Define.
	(E_ARC_OSABI_V4): Define.
	(E_ARC_OSABI_CURRENT): Reassign it.
	(TAG_CPU_*): Define.
	* opcode/arc-attrs.h: New file.
	* opcode/arc.h (insn_subclass_t): Assign enum values.
	(insn_subclass_t): Update enum with QUARKSE1, QUARKSE2, and LL64.
	(ARC_EA, ARC_CD, ARC_LLOCK, ARC_ATOMIC, ARC_MPY, ARC_MULT)
	(ARC_NPS400, ARC_DPFP, ARC_SPFP, ARC_FPU, ARC_FPUDA, ARC_SWAP)
	(ARC_NORM, ARC_BSCAN, ARC_UIX, ARC_TSTAMP, ARC_VBFDW)
	(ARC_BARREL, ARC_DSPA, ARC_SHIFT, ARC_INTR, ARC_DIV, ARC_XMAC)
	(ARC_CRC): Delete.

bfd/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* elf32-arc.c (FEATURE_LIST_NAME): Define.
	(CONFLICT_LIST): Likewise.
	(opcode/arc-attrs.h): Include.
	(arc_elf_print_private_bfd_data): Print OSABI v4 flag.
	(arc_extract_features): New file.
	(arc_stralloc): Likewise.
	(arc_elf_merge_attributes): Likewise.
	(arc_elf_merge_private_bfd_data): Use object attributes.
	(bfd_arc_get_mach_from_attributes): New function.
	(arc_elf_object_p): Use object attributes.
	(arc_elf_final_write_processing): Likewise.
	(elf32_arc_obj_attrs_arg_type): New function.
	(elf32_arc_obj_attrs_handle_unknown): Likewise.
	(elf32_arc_section_from_shdr): Likewise.
	(elf_backend_obj_attrs_vendor): Define.
	(elf_backend_obj_attrs_section): Likewise.
	(elf_backend_obj_attrs_arg_type): Likewise.
	(elf_backend_obj_attrs_section_type): Likewise.
	(elf_backend_obj_attrs_handle_unknown): Likewise.
	(elf_backend_section_from_shdr): Likewise.

ld/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* testsuite/ld-arc/attr-merge-0.d: New file.
	* testsuite/ld-arc/attr-merge-0.s: Likewise.
	* testsuite/ld-arc/attr-merge-0e.s: Likewise.
	* testsuite/ld-arc/attr-merge-1.d: Likewise.
	* testsuite/ld-arc/attr-merge-1.s: Likewise.
	* testsuite/ld-arc/attr-merge-1e.s: Likewise.
	* testsuite/ld-arc/attr-merge-2.d: Likewise.
	* testsuite/ld-arc/attr-merge-2.s: Likewise.
	* testsuite/ld-arc/attr-merge-3.d: Likewise.
	* testsuite/ld-arc/attr-merge-3.s: Likewise.
	* testsuite/ld-arc/attr-merge-3e.s: Likewise.
	* testsuite/ld-arc/attr-merge-4.s: Likewise.
	* testsuite/ld-arc/attr-merge-5.d: Likewise.
	* testsuite/ld-arc/attr-merge-5a.s: Likewise.
	* testsuite/ld-arc/attr-merge-5b.s: Likewise.
	* testsuite/ld-arc/attr-merge-conflict-isa.d: Likewise.
	* testsuite/ld-arc/attr-merge-err-isa.d: Likewise.
	* testsuite/ld-arc/attr-merge-incompatible-cpu.d: Likewise.
	* testsuite/ld-arc/got-01.d: Update test.
	* testsuite/ld-arc/attr-merge-err-quarkse.d: New file.
	* testsuite/ld-arc/attr-quarkse.s: Likewise.
	* testsuite/ld-arc/attr-quarkse2.s: Likewise.

opcodes/
2017-05-08  Claudiu Zissulescu  <claziss@synopsys.com>

	* arc-dis.c (parse_option): Update quarkse_em option..
	* arc-ext-tbl.h (dsp_fp_flt2i, dsp_fp_i2flt): Change subclass to
	QUARKSE1.
	(dsp_fp_div, dsp_fp_cmp): Change subclass to QUARKSE2.
---
 bfd/elf32-arc.c                                   | 412 +++++++++++++++++++++-
 binutils/readelf.c                                | 200 +++++++++++
 gas/config/tc-arc.c                               | 375 ++++++++++++++++----
 gas/config/tc-arc.h                               |  11 +
 gas/doc/c-arc.texi                                |  16 +
 gas/testsuite/gas/arc/attr-arc600.d               |  10 +
 gas/testsuite/gas/arc/attr-arc600_mul32x16.d      |  10 +
 gas/testsuite/gas/arc/attr-arc600_norm.d          |  10 +
 gas/testsuite/gas/arc/attr-arc601.d               |  10 +
 gas/testsuite/gas/arc/attr-arc601_mul32x16.d      |  10 +
 gas/testsuite/gas/arc/attr-arc601_mul64.d         |  10 +
 gas/testsuite/gas/arc/attr-arc601_norm.d          |  10 +
 gas/testsuite/gas/arc/attr-arc700.d               |  10 +
 gas/testsuite/gas/arc/attr-arcem.d                |  10 +
 gas/testsuite/gas/arc/attr-archs.d                |  11 +
 gas/testsuite/gas/arc/attr-autodetect-1.d         |  11 +
 gas/testsuite/gas/arc/attr-autodetect-1.s         |   4 +
 gas/testsuite/gas/arc/attr-cpu-a601.d             |   8 +
 gas/testsuite/gas/arc/attr-cpu-a601.s             |   1 +
 gas/testsuite/gas/arc/attr-cpu-a700.d             |   8 +
 gas/testsuite/gas/arc/attr-cpu-a700.s             |   1 +
 gas/testsuite/gas/arc/attr-cpu-em.d               |   8 +
 gas/testsuite/gas/arc/attr-cpu-em.s               |   1 +
 gas/testsuite/gas/arc/attr-cpu-hs.d               |   9 +
 gas/testsuite/gas/arc/attr-cpu-hs.s               |   1 +
 gas/testsuite/gas/arc/attr-em.d                   |  10 +
 gas/testsuite/gas/arc/attr-em4.d                  |  11 +
 gas/testsuite/gas/arc/attr-em4_dmips.d            |  11 +
 gas/testsuite/gas/arc/attr-em4_fpuda.d            |  11 +
 gas/testsuite/gas/arc/attr-em4_fpus.d             |  11 +
 gas/testsuite/gas/arc/attr-hs.d                   |  11 +
 gas/testsuite/gas/arc/attr-hs34.d                 |  11 +
 gas/testsuite/gas/arc/attr-hs38.d                 |  11 +
 gas/testsuite/gas/arc/attr-hs38_linux.d           |  11 +
 gas/testsuite/gas/arc/attr-mul64.d                |  10 +
 gas/testsuite/gas/arc/attr-name.d                 |  22 ++
 gas/testsuite/gas/arc/attr-name.s                 |  17 +
 gas/testsuite/gas/arc/attr-nps400.d               |  11 +
 gas/testsuite/gas/arc/attr-override-mcpu.d        |  10 +
 gas/testsuite/gas/arc/attr-override-mcpu.s        |   1 +
 gas/testsuite/gas/arc/attr-quarkse_em.d           |  11 +
 gas/testsuite/gas/arc/blank.s                     |   1 +
 gas/testsuite/gas/arc/cpu-pseudop-1.d             |   2 +-
 gas/testsuite/gas/arc/cpu-pseudop-2.d             |   2 +-
 gas/testsuite/gas/arc/nps400-0.d                  |   2 +-
 gas/testsuite/gas/elf/elf.exp                     |   3 +
 gas/testsuite/gas/elf/section2.e-arc              |   9 +
 include/elf/arc.h                                 |  34 +-
 include/opcode/arc-attrs.h                        |  72 ++++
 include/opcode/arc.h                              |  88 ++---
 ld/testsuite/ld-arc/attr-merge-0.d                |  12 +
 ld/testsuite/ld-arc/attr-merge-0.s                |   2 +
 ld/testsuite/ld-arc/attr-merge-0e.s               |   1 +
 ld/testsuite/ld-arc/attr-merge-1.d                |  12 +
 ld/testsuite/ld-arc/attr-merge-1.s                |   2 +
 ld/testsuite/ld-arc/attr-merge-1e.s               |   2 +
 ld/testsuite/ld-arc/attr-merge-2.d                |  12 +
 ld/testsuite/ld-arc/attr-merge-2.s                |   2 +
 ld/testsuite/ld-arc/attr-merge-3.d                |  12 +
 ld/testsuite/ld-arc/attr-merge-3.s                |   1 +
 ld/testsuite/ld-arc/attr-merge-3e.s               |   1 +
 ld/testsuite/ld-arc/attr-merge-4.s                |   2 +
 ld/testsuite/ld-arc/attr-merge-5.d                |  13 +
 ld/testsuite/ld-arc/attr-merge-5a.s               |   3 +
 ld/testsuite/ld-arc/attr-merge-5b.s               |   2 +
 ld/testsuite/ld-arc/attr-merge-conflict-isa.d     |   6 +
 ld/testsuite/ld-arc/attr-merge-err-isa.d          |   5 +
 ld/testsuite/ld-arc/attr-merge-err-quarkse.d      |   5 +
 ld/testsuite/ld-arc/attr-merge-incompatible-cpu.d |   5 +
 ld/testsuite/ld-arc/attr-quarkse.s                |   2 +
 ld/testsuite/ld-arc/attr-quarkse2.s               |   2 +
 ld/testsuite/ld-arc/got-01.d                      |   2 +-
 opcodes/arc-dis.c                                 |   3 +-
 opcodes/arc-ext-tbl.h                             |  10 +-
 opcodes/arc-tbl.h                                 |  46 +--
 75 files changed, 1550 insertions(+), 175 deletions(-)
 create mode 100644 gas/testsuite/gas/arc/attr-arc600.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc600_mul32x16.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc600_norm.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc601.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc601_mul32x16.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc601_mul64.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc601_norm.d
 create mode 100644 gas/testsuite/gas/arc/attr-arc700.d
 create mode 100644 gas/testsuite/gas/arc/attr-arcem.d
 create mode 100644 gas/testsuite/gas/arc/attr-archs.d
 create mode 100644 gas/testsuite/gas/arc/attr-autodetect-1.d
 create mode 100644 gas/testsuite/gas/arc/attr-autodetect-1.s
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-a601.d
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-a601.s
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-a700.d
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-a700.s
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-em.d
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-em.s
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-hs.d
 create mode 100644 gas/testsuite/gas/arc/attr-cpu-hs.s
 create mode 100644 gas/testsuite/gas/arc/attr-em.d
 create mode 100644 gas/testsuite/gas/arc/attr-em4.d
 create mode 100644 gas/testsuite/gas/arc/attr-em4_dmips.d
 create mode 100644 gas/testsuite/gas/arc/attr-em4_fpuda.d
 create mode 100644 gas/testsuite/gas/arc/attr-em4_fpus.d
 create mode 100644 gas/testsuite/gas/arc/attr-hs.d
 create mode 100644 gas/testsuite/gas/arc/attr-hs34.d
 create mode 100644 gas/testsuite/gas/arc/attr-hs38.d
 create mode 100644 gas/testsuite/gas/arc/attr-hs38_linux.d
 create mode 100644 gas/testsuite/gas/arc/attr-mul64.d
 create mode 100644 gas/testsuite/gas/arc/attr-name.d
 create mode 100644 gas/testsuite/gas/arc/attr-name.s
 create mode 100644 gas/testsuite/gas/arc/attr-nps400.d
 create mode 100644 gas/testsuite/gas/arc/attr-override-mcpu.d
 create mode 100644 gas/testsuite/gas/arc/attr-override-mcpu.s
 create mode 100644 gas/testsuite/gas/arc/attr-quarkse_em.d
 create mode 100644 gas/testsuite/gas/arc/blank.s
 create mode 100644 gas/testsuite/gas/elf/section2.e-arc
 create mode 100644 include/opcode/arc-attrs.h
 create mode 100644 ld/testsuite/ld-arc/attr-merge-0.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-0.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-0e.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-1.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-1.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-1e.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-2.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-2.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-3.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-3.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-3e.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-4.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-5.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-5a.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-5b.s
 create mode 100644 ld/testsuite/ld-arc/attr-merge-conflict-isa.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-err-isa.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-err-quarkse.d
 create mode 100644 ld/testsuite/ld-arc/attr-merge-incompatible-cpu.d
 create mode 100644 ld/testsuite/ld-arc/attr-quarkse.s
 create mode 100644 ld/testsuite/ld-arc/attr-quarkse2.s

diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index 5f1505e..7b3c820 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -29,6 +29,10 @@
 #include "opcode/arc.h"
 #include "arc-plt.h"
 
+#define FEATURE_LIST_NAME bfd_feature_list
+#define CONFLICT_LIST bfd_conflict_list
+#include "opcode/arc-attrs.h"
+
 /* #define ARC_ENABLE_DEBUG 1  */
 #ifdef ARC_ENABLE_DEBUG
 static const char *
@@ -442,8 +446,9 @@ arc_elf_print_private_bfd_data (bfd *abfd, void * ptr)
     case E_ARC_OSABI_ORIG : fprintf (file, " (ABI:legacy)"); break;
     case E_ARC_OSABI_V2   : fprintf (file, " (ABI:v2)");     break;
     case E_ARC_OSABI_V3   : fprintf (file, " (ABI:v3)");     break;
+    case E_ARC_OSABI_V4   : fprintf (file, " (ABI:v4)");     break;
     default:
-      fprintf (file, "(ABI:unknown)");
+      fprintf (file, " (ABI:unknown)");
       break;
     }
 
@@ -500,6 +505,274 @@ arc_info_to_howto_rel (bfd * abfd ATTRIBUTE_UNUSED,
   cache_ptr->howto = arc_elf_howto (r_type);
 }
 
+/* Extract CPU features from an NTBS.  */
+
+static unsigned
+arc_extract_features (const char *p)
+{
+  unsigned i, r = 0;
+
+  if (!p)
+    return 0;
+
+  for (i = 0; i < ARRAY_SIZE (bfd_feature_list); i++)
+    {
+      char *t = strstr (p, bfd_feature_list[i].attr);
+      unsigned l = strlen (bfd_feature_list[i].attr);
+      if ((t != NULL)
+	  && (t[l] == ','
+	      || t[l] == '\0'))
+	r |= bfd_feature_list[i].feature;
+    }
+
+  return r;
+}
+
+/* Allocate and concatenate two strings.  s1 can be NULL but not
+   s2.  s1 pointer is freed at end of this procedure.  */
+
+static char *
+arc_stralloc (char * s1, const char * s2)
+{
+  char * p;
+  int len = 0;
+
+  if (s1)
+    len = strlen (s1) + 1;
+
+  /* Only s1 can be null.  */
+  BFD_ASSERT (s2);
+  len += strlen (s2) + 1;
+
+  p = (char *) xmalloc (len);
+  if (p == NULL)
+    return NULL;
+
+  if (s1)
+    {
+      strcpy (p, s1);
+      strcat (p, ",");
+      strcat (p, s2);
+      free (s1);
+    }
+  else
+    strcpy (p, s2);
+
+  return p;
+}
+
+/* Merge ARC object attributes from IBFD into OBFD.  Raise an error if
+   there are conflicting attributes.  */
+
+static bfd_boolean
+arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+  int i;
+  bfd_boolean result = TRUE;
+  const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section;
+
+  /* Skip the linker stubs file.  This preserves previous behavior
+     of accepting unknown attributes in the first input file - but
+     is that a bug?  */
+  if (ibfd->flags & BFD_LINKER_CREATED)
+    return TRUE;
+
+  /* Skip any input that hasn't attribute section.
+     This enables to link object files without attribute section with
+     any others.  */
+  if (bfd_get_section_by_name (ibfd, sec_name) == NULL)
+    return TRUE;
+
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+      out_attr = elf_known_obj_attributes_proc (obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+	 initialized.  */
+      out_attr[0].i = 1;
+
+      return TRUE;
+    }
+
+  in_attr = elf_known_obj_attributes_proc (ibfd);
+  out_attr = elf_known_obj_attributes_proc (obfd);
+
+  for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
+    {
+      /* Merge this attribute with existing attributes.  */
+      switch (i)
+	{
+	case Tag_ARC_PCS_config:
+	  if (out_attr[i].i == 0)
+	    out_attr[i].i = in_attr[i].i;
+	  else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i)
+	    {
+	      /* It's sometimes ok to mix different configs, so this is only
+		 a warning.  */
+	      _bfd_error_handler
+		(_("Warning: %B: Conflicting platform configuration."), ibfd);
+	    }
+	  break;
+
+	case Tag_ARC_CPU_base:
+	  if (out_attr[i].i == 0)
+	    out_attr[i].i = in_attr[i].i;
+	  else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i
+		   && ((out_attr[i].i + in_attr[i].i) < 6))
+	    {
+	      /* We cannot mix code for different CPUs.  */
+	      _bfd_error_handler
+		(_("error: %B: unable to merge CPU base attributes "
+		   "with %B."),
+		 obfd, ibfd);
+	      result = FALSE;
+	      break;
+	    }
+	  else
+	    {
+	      /* The CPUs may be different, check if we can still mix
+		 the objects against the output choosen CPU.  */
+	      unsigned in_feature = 0;
+	      unsigned out_feature = 0;
+	      char *p1 = in_attr[Tag_ARC_ISA_config].s;
+	      char *p2 = out_attr[Tag_ARC_ISA_config].s;
+	      unsigned j;
+	      unsigned cpu_out;
+	      unsigned opcode_map[] = {0, ARC_OPCODE_ARC600, ARC_OPCODE_ARC700,
+				       ARC_OPCODE_ARCv2EM, ARC_OPCODE_ARCv2HS};
+
+	      BFD_ASSERT (in_attr[i].i < (sizeof (opcode_map)
+					  / sizeof (unsigned)));
+	      BFD_ASSERT (out_attr[i].i < (sizeof (opcode_map)
+					   / sizeof (unsigned)));
+	      cpu_out = opcode_map[out_attr[i].i];
+
+	      in_feature = arc_extract_features (p1);
+	      out_feature = arc_extract_features (p2);
+
+	      /* First, check if a feature is compatible with the
+		 output object chosen CPU.  */
+	      for (j = 0; j < ARRAY_SIZE (bfd_feature_list); j++)
+		if (((in_feature | out_feature) & bfd_feature_list[j].feature)
+		    && (!(cpu_out & bfd_feature_list[j].cpus)))
+		  {
+		    _bfd_error_handler
+		      (_("error: %B: unable to merge ISA extension attributes "
+			 "%s."),
+		       obfd, bfd_feature_list[j].name);
+		    result = FALSE;
+		    break;
+		  }
+	      /* Second, if we have compatible features with the
+		 chosen CPU, check if they are compatible among
+		 them.  */
+	      for (j = 0; j < ARRAY_SIZE (bfd_conflict_list); j++)
+		if (((in_feature | out_feature) & bfd_conflict_list[j])
+		    == bfd_conflict_list[j])
+		  {
+		    unsigned k;
+		    for (k = 0; k < ARRAY_SIZE (bfd_feature_list); k++)
+		      {
+			if (in_feature &  bfd_feature_list[k].feature
+			    & bfd_conflict_list[j])
+			  p1 = (char *) bfd_feature_list[k].name;
+			if (out_feature &  bfd_feature_list[k].feature
+			    & bfd_conflict_list[j])
+			  p2 = (char *) bfd_feature_list[k].name;
+		      }
+		    _bfd_error_handler
+		      (_("error: %B: conflicting ISA extension attributes "
+			 "%s with %s."),
+		       obfd, p1, p2);
+		    result = FALSE;
+		    break;
+		  }
+	      /* Everithing is alright.  */
+	      out_feature |= in_feature;
+	      p1 = NULL;
+	      for (j = 0; j < ARRAY_SIZE (bfd_feature_list); j++)
+		if (out_feature & bfd_feature_list[j].feature)
+		  p1 = arc_stralloc (p1, bfd_feature_list[j].attr);
+	      if (p1)
+		out_attr[Tag_ARC_ISA_config].s =
+		  _bfd_elf_attr_strdup (obfd, p1);
+	    }
+	  /* Fall through.  */
+	case Tag_ARC_CPU_variation:
+	case Tag_ARC_ISA_mpy_option:
+	case Tag_ARC_ABI_osver:
+	  /* Use the largest value specified.  */
+	  if (in_attr[i].i > out_attr[i].i)
+	    out_attr[i].i = in_attr[i].i;
+	  break;
+
+	case Tag_ARC_CPU_name:
+	  break;
+
+	case Tag_ARC_ABI_rf16:
+	  if (out_attr[i].i == 0)
+	    out_attr[i].i = in_attr[i].i;
+	  else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i)
+	    {
+	      /* We cannot mix code with rf16 and without.  */
+	      _bfd_error_handler
+		(_("error: %B: conflicting register set attributes "
+		   "with %B."),
+		 obfd, ibfd);
+	      result = FALSE;
+	    }
+	  break;
+
+	case Tag_ARC_ABI_pic:
+	case Tag_ARC_ABI_sda:
+	case Tag_ARC_ABI_tls:
+	case Tag_ARC_ABI_enumsize:
+	case Tag_ARC_ABI_double_size:
+	case Tag_ARC_ABI_exceptions:
+	  if (out_attr[i].i != 0 && in_attr[i].i != 0
+	      && out_attr[i].i != in_attr[i].i)
+	    {
+	      _bfd_error_handler
+		(_("error: %B: conflicting attributes "
+		   "with %B."),
+		 obfd, ibfd);
+	      result = FALSE;
+	    }
+	  break;
+
+	case Tag_ARC_ISA_apex:
+	  break; /* Do nothing for APEX attributes.  */
+
+	case Tag_ARC_ISA_config:
+	  /* It is handled in Tag_ARC_CPU_base.  */
+	  break;
+
+	default:
+	  result
+	    = result && _bfd_elf_merge_unknown_attribute_low (ibfd, obfd, i);
+	}
+
+      /* If out_attr was copied from in_attr then it won't have a type yet.  */
+      if (in_attr[i].type && !out_attr[i].type)
+	out_attr[i].type = in_attr[i].type;
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  if (!_bfd_elf_merge_object_attributes (ibfd, info))
+    return FALSE;
+
+  /* Check for any attributes not known on ARC.  */
+  result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd);
+
+  return result;
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -517,6 +790,10 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   if (! _bfd_generic_verify_endian_match (ibfd, info))
     return FALSE;
 
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return TRUE;
+
   /* Collect ELF flags.  */
   in_flags = elf_elfheader (ibfd)->e_flags & EF_ARC_MACH_MSK;
   out_flags = elf_elfheader (obfd)->e_flags & EF_ARC_MACH_MSK;
@@ -527,9 +804,8 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
       out_flags = in_flags;
     }
 
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return TRUE;
+  if (!arc_elf_merge_attributes (ibfd, info))
+    return FALSE;
 
   /* Check to see if the input BFD actually contains any sections.  Do
      not short-circuit dynamic objects; their section list may be
@@ -569,7 +845,11 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 			      ibfd, obfd);
 	  return FALSE;
 	}
-      else if (in_flags != out_flags)
+      else if ((in_flags != out_flags)
+	       /* If we have object attributes, then we already
+		  checked the objects compatibility, skip it.  */
+	       && !bfd_elf_get_obj_attr_int (ibfd, OBJ_ATTR_PROC,
+					     Tag_ARC_CPU_base))
 	{
 	  /* Warn if different flags.  */
 	  _bfd_error_handler
@@ -583,6 +863,11 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 	     eflags set by gcc.  */
 	  in_flags = in_flags > out_flags ? in_flags : out_flags;
 	}
+      else
+	{
+	  /* Everything is correct; don't change the output flags.  */
+	  in_flags = out_flags;
+	}
     }
 
   /* Update the flags.  */
@@ -596,6 +881,30 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   return TRUE;
 }
 
+/* Return a best guess for the machine number based on the attributes.  */
+
+static unsigned int
+bfd_arc_get_mach_from_attributes (bfd * abfd)
+{
+  int arch = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_ARC_CPU_base);
+  unsigned e_machine = elf_elfheader (abfd)->e_machine;
+
+  switch (arch)
+    {
+    case TAG_CPU_ARC6xx:
+      return bfd_mach_arc_arc600;
+    case TAG_CPU_ARC7xx:
+      return bfd_mach_arc_arc700;
+    case TAG_CPU_ARCEM:
+    case TAG_CPU_ARCHS:
+      return bfd_mach_arc_arcv2;
+    default:
+      break;
+    }
+  return (e_machine == EM_ARC_COMPACT)
+    ? bfd_mach_arc_arc700 : bfd_mach_arc_arcv2;
+}
+
 /* Set the right machine number for an ARC ELF file.  */
 static bfd_boolean
 arc_elf_object_p (bfd * abfd)
@@ -603,7 +912,7 @@ arc_elf_object_p (bfd * abfd)
   /* Make sure this is initialised, or you'll have the potential of passing
      garbage---or misleading values---into the call to
      bfd_default_set_arch_mach ().  */
-  int		  mach = bfd_mach_arc_arc700;
+  unsigned int	  mach = bfd_mach_arc_arc700;
   unsigned long   arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH_MSK;
   unsigned	  e_machine = elf_elfheader (abfd)->e_machine;
 
@@ -625,8 +934,7 @@ arc_elf_object_p (bfd * abfd)
 	    mach = bfd_mach_arc_arcv2;
 	    break;
 	  default:
-	    mach = (e_machine == EM_ARC_COMPACT)
-	      ? bfd_mach_arc_arc700 : bfd_mach_arc_arcv2;
+	    mach = bfd_arc_get_mach_from_attributes (abfd);
 	    break;
 	}
     }
@@ -657,6 +965,9 @@ arc_elf_final_write_processing (bfd * abfd,
 				bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   unsigned long emf;
+  int osver = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC,
+					Tag_ARC_ABI_osver);
+  flagword e_flags = elf_elfheader (abfd)->e_flags & ~EF_ARC_OSABI_MSK;
 
   switch (bfd_get_mach (abfd))
     {
@@ -673,16 +984,18 @@ arc_elf_final_write_processing (bfd * abfd,
       emf = EM_ARC_COMPACT2;
       break;
     default:
-      goto DO_NOTHING;
+      return;
     }
 
   elf_elfheader (abfd)->e_machine = emf;
 
   /* Record whatever is the current syscall ABI version.  */
-  elf_elfheader (abfd)->e_flags |= E_ARC_OSABI_CURRENT;
+  if (osver)
+    e_flags |= ((osver & 0x0f) << 8);
+  else
+    e_flags |= E_ARC_OSABI_V3;
 
-DO_NOTHING:
-  return;
+  elf_elfheader (abfd)->e_flags |=  e_flags;
 }
 
 #ifdef ARC_ENABLE_DEBUG
@@ -2465,6 +2778,69 @@ elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 					  note->descpos + offset);
 }
 
+/* Determine whether an object attribute tag takes an integer, a
+   string or both.  */
+
+static int
+elf32_arc_obj_attrs_arg_type (int tag)
+{
+  if (tag == Tag_ARC_CPU_name
+	   || tag == Tag_ARC_ISA_config
+	   || tag == Tag_ARC_ISA_apex)
+    return ATTR_TYPE_FLAG_STR_VAL;
+  else if (tag < (Tag_ARC_ISA_mpy_option + 1))
+    return ATTR_TYPE_FLAG_INT_VAL;
+  else
+    return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL;
+}
+
+/* Attribute numbers >=14 can be safely ignored.  */
+
+static bfd_boolean
+elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag)
+{
+  if ((tag & 127) < (Tag_ARC_ISA_mpy_option + 1))
+    {
+      _bfd_error_handler
+	(_("%B: Unknown mandatory ARC object attribute %d."),
+	 abfd, tag);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+  else
+    {
+      _bfd_error_handler
+	(_("Warning: %B: Unknown ARC object attribute %d."),
+	 abfd, tag);
+      return TRUE;
+    }
+}
+
+/* Handle an ARC specific section when reading an object file.  This is
+   called when bfd_section_from_shdr finds a section with an unknown
+   type.  */
+
+static bfd_boolean
+elf32_arc_section_from_shdr (bfd *abfd,
+			     Elf_Internal_Shdr * hdr,
+			     const char *name,
+			     int shindex)
+{
+  switch (hdr->sh_type)
+    {
+    case SHT_ARC_ATTRIBUTES:
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+    return FALSE;
+
+  return TRUE;
+}
+
 #define TARGET_LITTLE_SYM   arc_elf32_le_vec
 #define TARGET_LITTLE_NAME  "elf32-littlearc"
 #define TARGET_BIG_SYM	    arc_elf32_be_vec
@@ -2516,4 +2892,16 @@ elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
 #define elf_backend_default_execstack	0
 
+#undef  elf_backend_obj_attrs_vendor
+#define elf_backend_obj_attrs_vendor		"ARC"
+#undef  elf_backend_obj_attrs_section
+#define elf_backend_obj_attrs_section		".ARC.attributes"
+#undef  elf_backend_obj_attrs_arg_type
+#define elf_backend_obj_attrs_arg_type		elf32_arc_obj_attrs_arg_type
+#undef  elf_backend_obj_attrs_section_type
+#define elf_backend_obj_attrs_section_type	SHT_ARC_ATTRIBUTES
+#define elf_backend_obj_attrs_handle_unknown 	elf32_arc_obj_attrs_handle_unknown
+
+#define elf_backend_section_from_shdr  		elf32_arc_section_from_shdr
+
 #include "elf32-target.h"
diff --git a/binutils/readelf.c b/binutils/readelf.c
index fba6516..16eb866 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2508,6 +2508,9 @@ decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[])
     case E_ARC_OSABI_V3:
       strcat (buf, ", v3 no-legacy-syscalls ABI");
       break;
+    case E_ARC_OSABI_V4:
+      strcat (buf, ", v4 ABI");
+      break;
     default:
       strcat (buf, ", unrecognised ARC OSABI flag");
       break;
@@ -3898,6 +3901,18 @@ get_segment_type (unsigned long p_type)
 }
 
 static const char *
+get_arc_section_type_name (unsigned int sh_type)
+{
+  switch (sh_type)
+    {
+    case SHT_ARC_ATTRIBUTES:      return "ARC_ATTRIBUTES";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static const char *
 get_mips_section_type_name (unsigned int sh_type)
 {
   switch (sh_type)
@@ -4106,6 +4121,11 @@ get_section_type_name (unsigned int sh_type)
 	{
 	  switch (elf_header.e_machine)
 	    {
+	    case EM_ARC:
+	    case EM_ARC_COMPACT:
+	    case EM_ARC_COMPACT2:
+	      result = get_arc_section_type_name (sh_type);
+	      break;
 	    case EM_MIPS:
 	    case EM_MIPS_RS3_LE:
 	      result = get_mips_section_type_name (sh_type);
@@ -13491,6 +13511,180 @@ display_tag_value (signed int tag,
   return p;
 }
 
+/* ARC ABI attributes section.  */
+
+static unsigned char *
+display_arc_attribute (unsigned char * p,
+		       const unsigned char * const end)
+{
+  unsigned int tag;
+  unsigned int len;
+  unsigned int val;
+
+  tag = read_uleb128 (p, &len, end);
+  p += len;
+
+  switch (tag)
+    {
+    case Tag_ARC_PCS_config:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_PCS_config: ");
+      switch (val)
+	{
+	case 0:
+	  printf (_("Absent/Non standard\n"));
+	  break;
+	case 1:
+	  printf (_("Bare metal/mwdt\n"));
+	  break;
+	case 2:
+	  printf (_("Bare metal/newlib\n"));
+	  break;
+	case 3:
+	  printf (_("Linux/uclibc\n"));
+	  break;
+	case 4:
+	  printf (_("Linux/glibc\n"));
+	  break;
+	default:
+	  printf (_("Unknown\n"));
+	  break;
+	}
+      break;
+
+    case Tag_ARC_CPU_base:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_CPU_base: ");
+      switch (val)
+	{
+	default:
+	case TAG_CPU_NONE:
+	  printf (_("Absent\n"));
+	  break;
+	case TAG_CPU_ARC6xx:
+	  printf ("ARC6xx\n");
+	  break;
+	case TAG_CPU_ARC7xx:
+	  printf ("ARC7xx\n");
+	  break;
+	case TAG_CPU_ARCEM:
+	  printf ("ARCEM\n");
+	  break;
+	case TAG_CPU_ARCHS:
+	  printf ("ARCHS\n");
+	  break;
+	}
+      break;
+
+    case Tag_ARC_CPU_variation:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_CPU_variation: ");
+      switch (val)
+	{
+	default:
+	  if (val > 0 && val < 16)
+	    {
+	      printf ("Core%d\n", val);
+	      break;
+	    }
+	case 0:
+	  printf (_("Absent\n"));
+	  break;
+	}
+      break;
+
+    case Tag_ARC_CPU_name:
+      printf ("  Tag_ARC_CPU_name: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ABI_rf16:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_rf16: %s\n", val ? _("yes") : _("no"));
+      break;
+
+    case Tag_ARC_ABI_osver:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_osver: v%d\n", val);
+      break;
+
+    case Tag_ARC_ABI_pic:
+    case Tag_ARC_ABI_sda:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf (tag == Tag_ARC_ABI_sda ? "  Tag_ARC_ABI_sda: "
+	      : "  Tag_ARC_ABI_pic: ");
+      switch (val)
+	{
+	case 0:
+	  printf (_("Absent\n"));
+	  break;
+	case 1:
+	  printf ("MWDT\n");
+	  break;
+	case 2:
+	  printf ("GNU\n");
+	  break;
+	default:
+	  printf (_("Unknown\n"));
+	  break;
+	}
+      break;
+
+    case Tag_ARC_ABI_tls:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_tls: %s\n", val ? "r25": "none");
+      break;
+
+    case Tag_ARC_ABI_enumsize:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_enumsize: %s\n", val ? _("default") :
+	      _("smallest"));
+      break;
+
+    case Tag_ARC_ABI_exceptions:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_exceptions: %s\n", val ? _("OPTFP")
+	      : _("default"));
+      break;
+
+    case Tag_ARC_ABI_double_size:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ABI_double_size: %d\n", val);
+      break;
+
+    case Tag_ARC_ISA_config:
+      printf ("  Tag_ARC_ISA_config: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ISA_apex:
+      printf ("  Tag_ARC_ISA_apex: ");
+      p = display_tag_value (-1, p, end);
+      break;
+
+    case Tag_ARC_ISA_mpy_option:
+      val = read_uleb128 (p, &len, end);
+      p += len;
+      printf ("  Tag_ARC_ISA_mpy_option: %d\n", val);
+      break;
+
+    default:
+      return display_tag_value (tag & 1, p, end);
+    }
+
+  return p;
+}
+
 /* ARM EABI attributes section.  */
 typedef struct
 {
@@ -17573,6 +17767,12 @@ process_arch_specific (FILE * file)
 
   switch (elf_header.e_machine)
     {
+    case EM_ARC:
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
+      return process_attributes (file, "ARC", SHT_ARC_ATTRIBUTES,
+				 display_arc_attribute,
+				 display_generic_attribute);
     case EM_ARM:
       return process_attributes (file, "aeabi", SHT_ARM_ATTRIBUTES,
 				 display_arm_attribute,
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index f806ca3..a092892 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -28,6 +28,7 @@
 #include "safe-ctype.h"
 
 #include "opcode/arc.h"
+#include "opcode/arc-attrs.h"
 #include "elf/arc.h"
 #include "../opcodes/arc-ext.h"
 
@@ -55,6 +56,10 @@
 #define TARGET_WITH_CPU "arc700"
 #endif /* TARGET_WITH_CPU */
 
+#define ARC_GET_FLAG(s)   	(*symbol_get_tc (s))
+#define ARC_SET_FLAG(s,v) 	(*symbol_get_tc (s) |= (v))
+#define streq(a, b)	      (strcmp (a, b) == 0)
+
 /* Enum used to enumerate the relaxable ins operands.  */
 enum rlx_operand_type
 {
@@ -147,6 +152,7 @@ static void arc_option (int);
 static void arc_extra_reloc (int);
 static void arc_extinsn (int);
 static void arc_extcorereg (int);
+static void arc_attribute (int);
 
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -158,6 +164,7 @@ const pseudo_typeS md_pseudo_table[] =
   { "lcommon", arc_lcomm, 0 },
   { "cpu",     arc_option, 0 },
 
+  { "arc_attribute",   arc_attribute, 0 },
   { "extinstruction",  arc_extinsn, 0 },
   { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
   { "extauxregister",  arc_extcorereg, EXT_AUX_REGISTER },
@@ -451,21 +458,21 @@ static const struct cpu_type
   cpu_types[] =
 {
   ARC_CPU_TYPE_A7xx (arc700, 0x00),
-  ARC_CPU_TYPE_A7xx (nps400, ARC_NPS400),
+  ARC_CPU_TYPE_A7xx (nps400, NPS400),
 
   ARC_CPU_TYPE_AV2EM (arcem,	  0x00),
   ARC_CPU_TYPE_AV2EM (em,	  0x00),
-  ARC_CPU_TYPE_AV2EM (em4,	  ARC_CD),
-  ARC_CPU_TYPE_AV2EM (em4_dmips,  ARC_CD),
-  ARC_CPU_TYPE_AV2EM (em4_fpus,	  ARC_CD),
-  ARC_CPU_TYPE_AV2EM (em4_fpuda,  ARC_CD | ARC_FPUDA),
-  ARC_CPU_TYPE_AV2EM (quarkse_em, ARC_CD | ARC_SPFP | ARC_DPFP),
-
-  ARC_CPU_TYPE_AV2HS (archs,	  ARC_CD),
-  ARC_CPU_TYPE_AV2HS (hs,	  ARC_CD),
-  ARC_CPU_TYPE_AV2HS (hs34,	  ARC_CD),
-  ARC_CPU_TYPE_AV2HS (hs38,	  ARC_CD),
-  ARC_CPU_TYPE_AV2HS (hs38_linux, ARC_CD),
+  ARC_CPU_TYPE_AV2EM (em4,	  CD),
+  ARC_CPU_TYPE_AV2EM (em4_dmips,  CD),
+  ARC_CPU_TYPE_AV2EM (em4_fpus,	  CD),
+  ARC_CPU_TYPE_AV2EM (em4_fpuda,  CD | DPA),
+  ARC_CPU_TYPE_AV2EM (quarkse_em, CD | SPX | DPX),
+
+  ARC_CPU_TYPE_AV2HS (archs,	  CD),
+  ARC_CPU_TYPE_AV2HS (hs,	  CD),
+  ARC_CPU_TYPE_AV2HS (hs34,	  CD),
+  ARC_CPU_TYPE_AV2HS (hs38,	  CD),
+  ARC_CPU_TYPE_AV2HS (hs38_linux, CD),
 
   ARC_CPU_TYPE_A6xx (arc600, 0x00),
   ARC_CPU_TYPE_A6xx (arc600_norm,     0x00),
@@ -479,23 +486,19 @@ static const struct cpu_type
 };
 
 /* Information about the cpu/variant we're assembling for.  */
-static struct cpu_type selected_cpu = { 0, 0, 0, 0, 0 };
+static struct cpu_type selected_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 };
 
-/* A table with options.  */
-static const struct feature_type
-{
-  unsigned feature;
-  unsigned cpus;
-  const char *name;
-}
-  feature_list[] =
-{
-  { ARC_CD, ARC_OPCODE_ARCV2, "code-density" },
-  { ARC_NPS400, ARC_OPCODE_ARC700, "nps400" },
-  { ARC_SPFP, ARC_OPCODE_ARCFPX, "single-precision FPX" },
-  { ARC_DPFP, ARC_OPCODE_ARCFPX, "double-precision FPX" },
-  { ARC_FPUDA, ARC_OPCODE_ARCv2EM, "double assist FP" }
-};
+/* MPY option.  */
+static unsigned mpy_option = 0;
+
+/* Use PIC. */
+static unsigned pic_option = 0;
+
+/* Use small data.  */
+static unsigned sda_option = 0;
+
+/* Use TLS.  */
+static unsigned tls_option = 0;
 
 /* Command line given features.  */
 static unsigned cl_features = 0;
@@ -695,15 +698,15 @@ const struct arc_relaxable_ins arc_relaxable_insns[] =
 
 const unsigned arc_num_relaxable_ins = ARRAY_SIZE (arc_relaxable_insns);
 
-/* Flags to set in the elf header.  */
-static const flagword arc_initial_eflag = 0x00;
-
 /* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
 symbolS * GOT_symbol = 0;
 
 /* Set to TRUE when we assemble instructions.  */
 static bfd_boolean assembling_insn = FALSE;
 
+/* List with attributes set explicitly.  */
+static bfd_boolean attributes_set_explicitly[NUM_KNOWN_OBJ_ATTRIBUTES];
+
 /* Functions implementation.  */
 
 /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
@@ -832,15 +835,16 @@ arc_check_feature (void)
   if (!selected_cpu.features
       || !selected_cpu.name)
     return;
-  for (i = 0; (i < ARRAY_SIZE (feature_list)); i++)
-    {
-      if ((selected_cpu.features & feature_list[i].feature)
-	  && !(selected_cpu.flags & feature_list[i].cpus))
-	{
-	  as_bad (_("invalid %s option for %s cpu"), feature_list[i].name,
-		  selected_cpu.name);
-	}
-    }
+
+  for (i = 0; i < ARRAY_SIZE (feature_list); i++)
+    if ((selected_cpu.features & feature_list[i].feature)
+	&& !(selected_cpu.flags & feature_list[i].cpus))
+      as_bad (_("invalid %s option for %s cpu"), feature_list[i].name,
+	      selected_cpu.name);
+
+  for (i = 0; i < ARRAY_SIZE (conflict_list); i++)
+    if ((selected_cpu.features & conflict_list[i]) == conflict_list[i])
+      as_bad(_("conflicting ISA extension attributes."));
 }
 
 /* Select an appropriate entry from CPU_TYPES based on ARG and initialise
@@ -850,7 +854,6 @@ arc_check_feature (void)
 static void
 arc_select_cpu (const char *arg, enum mach_selection_type sel)
 {
-  int cpu_flags = 0;
   int i;
 
   /* We should only set a default if we've not made a selection from some
@@ -888,7 +891,8 @@ arc_select_cpu (const char *arg, enum mach_selection_type sel)
 	  selected_cpu.name = cpu_types[i].name;
 	  selected_cpu.features = cpu_types[i].features | cl_features;
 	  selected_cpu.mach = cpu_types[i].mach;
-	  cpu_flags = cpu_types[i].eflags;
+	  selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_MACH_MSK)
+				 | cpu_types[i].eflags);
           break;
         }
     }
@@ -898,8 +902,7 @@ arc_select_cpu (const char *arg, enum mach_selection_type sel)
 
   /* Check if set features are compatible with the chosen CPU.  */
   arc_check_feature ();
-  gas_assert (cpu_flags != 0);
-  selected_cpu.eflags = (arc_initial_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
+
   mach_selection_mode = sel;
 }
 
@@ -1026,12 +1029,6 @@ arc_option (int ignore ATTRIBUTE_UNUSED)
 
   arc_select_cpu (cpu_name, MACH_SELECTION_FROM_CPU_DIRECTIVE);
 
-  if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
-    as_fatal (_("could not set architecture and machine"));
-
-  /* Set elf header flags.  */
-  bfd_set_private_flags (stdoutput, selected_cpu.eflags);
-
   restore_line_pointer (c);
   demand_empty_rest_of_line ();
 }
@@ -1626,19 +1623,19 @@ allocate_tok (expressionS *tok, int ntok, int cidx)
 static bfd_boolean
 check_cpu_feature (insn_subclass_t sc)
 {
-  if (is_code_density_p (sc) && !(selected_cpu.features & ARC_CD))
+  if (is_code_density_p (sc) && !(selected_cpu.features & CD))
     return FALSE;
 
-  if (is_spfp_p (sc) && !(selected_cpu.features & ARC_SPFP))
+  if (is_spfp_p (sc) && !(selected_cpu.features & SPX))
     return FALSE;
 
-  if (is_dpfp_p (sc) && !(selected_cpu.features & ARC_DPFP))
+  if (is_dpfp_p (sc) && !(selected_cpu.features & DPX))
     return FALSE;
 
-  if (is_fpuda_p (sc) && !(selected_cpu.features & ARC_FPUDA))
+  if (is_fpuda_p (sc) && !(selected_cpu.features & DPA))
     return FALSE;
 
-  if (is_nps400_p (sc) && !(selected_cpu.features & ARC_NPS400))
+  if (is_nps400_p (sc) && !(selected_cpu.features & NPS400))
     return FALSE;
 
   return TRUE;
@@ -2345,7 +2342,56 @@ find_special_case (const char *opname,
   return entry;
 }
 
-/* Given an opcode name, pre-tokenized set of arguments and the
+/* Autodetect cpu attribute list.  */
+
+static void
+autodetect_attributes (const struct arc_opcode *opcode,
+			 const expressionS *tok,
+			 int ntok)
+{
+  unsigned i;
+  struct mpy_type
+  {
+    unsigned feature;
+    unsigned encoding;
+  } mpy_list[] = {{ MPY1E, 1 }, { MPY6E, 6 }, { MPY7E, 7 }, { MPY8E, 8 },
+		 { MPY9E, 9 }};
+
+  for (i = 0; i < ARRAY_SIZE (feature_list); i++)
+    if (opcode->subclass == feature_list[i].feature)
+      selected_cpu.features |= feature_list[i].feature;
+
+  for (i = 0; i < ARRAY_SIZE (mpy_list); i++)
+    if (opcode->subclass == mpy_list[i].feature)
+      mpy_option = mpy_list[i].encoding;
+
+  for (i = 0; i < (unsigned) ntok; i++)
+    {
+      switch (tok[i].X_md)
+	{
+	case O_gotoff:
+	case O_gotpc:
+	case O_plt:
+	  pic_option = 2;
+	  break;
+	case O_sda:
+	  sda_option = 2;
+	  break;
+	case O_tlsgd:
+	case O_tlsie:
+	case O_tpoff9:
+	case O_tpoff:
+	case O_dtpoff9:
+	case O_dtpoff:
+	  tls_option = 1;
+	  break;
+	default:
+	  break;
+	}
+    }
+}
+
+/* Given an opcode name, pre-tockenized set of argumenst and the
    opcode flags, take it all the way through emission.  */
 
 static void
@@ -2380,6 +2426,7 @@ assemble_tokens (const char *opname,
 	{
 	  struct arc_insn insn;
 
+	  autodetect_attributes (opcode,  tok, ntok);
 	  assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
 	  emit_insn (&insn);
 	  return;
@@ -3384,8 +3431,8 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
       break;
 
     case OPTION_CD:
-      selected_cpu.features |= ARC_CD;
-      cl_features |= ARC_CD;
+      selected_cpu.features |= CD;
+      cl_features |= CD;
       arc_check_feature ();
       break;
 
@@ -3394,26 +3441,26 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
       break;
 
     case OPTION_NPS400:
-      selected_cpu.features |= ARC_NPS400;
-      cl_features |= ARC_NPS400;
+      selected_cpu.features |= NPS400;
+      cl_features |= NPS400;
       arc_check_feature ();
       break;
 
     case OPTION_SPFP:
-      selected_cpu.features |= ARC_SPFP;
-      cl_features |= ARC_SPFP;
+      selected_cpu.features |= SPX;
+      cl_features |= SPX;
       arc_check_feature ();
       break;
 
     case OPTION_DPFP:
-      selected_cpu.features |= ARC_DPFP;
-      cl_features |= ARC_DPFP;
+      selected_cpu.features |= DPX;
+      cl_features |= DPX;
       arc_check_feature ();
       break;
 
     case OPTION_FPUDA:
-      selected_cpu.features |= ARC_FPUDA;
-      cl_features |= ARC_FPUDA;
+      selected_cpu.features |= DPA;
+      cl_features |= DPA;
       arc_check_feature ();
       break;
 
@@ -4828,6 +4875,202 @@ arc_extcorereg (int opertype)
   create_extcore_section (&ereg, opertype);
 }
 
+/* Parse a .arc_attribute directive.  */
+
+static void
+arc_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+  int tag = obj_elf_vendor_attribute (OBJ_ATTR_PROC);
+
+  if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
+    attributes_set_explicitly[tag] = TRUE;
+}
+
+/* Set an attribute if it has not already been set by the user.  */
+
+static void
+arc_set_attribute_int (int tag, int value)
+{
+  if (tag < 1
+      || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
+      || !attributes_set_explicitly[tag])
+    bfd_elf_add_proc_attr_int (stdoutput, tag, value);
+}
+
+static void
+arc_set_attribute_string (int tag, const char *value)
+{
+  if (tag < 1
+      || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
+      || !attributes_set_explicitly[tag])
+    bfd_elf_add_proc_attr_string (stdoutput, tag, value);
+}
+
+/* Allocate and concatenate two strings.  s1 can be NULL but not
+   s2.  s1 pointer is freed at end of this procedure.  */
+
+static char *
+arc_stralloc (char * s1, const char * s2)
+{
+  char * p;
+  int len = 0;
+
+  if (s1)
+    len = strlen (s1) + 1;
+
+  /* Only s1 can be null.  */
+  gas_assert (s2);
+  len += strlen (s2) + 1;
+
+  p = (char *) xmalloc (len);
+  if (p == NULL)
+    as_fatal (_("Virtual memory exhausted"));
+
+  if (s1)
+    {
+      strcpy (p, s1);
+      strcat (p, ",");
+      strcat (p, s2);
+      free (s1);
+    }
+  else
+    strcpy (p, s2);
+
+  return p;
+}
+
+/* Set the public ARC object attributes.  */
+
+static void
+arc_set_public_attributes (void)
+{
+  int base = 0;
+  char *s = NULL;
+  unsigned int i;
+
+  /* Tag_ARC_CPU_name.  */
+  arc_set_attribute_string (Tag_ARC_CPU_name, selected_cpu.name);
+
+  /* Tag_ARC_CPU_base.  */
+  switch (selected_cpu.eflags & EF_ARC_MACH_MSK)
+    {
+    case E_ARC_MACH_ARC600:
+    case E_ARC_MACH_ARC601:
+      base = TAG_CPU_ARC6xx;
+      break;
+    case E_ARC_MACH_ARC700:
+      base = TAG_CPU_ARC7xx;
+      break;
+    case EF_ARC_CPU_ARCV2EM:
+      base = TAG_CPU_ARCEM;
+      break;
+    case EF_ARC_CPU_ARCV2HS:
+      base = TAG_CPU_ARCHS;
+      break;
+    default:
+      base = 0;
+      break;
+    }
+  if (attributes_set_explicitly[Tag_ARC_CPU_base]
+      && (base != bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+					    Tag_ARC_CPU_base)))
+    as_warn (_("Overwrite explicitly set Tag_ARC_CPU_base"));
+  bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_CPU_base, base);
+
+  /* Tag_ARC_ABI_osver.  */
+  if (attributes_set_explicitly[Tag_ARC_ABI_osver])
+    {
+      int val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+					  Tag_ARC_ABI_osver);
+
+      selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_OSABI_MSK)
+			     | (val & 0x0f << 8));
+    }
+  else
+    {
+      arc_set_attribute_int (Tag_ARC_ABI_osver, E_ARC_OSABI_CURRENT >> 8);
+    }
+
+  /* Tag_ARC_ISA_config.  */
+  arc_check_feature();
+
+  for (i = 0; i < ARRAY_SIZE (feature_list); i++)
+    if (selected_cpu.features & feature_list[i].feature)
+      s = arc_stralloc (s, feature_list[i].attr);
+
+  if (s)
+    arc_set_attribute_string (Tag_ARC_ISA_config, s);
+
+  /* Tag_ARC_ISA_mpy_option.  */
+  arc_set_attribute_int (Tag_ARC_ISA_mpy_option, mpy_option);
+
+  /* Tag_ARC_ABI_pic.  */
+  arc_set_attribute_int (Tag_ARC_ABI_pic, pic_option);
+
+  /* Tag_ARC_ABI_sda.  */
+  arc_set_attribute_int (Tag_ARC_ABI_sda, sda_option);
+
+  /* Tag_ARC_ABI_tls.  */
+  arc_set_attribute_int (Tag_ARC_ABI_tls, tls_option);
+}
+
+/* Add the default contents for the .ARC.attributes section.  */
+
+void
+arc_md_end (void)
+{
+  arc_set_public_attributes ();
+
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
+    as_fatal (_("could not set architecture and machine"));
+
+  bfd_set_private_flags (stdoutput, selected_cpu.eflags);
+}
+
+void arc_copy_symbol_attributes (symbolS *dest, symbolS *src)
+{
+  ARC_GET_FLAG (dest) = ARC_GET_FLAG (src);
+}
+
+int arc_convert_symbolic_attribute (const char *name)
+{
+  static const struct
+  {
+    const char * name;
+    const int    tag;
+  }
+  attribute_table[] =
+    {
+#define T(tag) {#tag, tag}
+  T (Tag_ARC_PCS_config),
+  T (Tag_ARC_CPU_base),
+  T (Tag_ARC_CPU_variation),
+  T (Tag_ARC_CPU_name),
+  T (Tag_ARC_ABI_rf16),
+  T (Tag_ARC_ABI_osver),
+  T (Tag_ARC_ABI_sda),
+  T (Tag_ARC_ABI_pic),
+  T (Tag_ARC_ABI_tls),
+  T (Tag_ARC_ABI_enumsize),
+  T (Tag_ARC_ABI_exceptions),
+  T (Tag_ARC_ABI_double_size),
+  T (Tag_ARC_ISA_config),
+  T (Tag_ARC_ISA_apex),
+  T (Tag_ARC_ISA_mpy_option)
+#undef T
+    };
+  unsigned int i;
+
+  if (name == NULL)
+    return -1;
+
+  for (i = 0; i < ARRAY_SIZE (attribute_table); i++)
+    if (streq (name, attribute_table[i].name))
+      return attribute_table[i].tag;
+
+  return -1;
+}
+
 /* Local variables:
    eval: (c-set-style "gnu")
    indent-tabs-mode: t
diff --git a/gas/config/tc-arc.h b/gas/config/tc-arc.h
index 41d83d8..f4cafe9 100644
--- a/gas/config/tc-arc.h
+++ b/gas/config/tc-arc.h
@@ -190,6 +190,17 @@ extern long md_pcrel_from_section (struct fix *, segT);
 /* Adjust symbol table.  */
 #define obj_adjust_symtab() arc_adjust_symtab ()
 
+/* Object attribute hooks.  */
+#define md_end arc_md_end
+#define CONVERT_SYMBOLIC_ATTRIBUTE(name) arc_convert_symbolic_attribute (name)
+#ifndef TC_COPY_SYMBOL_ATTRIBUTES
+#define TC_COPY_SYMBOL_ATTRIBUTES(DEST, SRC) \
+  (arc_copy_symbol_attributes (DEST, SRC))
+#endif
+
+extern void arc_copy_symbol_attributes (symbolS *, symbolS *);
+extern int arc_convert_symbolic_attribute (const char *);
+extern void arc_md_end (void);
 extern void arc_adjust_symtab (void);
 extern int arc_pcrel_adjust (fragS *);
 extern bfd_boolean arc_parse_name (const char *, struct expressionS *);
diff --git a/gas/doc/c-arc.texi b/gas/doc/c-arc.texi
index 1ff0b0f..14fe10f 100644
--- a/gas/doc/c-arc.texi
+++ b/gas/doc/c-arc.texi
@@ -658,6 +658,22 @@ A two operands instruction variant would be:
 which describes a two operand instruction with an implicit first
 immediate operand.  The result of this operation would be discarded.
 
+@cindex @code{.arc_attribute} directive, ARC
+@item .arc_attribute @var{tag}, @var{value}
+Set the ARC object attribute @var{tag} to @var{value}.
+
+The @var{tag} is either an attribute number, or one of the following:
+@code{Tag_ARC_PCS_config}, @code{Tag_ARC_CPU_base},
+@code{Tag_ARC_CPU_variation}, @code{Tag_ARC_CPU_name},
+@code{Tag_ARC_ABI_rf16}, @code{Tag_ARC_ABI_osver}, @code{Tag_ARC_ABI_sda},
+@code{Tag_ARC_ABI_pic}, @code{Tag_ARC_ABI_tls}, @code{Tag_ARC_ABI_enumsize},
+@code{Tag_ARC_ABI_exceptions}, @code{Tag_ARC_ABI_double_size},
+@code{Tag_ARC_ISA_config}, @code{Tag_ARC_ISA_apex},
+@code{Tag_ARC_ISA_mpy_option}
+
+The @var{value} is either a @code{number}, @code{"string"}, or
+@code{number, "string"} depending on the tag.
+
 @end table
 
 @node ARC Modifiers
diff --git a/gas/testsuite/gas/arc/attr-arc600.d b/gas/testsuite/gas/arc/attr-arc600.d
new file mode 100644
index 0000000..07eecc6
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc600.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc600
+# source: blank.s
+# as: -mcpu=arc600
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc600"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc600_mul32x16.d b/gas/testsuite/gas/arc/attr-arc600_mul32x16.d
new file mode 100644
index 0000000..6ca411d
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc600_mul32x16.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc600_mul32x16
+# source: blank.s
+# as: -mcpu=arc600_mul32x16
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc600_mul32x16"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc600_norm.d b/gas/testsuite/gas/arc/attr-arc600_norm.d
new file mode 100644
index 0000000..2ff0a71
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc600_norm.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc600_norm
+# source: blank.s
+# as: -mcpu=arc600_norm
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc600_norm"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc601.d b/gas/testsuite/gas/arc/attr-arc601.d
new file mode 100644
index 0000000..f8fb744
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc601.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc601
+# source: blank.s
+# as: -mcpu=arc601
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc601"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc601_mul32x16.d b/gas/testsuite/gas/arc/attr-arc601_mul32x16.d
new file mode 100644
index 0000000..8104276
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc601_mul32x16.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc601_mul32x16
+# source: blank.s
+# as: -mcpu=arc601_mul32x16
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc601_mul32x16"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc601_mul64.d b/gas/testsuite/gas/arc/attr-arc601_mul64.d
new file mode 100644
index 0000000..9985476
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc601_mul64.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc601_mul64
+# source: blank.s
+# as: -mcpu=arc601_mul64
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc601_mul64"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc601_norm.d b/gas/testsuite/gas/arc/attr-arc601_norm.d
new file mode 100644
index 0000000..18131dc
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc601_norm.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc601_norm
+# source: blank.s
+# as: -mcpu=arc601_norm
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc601_norm"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arc700.d b/gas/testsuite/gas/arc/attr-arc700.d
new file mode 100644
index 0000000..cc4dc38
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arc700.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc700
+# source: blank.s
+# as: -mcpu=arc700
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC7xx
+  Tag_ARC_CPU_name: "arc700"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-arcem.d b/gas/testsuite/gas/arc/attr-arcem.d
new file mode 100644
index 0000000..da97473
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-arcem.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arcem
+# source: blank.s
+# as: -mcpu=arcem
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "arcem"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-archs.d b/gas/testsuite/gas/arc/attr-archs.d
new file mode 100644
index 0000000..c0d2e63
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-archs.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=archs
+# source: blank.s
+# as: -mcpu=archs
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "archs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-autodetect-1.d b/gas/testsuite/gas/arc/attr-autodetect-1.d
new file mode 100644
index 0000000..bbe8525
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-autodetect-1.d
@@ -0,0 +1,11 @@
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "archs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ABI_sda: GNU
+  Tag_ARC_ABI_pic: GNU
+  Tag_ARC_ABI_tls: r25
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-autodetect-1.s b/gas/testsuite/gas/arc/attr-autodetect-1.s
new file mode 100644
index 0000000..68f3e2b
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-autodetect-1.s
@@ -0,0 +1,4 @@
+	.cpu	archs
+        add_s   r0,gp,@a@sda
+        add     r0,pcl,@var@tlsgd
+        bl      @a@plt
diff --git a/gas/testsuite/gas/arc/attr-cpu-a601.d b/gas/testsuite/gas/arc/attr-cpu-a601.d
new file mode 100644
index 0000000..33a2f31
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-a601.d
@@ -0,0 +1,8 @@
+# as:
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc601"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-cpu-a601.s b/gas/testsuite/gas/arc/attr-cpu-a601.s
new file mode 100644
index 0000000..b6ebd8c
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-a601.s
@@ -0,0 +1 @@
+	.cpu arc601
diff --git a/gas/testsuite/gas/arc/attr-cpu-a700.d b/gas/testsuite/gas/arc/attr-cpu-a700.d
new file mode 100644
index 0000000..db69ade
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-a700.d
@@ -0,0 +1,8 @@
+# as:
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC7xx
+  Tag_ARC_CPU_name: "arc700"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-cpu-a700.s b/gas/testsuite/gas/arc/attr-cpu-a700.s
new file mode 100644
index 0000000..b84a24c
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-a700.s
@@ -0,0 +1 @@
+	.cpu ARC700
diff --git a/gas/testsuite/gas/arc/attr-cpu-em.d b/gas/testsuite/gas/arc/attr-cpu-em.d
new file mode 100644
index 0000000..c635bd5
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-em.d
@@ -0,0 +1,8 @@
+# as:
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-cpu-em.s b/gas/testsuite/gas/arc/attr-cpu-em.s
new file mode 100644
index 0000000..0b033e9
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-em.s
@@ -0,0 +1 @@
+	.cpu em
diff --git a/gas/testsuite/gas/arc/attr-cpu-hs.d b/gas/testsuite/gas/arc/attr-cpu-hs.d
new file mode 100644
index 0000000..4de82ad
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-hs.d
@@ -0,0 +1,9 @@
+# as:
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "hs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-cpu-hs.s b/gas/testsuite/gas/arc/attr-cpu-hs.s
new file mode 100644
index 0000000..d413612
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-cpu-hs.s
@@ -0,0 +1 @@
+	.cpu hs
diff --git a/gas/testsuite/gas/arc/attr-em.d b/gas/testsuite/gas/arc/attr-em.d
new file mode 100644
index 0000000..a322ff6
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-em.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=em
+# source: blank.s
+# as: -mcpu=em
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-em4.d b/gas/testsuite/gas/arc/attr-em4.d
new file mode 100644
index 0000000..bbc6e67
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-em4.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=em4
+# source: blank.s
+# as: -mcpu=em4
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em4"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-em4_dmips.d b/gas/testsuite/gas/arc/attr-em4_dmips.d
new file mode 100644
index 0000000..4d923bd
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-em4_dmips.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=em4_dmips
+# source: blank.s
+# as: -mcpu=em4_dmips
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em4_dmips"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-em4_fpuda.d b/gas/testsuite/gas/arc/attr-em4_fpuda.d
new file mode 100644
index 0000000..432315a
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-em4_fpuda.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=em4_fpuda
+# source: blank.s
+# as: -mcpu=em4_fpuda
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em4_fpuda"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD,FPUDA"
diff --git a/gas/testsuite/gas/arc/attr-em4_fpus.d b/gas/testsuite/gas/arc/attr-em4_fpus.d
new file mode 100644
index 0000000..b658e2a
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-em4_fpus.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=em4_fpus
+# source: blank.s
+# as: -mcpu=em4_fpus
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em4_fpus"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-hs.d b/gas/testsuite/gas/arc/attr-hs.d
new file mode 100644
index 0000000..8486214
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-hs.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=hs
+# source: blank.s
+# as: -mcpu=hs
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "hs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-hs34.d b/gas/testsuite/gas/arc/attr-hs34.d
new file mode 100644
index 0000000..8b92ec6
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-hs34.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=hs34
+# source: blank.s
+# as: -mcpu=hs34
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "hs34"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-hs38.d b/gas/testsuite/gas/arc/attr-hs38.d
new file mode 100644
index 0000000..8972431
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-hs38.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=hs38
+# source: blank.s
+# as: -mcpu=hs38
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "hs38"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-hs38_linux.d b/gas/testsuite/gas/arc/attr-hs38_linux.d
new file mode 100644
index 0000000..a695f29
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-hs38_linux.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=hs38_linux
+# source: blank.s
+# as: -mcpu=hs38_linux
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "hs38_linux"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-mul64.d b/gas/testsuite/gas/arc/attr-mul64.d
new file mode 100644
index 0000000..5fc75ff
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-mul64.d
@@ -0,0 +1,10 @@
+# name: attributes for -mcpu=arc600_mul64
+# source: blank.s
+# as: -mcpu=arc600_mul64
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_name: "arc600_mul64"
+  Tag_ARC_ABI_osver: v4
diff --git a/gas/testsuite/gas/arc/attr-name.d b/gas/testsuite/gas/arc/attr-name.d
new file mode 100644
index 0000000..ff9a34b
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-name.d
@@ -0,0 +1,22 @@
+# name: ARC object attribute names
+# source: attr-name.s
+# as:
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_PCS_config: Bare metal/mwdt
+  Tag_ARC_CPU_base: ARC6xx
+  Tag_ARC_CPU_variation: Core1
+  Tag_ARC_CPU_name: "random-cpu"
+  Tag_ARC_ABI_rf16: yes
+  Tag_ARC_ABI_osver: v3
+  Tag_ARC_ABI_sda: GNU
+  Tag_ARC_ABI_pic: GNU
+  Tag_ARC_ABI_tls: r25
+  Tag_ARC_ABI_enumsize: default
+  Tag_ARC_ABI_exceptions: OPTFP
+  Tag_ARC_ABI_double_size: 8
+  Tag_ARC_ISA_config: "CD,FPUDA"
+  Tag_ARC_ISA_apex: "QUARKSE"
+  Tag_ARC_ISA_mpy_option: 6
diff --git a/gas/testsuite/gas/arc/attr-name.s b/gas/testsuite/gas/arc/attr-name.s
new file mode 100644
index 0000000..cddc850
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-name.s
@@ -0,0 +1,17 @@
+;;; Set the cpu to avoid the eventual warning when setting Tag_ARC_CPU_base.
+	.cpu ARC600
+	.arc_attribute Tag_ARC_PCS_config,1
+	.arc_attribute Tag_ARC_CPU_base, 1
+	.arc_attribute Tag_ARC_CPU_variation, 1
+	.arc_attribute Tag_ARC_CPU_name, "random-cpu"
+	.arc_attribute Tag_ARC_ABI_rf16, 1
+	.arc_attribute Tag_ARC_ABI_osver, 3
+	.arc_attribute Tag_ARC_ABI_sda, 2
+	.arc_attribute Tag_ARC_ABI_pic, 2
+	.arc_attribute Tag_ARC_ABI_tls, 25
+	.arc_attribute Tag_ARC_ABI_enumsize, 1
+	.arc_attribute Tag_ARC_ABI_exceptions, 1
+	.arc_attribute Tag_ARC_ABI_double_size, 8
+	.arc_attribute Tag_ARC_ISA_config, "CD,FPUDA"
+	.arc_attribute Tag_ARC_ISA_apex, "QUARKSE"
+	.arc_attribute Tag_ARC_ISA_mpy_option, 6
diff --git a/gas/testsuite/gas/arc/attr-nps400.d b/gas/testsuite/gas/arc/attr-nps400.d
new file mode 100644
index 0000000..15009ce
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-nps400.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=nps400
+# source: blank.s
+# as: -mcpu=nps400
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARC7xx
+  Tag_ARC_CPU_name: "nps400"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "NPS400"
diff --git a/gas/testsuite/gas/arc/attr-override-mcpu.d b/gas/testsuite/gas/arc/attr-override-mcpu.d
new file mode 100644
index 0000000..67241e9
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-override-mcpu.d
@@ -0,0 +1,10 @@
+# source: attr-override-mcpu.s
+# as: -mcpu=archs
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "archs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/gas/testsuite/gas/arc/attr-override-mcpu.s b/gas/testsuite/gas/arc/attr-override-mcpu.s
new file mode 100644
index 0000000..f68af58
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-override-mcpu.s
@@ -0,0 +1 @@
+	.cpu	EM
diff --git a/gas/testsuite/gas/arc/attr-quarkse_em.d b/gas/testsuite/gas/arc/attr-quarkse_em.d
new file mode 100644
index 0000000..64c85c3
--- /dev/null
+++ b/gas/testsuite/gas/arc/attr-quarkse_em.d
@@ -0,0 +1,11 @@
+# name: attributes for -mcpu=quarkse_em
+# source: blank.s
+# as: -mcpu=quarkse_em
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "quarkse_em"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD,DPFP,SPFP"
diff --git a/gas/testsuite/gas/arc/blank.s b/gas/testsuite/gas/arc/blank.s
new file mode 100644
index 0000000..46641c4
--- /dev/null
+++ b/gas/testsuite/gas/arc/blank.s
@@ -0,0 +1 @@
+# this file left intentionally blank
diff --git a/gas/testsuite/gas/arc/cpu-pseudop-1.d b/gas/testsuite/gas/arc/cpu-pseudop-1.d
index 09c47c9..8aeb13a 100644
--- a/gas/testsuite/gas/arc/cpu-pseudop-1.d
+++ b/gas/testsuite/gas/arc/cpu-pseudop-1.d
@@ -2,7 +2,7 @@
 #objdump: -dp -M dpfp
 
 .*: +file format .*arc.*
-private flags = 0x305: -mcpu=ARCv2EM .*
+private flags = 0x\d05: -mcpu=ARCv2EM .*
 
 
 Disassembly of section .text:
diff --git a/gas/testsuite/gas/arc/cpu-pseudop-2.d b/gas/testsuite/gas/arc/cpu-pseudop-2.d
index 3bde329..6ad0d26 100644
--- a/gas/testsuite/gas/arc/cpu-pseudop-2.d
+++ b/gas/testsuite/gas/arc/cpu-pseudop-2.d
@@ -2,7 +2,7 @@
 #objdump: -dp
 
 .*: +file format .*arc.*
-private flags = 0x306: -mcpu=ARCv2HS .*
+private flags = 0x\d06: -mcpu=ARCv2HS .*
 
 
 Disassembly of section .text:
diff --git a/gas/testsuite/gas/arc/nps400-0.d b/gas/testsuite/gas/arc/nps400-0.d
index e5920c8..bcb2b51 100644
--- a/gas/testsuite/gas/arc/nps400-0.d
+++ b/gas/testsuite/gas/arc/nps400-0.d
@@ -11,5 +11,5 @@
   Machine:                           ARCompact
   Version:                           0x1
 #...
-  Flags:                             0x303, ARC700, v3 no-legacy-syscalls ABI
+  Flags:                             0x\d03, ARC700, .*
 #...
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 2a1bb27..ad38d66 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -85,6 +85,9 @@ if { [is_elf_format] } then {
     if {[istarget "arm*-*-*"]} {
 	set target_machine -arm
     }
+    if {[istarget "arc*-*-*"]} {
+	set target_machine -arc
+    }
 
     # The MN10300 and Xtensa ports disable the assembler's call frame
     # optimization because it interfers with link-time relaxation of
diff --git a/gas/testsuite/gas/elf/section2.e-arc b/gas/testsuite/gas/elf/section2.e-arc
new file mode 100644
index 0000000..115bae2
--- /dev/null
+++ b/gas/testsuite/gas/elf/section2.e-arc
@@ -0,0 +1,9 @@
+
+Symbol table '.symtab' contains 6 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +0: 0+0 +0 +NOTYPE +LOCAL +DEFAULT +UND 
+ +1: 0+0 +0 +SECTION +LOCAL +DEFAULT +1 
+ +2: 0+0 +0 +SECTION +LOCAL +DEFAULT +2 
+ +3: 0+0 +0 +SECTION +LOCAL +DEFAULT +3 
+ +4: 0+0 +0 +SECTION +LOCAL +DEFAULT +4 
+ +5: 0+0 +0 +SECTION +LOCAL +DEFAULT +5 
diff --git a/include/elf/arc.h b/include/elf/arc.h
index 944f49a..78da89c 100644
--- a/include/elf/arc.h
+++ b/include/elf/arc.h
@@ -55,12 +55,42 @@ END_RELOC_NUMBERS (R_ARC_max)
 #define E_ARC_OSABI_ORIG	0x00000000   /* MUST be 0 for back-compat.  */
 #define E_ARC_OSABI_V2		0x00000200
 #define E_ARC_OSABI_V3		0x00000300
-#define E_ARC_OSABI_CURRENT	E_ARC_OSABI_V3
-
+#define E_ARC_OSABI_V4		0x00000400
+#define E_ARC_OSABI_CURRENT	E_ARC_OSABI_V4
 /* Leave bits 0xf0 alone in case we ever have more than 16 cpu types.  */
 
 /* File contains position independent code.  */
 
 #define EF_ARC_PIC 0x00000100
 
+/* Additional section types.  */
+#define SHT_ARC_ATTRIBUTES     0x70000001	/* Section holds attributes.  */
+
+/* ARC ABI object attributes.  */
+enum {
+  /* 0-3 are generic.  */
+  Tag_ARC_PCS_config = 4,
+  Tag_ARC_CPU_base,
+  Tag_ARC_CPU_variation,
+  Tag_ARC_CPU_name,
+  Tag_ARC_ABI_rf16,
+  Tag_ARC_ABI_osver,
+  Tag_ARC_ABI_sda,
+  Tag_ARC_ABI_pic,
+  Tag_ARC_ABI_tls,
+  Tag_ARC_ABI_enumsize,
+  Tag_ARC_ABI_exceptions,
+  Tag_ARC_ABI_double_size,
+  Tag_ARC_ISA_config,
+  Tag_ARC_ISA_apex,
+  Tag_ARC_ISA_mpy_option
+};
+
+/* Values for the Tag_ARC_cpu_base attribute.  */
+#define TAG_CPU_NONE	  0
+#define TAG_CPU_ARC6xx	  1
+#define TAG_CPU_ARC7xx	  2
+#define TAG_CPU_ARCEM	  3
+#define TAG_CPU_ARCHS	  4
+
 #endif /* _ELF_ARC_H */
diff --git a/include/opcode/arc-attrs.h b/include/opcode/arc-attrs.h
new file mode 100644
index 0000000..4c36d00
--- /dev/null
+++ b/include/opcode/arc-attrs.h
@@ -0,0 +1,72 @@
+/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+
+   Contributed by Claudiu Zissulescu (claziss@synopsys.com)
+
+   This file is part of GAS, the GNU Assembler, GDB, the GNU debugger, and
+   the GNU Binutils.
+
+   GAS/GDB 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 3, or (at your option)
+   any later version.
+
+   GAS/GDB is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS or GDB; see the file COPYING3.  If not, write to
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#ifndef ATTRS_ARC_H
+#define ATTRS_ARC_H
+
+#ifndef FEATURE_LIST_NAME
+#define FEATURE_LIST_NAME feature_list
+#endif
+
+/* A table with cpu features.  */
+const struct feature_type
+{
+  unsigned feature;
+  unsigned cpus;
+  const char *attr;
+  const char *name;
+}  FEATURE_LIST_NAME [] =
+  {
+    { BTSCN,    ARC_OPCODE_ARCALL,   "BITSCAN",  "bit-scan" },
+    { CD,       ARC_OPCODE_ARCV2,    "CD",       "code-density" },
+    { DIV,      ARC_OPCODE_ARCV2,    "DIV_REM",  "div/rem" },
+    { DP,       ARC_OPCODE_ARCv2HS,  "FPUD",     "double-precision FPU" },
+    { DPA,      ARC_OPCODE_ARCv2EM,  "FPUDA",    "double assist FP" },
+    { DPX,      ARC_OPCODE_ARCFPX,   "DPFP",     "double-precision FPX" },
+    { LL64,     ARC_OPCODE_ARCv2HS,  "LL64",     "double load/store" },
+    { NPS400,   ARC_OPCODE_ARC700,   "NPS400",   "nps400" },
+    { QUARKSE1, ARC_OPCODE_ARCv2EM,  "QUARKSE1", "QuarkSE-EM" },
+    { QUARKSE2, ARC_OPCODE_ARCv2EM,  "QUARKSE2", "QuarkSE-EM" },
+    { SHFT1,    ARC_OPCODE_ARCALL,   "SA",       "shift assist" },
+    { SHFT2,    ARC_OPCODE_ARCALL,   "BS",       "barrel-shifter" },
+    { SWAP,     ARC_OPCODE_ARCALL,   "SWAP",     "swap" },
+    { SP,       ARC_OPCODE_ARCV2,    "FPUS",     "single-precision FPU" },
+    { SPX,      ARC_OPCODE_ARCFPX,   "SPFP",     "single-precision FPX" }
+  };
+
+#ifndef CONFLICT_LIST
+#define CONFLICT_LIST conflict_list
+#endif
+
+/* A table with conflicting features.  */
+unsigned CONFLICT_LIST [] = {
+  NPS400 | SPX,
+  NPS400 | DPX,
+  DPX | DPA,
+  SP | DPX,
+  SP | SPX,
+  DP | DPX,
+  DP | SPX,
+  QUARKSE1 | DP,
+  QUARKSE1 | SP
+};
+#endif
diff --git a/include/opcode/arc.h b/include/opcode/arc.h
index 97db92c..0524fda 100644
--- a/include/opcode/arc.h
+++ b/include/opcode/arc.h
@@ -85,28 +85,31 @@ typedef enum
 /* Instruction Subclass.  */
 typedef enum
 {
-  NONE,
-  CVT,
-  BTSCN,
-  CD1,
-  CD2,
-  COND,
-  DIV,
-  DP,
-  DPA,
-  DPX,
-  MPY1E,
-  MPY6E,
-  MPY7E,
-  MPY8E,
-  MPY9E,
-  NPS400,
-  QUARKSE,
-  SHFT1,
-  SHFT2,
-  SWAP,
-  SP,
-  SPX
+  NONE     = 0,
+  CVT      = (1U << 1),
+  BTSCN    = (1U << 2),
+  CD       = (1U << 3),
+  CD1      = CD,
+  CD2      = CD,
+  COND     = (1U << 4),
+  DIV      = (1U << 5),
+  DP       = (1U << 6),
+  DPA      = (1U << 7),
+  DPX      = (1U << 8),
+  LL64     = (1U << 9),
+  MPY1E    = (1U << 10),
+  MPY6E    = (1U << 11),
+  MPY7E    = (1U << 12),
+  MPY8E    = (1U << 13),
+  MPY9E    = (1U << 14),
+  NPS400   = (1U << 15),
+  QUARKSE1 = (1U << 16),
+  QUARKSE2 = (1U << 17),
+  SHFT1    = (1U << 18),
+  SHFT2    = (1U << 19),
+  SWAP     = (1U << 20),
+  SP       = (1U << 21),
+  SPX      = (1U << 22)
 } insn_subclass_t;
 
 /* Flags class.  */
@@ -197,46 +200,7 @@ extern int arc_opcode_len (const struct arc_opcode *opcode);
 			    | ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS)
 #define ARC_OPCODE_ARCFPX  (ARC_OPCODE_ARC700 | ARC_OPCODE_ARCv2EM)
 #define ARC_OPCODE_ARCV2   (ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS)
-
-/* CPU extensions.  */
-#define ARC_EA       0x0001
-#define ARC_CD       0x0001    /* Mutual exclusive with EA.  */
-#define ARC_LLOCK    0x0002
-#define ARC_ATOMIC   0x0002    /* Mutual exclusive with LLOCK.  */
-#define ARC_MPY      0x0004
-#define ARC_MULT     0x0004
-#define ARC_NPS400   0x0008
-
-/* Floating point support.  */
-#define ARC_DPFP     0x0010
-#define ARC_SPFP     0x0020
-#define ARC_FPU      0x0030
-#define ARC_FPUDA    0x0040
-
-/* NORM & SWAP.  */
-#define ARC_SWAP     0x0100
-#define ARC_NORM     0x0200
-#define ARC_BSCAN    0x0200
-
-/* A7 specific.  */
-#define ARC_UIX      0x1000
-#define ARC_TSTAMP   0x1000
-
-/* A6 specific.  */
-#define ARC_VBFDW    0x1000
-#define ARC_BARREL   0x1000
-#define ARC_DSPA     0x1000
-
-/* EM specific.  */
-#define ARC_SHIFT    0x1000
-
-/* V2 specific.  */
-#define ARC_INTR     0x1000
-#define ARC_DIV      0x1000
-
-/* V1 specific.  */
-#define ARC_XMAC     0x1000
-#define ARC_CRC      0x1000
+#define ARC_OPCODE_ARCMPY6E  (ARC_OPCODE_ARC700 | ARC_OPCODE_ARCV2)
 
 /* The operands table is an array of struct arc_operand.  */
 struct arc_operand
diff --git a/ld/testsuite/ld-arc/attr-merge-0.d b/ld/testsuite/ld-arc/attr-merge-0.d
new file mode 100644
index 0000000..2c3a909
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-0.d
@@ -0,0 +1,12 @@
+# source: attr-merge-0.s
+# source: attr-merge-0.s
+# as:
+# ld: -r
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD"
diff --git a/ld/testsuite/ld-arc/attr-merge-0.s b/ld/testsuite/ld-arc/attr-merge-0.s
new file mode 100644
index 0000000..de29811
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-0.s
@@ -0,0 +1,2 @@
+	.cpu em
+	.arc_attribute Tag_ARC_ISA_config, "CD"
diff --git a/ld/testsuite/ld-arc/attr-merge-0e.s b/ld/testsuite/ld-arc/attr-merge-0e.s
new file mode 100644
index 0000000..b84a24c
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-0e.s
@@ -0,0 +1 @@
+	.cpu ARC700
diff --git a/ld/testsuite/ld-arc/attr-merge-1.d b/ld/testsuite/ld-arc/attr-merge-1.d
new file mode 100644
index 0000000..e2e804d
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-1.d
@@ -0,0 +1,12 @@
+# source: attr-merge-0.s
+# source: attr-merge-1.s
+# as:
+# ld: -r
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD,DPFP,SPFP"
diff --git a/ld/testsuite/ld-arc/attr-merge-1.s b/ld/testsuite/ld-arc/attr-merge-1.s
new file mode 100644
index 0000000..527ae10
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-1.s
@@ -0,0 +1,2 @@
+	.cpu em
+	.arc_attribute Tag_ARC_ISA_config, "DPFP,SPFP"
diff --git a/ld/testsuite/ld-arc/attr-merge-1e.s b/ld/testsuite/ld-arc/attr-merge-1e.s
new file mode 100644
index 0000000..b9cd0e0
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-1e.s
@@ -0,0 +1,2 @@
+	.cpu em
+	.arc_attribute Tag_ARC_ISA_config, "FPUS"
diff --git a/ld/testsuite/ld-arc/attr-merge-2.d b/ld/testsuite/ld-arc/attr-merge-2.d
new file mode 100644
index 0000000..4c6898e
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-2.d
@@ -0,0 +1,12 @@
+# source: attr-merge-0.s
+# source: attr-merge-2.s
+# as:
+# ld: -r
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "em"
+  Tag_ARC_ABI_osver: v5
+  Tag_ARC_ISA_config: "CD"
diff --git a/ld/testsuite/ld-arc/attr-merge-2.s b/ld/testsuite/ld-arc/attr-merge-2.s
new file mode 100644
index 0000000..9250f02
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-2.s
@@ -0,0 +1,2 @@
+	.cpu em
+	.arc_attribute Tag_ARC_ABI_osver, 5
diff --git a/ld/testsuite/ld-arc/attr-merge-3.d b/ld/testsuite/ld-arc/attr-merge-3.d
new file mode 100644
index 0000000..00d6de0
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-3.d
@@ -0,0 +1,12 @@
+# source: attr-merge-3.s
+# source: attr-merge-4.s
+# as:
+# ld: -r
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCHS
+  Tag_ARC_CPU_name: "archs"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD,FPUS"
diff --git a/ld/testsuite/ld-arc/attr-merge-3.s b/ld/testsuite/ld-arc/attr-merge-3.s
new file mode 100644
index 0000000..9eb7eba
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-3.s
@@ -0,0 +1 @@
+	.cpu HS
diff --git a/ld/testsuite/ld-arc/attr-merge-3e.s b/ld/testsuite/ld-arc/attr-merge-3e.s
new file mode 100644
index 0000000..f0cd616
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-3e.s
@@ -0,0 +1 @@
+	.cpu quarkse_em
diff --git a/ld/testsuite/ld-arc/attr-merge-4.s b/ld/testsuite/ld-arc/attr-merge-4.s
new file mode 100644
index 0000000..b9cd0e0
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-4.s
@@ -0,0 +1,2 @@
+	.cpu em
+	.arc_attribute Tag_ARC_ISA_config, "FPUS"
diff --git a/ld/testsuite/ld-arc/attr-merge-5.d b/ld/testsuite/ld-arc/attr-merge-5.d
new file mode 100644
index 0000000..f08b762
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-5.d
@@ -0,0 +1,13 @@
+# source: attr-merge-5a.s
+# source: attr-merge-5b.s
+# as:
+# ld: -r
+# readelf: -A
+
+Attribute Section: ARC
+File Attributes
+  Tag_ARC_CPU_base: ARCEM
+  Tag_ARC_CPU_name: "arcem"
+  Tag_ARC_ABI_osver: v4
+  Tag_ARC_ISA_config: "CD,FPUDA,BS"
+  Tag_ARC_ISA_mpy_option: 6
diff --git a/ld/testsuite/ld-arc/attr-merge-5a.s b/ld/testsuite/ld-arc/attr-merge-5a.s
new file mode 100644
index 0000000..f428d06
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-5a.s
@@ -0,0 +1,3 @@
+	.cpu	arcem
+	.arc_attribute Tag_ARC_ISA_config, "FPUDA,CD"
+	.arc_attribute Tag_ARC_ISA_mpy_option, 6
diff --git a/ld/testsuite/ld-arc/attr-merge-5b.s b/ld/testsuite/ld-arc/attr-merge-5b.s
new file mode 100644
index 0000000..7806803
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-5b.s
@@ -0,0 +1,2 @@
+	.cpu	arcem
+	.arc_attribute Tag_ARC_ISA_config, "FPUDA,CD,BS"
diff --git a/ld/testsuite/ld-arc/attr-merge-conflict-isa.d b/ld/testsuite/ld-arc/attr-merge-conflict-isa.d
new file mode 100644
index 0000000..65fefe2
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-conflict-isa.d
@@ -0,0 +1,6 @@
+# source: attr-merge-1.s
+# source: attr-merge-1e.s
+# as:
+# ld: -r
+# error: .* conflicting ISA extension attributes
+
diff --git a/ld/testsuite/ld-arc/attr-merge-err-isa.d b/ld/testsuite/ld-arc/attr-merge-err-isa.d
new file mode 100644
index 0000000..4e27d86
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-err-isa.d
@@ -0,0 +1,5 @@
+# source: attr-merge-3.s
+# source: attr-merge-3e.s
+# as:
+# ld: -r
+# error: .* unable to merge ISA extension attributes
diff --git a/ld/testsuite/ld-arc/attr-merge-err-quarkse.d b/ld/testsuite/ld-arc/attr-merge-err-quarkse.d
new file mode 100644
index 0000000..34f0409
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-err-quarkse.d
@@ -0,0 +1,5 @@
+# source: attr-quarkse.s
+# source: attr-quarkse2.s
+# as:
+# ld: -r
+# error: .* conflicting ISA extension attributes
diff --git a/ld/testsuite/ld-arc/attr-merge-incompatible-cpu.d b/ld/testsuite/ld-arc/attr-merge-incompatible-cpu.d
new file mode 100644
index 0000000..5c51d0f
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-merge-incompatible-cpu.d
@@ -0,0 +1,5 @@
+# source: attr-merge-0.s
+# source: attr-merge-0e.s
+# as:
+# ld: -r
+# error: .* unable to merge CPU base attributes
diff --git a/ld/testsuite/ld-arc/attr-quarkse.s b/ld/testsuite/ld-arc/attr-quarkse.s
new file mode 100644
index 0000000..1d64a65
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-quarkse.s
@@ -0,0 +1,2 @@
+	.cpu quarkse_em
+	dsp_fp_cmp	r3,r0,r2
diff --git a/ld/testsuite/ld-arc/attr-quarkse2.s b/ld/testsuite/ld-arc/attr-quarkse2.s
new file mode 100644
index 0000000..5f9f918
--- /dev/null
+++ b/ld/testsuite/ld-arc/attr-quarkse2.s
@@ -0,0 +1,2 @@
+	.cpu	arcem
+	fscmp r0, 0x3f800000
diff --git a/ld/testsuite/ld-arc/got-01.d b/ld/testsuite/ld-arc/got-01.d
index c34d6a7..57b2903 100644
--- a/ld/testsuite/ld-arc/got-01.d
+++ b/ld/testsuite/ld-arc/got-01.d
@@ -3,5 +3,5 @@
 #ld:
 #readelf: -S
 
-There are . section headers, starting at offset 0x[0-9a-f]+:
+There are \d+ section headers, starting at offset 0x[0-9a-f]+:
 #...
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index 6fb030e..0cf4bff 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -748,7 +748,8 @@ parse_option (const char *option)
     {
       add_to_decodelist (FLOAT, DPX);
       add_to_decodelist (FLOAT, SPX);
-      add_to_decodelist (FLOAT, QUARKSE);
+      add_to_decodelist (FLOAT, QUARKSE1);
+      add_to_decodelist (FLOAT, QUARKSE2);
     }
 
   else if (CONST_STRNEQ (option, "fpuda"))
diff --git a/opcodes/arc-ext-tbl.h b/opcodes/arc-ext-tbl.h
index 422b93c..26a6683 100644
--- a/opcodes/arc-ext-tbl.h
+++ b/opcodes/arc-ext-tbl.h
@@ -116,12 +116,12 @@
       ARG_32BIT_ZALIMMLIMM, FLAGS_CCF },
 
 /* Extension instruction declarations.  */
-EXTINSN2OP ("dsp_fp_flt2i",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE, 7, 43)
-EXTINSN2OP ("dsp_fp_i2flt",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE, 7, 44)
-EXTINSN2OP ("dsp_fp_sqrt",   ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE, 7, 45)
+EXTINSN2OP ("dsp_fp_flt2i",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 43)
+EXTINSN2OP ("dsp_fp_i2flt",  ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 44)
+EXTINSN2OP ("dsp_fp_sqrt",   ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE2, 7, 45)
 
-EXTINSN3OP ("dsp_fp_div", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE, 7, 42)
-EXTINSN3OP ("dsp_fp_cmp", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE, 7, 43)
+EXTINSN3OP ("dsp_fp_div", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE2, 7, 42)
+EXTINSN3OP ("dsp_fp_cmp", ARC_OPCODE_ARCv2EM, FLOAT, QUARKSE1, 7, 43)
 
 /* Bitstream extensions.  */
 EXTINSN2OP ("bspeek", ARC_OPCODE_ARCv2EM, BITSTREAM, NONE, 0x05, 0x2E)
diff --git a/opcodes/arc-tbl.h b/opcodes/arc-tbl.h
index 826b2ce..79e6b89 100644
--- a/opcodes/arc-tbl.h
+++ b/opcodes/arc-tbl.h
@@ -8086,46 +8086,46 @@
 { "ldb_s", 0x0000CA00, 0x0000FE00, ARC_OPCODE_ARC600 | ARC_OPCODE_ARC700 | ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS, LOAD, NONE, { R0_S, BRAKET, GP_S, SIMM9_7_S, BRAKETdup }, { C_ZZ_B }},
 
 /* ldd<.di><.aa> a,b 00010bbb000000000BBBDaa110AAAAAA.  */
-{ "ldd", 0x10000180, 0xF8FF81C0, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, RB, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x10000180, 0xF8FF81C0, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, RB, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldd<.di><.aa> a,b,c 00100bbbaa110110DBBBCCCCCCAAAAAA.  */
-{ "ldd", 0x20360000, 0xF83F0000, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, RB, RC, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
+{ "ldd", 0x20360000, 0xF83F0000, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, RB, RC, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
 
 /* ldd<.di><.aa> 0,b 00010bbb000000000BBBDaa110111110.  */
-{ "ldd", 0x100001BE, 0xF8FF81FF, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, RB, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x100001BE, 0xF8FF81FF, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, RB, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldd<.di><.aa> 0,b,c 00100bbbaa110110DBBBCCCCCC111110.  */
-{ "ldd", 0x2036003E, 0xF83F003F, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, RB, RC, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
+{ "ldd", 0x2036003E, 0xF83F003F, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, RB, RC, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
 
 /* ldd<.di><.aa> a,b,s9 00010bbbssssssssSBBBDaa110AAAAAA.  */
-{ "ldd", 0x10000180, 0xF80001C0, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x10000180, 0xF80001C0, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldd<.di><.aa> 0,b,s9 00010bbbssssssssSBBBDaa110111110.  */
-{ "ldd", 0x100001BE, 0xF80001FF, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x100001BE, 0xF80001FF, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldd<.di> a,limm 00010110000000000111DRR110AAAAAA.  */
-{ "ldd", 0x16007180, 0xFFFFF1C0, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, LIMM, BRAKETdup }, { C_DI20, C_ZZ_D }},
+{ "ldd", 0x16007180, 0xFFFFF1C0, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, LIMM, BRAKETdup }, { C_DI20, C_ZZ_D }},
 
 /* ldd<.di><.aa> a,b,limm 00100bbbaa110110DBBB111110AAAAAA.  */
-{ "ldd", 0x20360F80, 0xF83F0FC0, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, RB, LIMM, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
+{ "ldd", 0x20360F80, 0xF83F0FC0, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, RB, LIMM, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
 
 /* ldd<.di> a,limm,c 00100110RR110110D111CCCCCCAAAAAA.  */
-{ "ldd", 0x26367000, 0xFF3F7000, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, LIMM, RC, BRAKETdup }, { C_DI16, C_ZZ_D }},
+{ "ldd", 0x26367000, 0xFF3F7000, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, LIMM, RC, BRAKETdup }, { C_DI16, C_ZZ_D }},
 
 /* ldd<.di> 0,limm 00010110000000000111DRR110111110.  */
-{ "ldd", 0x160071BE, 0xFFFFF1FF, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, LIMM, BRAKETdup }, { C_DI20, C_ZZ_D }},
+{ "ldd", 0x160071BE, 0xFFFFF1FF, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, LIMM, BRAKETdup }, { C_DI20, C_ZZ_D }},
 
 /* ldd<.di><.aa> 0,b,limm 00100bbbaa110110DBBB111110111110.  */
-{ "ldd", 0x20360FBE, 0xF83F0FFF, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, RB, LIMM, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
+{ "ldd", 0x20360FBE, 0xF83F0FFF, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, RB, LIMM, BRAKETdup }, { C_DI16, C_AA8, C_ZZ_D }},
 
 /* ldd<.di> 0,limm,c 00100110RR110110D111CCCCCC111110.  */
-{ "ldd", 0x2636703E, 0xFF3F703F, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, LIMM, RC, BRAKETdup }, { C_DI16, C_ZZ_D }},
+{ "ldd", 0x2636703E, 0xFF3F703F, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, LIMM, RC, BRAKETdup }, { C_DI16, C_ZZ_D }},
 
 /* ldd<.di><.aa> a,limm,s9 00010110ssssssssS111Daa110AAAAAA.  */
-{ "ldd", 0x16007180, 0xFF0071C0, ARC_OPCODE_ARCv2HS, LOAD, NONE, { RAD, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x16007180, 0xFF0071C0, ARC_OPCODE_ARCv2HS, LOAD, LL64, { RAD, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldd<.di><.aa> 0,limm,s9 00010110ssssssssS111Daa110111110.  */
-{ "ldd", 0x160071BE, 0xFF0071FF, ARC_OPCODE_ARCv2HS, LOAD, NONE, { ZA, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
+{ "ldd", 0x160071BE, 0xFF0071FF, ARC_OPCODE_ARCv2HS, LOAD, LL64, { ZA, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI20, C_AA21, C_ZZ_D }},
 
 /* ldh_s a,b,c 01100bbbccc10aaa.  */
 { "ldh_s", 0x00006010, 0x0000F818, ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS, LOAD, NONE, { RA_S, BRAKET, RB_S, RC_S, BRAKETdup }, { C_ZZ_H }},
@@ -14649,31 +14649,31 @@
 { "stb_s", 0x0000C060, 0x0000F8E0, ARC_OPCODE_ARC600 | ARC_OPCODE_ARC700 | ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS, STORE, NONE, { RB_S, BRAKET, SP_S, UIMM7_A32_11_S, BRAKETdup }, { C_ZZ_B }},
 
 /* std<.di><.aa> c,b 00011bbb000000000BBBCCCCCCDaa110.  */
-{ "std", 0x18000006, 0xF8FF8007, ARC_OPCODE_ARCv2HS, STORE, NONE, { RCD, BRAKET, RB, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x18000006, 0xF8FF8007, ARC_OPCODE_ARCv2HS, STORE, LL64, { RCD, BRAKET, RB, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di><.aa> w6,b 00011bbb000000000BBBwwwwwwDaa111.  */
-{ "std", 0x18000007, 0xF8FF8007, ARC_OPCODE_ARCv2HS, STORE, NONE, { W6, BRAKET, RB, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x18000007, 0xF8FF8007, ARC_OPCODE_ARCv2HS, STORE, LL64, { W6, BRAKET, RB, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di><.aa> c,b,s9 00011bbbssssssssSBBBCCCCCCDaa110.  */
-{ "std", 0x18000006, 0xF8000007, ARC_OPCODE_ARCv2HS, STORE, NONE, { RCD, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x18000006, 0xF8000007, ARC_OPCODE_ARCv2HS, STORE, LL64, { RCD, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di><.aa> w6,b,s9 00011bbbssssssssSBBBwwwwwwDaa111.  */
-{ "std", 0x18000007, 0xF8000007, ARC_OPCODE_ARCv2HS, STORE, NONE, { W6, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x18000007, 0xF8000007, ARC_OPCODE_ARCv2HS, STORE, LL64, { W6, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di> c,limm 00011110000000000111CCCCCCDRR110.  */
-{ "std", 0x1E007006, 0xFFFFF007, ARC_OPCODE_ARCv2HS, STORE, NONE, { RCD, BRAKET, LIMM, BRAKETdup }, { C_DI26, C_ZZ_D }},
+{ "std", 0x1E007006, 0xFFFFF007, ARC_OPCODE_ARCv2HS, STORE, LL64, { RCD, BRAKET, LIMM, BRAKETdup }, { C_DI26, C_ZZ_D }},
 
 /* std<.di> w6,limm 00011110000000000111wwwwwwDRR111.  */
-{ "std", 0x1E007007, 0xFFFFF007, ARC_OPCODE_ARCv2HS, STORE, NONE, { W6, BRAKET, LIMM, BRAKETdup }, { C_DI26, C_ZZ_D }},
+{ "std", 0x1E007007, 0xFFFFF007, ARC_OPCODE_ARCv2HS, STORE, LL64, { W6, BRAKET, LIMM, BRAKETdup }, { C_DI26, C_ZZ_D }},
 
 /* std<.di><.aa> limm,b,s9 00011bbbssssssssSBBB111110Daa110.  */
-{ "std", 0x18000F86, 0xF8000FC7, ARC_OPCODE_ARCv2HS, STORE, NONE, { LIMM, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x18000F86, 0xF8000FC7, ARC_OPCODE_ARCv2HS, STORE, LL64, { LIMM, BRAKET, RB, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di><.aa> w6,limm,s9 00011110ssssssssS111wwwwwwDaa111.  */
-{ "std", 0x1E007007, 0xFF007007, ARC_OPCODE_ARCv2HS, STORE, NONE, { W6, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x1E007007, 0xFF007007, ARC_OPCODE_ARCv2HS, STORE, LL64, { W6, BRAKET, LIMM, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* std<.di><.aa> limm,limm,s9 00011110ssssssssS111111110Daa110.  */
-{ "std", 0x1E007F86, 0xFF007FC7, ARC_OPCODE_ARCv2HS, STORE, NONE, { LIMM, BRAKET, LIMMdup, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
+{ "std", 0x1E007F86, 0xFF007FC7, ARC_OPCODE_ARCv2HS, STORE, LL64, { LIMM, BRAKET, LIMMdup, SIMM9_8, BRAKETdup }, { C_DI26, C_AA27, C_ZZ_D }},
 
 /* sth_s c,b,u6 10110bbbcccuuuuu.  */
 { "sth_s", 0x0000B000, 0x0000F800, ARC_OPCODE_ARCv2EM | ARC_OPCODE_ARCv2HS, STORE, NONE, { RC_S, BRAKET, RB_S, UIMM6_A16_11_S, BRAKETdup }, { C_ZZ_H }},
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]