]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-arc.c
-Wimplicit-fallthrough warning fixes
[thirdparty/binutils-gdb.git] / gas / config / tc-arc.c
index 4f4e970400ef0e021033f6ef0e1c5ebd487fff1b..f28abf492a6116aeb042c9fb87dbaf7a41226b1b 100644 (file)
 
 #define MAJOR_OPCODE(x)  (((x) & 0xF8000000) >> 27)
 #define SUB_OPCODE(x)   (((x) & 0x003F0000) >> 16)
-#define LP_INSN(x)      ((MAJOR_OPCODE (x) == 0x4) && \
-                         (SUB_OPCODE (x) == 0x28))
+#define LP_INSN(x)      ((MAJOR_OPCODE (x) == 0x4) \
+                         && (SUB_OPCODE (x) == 0x28))
 
 /* Equal to MAX_PRECISION in atof-ieee.c.  */
 #define MAX_LITTLENUMS 6
 
+#ifndef TARGET_WITH_CPU
+#define TARGET_WITH_CPU "arc700"
+#endif /* TARGET_WITH_CPU */
+
 /* Enum used to enumerate the relaxable ins operands.  */
 enum rlx_operand_type
 {
@@ -98,8 +102,10 @@ enum arc_rlx_types
 #define is_spfp_p(op)           (((sc) == SPX))
 #define is_dpfp_p(op)           (((sc) == DPX))
 #define is_fpuda_p(op)          (((sc) == DPA))
-#define is_br_jmp_insn_p(op)    (((op)->class == BRANCH || (op)->class == JUMP))
-#define is_kernel_insn_p(op)    (((op)->class == KERNEL))
+#define is_br_jmp_insn_p(op)    (((op)->insn_class == BRANCH \
+                                 || (op)->insn_class == JUMP))
+#define is_kernel_insn_p(op)    (((op)->insn_class == KERNEL))
+#define is_nps400_p(op)         (((sc) == NPS400))
 
 /* Generic assembler global variables which must be defined by all
    targets.  */
@@ -179,6 +185,11 @@ enum options
   OPTION_MCPU,
   OPTION_CD,
   OPTION_RELAX,
+  OPTION_NPS400,
+
+  OPTION_SPFP,
+  OPTION_DPFP,
+  OPTION_FPUDA,
 
   /* The following options are deprecated and provided here only for
      compatibility reasons.  */
@@ -192,8 +203,6 @@ enum options
   OPTION_EA,
   OPTION_MUL64,
   OPTION_SIMD,
-  OPTION_SPFP,
-  OPTION_DPFP,
   OPTION_XMAC_D16,
   OPTION_XMAC_24,
   OPTION_DSP_PACKA,
@@ -203,8 +212,7 @@ enum options
   OPTION_XYMEMORY,
   OPTION_LOCK,
   OPTION_SWAPE,
-  OPTION_RTSC,
-  OPTION_FPUDA
+  OPTION_RTSC
 };
 
 struct option md_longopts[] =
@@ -221,6 +229,20 @@ struct option md_longopts[] =
   { "mHS",             no_argument,       NULL, OPTION_ARCHS },
   { "mcode-density",   no_argument,       NULL, OPTION_CD },
   { "mrelax",           no_argument,       NULL, OPTION_RELAX },
+  { "mnps400",          no_argument,       NULL, OPTION_NPS400 },
+
+  /* Floating point options */
+  { "mspfp", no_argument, NULL, OPTION_SPFP},
+  { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
+  { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
+  { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
+  { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
+  { "mdpfp", no_argument, NULL, OPTION_DPFP},
+  { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
+  { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
+  { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
+  { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
+  { "mfpuda", no_argument, NULL, OPTION_FPUDA},
 
   /* The following options are deprecated and provided here only for
      compatibility reasons.  */
@@ -239,16 +261,6 @@ struct option md_longopts[] =
   { "mEA", no_argument, NULL, OPTION_EA },
   { "mmul64", no_argument, NULL, OPTION_MUL64 },
   { "msimd", no_argument, NULL, OPTION_SIMD},
-  { "mspfp", no_argument, NULL, OPTION_SPFP},
-  { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
-  { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
-  { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
-  { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
-  { "mdpfp", no_argument, NULL, OPTION_DPFP},
-  { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
-  { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
-  { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
-  { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
   { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
   { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
   { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
@@ -262,7 +274,6 @@ struct option md_longopts[] =
   { "mlock", no_argument, NULL, OPTION_LOCK},
   { "mswape", no_argument, NULL, OPTION_SWAPE},
   { "mrtsc", no_argument, NULL, OPTION_RTSC},
-  { "mfpuda", no_argument, NULL, OPTION_FPUDA},
 
   { NULL,              no_argument, NULL, 0 }
 };
@@ -323,7 +334,7 @@ typedef struct
 {
   const char *name;
   int  len;
-  int  class;
+  int  attr_class;
 } attributes_t;
 
 static const attributes_t suffixclass[] =
@@ -337,7 +348,9 @@ static const attributes_t suffixclass[] =
 static const attributes_t syntaxclass[] =
 {
   { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
-  { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP }
+  { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP },
+  { "SYNTAX_1OP", 10, ARC_SYNTAX_1OP },
+  { "SYNTAX_NOP", 10, ARC_SYNTAX_NOP }
 };
 
 /* Extension instruction syntax classes modifiers.  */
@@ -408,6 +421,9 @@ static struct hash_control *arc_reg_hash;
 /* The hash table of aux register symbols.  */
 static struct hash_control *arc_aux_hash;
 
+/* The hash table of address types.  */
+static struct hash_control *arc_addrtype_hash;
+
 /* A table of CPU names and opcode sets.  */
 static const struct cpu_type
 {
@@ -423,10 +439,10 @@ static const struct cpu_type
     E_ARC_MACH_ARC600,  0x00},
   { "arc700", ARC_OPCODE_ARC700,  bfd_mach_arc_arc700,
     E_ARC_MACH_ARC700,  0x00},
-  { "nps400", ARC_OPCODE_ARC700 | ARC_OPCODE_NPS400, bfd_mach_arc_nps400,
-    E_ARC_MACH_NPS400,  0x00},
+  { "nps400", ARC_OPCODE_ARC700 , bfd_mach_arc_arc700,
+    E_ARC_MACH_ARC700,  ARC_NPS400},
   { "arcem",  ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
-    EF_ARC_CPU_ARCV2EM, ARC_CD},
+    EF_ARC_CPU_ARCV2EM, 0x00},
   { "archs",  ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
     EF_ARC_CPU_ARCV2HS, ARC_CD},
   { 0, 0, 0, 0, 0 }
@@ -449,6 +465,12 @@ static const struct cpu_type
 /* Used to define a bracket as operand in tokens.  */
 #define O_bracket O_md32
 
+/* Used to define a colon as an operand in tokens.  */
+#define O_colon O_md31
+
+/* Used to define address types in nps400.  */
+#define O_addrtype O_md30
+
 /* Dummy relocation, to be sorted out.  */
 #define DUMMY_RELOC_ARC_ENTRY     (BFD_RELOC_UNUSED + 1)
 
@@ -490,7 +512,7 @@ static const struct arc_reloc_op_tag
   DEF (tpoff9,  BFD_RELOC_ARC_TLS_LE_S9,       0),
   DEF (tpoff,   BFD_RELOC_ARC_TLS_LE_32,       1),
   DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9,   0),
-  DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,      0),
+  DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,      1),
 };
 
 static const int arc_num_reloc_op
@@ -541,56 +563,56 @@ const relax_typeS md_relax_table[] =
 
   /* BL_S s13 ->
      BL s25.  */
-  RELAX_TABLE_ENTRY(13, 1, 2, ARC_RLX_BL),
-  RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (13, 1, 2, ARC_RLX_BL),
+  RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
 
   /* B_S s10 ->
      B s25.  */
-  RELAX_TABLE_ENTRY(10, 1, 2, ARC_RLX_B),
-  RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (10, 1, 2, ARC_RLX_B),
+  RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
 
   /* ADD_S c,b, u3 ->
      ADD<.f> a,b,u6 ->
      ADD<.f> a,b,limm.  */
-  RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_ADD_U6),
-  RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_LIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_ADD_U6),
+  RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_LIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 
   /* LD_S a, [b, u7] ->
      LD<zz><.x><.aa><.di> a, [b, s9] ->
      LD<zz><.x><.aa><.di> a, [b, limm] */
-  RELAX_TABLE_ENTRY(7, 0, 2, ARC_RLX_LD_S9),
-  RELAX_TABLE_ENTRY(9, 1, 4, ARC_RLX_LD_LIMM),
-  RELAX_TABLE_ENTRY_MAX(1, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (7, 0, 2, ARC_RLX_LD_S9),
+  RELAX_TABLE_ENTRY (9, 1, 4, ARC_RLX_LD_LIMM),
+  RELAX_TABLE_ENTRY_MAX (1, 8, ARC_RLX_NONE),
 
   /* MOV_S b, u8 ->
      MOV<.f> b, s12 ->
      MOV<.f> b, limm.  */
-  RELAX_TABLE_ENTRY(8, 0, 2, ARC_RLX_MOV_S12),
-  RELAX_TABLE_ENTRY(8, 0, 4, ARC_RLX_MOV_LIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (8, 0, 2, ARC_RLX_MOV_S12),
+  RELAX_TABLE_ENTRY (8, 0, 4, ARC_RLX_MOV_LIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 
   /* SUB_S c, b, u3 ->
      SUB<.f> a, b, u6 ->
      SUB<.f> a, b, limm.  */
-  RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_SUB_U6),
-  RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_SUB_LIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_SUB_U6),
+  RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_SUB_LIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 
   /* MPY<.f> a, b, u6 ->
      MPY<.f> a, b, limm.  */
-  RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MPY_LIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MPY_LIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 
   /* MOV<.f><.cc> b, u6 ->
      MOV<.f><.cc> b, limm.  */
-  RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MOV_RLIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MOV_RLIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 
   /* ADD<.f><.cc> b, b, u6 ->
      ADD<.f><.cc> b, b, limm.  */
-  RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_RRLIMM),
-  RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
+  RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_RRLIMM),
+  RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
 };
 
 /* Order of this table's entries matters!  */
@@ -672,8 +694,8 @@ arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
       const char *old_name = iter->opcode->name;
 
       iter->opcode++;
-      if (iter->opcode->name
-         && (strcmp (old_name, iter->opcode->name) != 0))
+      if (iter->opcode->name == NULL
+         || strcmp (old_name, iter->opcode->name) != 0)
        {
          iter->index++;
          if (iter->index == entry->count)
@@ -698,7 +720,7 @@ arc_insert_opcode (const struct arc_opcode *opcode)
   entry = hash_find (arc_opcode_hash, name);
   if (entry == NULL)
     {
-      entry = xmalloc (sizeof (*entry));
+      entry = XNEW (struct arc_opcode_hash_entry);
       entry->count = 0;
       entry->opcode = NULL;
 
@@ -708,9 +730,8 @@ arc_insert_opcode (const struct arc_opcode *opcode)
                  name, retval);
     }
 
-  entry->opcode = xrealloc (entry->opcode,
-                           sizeof (const struct arc_opcode *)
-                           * (entry->count + 1));
+  entry->opcode = XRESIZEVEC (const struct arc_opcode *, entry->opcode,
+                             entry->count + 1);
 
   if (entry->opcode == NULL)
     as_fatal (_("Virtual memory exhausted"));
@@ -878,26 +899,26 @@ arc_option (int ignore ATTRIBUTE_UNUSED)
 
   if (!mach_type_specified_p)
     {
-      if ((!strcasecmp ("ARC600", cpu))
-         || (!strcasecmp ("ARC601", cpu))
-         || (!strcasecmp ("A6", cpu)))
+      if ((!strcmp ("ARC600", cpu))
+         || (!strcmp ("ARC601", cpu))
+         || (!strcmp ("A6", cpu)))
        {
          md_parse_option (OPTION_MCPU, "arc600");
        }
-      else if ((!strcasecmp ("ARC700", cpu))
-              || (!strcasecmp ("A7", cpu)))
+      else if ((!strcmp ("ARC700", cpu))
+              || (!strcmp ("A7", cpu)))
        {
          md_parse_option (OPTION_MCPU, "arc700");
        }
-      else if (!strcasecmp ("EM", cpu))
+      else if (!strcmp ("EM", cpu))
        {
          md_parse_option (OPTION_MCPU, "arcem");
        }
-      else if (!strcasecmp ("HS", cpu))
+      else if (!strcmp ("HS", cpu))
        {
          md_parse_option (OPTION_MCPU, "archs");
        }
-      else if (!strcasecmp ("NPS400", cpu))
+      else if (!strcmp ("NPS400", cpu))
        {
          md_parse_option (OPTION_MCPU, "nps400");
        }
@@ -968,6 +989,8 @@ debug_exp (expressionS *t)
     case O_logical_or:         name = "O_logical_or";          break;
     case O_index:              name = "O_index";               break;
     case O_bracket:            name = "O_bracket";             break;
+    case O_colon:              name = "O_colon";               break;
+    case O_addrtype:           name = "O_addrtype";            break;
     }
 
   switch (t->X_md)
@@ -1038,7 +1061,7 @@ tokenize_arguments (char *str,
        case ']':
          ++input_line_pointer;
          --brk_lvl;
-         if (!saw_arg)
+         if (!saw_arg || num_args == ntok)
            goto err;
          tok->X_op = O_bracket;
          ++tok;
@@ -1048,7 +1071,7 @@ tokenize_arguments (char *str,
        case '{':
        case '[':
          input_line_pointer++;
-         if (brk_lvl)
+         if (brk_lvl || num_args == ntok)
            goto err;
          ++brk_lvl;
          tok->X_op = O_bracket;
@@ -1056,10 +1079,20 @@ tokenize_arguments (char *str,
          ++num_args;
          break;
 
+        case ':':
+          input_line_pointer++;
+          if (!saw_arg || num_args == ntok)
+            goto err;
+          tok->X_op = O_colon;
+          saw_arg = FALSE;
+          ++tok;
+          ++num_args;
+          break;
+
        case '@':
          /* We have labels, function names and relocations, all
             starting with @ symbol.  Sort them out.  */
-         if (saw_arg && !saw_comma)
+         if ((saw_arg && !saw_comma) || num_args == ntok)
            goto err;
 
          /* Parse @label.  */
@@ -1124,7 +1157,7 @@ tokenize_arguments (char *str,
              restore_line_pointer (c);
              tmpE.X_add_number = 0;
            }
-         else if ((*input_line_pointer != '+')
+         if ((*input_line_pointer != '+')
                   && (*input_line_pointer != '-'))
            {
              tmpE.X_add_number = 0;
@@ -1164,7 +1197,7 @@ tokenize_arguments (char *str,
          /* Fall through.  */
        default:
 
-         if (saw_arg && !saw_comma)
+         if ((saw_arg && !saw_comma) || num_args == ntok)
            goto err;
 
          tok->X_op = O_absent;
@@ -1180,7 +1213,9 @@ tokenize_arguments (char *str,
        normalsymbol:
          debug_exp (tok);
 
-         if (tok->X_op == O_illegal || tok->X_op == O_absent)
+         if (tok->X_op == O_illegal
+              || tok->X_op == O_absent
+              || num_args == ntok)
            goto err;
 
          saw_comma = FALSE;
@@ -1526,25 +1561,108 @@ allocate_tok (expressionS *tok, int ntok, int cidx)
 static bfd_boolean
 check_cpu_feature (insn_subclass_t sc)
 {
-  if (!(arc_features & ARC_CD)
-      && is_code_density_p (sc))
+  if (is_code_density_p (sc) && !(arc_features & ARC_CD))
+    return FALSE;
+
+  if (is_spfp_p (sc) && !(arc_features & ARC_SPFP))
     return FALSE;
 
-  if (!(arc_features & ARC_SPFP)
-      && is_spfp_p (sc))
+  if (is_dpfp_p (sc) && !(arc_features & ARC_DPFP))
     return FALSE;
 
-  if (!(arc_features & ARC_DPFP)
-      && is_dpfp_p (sc))
+  if (is_fpuda_p (sc) && !(arc_features & ARC_FPUDA))
     return FALSE;
 
-  if (!(arc_features & ARC_FPUDA)
-      && is_fpuda_p (sc))
+  if (is_nps400_p (sc) && !(arc_features & ARC_NPS400))
     return FALSE;
 
   return TRUE;
 }
 
+/* Parse the flags described by FIRST_PFLAG and NFLGS against the flag
+   operands in OPCODE.  Stores the matching OPCODES into the FIRST_PFLAG
+   array and returns TRUE if the flag operands all match, otherwise,
+   returns FALSE, in which case the FIRST_PFLAG array may have been
+   modified.  */
+
+static bfd_boolean
+parse_opcode_flags (const struct arc_opcode *opcode,
+                    int nflgs,
+                    struct arc_flags *first_pflag)
+{
+  int lnflg, i;
+  const unsigned char *flgidx;
+
+  lnflg = nflgs;
+  for (i = 0; i < nflgs; i++)
+    first_pflag[i].flgp = NULL;
+
+  /* Check the flags.  Iterate over the valid flag classes.  */
+  for (flgidx = opcode->flags; *flgidx; ++flgidx)
+    {
+      /* Get a valid flag class.  */
+      const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
+      const unsigned *flgopridx;
+      int cl_matches = 0;
+      struct arc_flags *pflag = NULL;
+
+      /* Check for extension conditional codes.  */
+      if (ext_condcode.arc_ext_condcode
+          && cl_flags->flag_class & F_CLASS_EXTEND)
+        {
+          struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
+          while (pf->name)
+            {
+              pflag = first_pflag;
+              for (i = 0; i < nflgs; i++, pflag++)
+                {
+                  if (!strcmp (pf->name, pflag->name))
+                    {
+                      if (pflag->flgp != NULL)
+                        return FALSE;
+                      /* Found it.  */
+                      cl_matches++;
+                      pflag->flgp = pf;
+                      lnflg--;
+                      break;
+                    }
+                }
+              pf++;
+            }
+        }
+
+      for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
+        {
+          const struct arc_flag_operand *flg_operand;
+
+          pflag = first_pflag;
+          flg_operand = &arc_flag_operands[*flgopridx];
+          for (i = 0; i < nflgs; i++, pflag++)
+            {
+              /* Match against the parsed flags.  */
+              if (!strcmp (flg_operand->name, pflag->name))
+                {
+                  if (pflag->flgp != NULL)
+                    return FALSE;
+                  cl_matches++;
+                  pflag->flgp = flg_operand;
+                  lnflg--;
+                  break; /* goto next flag class and parsed flag.  */
+                }
+            }
+        }
+
+      if ((cl_flags->flag_class & F_CLASS_REQUIRED) && cl_matches == 0)
+        return FALSE;
+      if ((cl_flags->flag_class & F_CLASS_OPTIONAL) && cl_matches > 1)
+        return FALSE;
+    }
+
+  /* Did I check all the parsed flags?  */
+  return lnflg ? FALSE : TRUE;
+}
+
+
 /* Search forward through all variants of an opcode looking for a
    syntax match.  */
 
@@ -1574,8 +1692,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
        opcode = arc_opcode_hash_entry_iterator_next (entry, &iter))
     {
       const unsigned char *opidx;
-      const unsigned char *flgidx;
-      int tokidx = 0, lnflg, i;
+      int tokidx = 0;
       const expressionS *t = &emptyE;
 
       pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
@@ -1598,8 +1715,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
          const struct arc_operand *operand = &arc_operands[*opidx];
 
          /* Only take input from real operands.  */
-         if ((operand->flags & ARC_OPERAND_FAKE)
-             && !(operand->flags & ARC_OPERAND_BRAKET))
+         if (ARC_OPERAND_IS_FAKE (operand))
            continue;
 
          /* When we expect input, make sure we have it.  */
@@ -1609,6 +1725,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
          /* Match operand type with expression type.  */
          switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
            {
+            case ARC_OPERAND_ADDRTYPE:
+              /* Check to be an address type.  */
+              if (tok[tokidx].X_op != O_addrtype)
+                goto match_failed;
+              break;
+
            case ARC_OPERAND_IR:
              /* Check to be a register.  */
              if ((tok[tokidx].X_op != O_register
@@ -1660,6 +1782,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                goto match_failed;
              break;
 
+            case ARC_OPERAND_COLON:
+              /* Check if colon is also in opcode table as operand.  */
+              if (tok[tokidx].X_op != O_colon)
+                goto match_failed;
+              break;
+
            case ARC_OPERAND_LIMM:
            case ARC_OPERAND_SIGNED:
            case ARC_OPERAND_UNSIGNED:
@@ -1689,7 +1817,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                    const char *p;
                    const struct arc_aux_reg *auxr;
 
-                   if (opcode->class != AUXREG)
+                   if (opcode->insn_class != AUXREG)
                      goto de_fault;
                    p = S_GET_NAME (tok[tokidx].X_add_symbol);
 
@@ -1708,7 +1836,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                    if (tok[tokidx].X_op != O_constant)
                      goto de_fault;
                  }
-                 /* Fall-through */
+                 /* Fall through.  */
                case O_constant:
                  /* Check the range.  */
                  if (operand->bits != 32
@@ -1751,7 +1879,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                          if (errmsg)
                            goto match_failed;
                        }
-                     else
+                     else if (!(operand->flags & ARC_OPERAND_IGNORE))
                        goto match_failed;
                    }
                  break;
@@ -1780,6 +1908,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                        goto match_failed;
                      break;
                    }
+                 /* Fall through.  */
                default:
                de_fault:
                  if (operand->default_reloc == 0)
@@ -1798,9 +1927,11 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
                    case O_tlsie:
                      if (!(operand->flags & ARC_OPERAND_LIMM))
                        goto match_failed;
+                     /* Fall through.  */
                    case O_absent:
                      if (!generic_reloc_p (operand->default_reloc))
                        goto match_failed;
+                     break;
                    default:
                      break;
                    }
@@ -1828,72 +1959,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry,
       pr_debug ("opr ");
 
       /* Setup ready for flag parsing.  */
-      lnflg = nflgs;
-      for (i = 0; i < nflgs; i++)
-       first_pflag[i].flgp = NULL;
-
-      /* Check the flags.  Iterate over the valid flag classes.  */
-      for (flgidx = opcode->flags; *flgidx; ++flgidx)
-       {
-         /* Get a valid flag class.  */
-         const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
-         const unsigned *flgopridx;
-         int cl_matches = 0;
-         struct arc_flags *pflag = NULL;
-
-         /* Check for extension conditional codes.  */
-         if (ext_condcode.arc_ext_condcode
-             && cl_flags->class & F_CLASS_EXTEND)
-           {
-             struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
-             while (pf->name)
-               {
-                 pflag = first_pflag;
-                 for (i = 0; i < nflgs; i++, pflag++)
-                   {
-                     if (!strcmp (pf->name, pflag->name))
-                       {
-                         if (pflag->flgp != NULL)
-                           goto match_failed;
-                         /* Found it.  */
-                         cl_matches++;
-                         pflag->flgp = pf;
-                         lnflg--;
-                         break;
-                       }
-                   }
-                 pf++;
-               }
-           }
-
-         for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
-           {
-             const struct arc_flag_operand *flg_operand;
-
-             pflag = first_pflag;
-             flg_operand = &arc_flag_operands[*flgopridx];
-             for (i = 0; i < nflgs; i++, pflag++)
-               {
-                 /* Match against the parsed flags.  */
-                 if (!strcmp (flg_operand->name, pflag->name))
-                   {
-                     if (pflag->flgp != NULL)
-                       goto match_failed;
-                     cl_matches++;
-                     pflag->flgp = (struct arc_flag_operand *) flg_operand;
-                     lnflg--;
-                     break; /* goto next flag class and parsed flag.  */
-                   }
-               }
-           }
-
-         if ((cl_flags->class & F_CLASS_REQUIRED) && cl_matches == 0)
-           goto match_failed;
-         if ((cl_flags->class & F_CLASS_OPTIONAL) && cl_matches > 1)
-           goto match_failed;
-       }
-      /* Did I check all the parsed flags?  */
-      if (lnflg)
+      if (!parse_opcode_flags (opcode, nflgs, first_pflag))
        goto match_failed;
 
       pr_debug ("flg");
@@ -1980,8 +2046,9 @@ pseudo_operand_match (const expressionS *tok,
 
     case O_symbol:
       /* Handle all symbols as long immediates or signed 9.  */
-      if (operand_real->flags & ARC_OPERAND_LIMM ||
-         ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
+      if (operand_real->flags & ARC_OPERAND_LIMM
+         || ((operand_real->flags & ARC_OPERAND_SIGNED)
+             && operand_real->bits == 9))
        ret = TRUE;
       break;
 
@@ -2064,8 +2131,8 @@ find_special_case_pseudo (const char *opname,
       operand_pseudo = &pseudo_insn->operand[i];
       operand_real = &arc_operands[operand_pseudo->operand_idx];
 
-      if (operand_real->flags & ARC_OPERAND_BRAKET &&
-         !operand_pseudo->needs_insert)
+      if (operand_real->flags & ARC_OPERAND_BRAKET
+         && !operand_pseudo->needs_insert)
        continue;
 
       /* Has to be inserted (i.e. this token does not exist yet).  */
@@ -2176,6 +2243,108 @@ find_special_case_flag (const char *opname,
   return NULL;
 }
 
+/* The long instructions are not stored in a hash (there's not many of
+   them) and so there's no arc_opcode_hash_entry structure to return.  This
+   helper function for find_special_case_long_opcode takes an arc_opcode
+   result and places it into a fake arc_opcode_hash_entry that points to
+   the single arc_opcode OPCODE, which is then returned.  */
+
+static const struct arc_opcode_hash_entry *
+build_fake_opcode_hash_entry (const struct arc_opcode *opcode)
+{
+  static struct arc_opcode_hash_entry entry;
+  static struct arc_opcode tmp[2];
+  static const struct arc_opcode *ptr[2];
+
+  memcpy (&tmp[0], opcode, sizeof (struct arc_opcode));
+  memset (&tmp[1], 0, sizeof (struct arc_opcode));
+  entry.count = 1;
+  entry.opcode = ptr;
+  ptr[0] = tmp;
+  ptr[1] = NULL;
+  return &entry;
+}
+
+
+/* Used by the assembler to match the list of tokens against a long (48 or
+   64 bits) instruction.  If a matching long instruction is found, then
+   some of the tokens are consumed in this function and converted into a
+   single LIMM value, which is then added to the end of the token list,
+   where it will be consumed by a LIMM operand that exists in the base
+   opcode of the long instruction.  */
+
+static const struct arc_opcode_hash_entry *
+find_special_case_long_opcode (const char *opname,
+                               int *ntok ATTRIBUTE_UNUSED,
+                               expressionS *tok ATTRIBUTE_UNUSED,
+                               int *nflgs,
+                               struct arc_flags *pflags)
+{
+  unsigned i;
+
+  if (*ntok == MAX_INSN_ARGS)
+    return NULL;
+
+  for (i = 0; i < arc_num_long_opcodes; ++i)
+    {
+      struct arc_opcode fake_opcode;
+      const struct arc_opcode *opcode;
+      struct arc_insn insn;
+      expressionS *limm_token;
+
+      opcode = &arc_long_opcodes[i].base_opcode;
+
+      if (!(opcode->cpu & arc_target))
+        continue;
+
+      if (!check_cpu_feature (opcode->subclass))
+        continue;
+
+      if (strcmp (opname, opcode->name) != 0)
+        continue;
+
+      /* Check that the flags are a match.  */
+      if (!parse_opcode_flags (opcode, *nflgs, pflags))
+        continue;
+
+      /* Parse the LIMM operands into the LIMM template.  */
+      memset (&fake_opcode, 0, sizeof (fake_opcode));
+      fake_opcode.name = "fake limm";
+      fake_opcode.opcode = arc_long_opcodes[i].limm_template;
+      fake_opcode.mask = arc_long_opcodes[i].limm_mask;
+      fake_opcode.cpu = opcode->cpu;
+      fake_opcode.insn_class = opcode->insn_class;
+      fake_opcode.subclass = opcode->subclass;
+      memcpy (&fake_opcode.operands[0],
+              &arc_long_opcodes[i].operands,
+              MAX_INSN_ARGS);
+      /* Leave fake_opcode.flags as zero.  */
+
+      pr_debug ("Calling assemble_insn to build fake limm value\n");
+      assemble_insn (&fake_opcode, tok, *ntok,
+                     NULL, 0, &insn);
+      pr_debug ("   got limm value: 0x%x\n", insn.insn);
+
+      /* Now create a new token at the end of the token array (We know this
+         is safe as the token array is always created with enough space for
+         MAX_INSN_ARGS, and we check at the start at the start of this
+         function that we're not there yet).  This new token will
+         correspond to a LIMM operand that will be contained in the
+         base_opcode of the arc_long_opcode.  */
+      limm_token = &tok[(*ntok)];
+      (*ntok)++;
+
+      /* Modify the LIMM token to hold the constant.  */
+      limm_token->X_op = O_constant;
+      limm_token->X_add_number = insn.insn;
+
+      /* Return the base opcode.  */
+      return build_fake_opcode_hash_entry (opcode);
+    }
+
+    return NULL;
+}
+
 /* Used to find special case opcode.  */
 
 static const struct arc_opcode_hash_entry *
@@ -2192,6 +2361,9 @@ find_special_case (const char *opname,
   if (entry == NULL)
     entry = find_special_case_flag (opname, nflgs, pflags);
 
+  if (entry == NULL)
+    entry = find_special_case_long_opcode (opname, ntok, tok, nflgs, pflags);
+
   return entry;
 }
 
@@ -2260,9 +2432,7 @@ md_assemble (char *str)
 
   /* Split off the opcode.  */
   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
-  opname = xmalloc (opnamelen + 1);
-  memcpy (opname, str, opnamelen);
-  opname[opnamelen] = '\0';
+  opname = xmemdup0 (str, opnamelen);
 
   /* Signalize we are assmbling the instructions.  */
   assembling_insn = TRUE;
@@ -2328,6 +2498,22 @@ declare_register_set (void)
     }
 }
 
+/* Construct a symbol for an address type.  */
+
+static void
+declare_addrtype (const char *name, int number)
+{
+  const char *err;
+  symbolS *addrtypeS = symbol_create (name, undefined_section,
+                                      number, &zero_address_frag);
+
+  err = hash_insert (arc_addrtype_hash, S_GET_NAME (addrtypeS),
+                     (void *) addrtypeS);
+  if (err)
+    as_fatal (_("Inserting \"%s\" into address type table failed: %s"),
+              name, err);
+}
+
 /* Port-specific assembler initialization.  This function is called
    once, at assembler startup time.  */
 
@@ -2337,7 +2523,7 @@ md_begin (void)
   const struct arc_opcode *opcode = arc_opcodes;
 
   if (!mach_type_specified_p)
-    arc_select_cpu ("arc700");
+    arc_select_cpu (TARGET_WITH_CPU);
 
   /* The endianness can be chosen "at the factory".  */
   target_big_endian = byte_order == BIG_ENDIAN;
@@ -2380,6 +2566,32 @@ md_begin (void)
   declare_register ("ilink2", 30);
   declare_register ("blink", 31);
 
+  /* XY memory registers.  */
+  declare_register ("x0_u0", 32);
+  declare_register ("x0_u1", 33);
+  declare_register ("x1_u0", 34);
+  declare_register ("x1_u1", 35);
+  declare_register ("x2_u0", 36);
+  declare_register ("x2_u1", 37);
+  declare_register ("x3_u0", 38);
+  declare_register ("x3_u1", 39);
+  declare_register ("y0_u0", 40);
+  declare_register ("y0_u1", 41);
+  declare_register ("y1_u0", 42);
+  declare_register ("y1_u1", 43);
+  declare_register ("y2_u0", 44);
+  declare_register ("y2_u1", 45);
+  declare_register ("y3_u0", 46);
+  declare_register ("y3_u1", 47);
+  declare_register ("x0_nu", 48);
+  declare_register ("x1_nu", 49);
+  declare_register ("x2_nu", 50);
+  declare_register ("x3_nu", 51);
+  declare_register ("y0_nu", 52);
+  declare_register ("y1_nu", 53);
+  declare_register ("y2_nu", 54);
+  declare_register ("y3_nu", 55);
+
   declare_register ("mlo", 57);
   declare_register ("mmid", 58);
   declare_register ("mhi", 59);
@@ -2416,6 +2628,28 @@ md_begin (void)
        as_fatal (_("internal error: can't hash aux register '%s': %s"),
                  auxr->name, retval);
     }
+
+  /* Address type declaration.  */
+  arc_addrtype_hash = hash_new ();
+  if (arc_addrtype_hash == NULL)
+    as_fatal (_("Virtual memory exhausted"));
+
+  declare_addrtype ("bd", ARC_NPS400_ADDRTYPE_BD);
+  declare_addrtype ("jid", ARC_NPS400_ADDRTYPE_JID);
+  declare_addrtype ("lbd", ARC_NPS400_ADDRTYPE_LBD);
+  declare_addrtype ("mbd", ARC_NPS400_ADDRTYPE_MBD);
+  declare_addrtype ("sd", ARC_NPS400_ADDRTYPE_SD);
+  declare_addrtype ("sm", ARC_NPS400_ADDRTYPE_SM);
+  declare_addrtype ("xa", ARC_NPS400_ADDRTYPE_XA);
+  declare_addrtype ("xd", ARC_NPS400_ADDRTYPE_XD);
+  declare_addrtype ("cd", ARC_NPS400_ADDRTYPE_CD);
+  declare_addrtype ("cbd", ARC_NPS400_ADDRTYPE_CBD);
+  declare_addrtype ("cjid", ARC_NPS400_ADDRTYPE_CJID);
+  declare_addrtype ("clbd", ARC_NPS400_ADDRTYPE_CLBD);
+  declare_addrtype ("cm", ARC_NPS400_ADDRTYPE_CM);
+  declare_addrtype ("csd", ARC_NPS400_ADDRTYPE_CSD);
+  declare_addrtype ("cxa", ARC_NPS400_ADDRTYPE_CXA);
+  declare_addrtype ("cxd", ARC_NPS400_ADDRTYPE_CXD);
 }
 
 /* Write a value out to the object file, using the appropriate
@@ -2504,7 +2738,8 @@ md_pcrel_from_section (fixS *fixP,
        }
     }
 
-  pr_debug ("pcrel from %x + %lx = %x, symbol: %s (%x)\n",
+  pr_debug ("pcrel from %"BFD_VMA_FMT"x + %lx = %"BFD_VMA_FMT"x, "
+           "symbol: %s (%"BFD_VMA_FMT"x)\n",
            fixP->fx_frag->fr_address, fixP->fx_where, base,
            fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
            fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
@@ -2765,7 +3000,7 @@ md_apply_fix (fixS *fixP,
      bits of a 32-bit negative value read in by the parser are set,
      so that the correct comparisons are made.  */
   if (value & 0x80000000)
-    value |= (-1L << 31);
+    value |= (-1UL << 31);
 
   reloc = fixP->fx_r_type;
   switch (reloc)
@@ -2789,6 +3024,7 @@ md_apply_fix (fixS *fixP,
     case BFD_RELOC_ARC_TLS_LE_32:
       gas_assert (!fixP->fx_addsy);
       gas_assert (!fixP->fx_subsy);
+      /* Fall through.  */
 
     case BFD_RELOC_ARC_GOTOFF:
     case BFD_RELOC_ARC_32_ME:
@@ -2814,6 +3050,7 @@ md_apply_fix (fixS *fixP,
 
     case BFD_RELOC_ARC_S21W_PCREL_PLT:
       reloc = BFD_RELOC_ARC_S21W_PCREL;
+      /* Fall through.  */
 
     case BFD_RELOC_ARC_S25W_PCREL:
     case BFD_RELOC_ARC_S21W_PCREL:
@@ -2937,8 +3174,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
   arelent *reloc;
   bfd_reloc_code_real_type code;
 
-  reloc = (arelent *) xmalloc (sizeof (* reloc));
-  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  reloc = XNEW (arelent);
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
 
@@ -2970,28 +3207,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
 
   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
 
-  if (code == BFD_RELOC_ARC_TLS_DTPOFF
-      || code ==  BFD_RELOC_ARC_TLS_DTPOFF_S9)
-    {
-      asymbol *sym
-       = fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
-      /* We just want to store a 24 bit index, but we have to wait
-        till after write_contents has been called via
-        bfd_map_over_sections before we can get the index from
-        _bfd_elf_symbol_from_bfd_symbol.  Thus, the write_relocs
-        function is elf32-arc.c has to pick up the slack.
-        Unfortunately, this leads to problems with hosts that have
-        pointers wider than long (bfd_vma).  There would be various
-        ways to handle this, all error-prone :-(  */
-      reloc->addend = (bfd_vma) sym;
-      if ((asymbol *) reloc->addend != sym)
-       {
-         as_bad ("Can't store pointer\n");
-         return NULL;
-       }
-    }
-  else
-    reloc->addend = fixP->fx_offset;
+  reloc->addend = fixP->fx_offset;
 
   return reloc;
 }
@@ -3020,7 +3236,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
   dest = fragP->fr_literal + fix;
   table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype;
 
-  pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, var: %d\n",
+  pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, "
+           "var: %"BFD_VMA_FMT"d\n",
            fragP->fr_file, fragP->fr_line,
            fragP->fr_subtype, fix, fragP->fr_var);
 
@@ -3114,7 +3331,7 @@ arc_parse_name (const char *name,
   if (!assembling_insn)
     return FALSE;
 
-  /* Handle only registers.  */
+  /* Handle only registers and address types.  */
   if (e->X_op != O_absent)
     return FALSE;
 
@@ -3125,6 +3342,15 @@ arc_parse_name (const char *name,
       e->X_add_number = S_GET_VALUE (sym);
       return TRUE;
     }
+
+  sym = hash_find (arc_addrtype_hash, name);
+  if (sym)
+    {
+      e->X_op = O_addrtype;
+      e->X_add_number = S_GET_VALUE (sym);
+      return TRUE;
+    }
+
   return FALSE;
 }
 
@@ -3140,7 +3366,7 @@ arc_parse_name (const char *name,
    -mrelax                       Enable relaxation
 
    The following CPU names are recognized:
-   arc700, av2em, av2hs.  */
+   arc600, arc700, arcem, archs, nps400.  */
 
 int
 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
@@ -3189,17 +3415,8 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
       relaxation_state = 1;
       break;
 
-    case OPTION_USER_MODE:
-    case OPTION_LD_EXT_MASK:
-    case OPTION_SWAP:
-    case OPTION_NORM:
-    case OPTION_BARREL_SHIFT:
-    case OPTION_MIN_MAX:
-    case OPTION_NO_MPY:
-    case OPTION_EA:
-    case OPTION_MUL64:
-    case OPTION_SIMD:
-      /* Dummy options are accepted but have no effect.  */
+    case OPTION_NPS400:
+      arc_features |= ARC_NPS400;
       break;
 
     case OPTION_SPFP:
@@ -3210,6 +3427,25 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
       arc_features |= ARC_DPFP;
       break;
 
+    case OPTION_FPUDA:
+      /* This option has an effect only on ARC EM.  */
+      if (arc_target & ARC_OPCODE_ARCv2EM)
+       arc_features |= ARC_FPUDA;
+      else
+       as_warn (_("FPUDA invalid for selected CPU"));
+      break;
+
+    /* Dummy options are accepted but have no effect.  */
+    case OPTION_USER_MODE:
+    case OPTION_LD_EXT_MASK:
+    case OPTION_SWAP:
+    case OPTION_NORM:
+    case OPTION_BARREL_SHIFT:
+    case OPTION_MIN_MAX:
+    case OPTION_NO_MPY:
+    case OPTION_EA:
+    case OPTION_MUL64:
+    case OPTION_SIMD:
     case OPTION_XMAC_D16:
     case OPTION_XMAC_24:
     case OPTION_DSP_PACKA:
@@ -3220,15 +3456,6 @@ md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
     case OPTION_LOCK:
     case OPTION_SWAPE:
     case OPTION_RTSC:
-      /* Dummy options are accepted but have no effect.  */
-      break;
-
-    case OPTION_FPUDA:
-      /* This option has an effect only on ARC EM.  */
-      if (arc_target & ARC_OPCODE_ARCv2EM)
-       arc_features |= ARC_FPUDA;
-      else
-       as_warn (_("FPUDA invalid for selected CPU"));
       break;
 
     default:
@@ -3243,7 +3470,20 @@ md_show_usage (FILE *stream)
 {
   fprintf (stream, _("ARC-specific assembler options:\n"));
 
-  fprintf (stream, "  -mcpu=<cpu name>\t  assemble for CPU <cpu name>\n");
+  fprintf (stream, "  -mcpu=<cpu name>\t  assemble for CPU <cpu name> "
+           "(default: %s)\n", TARGET_WITH_CPU);
+  fprintf (stream, "  -mcpu=nps400\t\t  same as -mcpu=arc700 -mnps400\n");
+  fprintf (stream, "  -mA6/-mARC600/-mARC601  same as -mcpu=arc600\n");
+  fprintf (stream, "  -mA7/-mARC700\t\t  same as -mcpu=arc700\n");
+  fprintf (stream, "  -mEM\t\t\t  same as -mcpu=arcem\n");
+  fprintf (stream, "  -mHS\t\t\t  same as -mcpu=archs\n");
+
+  fprintf (stream, "  -mnps400\t\t  enable NPS-400 extended instructions\n");
+  fprintf (stream, "  -mspfp\t\t  enable single-precision floating point instructions\n");
+  fprintf (stream, "  -mdpfp\t\t  enable double-precision floating point instructions\n");
+  fprintf (stream, "  -mfpuda\t\t  enable double-precision assist floating "
+                   "point\n\t\t\t  instructions for ARC EM\n");
+
   fprintf (stream,
           "  -mcode-density\t  enable code density option for ARC EM\n");
 
@@ -3252,8 +3492,36 @@ md_show_usage (FILE *stream)
   fprintf (stream, _("\
   -EL                     assemble code for a little-endian cpu\n"));
   fprintf (stream, _("\
-  -mrelax                  Enable relaxation\n"));
-
+  -mrelax                 enable relaxation\n"));
+
+  fprintf (stream, _("The following ARC-specific assembler options are "
+                     "deprecated and are accepted\nfor compatibility only:\n"));
+
+  fprintf (stream, _("  -mEA\n"
+                     "  -mbarrel-shifter\n"
+                     "  -mbarrel_shifter\n"
+                     "  -mcrc\n"
+                     "  -mdsp-packa\n"
+                     "  -mdsp_packa\n"
+                     "  -mdvbf\n"
+                     "  -mld-extension-reg-mask\n"
+                     "  -mlock\n"
+                     "  -mmac-24\n"
+                     "  -mmac-d16\n"
+                     "  -mmac_24\n"
+                     "  -mmac_d16\n"
+                     "  -mmin-max\n"
+                     "  -mmin_max\n"
+                     "  -mmul64\n"
+                     "  -mno-mpy\n"
+                     "  -mnorm\n"
+                     "  -mrtsc\n"
+                     "  -msimd\n"
+                     "  -mswap\n"
+                     "  -mswape\n"
+                     "  -mtelephony\n"
+                    "  -muser-mode-only\n"
+                     "  -mxy\n"));
 }
 
 /* Find the proper relocation for the given opcode.  */
@@ -3544,8 +3812,7 @@ assemble_insn (const struct arc_opcode *opcode,
       const struct arc_operand *operand = &arc_operands[*argidx];
       const expressionS *t = (const expressionS *) 0;
 
-      if ((operand->flags & ARC_OPERAND_FAKE)
-         && !(operand->flags & ARC_OPERAND_BRAKET))
+      if (ARC_OPERAND_IS_FAKE (operand))
        continue;
 
       if (operand->flags & ARC_OPERAND_DUPLICATE)
@@ -3582,7 +3849,9 @@ assemble_insn (const struct arc_opcode *opcode,
          break;
 
        case O_bracket:
-         /* Ignore brackets.  */
+        case O_colon:
+        case O_addrtype:
+         /* Ignore brackets, colons, and address types.  */
          break;
 
        case O_absent:
@@ -3603,6 +3872,7 @@ assemble_insn (const struct arc_opcode *opcode,
              image = insert_operand (image, operand, regs, NULL, 0);
              break;
            }
+         /* Fall through.  */
 
        default:
          /* This operand needs a relocation.  */
@@ -3611,7 +3881,7 @@ assemble_insn (const struct arc_opcode *opcode,
          switch (t->X_md)
            {
            case O_plt:
-             if (opcode->class == JUMP)
+             if (opcode->insn_class == JUMP)
                as_bad_where (frag_now->fr_file, frag_now->fr_line,
                              _("Unable to use @plt relocatio for insn %s"),
                              opcode->name);
@@ -3628,7 +3898,7 @@ assemble_insn (const struct arc_opcode *opcode,
              break;
            case O_pcl:
              reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
-             if (ARC_SHORT (opcode->mask) || opcode->class == JUMP)
+             if (ARC_SHORT (opcode->mask) || opcode->insn_class == JUMP)
                as_bad_where (frag_now->fr_file, frag_now->fr_line,
                              _("Unable to use @pcl relocation for insn %s"),
                              opcode->name);
@@ -3918,7 +4188,6 @@ check_zol (symbolS *s)
 end of the ZOL label @%s"), S_GET_NAME (s));
 
       /* Fall through.  */
-    case bfd_mach_arc_nps400:
     case bfd_mach_arc_arc700:
       if (arc_last_insns[0].has_delay_slot)
        as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
@@ -3963,7 +4232,7 @@ void
 tc_arc_frame_initial_instructions (void)
 {
   /* Stack pointer is register 28.  */
-  cfi_add_CFA_def_cfa_register (28);
+  cfi_add_CFA_def_cfa (28, 0);
 }
 
 int
@@ -4060,7 +4329,7 @@ tokenize_extinsn (extInstruction_t *einsn)
          if (!strncmp (suffixclass[i].name, input_line_pointer,
                        suffixclass[i].len))
            {
-             suffix_class |= suffixclass[i].class;
+             suffix_class |= suffixclass[i].attr_class;
              input_line_pointer += suffixclass[i].len;
              break;
            }
@@ -4100,7 +4369,7 @@ tokenize_extinsn (extInstruction_t *einsn)
                        input_line_pointer,
                        syntaxclassmod[i].len))
            {
-             syntax_class_modifiers |= syntaxclassmod[i].class;
+             syntax_class_modifiers |= syntaxclassmod[i].attr_class;
              input_line_pointer += syntaxclassmod[i].len;
              break;
            }
@@ -4114,7 +4383,7 @@ tokenize_extinsn (extInstruction_t *einsn)
                            input_line_pointer,
                            syntaxclass[i].len))
                {
-                 syntax_class |= syntaxclass[i].class;
+                 syntax_class |= syntaxclass[i].attr_class;
                  input_line_pointer += syntaxclass[i].len;
                  break;
                }
@@ -4233,13 +4502,15 @@ arc_extinsn (int ignore ATTRIBUTE_UNUSED)
       && (einsn.major != 5) && (einsn.major != 9))
     as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
 
-  switch (einsn.syntax & (ARC_SYNTAX_3OP | ARC_SYNTAX_2OP))
+  switch (einsn.syntax & ARC_SYNTAX_MASK)
     {
     case ARC_SYNTAX_3OP:
       if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
        as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
       break;
     case ARC_SYNTAX_2OP:
+    case ARC_SYNTAX_1OP:
+    case ARC_SYNTAX_NOP:
       if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
        as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
       break;
@@ -4469,7 +4740,7 @@ arc_extcorereg (int opertype)
       break;
     case EXT_AUX_REGISTER:
       /* Auxiliary register.  */
-      auxr = xmalloc (sizeof (struct arc_aux_reg));
+      auxr = XNEW (struct arc_aux_reg);
       auxr->name = ereg.name;
       auxr->cpu = arc_target;
       auxr->subclass = NONE;
@@ -4486,8 +4757,8 @@ arc_extcorereg (int opertype)
                ereg.number);
       ext_condcode.size ++;
       ext_condcode.arc_ext_condcode =
-       xrealloc (ext_condcode.arc_ext_condcode,
-                 (ext_condcode.size + 1) * sizeof (struct arc_flag_operand));
+       XRESIZEVEC (struct arc_flag_operand, ext_condcode.arc_ext_condcode,
+                   ext_condcode.size + 1);
       if (ext_condcode.arc_ext_condcode == NULL)
        as_fatal (_("Virtual memory exhausted"));