[AArch64][SVE 31/32] Add SVE instructions
[deliverable/binutils-gdb.git] / opcodes / aarch64-opc.c
index 9880142873e6bbc65e0742eb1d41d815e4405a5c..d22e419e421e7f2342ebeb62c9506a024e38248f 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-opc.c -- AArch64 opcode support.
 /* aarch64-opc.c -- AArch64 opcode support.
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of the GNU opcodes library.
    Contributed by ARM Ltd.
 
    This file is part of the GNU opcodes library.
@@ -27,6 +27,7 @@
 #include <inttypes.h>
 
 #include "opintl.h"
 #include <inttypes.h>
 
 #include "opintl.h"
+#include "libiberty.h"
 
 #include "aarch64-opc.h"
 
 
 #include "aarch64-opc.h"
 
 int debug_dump = FALSE;
 #endif /* DEBUG_AARCH64 */
 
 int debug_dump = FALSE;
 #endif /* DEBUG_AARCH64 */
 
+/* The enumeration strings associated with each value of a 5-bit SVE
+   pattern operand.  A null entry indicates a reserved meaning.  */
+const char *const aarch64_sve_pattern_array[32] = {
+  /* 0-7.  */
+  "pow2",
+  "vl1",
+  "vl2",
+  "vl3",
+  "vl4",
+  "vl5",
+  "vl6",
+  "vl7",
+  /* 8-15.  */
+  "vl8",
+  "vl16",
+  "vl32",
+  "vl64",
+  "vl128",
+  "vl256",
+  0,
+  0,
+  /* 16-23.  */
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  /* 24-31.  */
+  0,
+  0,
+  0,
+  0,
+  0,
+  "mul4",
+  "mul3",
+  "all"
+};
+
+/* The enumeration strings associated with each value of a 4-bit SVE
+   prefetch operand.  A null entry indicates a reserved meaning.  */
+const char *const aarch64_sve_prfop_array[16] = {
+  /* 0-7.  */
+  "pldl1keep",
+  "pldl1strm",
+  "pldl2keep",
+  "pldl2strm",
+  "pldl3keep",
+  "pldl3strm",
+  0,
+  0,
+  /* 8-15.  */
+  "pstl1keep",
+  "pstl1strm",
+  "pstl2keep",
+  "pstl2strm",
+  "pstl3keep",
+  "pstl3strm",
+  0,
+  0
+};
+
 /* Helper functions to determine which operand to be used to encode/decode
    the size:Q fields for AdvSIMD instructions.  */
 
 /* Helper functions to determine which operand to be used to encode/decode
    the size:Q fields for AdvSIMD instructions.  */
 
@@ -199,6 +264,51 @@ const aarch64_field fields[] =
     { 31,  1 },        /* b5: in the test bit and branch instructions.  */
     { 19,  5 },        /* b40: in the test bit and branch instructions.  */
     { 10,  6 },        /* scale: in the fixed-point scalar to fp converting inst.  */
     { 31,  1 },        /* b5: in the test bit and branch instructions.  */
     { 19,  5 },        /* b40: in the test bit and branch instructions.  */
     { 10,  6 },        /* scale: in the fixed-point scalar to fp converting inst.  */
+    {  4,  1 }, /* SVE_M_4: Merge/zero select, bit 4.  */
+    { 14,  1 }, /* SVE_M_14: Merge/zero select, bit 14.  */
+    { 16,  1 }, /* SVE_M_16: Merge/zero select, bit 16.  */
+    { 17,  1 }, /* SVE_N: SVE equivalent of N.  */
+    {  0,  4 }, /* SVE_Pd: p0-p15, bits [3,0].  */
+    { 10,  3 }, /* SVE_Pg3: p0-p7, bits [12,10].  */
+    {  5,  4 }, /* SVE_Pg4_5: p0-p15, bits [8,5].  */
+    { 10,  4 }, /* SVE_Pg4_10: p0-p15, bits [13,10].  */
+    { 16,  4 }, /* SVE_Pg4_16: p0-p15, bits [19,16].  */
+    { 16,  4 }, /* SVE_Pm: p0-p15, bits [19,16].  */
+    {  5,  4 }, /* SVE_Pn: p0-p15, bits [8,5].  */
+    {  0,  4 }, /* SVE_Pt: p0-p15, bits [3,0].  */
+    {  5,  5 }, /* SVE_Rm: SVE alternative position for Rm.  */
+    { 16,  5 }, /* SVE_Rn: SVE alternative position for Rn.  */
+    {  0,  5 }, /* SVE_Vd: Scalar SIMD&FP register, bits [4,0].  */
+    {  5,  5 }, /* SVE_Vm: Scalar SIMD&FP register, bits [9,5].  */
+    {  5,  5 }, /* SVE_Vn: Scalar SIMD&FP register, bits [9,5].  */
+    {  5,  5 }, /* SVE_Za_5: SVE vector register, bits [9,5].  */
+    { 16,  5 }, /* SVE_Za_16: SVE vector register, bits [20,16].  */
+    {  0,  5 }, /* SVE_Zd: SVE vector register. bits [4,0].  */
+    {  5,  5 }, /* SVE_Zm_5: SVE vector register, bits [9,5].  */
+    { 16,  5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
+    {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
+    {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
+    {  5,  1 }, /* SVE_i1: single-bit immediate.  */
+    { 16,  3 }, /* SVE_imm3: 3-bit immediate field.  */
+    { 16,  4 }, /* SVE_imm4: 4-bit immediate field.  */
+    {  5,  5 }, /* SVE_imm5: 5-bit immediate field.  */
+    { 16,  5 }, /* SVE_imm5b: secondary 5-bit immediate field.  */
+    { 16,  6 }, /* SVE_imm6: 6-bit immediate field.  */
+    { 14,  7 }, /* SVE_imm7: 7-bit immediate field.  */
+    {  5,  8 }, /* SVE_imm8: 8-bit immediate field.  */
+    {  5,  9 }, /* SVE_imm9: 9-bit immediate field.  */
+    { 11,  6 }, /* SVE_immr: SVE equivalent of immr.  */
+    {  5,  6 }, /* SVE_imms: SVE equivalent of imms.  */
+    { 10,  2 }, /* SVE_msz: 2-bit shift amount for ADR.  */
+    {  5,  5 }, /* SVE_pattern: vector pattern enumeration.  */
+    {  0,  4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD].  */
+    { 22,  1 }, /* SVE_sz: 1-bit element size select.  */
+    { 16,  4 }, /* SVE_tsz: triangular size select.  */
+    { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
+    {  8,  2 }, /* SVE_tszl_8: triangular size select low, bits [9,8].  */
+    { 19,  2 }, /* SVE_tszl_19: triangular size select low, bits [20,19].  */
+    { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
+    { 22,  1 }  /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
 };
 
 enum aarch64_operand_class
 };
 
 enum aarch64_operand_class
@@ -276,6 +386,8 @@ const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
     {"sxth", 0x5},
     {"sxtw", 0x6},
     {"sxtx", 0x7},
     {"sxth", 0x5},
     {"sxtw", 0x6},
     {"sxtx", 0x7},
+    {"mul", 0x0},
+    {"mul vl", 0x0},
     {NULL, 0},
 };
 
     {NULL, 0},
 };
 
@@ -335,6 +447,19 @@ const struct aarch64_name_value_pair aarch64_barrier_options[16] =
     { "sy",    0xf },
 };
 
     { "sy",    0xf },
 };
 
+/* Table describing the operands supported by the aliases of the HINT
+   instruction.
+
+   The name column is the operand that is accepted for the alias.  The value
+   column is the hint number of the alias.  The list of operands is terminated
+   by NULL in the name column.  */
+
+const struct aarch64_name_value_pair aarch64_hint_options[] =
+{
+  { "csync", 0x11 },    /* PSB CSYNC.  */
+  { NULL, 0x0 },
+};
+
 /* op -> op:       load = 0 instruction = 1 store = 2
    l  -> level:    1-3
    t  -> temporal: temporal (retained) = 0 non-temporal (streaming) = 1   */
 /* op -> op:       load = 0 instruction = 1 store = 2
    l  -> level:    1-3
    t  -> temporal: temporal (retained) = 0 non-temporal (streaming) = 1   */
@@ -384,10 +509,11 @@ value_in_range_p (int64_t value, int low, int high)
   return (value >= low && value <= high) ? 1 : 0;
 }
 
   return (value >= low && value <= high) ? 1 : 0;
 }
 
+/* Return true if VALUE is a multiple of ALIGN.  */
 static inline int
 value_aligned_p (int64_t value, int align)
 {
 static inline int
 value_aligned_p (int64_t value, int align)
 {
-  return ((value & (align - 1)) == 0) ? 1 : 0;
+  return (value % align) == 0;
 }
 
 /* A signed value fits in a field.  */
 }
 
 /* A signed value fits in a field.  */
@@ -565,6 +691,7 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
 
   {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
   {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
 
   {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
   {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
+  {2, 2, 0x0, "2h", OQK_OPD_VARIANT},
   {2, 4, 0x2, "4h", OQK_OPD_VARIANT},
   {2, 8, 0x3, "8h", OQK_OPD_VARIANT},
   {4, 2, 0x4, "2s", OQK_OPD_VARIANT},
   {2, 4, 0x2, "4h", OQK_OPD_VARIANT},
   {2, 8, 0x3, "8h", OQK_OPD_VARIANT},
   {4, 2, 0x4, "2s", OQK_OPD_VARIANT},
@@ -573,6 +700,9 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
   {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
   {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
 
   {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
   {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
 
+  {0, 0, 0, "z", OQK_OPD_VARIANT},
+  {0, 0, 0, "m", OQK_OPD_VARIANT},
+
   /* Qualifiers constraining the value range.
      First 3 fields:
      Lower bound, higher bound, unused.  */
   /* Qualifiers constraining the value range.
      First 3 fields:
      Lower bound, higher bound, unused.  */
@@ -840,7 +970,7 @@ aarch64_find_best_match (const aarch64_inst *inst,
 static int
 match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
 {
 static int
 match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
 {
-  int i;
+  int i, nops;
   aarch64_opnd_qualifier_seq_t qualifiers;
 
   if (!aarch64_find_best_match (inst, inst->opcode->qualifiers_list, -1,
   aarch64_opnd_qualifier_seq_t qualifiers;
 
   if (!aarch64_find_best_match (inst, inst->opcode->qualifiers_list, -1,
@@ -850,6 +980,15 @@ match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
       return 0;
     }
 
       return 0;
     }
 
+  if (inst->opcode->flags & F_STRICT)
+    {
+      /* Require an exact qualifier match, even for NIL qualifiers.  */
+      nops = aarch64_num_of_operands (inst->opcode);
+      for (i = 0; i < nops; ++i)
+       if (inst->operands[i].qualifier != qualifiers[i])
+         return FALSE;
+    }
+
   /* Update the qualifiers.  */
   if (update_p == TRUE)
     for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
   /* Update the qualifiers.  */
   if (update_p == TRUE)
     for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
@@ -1039,16 +1178,18 @@ build_immediate_table (void)
    be accepted by logical (immediate) instructions
    e.g. ORR <Xd|SP>, <Xn>, #<imm>.
 
    be accepted by logical (immediate) instructions
    e.g. ORR <Xd|SP>, <Xn>, #<imm>.
 
-   IS32 indicates whether or not VALUE is a 32-bit immediate.
+   ESIZE is the number of bytes in the decoded immediate value.
    If ENCODING is not NULL, on the return of TRUE, the standard encoding for
    VALUE will be returned in *ENCODING.  */
 
 bfd_boolean
    If ENCODING is not NULL, on the return of TRUE, the standard encoding for
    VALUE will be returned in *ENCODING.  */
 
 bfd_boolean
-aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
+aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding)
 {
   simd_imm_encoding imm_enc;
   const simd_imm_encoding *imm_encoding;
   static bfd_boolean initialized = FALSE;
 {
   simd_imm_encoding imm_enc;
   const simd_imm_encoding *imm_encoding;
   static bfd_boolean initialized = FALSE;
+  uint64_t upper;
+  int i;
 
   DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
               value, is32);
 
   DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
               value, is32);
@@ -1059,17 +1200,16 @@ aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
       initialized = TRUE;
     }
 
       initialized = TRUE;
     }
 
-  if (is32)
-    {
-      /* Allow all zeros or all ones in top 32-bits, so that
-        constant expressions like ~1 are permitted.  */
-      if (value >> 32 != 0 && value >> 32 != 0xffffffff)
-       return FALSE;
+  /* Allow all zeros or all ones in top bits, so that
+     constant expressions like ~1 are permitted.  */
+  upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
+  if ((value & ~upper) != value && (value | upper) != value)
+    return FALSE;
 
 
-      /* Replicate the 32 lower bits to the 32 upper bits.  */
-      value &= 0xffffffff;
-      value |= value << 32;
-    }
+  /* Replicate to a full 64-bit value.  */
+  value &= ~upper;
+  for (i = esize * 8; i < 64; i *= 2)
+    value |= (value << i);
 
   imm_enc.imm = value;
   imm_encoding = (const simd_imm_encoding *)
 
   imm_enc.imm = value;
   imm_encoding = (const simd_imm_encoding *)
@@ -1193,6 +1333,18 @@ set_sft_amount_out_of_range_error (aarch64_operand_error *mismatch_detail,
                          _("shift amount"));
 }
 
                          _("shift amount"));
 }
 
+/* Report that the MUL modifier in operand IDX should be in the range
+   [LOWER_BOUND, UPPER_BOUND].  */
+static inline void
+set_multiplier_out_of_range_error (aarch64_operand_error *mismatch_detail,
+                                  int idx, int lower_bound, int upper_bound)
+{
+  if (mismatch_detail == NULL)
+    return;
+  set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+                         _("multiplier"));
+}
+
 static inline void
 set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
                     int alignment)
 static inline void
 set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
                     int alignment)
@@ -1244,9 +1396,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                                  const aarch64_opcode *opcode,
                                  aarch64_operand_error *mismatch_detail)
 {
                                  const aarch64_opcode *opcode,
                                  aarch64_operand_error *mismatch_detail)
 {
-  unsigned num;
+  unsigned num, modifiers, shift;
   unsigned char size;
   unsigned char size;
-  int64_t imm;
+  int64_t imm, min_value, max_value;
+  uint64_t uvalue, mask;
   const aarch64_opnd_info *opnd = opnds + idx;
   aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
 
   const aarch64_opnd_info *opnd = opnds + idx;
   aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
 
@@ -1279,12 +1432,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        {
          assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
                               == AARCH64_OPND_CLASS_SYSTEM));
        {
          assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
                               == AARCH64_OPND_CLASS_SYSTEM));
-         if (opnds[1].present && !opnds[0].sysins_op->has_xt)
+         if (opnds[1].present
+             && !aarch64_sys_ins_reg_has_xt (opnds[0].sysins_op))
            {
              set_other_error (mismatch_detail, idx, _("extraneous register"));
              return 0;
            }
            {
              set_other_error (mismatch_detail, idx, _("extraneous register"));
              return 0;
            }
-         if (!opnds[1].present && opnds[0].sysins_op->has_xt)
+         if (!opnds[1].present
+             && aarch64_sys_ins_reg_has_xt (opnds[0].sysins_op))
            {
              set_other_error (mismatch_detail, idx, _("missing register"));
              return 0;
            {
              set_other_error (mismatch_detail, idx, _("missing register"));
              return 0;
@@ -1306,6 +1461,43 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        }
       break;
 
        }
       break;
 
+    case AARCH64_OPND_CLASS_SVE_REG:
+      switch (type)
+       {
+       case AARCH64_OPND_SVE_Zn_INDEX:
+         size = aarch64_get_qualifier_esize (opnd->qualifier);
+         if (!value_in_range_p (opnd->reglane.index, 0, 64 / size - 1))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx,
+                                              0, 64 / size - 1);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ZnxN:
+       case AARCH64_OPND_SVE_ZtxN:
+         if (opnd->reglist.num_regs != get_opcode_dependent_value (opcode))
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid register list"));
+             return 0;
+           }
+         break;
+
+       default:
+         break;
+       }
+      break;
+
+    case AARCH64_OPND_CLASS_PRED_REG:
+      if (opnd->reg.regno >= 8
+         && get_operand_fields_width (get_operand_from_code (type)) == 3)
+       {
+         set_other_error (mismatch_detail, idx, _("p0-p7 expected"));
+         return 0;
+       }
+      break;
+
     case AARCH64_OPND_CLASS_COND:
       if (type == AARCH64_OPND_COND1
          && (opnds[idx].cond->value & 0xe) == 0xe)
     case AARCH64_OPND_CLASS_COND:
       if (type == AARCH64_OPND_COND1
          && (opnds[idx].cond->value & 0xe) == 0xe)
@@ -1499,12 +1691,172 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
            }
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
+         min_value = -8;
+         max_value = 7;
+       sve_imm_offset_vl:
+         assert (!opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         num = 1 + get_operand_specific_data (&aarch64_operands[type]);
+         min_value *= num;
+         max_value *= num;
+         if ((opnd->addr.offset.imm != 0 && !opnd->shifter.operator_present)
+             || (opnd->shifter.operator_present
+                 && opnd->shifter.kind != AARCH64_MOD_MUL_VL))
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         if (!value_in_range_p (opnd->addr.offset.imm, min_value, max_value))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx,
+                                            min_value, max_value);
+             return 0;
+           }
+         if (!value_aligned_p (opnd->addr.offset.imm, num))
+           {
+             set_unaligned_error (mismatch_detail, idx, num);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
+         min_value = -32;
+         max_value = 31;
+         goto sve_imm_offset_vl;
+
+       case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
+         min_value = -256;
+         max_value = 255;
+         goto sve_imm_offset_vl;
+
+       case AARCH64_OPND_SVE_ADDR_RI_U6:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x2:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x4:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x8:
+         min_value = 0;
+         max_value = 63;
+       sve_imm_offset:
+         assert (!opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         num = 1 << get_operand_specific_data (&aarch64_operands[type]);
+         min_value *= num;
+         max_value *= num;
+         if (opnd->shifter.operator_present
+             || opnd->shifter.amount_present)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         if (!value_in_range_p (opnd->addr.offset.imm, min_value, max_value))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx,
+                                            min_value, max_value);
+             return 0;
+           }
+         if (!value_aligned_p (opnd->addr.offset.imm, num))
+           {
+             set_unaligned_error (mismatch_detail, idx, num);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RR:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RX:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RZ:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
+         modifiers = 1 << AARCH64_MOD_LSL;
+       sve_rr_operand:
+         assert (opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         if ((aarch64_operands[type].flags & OPD_F_NO_ZR) != 0
+             && opnd->addr.offset.regno == 31)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("index register xzr is not allowed"));
+             return 0;
+           }
+         if (((1 << opnd->shifter.kind) & modifiers) == 0
+             || (opnd->shifter.amount
+                 != get_operand_specific_data (&aarch64_operands[type])))
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
+         modifiers = (1 << AARCH64_MOD_SXTW) | (1 << AARCH64_MOD_UXTW);
+         goto sve_rr_operand;
+
+       case AARCH64_OPND_SVE_ADDR_ZI_U5:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
+         min_value = 0;
+         max_value = 31;
+         goto sve_imm_offset;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
+         modifiers = 1 << AARCH64_MOD_LSL;
+       sve_zz_operand:
+         assert (opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         if (((1 << opnd->shifter.kind) & modifiers) == 0
+             || opnd->shifter.amount < 0
+             || opnd->shifter.amount > 3)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
+         modifiers = (1 << AARCH64_MOD_SXTW);
+         goto sve_zz_operand;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
+         modifiers = 1 << AARCH64_MOD_UXTW;
+         goto sve_zz_operand;
+
        default:
          break;
        }
       break;
 
     case AARCH64_OPND_CLASS_SIMD_REGLIST:
        default:
          break;
        }
       break;
 
     case AARCH64_OPND_CLASS_SIMD_REGLIST:
+      if (type == AARCH64_OPND_LEt)
+       {
+         /* Get the upper bound for the element index.  */
+         num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+         if (!value_in_range_p (opnd->reglist.index, 0, num))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
+             return 0;
+           }
+       }
       /* The opcode dependent area stores the number of elements in
         each structure to be loaded/stored.  */
       num = get_opcode_dependent_value (opcode);
       /* The opcode dependent area stores the number of elements in
         each structure to be loaded/stored.  */
       num = get_opcode_dependent_value (opcode);
@@ -1610,7 +1962,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
        case AARCH64_OPND_IMM_MOV:
            {
 
        case AARCH64_OPND_IMM_MOV:
            {
-             int is32 = aarch64_get_qualifier_esize (opnds[0].qualifier) == 4;
+             int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
              imm = opnd->imm.value;
              assert (idx == 1);
              switch (opcode->op)
              imm = opnd->imm.value;
              assert (idx == 1);
              switch (opcode->op)
@@ -1619,7 +1971,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                  imm = ~imm;
                  /* Fall through...  */
                case OP_MOV_IMM_WIDE:
                  imm = ~imm;
                  /* Fall through...  */
                case OP_MOV_IMM_WIDE:
-                 if (!aarch64_wide_constant_p (imm, is32, NULL))
+                 if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
@@ -1627,7 +1979,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                    }
                  break;
                case OP_MOV_IMM_LOG:
                    }
                  break;
                case OP_MOV_IMM_LOG:
-                 if (!aarch64_logical_immediate_p (imm, is32, NULL))
+                 if (!aarch64_logical_immediate_p (imm, esize, NULL))
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
@@ -1648,6 +2000,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        case AARCH64_OPND_UIMM7:
        case AARCH64_OPND_UIMM3_OP1:
        case AARCH64_OPND_UIMM3_OP2:
        case AARCH64_OPND_UIMM7:
        case AARCH64_OPND_UIMM3_OP1:
        case AARCH64_OPND_UIMM3_OP2:
+       case AARCH64_OPND_SVE_UIMM3:
+       case AARCH64_OPND_SVE_UIMM7:
+       case AARCH64_OPND_SVE_UIMM8:
+       case AARCH64_OPND_SVE_UIMM8_53:
          size = get_operand_fields_width (get_operand_from_code (type));
          assert (size < 32);
          if (!value_fit_unsigned_field_p (opnd->imm.value, size))
          size = get_operand_fields_width (get_operand_from_code (type));
          assert (size < 32);
          if (!value_fit_unsigned_field_p (opnd->imm.value, size))
@@ -1658,8 +2014,24 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
            }
          break;
 
+       case AARCH64_OPND_SIMM5:
+       case AARCH64_OPND_SVE_SIMM5:
+       case AARCH64_OPND_SVE_SIMM5B:
+       case AARCH64_OPND_SVE_SIMM6:
+       case AARCH64_OPND_SVE_SIMM8:
+         size = get_operand_fields_width (get_operand_from_code (type));
+         assert (size < 32);
+         if (!value_fit_signed_field_p (opnd->imm.value, size))
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx,
+                                         -(1 << (size - 1)),
+                                         (1 << (size - 1)) - 1);
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_WIDTH:
        case AARCH64_OPND_WIDTH:
-         assert (idx == 3 && opnds[idx-1].type == AARCH64_OPND_IMM
+         assert (idx > 1 && opnds[idx-1].type == AARCH64_OPND_IMM
                  && opnds[0].type == AARCH64_OPND_Rd);
          size = get_upper_bound (qualifier);
          if (opnd->imm.value + opnds[idx-1].imm.value > size)
                  && opnds[0].type == AARCH64_OPND_Rd);
          size = get_upper_bound (qualifier);
          if (opnd->imm.value + opnds[idx-1].imm.value > size)
@@ -1672,18 +2044,19 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          break;
 
        case AARCH64_OPND_LIMM:
          break;
 
        case AARCH64_OPND_LIMM:
-           {
-             int is32 = opnds[0].qualifier == AARCH64_OPND_QLF_W;
-             uint64_t uimm = opnd->imm.value;
-             if (opcode->op == OP_BIC)
-               uimm = ~uimm;
-             if (aarch64_logical_immediate_p (uimm, is32, NULL) == FALSE)
-               {
-                 set_other_error (mismatch_detail, idx,
-                                  _("immediate out of range"));
-                 return 0;
-               }
-           }
+       case AARCH64_OPND_SVE_LIMM:
+         {
+           int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
+           uint64_t uimm = opnd->imm.value;
+           if (opcode->op == OP_BIC)
+             uimm = ~uimm;
+           if (aarch64_logical_immediate_p (uimm, esize, NULL) == FALSE)
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("immediate out of range"));
+               return 0;
+             }
+         }
          break;
 
        case AARCH64_OPND_IMM0:
          break;
 
        case AARCH64_OPND_IMM0:
@@ -1818,6 +2191,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
        case AARCH64_OPND_FPIMM:
        case AARCH64_OPND_SIMD_FPIMM:
 
        case AARCH64_OPND_FPIMM:
        case AARCH64_OPND_SIMD_FPIMM:
+       case AARCH64_OPND_SVE_FPIMM8:
          if (opnd->imm.is_fp == 0)
            {
              set_other_error (mismatch_detail, idx,
          if (opnd->imm.is_fp == 0)
            {
              set_other_error (mismatch_detail, idx,
@@ -1842,6 +2216,150 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
            }
          break;
 
+       case AARCH64_OPND_SVE_AIMM:
+         min_value = 0;
+       sve_aimm:
+         assert (opnd->shifter.kind == AARCH64_MOD_LSL);
+         size = aarch64_get_qualifier_esize (opnds[0].qualifier);
+         mask = ~((uint64_t) -1 << (size * 4) << (size * 4));
+         uvalue = opnd->imm.value;
+         shift = opnd->shifter.amount;
+         if (size == 1)
+           {
+             if (shift != 0)
+               {
+                 set_other_error (mismatch_detail, idx,
+                                  _("no shift amount allowed for"
+                                    " 8-bit constants"));
+                 return 0;
+               }
+           }
+         else
+           {
+             if (shift != 0 && shift != 8)
+               {
+                 set_other_error (mismatch_detail, idx,
+                                  _("shift amount must be 0 or 8"));
+                 return 0;
+               }
+             if (shift == 0 && (uvalue & 0xff) == 0)
+               {
+                 shift = 8;
+                 uvalue = (int64_t) uvalue / 256;
+               }
+           }
+         mask >>= shift;
+         if ((uvalue & mask) != uvalue && (uvalue | ~mask) != uvalue)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("immediate too big for element size"));
+             return 0;
+           }
+         uvalue = (uvalue - min_value) & mask;
+         if (uvalue > 0xff)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid arithmetic immediate"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ASIMM:
+         min_value = -128;
+         goto sve_aimm;
+
+       case AARCH64_OPND_SVE_I1_HALF_ONE:
+         assert (opnd->imm.is_fp);
+         if (opnd->imm.value != 0x3f000000 && opnd->imm.value != 0x3f800000)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("floating-point value must be 0.5 or 1.0"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_I1_HALF_TWO:
+         assert (opnd->imm.is_fp);
+         if (opnd->imm.value != 0x3f000000 && opnd->imm.value != 0x40000000)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("floating-point value must be 0.5 or 2.0"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_I1_ZERO_ONE:
+         assert (opnd->imm.is_fp);
+         if (opnd->imm.value != 0 && opnd->imm.value != 0x3f800000)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("floating-point value must be 0.0 or 1.0"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_INV_LIMM:
+         {
+           int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
+           uint64_t uimm = ~opnd->imm.value;
+           if (!aarch64_logical_immediate_p (uimm, esize, NULL))
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("immediate out of range"));
+               return 0;
+             }
+         }
+         break;
+
+       case AARCH64_OPND_SVE_LIMM_MOV:
+         {
+           int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
+           uint64_t uimm = opnd->imm.value;
+           if (!aarch64_logical_immediate_p (uimm, esize, NULL))
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("immediate out of range"));
+               return 0;
+             }
+           if (!aarch64_sve_dupm_mov_immediate_p (uimm, esize))
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("invalid replicated MOV immediate"));
+               return 0;
+             }
+         }
+         break;
+
+       case AARCH64_OPND_SVE_PATTERN_SCALED:
+         assert (opnd->shifter.kind == AARCH64_MOD_MUL);
+         if (!value_in_range_p (opnd->shifter.amount, 1, 16))
+           {
+             set_multiplier_out_of_range_error (mismatch_detail, idx, 1, 16);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_SHLIMM_PRED:
+       case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+         size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
+         if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1))
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx,
+                                         0, 8 * size - 1);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_SHRIMM_PRED:
+       case AARCH64_OPND_SVE_SHRIMM_UNPRED:
+         size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
+         if (!value_in_range_p (opnd->imm.value, 1, 8 * size))
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size);
+             return 0;
+           }
+         break;
+
        default:
          break;
        }
        default:
          break;
        }
@@ -1862,6 +2380,16 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        {
        case AARCH64_OPND_PSTATEFIELD:
          assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
        {
        case AARCH64_OPND_PSTATEFIELD:
          assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
+         /* MSR UAO, #uimm4
+            MSR PAN, #uimm4
+            The immediate must be #0 or #1.  */
+         if ((opnd->pstatefield == 0x03        /* UAO.  */
+              || opnd->pstatefield == 0x04)    /* PAN.  */
+             && opnds[1].imm.value > 1)
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
+             return 0;
+           }
          /* MSR SPSel, #uimm4
             Uses uimm4 as a control value to select the stack pointer: if
             bit 0 is set it selects the current exception level's stack
          /* MSR SPSel, #uimm4
             Uses uimm4 as a control value to select the stack pointer: if
             bit 0 is set it selects the current exception level's stack
@@ -2012,6 +2540,23 @@ aarch64_match_operands_constraint (aarch64_inst *inst,
 
   DEBUG_TRACE ("enter");
 
 
   DEBUG_TRACE ("enter");
 
+  /* Check for cases where a source register needs to be the same as the
+     destination register.  Do this before matching qualifiers since if
+     an instruction has both invalid tying and invalid qualifiers,
+     the error about qualifiers would suggest several alternative
+     instructions that also have invalid tying.  */
+  i = inst->opcode->tied_operand;
+  if (i > 0 && (inst->operands[0].reg.regno != inst->operands[i].reg.regno))
+    {
+      if (mismatch_detail)
+       {
+         mismatch_detail->kind = AARCH64_OPDE_UNTIED_OPERAND;
+         mismatch_detail->index = i;
+         mismatch_detail->error = NULL;
+       }
+      return 0;
+    }
+
   /* Match operands' qualifier.
      *INST has already had qualifier establish for some, if not all, of
      its operands; we need to find out whether these established
   /* Match operands' qualifier.
      *INST has already had qualifier establish for some, if not all, of
      its operands; we need to find out whether these established
@@ -2103,33 +2648,37 @@ aarch64_operand_index (const enum aarch64_opnd *operands, enum aarch64_opnd oper
   return -1;
 }
 \f
   return -1;
 }
 \f
+/* R0...R30, followed by FOR31.  */
+#define BANK(R, FOR31) \
+  { R  (0), R  (1), R  (2), R  (3), R  (4), R  (5), R  (6), R  (7), \
+    R  (8), R  (9), R (10), R (11), R (12), R (13), R (14), R (15), \
+    R (16), R (17), R (18), R (19), R (20), R (21), R (22), R (23), \
+    R (24), R (25), R (26), R (27), R (28), R (29), R (30),  FOR31 }
 /* [0][0]  32-bit integer regs with sp   Wn
    [0][1]  64-bit integer regs with sp   Xn  sf=1
    [1][0]  32-bit integer regs with #0   Wn
    [1][1]  64-bit integer regs with #0   Xn  sf=1 */
 static const char *int_reg[2][2][32] = {
 /* [0][0]  32-bit integer regs with sp   Wn
    [0][1]  64-bit integer regs with sp   Xn  sf=1
    [1][0]  32-bit integer regs with #0   Wn
    [1][1]  64-bit integer regs with #0   Xn  sf=1 */
 static const char *int_reg[2][2][32] = {
-#define R32 "w"
-#define R64 "x"
-  { { R32  "0", R32  "1", R32  "2", R32  "3", R32  "4", R32  "5", R32  "6", R32  "7",
-      R32  "8", R32  "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
-      R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
-      R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30",    "wsp" },
-    { R64  "0", R64  "1", R64  "2", R64  "3", R64  "4", R64  "5", R64  "6", R64  "7",
-      R64  "8", R64  "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
-      R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
-      R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30",     "sp" } },
-  { { R32  "0", R32  "1", R32  "2", R32  "3", R32  "4", R32  "5", R32  "6", R32  "7",
-      R32  "8", R32  "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
-      R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
-      R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30", R32 "zr" },
-    { R64  "0", R64  "1", R64  "2", R64  "3", R64  "4", R64  "5", R64  "6", R64  "7",
-      R64  "8", R64  "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
-      R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
-      R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30", R64 "zr" } }
+#define R32(X) "w" #X
+#define R64(X) "x" #X
+  { BANK (R32, "wsp"), BANK (R64, "sp") },
+  { BANK (R32, "wzr"), BANK (R64, "xzr") }
 #undef R64
 #undef R32
 };
 
 #undef R64
 #undef R32
 };
 
+/* Names of the SVE vector registers, first with .S suffixes,
+   then with .D suffixes.  */
+
+static const char *sve_reg[2][32] = {
+#define ZS(X) "z" #X ".s"
+#define ZD(X) "z" #X ".d"
+  BANK (ZS, ZS (31)), BANK (ZD, ZD (31))
+#undef ZD
+#undef ZS
+};
+#undef BANK
+
 /* Return the integer register name.
    if SP_REG_P is not 0, R31 is an SP reg, other R31 is the zero reg.  */
 
 /* Return the integer register name.
    if SP_REG_P is not 0, R31 is an SP reg, other R31 is the zero reg.  */
 
@@ -2150,6 +2699,38 @@ get_64bit_int_reg_name (int regno, int sp_reg_p)
   return int_reg[has_zr][1][regno];
 }
 
   return int_reg[has_zr][1][regno];
 }
 
+/* Get the name of the integer offset register in OPND, using the shift type
+   to decide whether it's a word or doubleword.  */
+
+static inline const char *
+get_offset_int_reg_name (const aarch64_opnd_info *opnd)
+{
+  switch (opnd->shifter.kind)
+    {
+    case AARCH64_MOD_UXTW:
+    case AARCH64_MOD_SXTW:
+      return get_int_reg_name (opnd->addr.offset.regno, AARCH64_OPND_QLF_W, 0);
+
+    case AARCH64_MOD_LSL:
+    case AARCH64_MOD_SXTX:
+      return get_int_reg_name (opnd->addr.offset.regno, AARCH64_OPND_QLF_X, 0);
+
+    default:
+      abort ();
+    }
+}
+
+/* Get the name of the SVE vector offset register in OPND, using the operand
+   qualifier to decide whether the suffix should be .S or .D.  */
+
+static inline const char *
+get_addr_sve_reg_name (int regno, aarch64_opnd_qualifier_t qualifier)
+{
+  assert (qualifier == AARCH64_OPND_QLF_S_S
+         || qualifier == AARCH64_OPND_QLF_S_D);
+  return sve_reg[qualifier == AARCH64_OPND_QLF_S_D][regno];
+}
+
 /* Types for expanding an encoded 8-bit value to a floating-point value.  */
 
 typedef union
 /* Types for expanding an encoded 8-bit value to a floating-point value.  */
 
 typedef union
@@ -2164,14 +2745,22 @@ typedef union
   float    f;
 } single_conv_t;
 
   float    f;
 } single_conv_t;
 
+typedef union
+{
+  uint32_t i;
+  float    f;
+} half_conv_t;
+
 /* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and
    normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8
    (depending on the type of the instruction).  IMM8 will be expanded to a
 /* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and
    normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8
    (depending on the type of the instruction).  IMM8 will be expanded to a
-   single-precision floating-point value (IS_DP == 0) or a double-precision
-   floating-point value (IS_DP == 1).  The expanded value is returned.  */
+   single-precision floating-point value (SIZE == 4) or a double-precision
+   floating-point value (SIZE == 8).  A half-precision floating-point value
+   (SIZE == 2) is expanded to a single-precision floating-point value.  The
+   expanded value is returned.  */
 
 static uint64_t
 
 static uint64_t
-expand_fp_imm (int is_dp, uint32_t imm8)
+expand_fp_imm (int size, uint32_t imm8)
 {
   uint64_t imm;
   uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
 {
   uint64_t imm;
   uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
@@ -2181,7 +2770,7 @@ expand_fp_imm (int is_dp, uint32_t imm8)
   imm8_6 = imm8_6_0 >> 6;      /* imm8<6>   */
   imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2)
     | (imm8_6 << 1) | imm8_6;  /* Replicate(imm8<6>,4) */
   imm8_6 = imm8_6_0 >> 6;      /* imm8<6>   */
   imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2)
     | (imm8_6 << 1) | imm8_6;  /* Replicate(imm8<6>,4) */
-  if (is_dp)
+  if (size == 8)
     {
       imm = (imm8_7 << (63-32))                /* imm8<7>  */
        | ((imm8_6 ^ 1) << (62-32))     /* NOT(imm8<6)  */
     {
       imm = (imm8_7 << (63-32))                /* imm8<7>  */
        | ((imm8_6 ^ 1) << (62-32))     /* NOT(imm8<6)  */
@@ -2190,21 +2779,28 @@ expand_fp_imm (int is_dp, uint32_t imm8)
        | (imm8_6_0 << (48-32));        /* imm8<6>:imm8<5:0>    */
       imm <<= 32;
     }
        | (imm8_6_0 << (48-32));        /* imm8<6>:imm8<5:0>    */
       imm <<= 32;
     }
-  else
+  else if (size == 4 || size == 2)
     {
       imm = (imm8_7 << 31)     /* imm8<7>              */
        | ((imm8_6 ^ 1) << 30)  /* NOT(imm8<6>)         */
        | (imm8_6_repl4 << 26)  /* Replicate(imm8<6>,4) */
        | (imm8_6_0 << 19);     /* imm8<6>:imm8<5:0>    */
     }
     {
       imm = (imm8_7 << 31)     /* imm8<7>              */
        | ((imm8_6 ^ 1) << 30)  /* NOT(imm8<6>)         */
        | (imm8_6_repl4 << 26)  /* Replicate(imm8<6>,4) */
        | (imm8_6_0 << 19);     /* imm8<6>:imm8<5:0>    */
     }
+  else
+    {
+      /* An unsupported size.  */
+      assert (0);
+    }
 
   return imm;
 }
 
 /* Produce the string representation of the register list operand *OPND
 
   return imm;
 }
 
 /* Produce the string representation of the register list operand *OPND
-   in the buffer pointed by BUF of size SIZE.  */
+   in the buffer pointed by BUF of size SIZE.  PREFIX is the part of
+   the register name that comes before the register number, such as "v".  */
 static void
 static void
-print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
+print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
+                    const char *prefix)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
@@ -2217,7 +2813,7 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
 
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
 
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
-    snprintf (tb, 8, "[%d]", opnd->reglist.index);
+    snprintf (tb, 8, "[%" PRIi64 "]", opnd->reglist.index);
   else
     tb[0] = '\0';
 
   else
     tb[0] = '\0';
 
@@ -2225,8 +2821,8 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{v%d.%s-v%d.%s}%s", first_reg, qlf_name,
-             last_reg, qlf_name, tb);
+    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
+             prefix, last_reg, qlf_name, tb);
   else
     {
       const int reg0 = first_reg;
   else
     {
       const int reg0 = first_reg;
@@ -2237,48 +2833,69 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
       switch (num_regs)
        {
        case 1:
       switch (num_regs)
        {
        case 1:
-         snprintf (buf, size, "{v%d.%s}%s", reg0, qlf_name, tb);
+         snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
          break;
        case 2:
          break;
        case 2:
-         snprintf (buf, size, "{v%d.%s, v%d.%s}%s", reg0, qlf_name,
-                   reg1, qlf_name, tb);
+         snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
+                   prefix, reg1, qlf_name, tb);
          break;
        case 3:
          break;
        case 3:
-         snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s}%s", reg0, qlf_name,
-                   reg1, qlf_name, reg2, qlf_name, tb);
+         snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
+                   prefix, reg0, qlf_name, prefix, reg1, qlf_name,
+                   prefix, reg2, qlf_name, tb);
          break;
        case 4:
          break;
        case 4:
-         snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s, v%d.%s}%s",
-                   reg0, qlf_name, reg1, qlf_name, reg2, qlf_name,
-                   reg3, qlf_name, tb);
+         snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
+                   prefix, reg0, qlf_name, prefix, reg1, qlf_name,
+                   prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
          break;
        }
     }
 }
 
          break;
        }
     }
 }
 
+/* Print the register+immediate address in OPND to BUF, which has SIZE
+   characters.  BASE is the name of the base register.  */
+
+static void
+print_immediate_offset_address (char *buf, size_t size,
+                               const aarch64_opnd_info *opnd,
+                               const char *base)
+{
+  if (opnd->addr.writeback)
+    {
+      if (opnd->addr.preind)
+       snprintf (buf, size, "[%s,#%d]!", base, opnd->addr.offset.imm);
+      else
+       snprintf (buf, size, "[%s],#%d", base, opnd->addr.offset.imm);
+    }
+  else
+    {
+      if (opnd->shifter.operator_present)
+       {
+         assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
+         snprintf (buf, size, "[%s,#%d,mul vl]",
+                   base, opnd->addr.offset.imm);
+       }
+      else if (opnd->addr.offset.imm)
+       snprintf (buf, size, "[%s,#%d]", base, opnd->addr.offset.imm);
+      else
+       snprintf (buf, size, "[%s]", base);
+    }
+}
+
 /* Produce the string representation of the register offset address operand
 /* Produce the string representation of the register offset address operand
-   *OPND in the buffer pointed by BUF of size SIZE.  */
+   *OPND in the buffer pointed by BUF of size SIZE.  BASE and OFFSET are
+   the names of the base and offset registers.  */
 static void
 print_register_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
-                              const aarch64_opnd_info *opnd)
+                              const aarch64_opnd_info *opnd,
+                              const char *base, const char *offset)
 {
 {
-  const size_t tblen = 16;
-  char tb[tblen];              /* Temporary buffer.  */
-  bfd_boolean lsl_p = FALSE;   /* Is LSL shift operator?  */
-  bfd_boolean wm_p = FALSE;    /* Should Rm be Wm?  */
+  char tb[16];                 /* Temporary buffer.  */
   bfd_boolean print_extend_p = TRUE;
   bfd_boolean print_amount_p = TRUE;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
 
   bfd_boolean print_extend_p = TRUE;
   bfd_boolean print_amount_p = TRUE;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
 
-  switch (opnd->shifter.kind)
-    {
-    case AARCH64_MOD_UXTW: wm_p = TRUE; break;
-    case AARCH64_MOD_LSL : lsl_p = TRUE; break;
-    case AARCH64_MOD_SXTW: wm_p = TRUE; break;
-    case AARCH64_MOD_SXTX: break;
-    default: assert (0);
-    }
-
   if (!opnd->shifter.amount && (opnd->qualifier != AARCH64_OPND_QLF_S_B
                                || !opnd->shifter.amount_present))
     {
   if (!opnd->shifter.amount && (opnd->qualifier != AARCH64_OPND_QLF_S_B
                                || !opnd->shifter.amount_present))
     {
@@ -2287,7 +2904,7 @@ print_register_offset_address (char *buf, size_t size,
       print_amount_p = FALSE;
       /* Likewise, no need to print the shift operator LSL in such a
         situation.  */
       print_amount_p = FALSE;
       /* Likewise, no need to print the shift operator LSL in such a
         situation.  */
-      if (lsl_p)
+      if (opnd->shifter.kind == AARCH64_MOD_LSL)
        print_extend_p = FALSE;
     }
 
        print_extend_p = FALSE;
     }
 
@@ -2295,19 +2912,15 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
   if (print_extend_p)
     {
       if (print_amount_p)
-       snprintf (tb, tblen, ",%s #%d", shift_name, opnd->shifter.amount);
+       snprintf (tb, sizeof (tb), ",%s #%" PRIi64, shift_name,
+                 opnd->shifter.amount);
       else
       else
-       snprintf (tb, tblen, ",%s", shift_name);
+       snprintf (tb, sizeof (tb), ",%s", shift_name);
     }
   else
     tb[0] = '\0';
 
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s,%s%s]",
-           get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-           get_int_reg_name (opnd->addr.offset.regno,
-                             wm_p ? AARCH64_OPND_QLF_W : AARCH64_OPND_QLF_X,
-                             0 /* sp_reg_p */),
-           tb);
+  snprintf (buf, size, "[%s,%s%s]", base, offset, tb);
 }
 
 /* Generate the string representation of the operand OPNDS[IDX] for OPCODE
 }
 
 /* Generate the string representation of the operand OPNDS[IDX] for OPCODE
@@ -2331,7 +2944,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
   const char *name = NULL;
   const aarch64_opnd_info *opnd = opnds + idx;
   enum aarch64_modifier_kind kind;
   const char *name = NULL;
   const aarch64_opnd_info *opnd = opnds + idx;
   enum aarch64_modifier_kind kind;
-  uint64_t addr;
+  uint64_t addr, enum_value;
 
   buf[0] = '\0';
   if (pcrel_p)
 
   buf[0] = '\0';
   if (pcrel_p)
@@ -2348,6 +2961,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Ra:
     case AARCH64_OPND_Rt_SYS:
     case AARCH64_OPND_PAIRREG:
     case AARCH64_OPND_Ra:
     case AARCH64_OPND_Rt_SYS:
     case AARCH64_OPND_PAIRREG:
+    case AARCH64_OPND_SVE_Rm:
       /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
         the <ic_op>, therefore we we use opnd->present to override the
         generic optional-ness information.  */
       /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
         the <ic_op>, therefore we we use opnd->present to override the
         generic optional-ness information.  */
@@ -2365,6 +2979,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_Rd_SP:
     case AARCH64_OPND_Rn_SP:
 
     case AARCH64_OPND_Rd_SP:
     case AARCH64_OPND_Rn_SP:
+    case AARCH64_OPND_SVE_Rn_SP:
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_WSP
              || opnd->qualifier == AARCH64_OPND_QLF_X
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_WSP
              || opnd->qualifier == AARCH64_OPND_QLF_X
@@ -2395,7 +3010,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
            }
        }
       if (opnd->shifter.amount)
            }
        }
       if (opnd->shifter.amount)
-       snprintf (buf, size, "%s, %s #%d",
+       snprintf (buf, size, "%s, %s #%" PRIi64,
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
                  aarch64_operand_modifiers[kind].name,
                  opnd->shifter.amount);
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
                  aarch64_operand_modifiers[kind].name,
                  opnd->shifter.amount);
@@ -2412,7 +3027,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
        snprintf (buf, size, "%s",
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       else
        snprintf (buf, size, "%s",
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       else
-       snprintf (buf, size, "%s, %s #%d",
+       snprintf (buf, size, "%s, %s #%" PRIi64,
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
                  aarch64_operand_modifiers[opnd->shifter.kind].name,
                  opnd->shifter.amount);
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
                  aarch64_operand_modifiers[opnd->shifter.kind].name,
                  opnd->shifter.amount);
@@ -2427,6 +3042,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Sd:
     case AARCH64_OPND_Sn:
     case AARCH64_OPND_Sm:
     case AARCH64_OPND_Sd:
     case AARCH64_OPND_Sn:
     case AARCH64_OPND_Sm:
+    case AARCH64_OPND_SVE_VZn:
+    case AARCH64_OPND_SVE_Vd:
+    case AARCH64_OPND_SVE_Vm:
+    case AARCH64_OPND_SVE_Vn:
       snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reg.regno);
       break;
       snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reg.regno);
       break;
@@ -2441,7 +3060,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Ed:
     case AARCH64_OPND_En:
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Ed:
     case AARCH64_OPND_En:
     case AARCH64_OPND_Em:
-      snprintf (buf, size, "v%d.%s[%d]", opnd->reglane.regno,
+      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
       break;
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
       break;
@@ -2455,7 +3074,51 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd);
+      print_register_list (buf, size, opnd, "v");
+      break;
+
+    case AARCH64_OPND_SVE_Pd:
+    case AARCH64_OPND_SVE_Pg3:
+    case AARCH64_OPND_SVE_Pg4_5:
+    case AARCH64_OPND_SVE_Pg4_10:
+    case AARCH64_OPND_SVE_Pg4_16:
+    case AARCH64_OPND_SVE_Pm:
+    case AARCH64_OPND_SVE_Pn:
+    case AARCH64_OPND_SVE_Pt:
+      if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+       snprintf (buf, size, "p%d", opnd->reg.regno);
+      else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
+              || opnd->qualifier == AARCH64_OPND_QLF_P_M)
+       snprintf (buf, size, "p%d/%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
+      else
+       snprintf (buf, size, "p%d.%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_Za_5:
+    case AARCH64_OPND_SVE_Za_16:
+    case AARCH64_OPND_SVE_Zd:
+    case AARCH64_OPND_SVE_Zm_5:
+    case AARCH64_OPND_SVE_Zm_16:
+    case AARCH64_OPND_SVE_Zn:
+    case AARCH64_OPND_SVE_Zt:
+      if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+       snprintf (buf, size, "z%d", opnd->reg.regno);
+      else
+       snprintf (buf, size, "z%d.%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_ZnxN:
+    case AARCH64_OPND_SVE_ZtxN:
+      print_register_list (buf, size, opnd, "z");
+      break;
+
+    case AARCH64_OPND_SVE_Zn_INDEX:
+      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+               aarch64_get_qualifier_name (opnd->qualifier),
+               opnd->reglane.index);
       break;
 
     case AARCH64_OPND_Cn:
       break;
 
     case AARCH64_OPND_Cn:
@@ -2476,9 +3139,73 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_IMMR:
     case AARCH64_OPND_IMMS:
     case AARCH64_OPND_FBITS:
     case AARCH64_OPND_IMMR:
     case AARCH64_OPND_IMMS:
     case AARCH64_OPND_FBITS:
+    case AARCH64_OPND_SIMM5:
+    case AARCH64_OPND_SVE_SHLIMM_PRED:
+    case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+    case AARCH64_OPND_SVE_SHRIMM_PRED:
+    case AARCH64_OPND_SVE_SHRIMM_UNPRED:
+    case AARCH64_OPND_SVE_SIMM5:
+    case AARCH64_OPND_SVE_SIMM5B:
+    case AARCH64_OPND_SVE_SIMM6:
+    case AARCH64_OPND_SVE_SIMM8:
+    case AARCH64_OPND_SVE_UIMM3:
+    case AARCH64_OPND_SVE_UIMM7:
+    case AARCH64_OPND_SVE_UIMM8:
+    case AARCH64_OPND_SVE_UIMM8_53:
       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
       break;
 
       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
       break;
 
+    case AARCH64_OPND_SVE_I1_HALF_ONE:
+    case AARCH64_OPND_SVE_I1_HALF_TWO:
+    case AARCH64_OPND_SVE_I1_ZERO_ONE:
+      {
+       single_conv_t c;
+       c.i = opnd->imm.value;
+       snprintf (buf, size, "#%.1f", c.f);
+       break;
+      }
+
+    case AARCH64_OPND_SVE_PATTERN:
+      if (optional_operand_p (opcode, idx)
+         && opnd->imm.value == get_optional_operand_default_value (opcode))
+       break;
+      enum_value = opnd->imm.value;
+      assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
+      if (aarch64_sve_pattern_array[enum_value])
+       snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+      else
+       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      break;
+
+    case AARCH64_OPND_SVE_PATTERN_SCALED:
+      if (optional_operand_p (opcode, idx)
+         && !opnd->shifter.operator_present
+         && opnd->imm.value == get_optional_operand_default_value (opcode))
+       break;
+      enum_value = opnd->imm.value;
+      assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
+      if (aarch64_sve_pattern_array[opnd->imm.value])
+       snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+      else
+       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      if (opnd->shifter.operator_present)
+       {
+         size_t len = strlen (buf);
+         snprintf (buf + len, size - len, ", %s #%" PRIi64,
+                   aarch64_operand_modifiers[opnd->shifter.kind].name,
+                   opnd->shifter.amount);
+       }
+      break;
+
+    case AARCH64_OPND_SVE_PRFOP:
+      enum_value = opnd->imm.value;
+      assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
+      if (aarch64_sve_prfop_array[enum_value])
+       snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+      else
+       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      break;
+
     case AARCH64_OPND_IMM_MOV:
       switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
        {
     case AARCH64_OPND_IMM_MOV:
       switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
        {
@@ -2503,8 +3230,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_LIMM:
     case AARCH64_OPND_AIMM:
     case AARCH64_OPND_HALF:
     case AARCH64_OPND_LIMM:
     case AARCH64_OPND_AIMM:
     case AARCH64_OPND_HALF:
+    case AARCH64_OPND_SVE_INV_LIMM:
+    case AARCH64_OPND_SVE_LIMM:
+    case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
       if (opnd->shifter.amount)
-       snprintf (buf, size, "#0x%" PRIx64 ", lsl #%d", opnd->imm.value,
+       snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
                  opnd->shifter.amount);
       else
        snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
                  opnd->shifter.amount);
       else
        snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
@@ -2516,26 +3246,43 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
          || opnd->shifter.kind == AARCH64_MOD_NONE)
        snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
       else
          || opnd->shifter.kind == AARCH64_MOD_NONE)
        snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
       else
-       snprintf (buf, size, "#0x%" PRIx64 ", %s #%d", opnd->imm.value,
+       snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
                  aarch64_operand_modifiers[opnd->shifter.kind].name,
                  opnd->shifter.amount);
       break;
 
                  aarch64_operand_modifiers[opnd->shifter.kind].name,
                  opnd->shifter.amount);
       break;
 
+    case AARCH64_OPND_SVE_AIMM:
+    case AARCH64_OPND_SVE_ASIMM:
+      if (opnd->shifter.amount)
+       snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
+                 opnd->shifter.amount);
+      else
+       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      break;
+
     case AARCH64_OPND_FPIMM:
     case AARCH64_OPND_SIMD_FPIMM:
     case AARCH64_OPND_FPIMM:
     case AARCH64_OPND_SIMD_FPIMM:
+    case AARCH64_OPND_SVE_FPIMM8:
       switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
        {
       switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
        {
+       case 2: /* e.g. FMOV <Hd>, #<imm>.  */
+           {
+             half_conv_t c;
+             c.i = expand_fp_imm (2, opnd->imm.value);
+             snprintf (buf, size,  "#%.18e", c.f);
+           }
+         break;
        case 4: /* e.g. FMOV <Vd>.4S, #<imm>.  */
            {
              single_conv_t c;
        case 4: /* e.g. FMOV <Vd>.4S, #<imm>.  */
            {
              single_conv_t c;
-             c.i = expand_fp_imm (0, opnd->imm.value);
+             c.i = expand_fp_imm (4, opnd->imm.value);
              snprintf (buf, size,  "#%.18e", c.f);
            }
          break;
        case 8: /* e.g. FMOV <Sd>, #<imm>.  */
            {
              double_conv_t c;
              snprintf (buf, size,  "#%.18e", c.f);
            }
          break;
        case 8: /* e.g. FMOV <Sd>, #<imm>.  */
            {
              double_conv_t c;
-             c.i = expand_fp_imm (1, opnd->imm.value);
+             c.i = expand_fp_imm (8, opnd->imm.value);
              snprintf (buf, size,  "#%.18e", c.d);
            }
          break;
              snprintf (buf, size,  "#%.18e", c.d);
            }
          break;
@@ -2607,27 +3354,69 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
-      print_register_offset_address (buf, size, opnd);
+    case AARCH64_OPND_SVE_ADDR_RR:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+    case AARCH64_OPND_SVE_ADDR_RX:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL3:
+      print_register_offset_address
+       (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+        get_offset_int_reg_name (opnd));
+      break;
+
+    case AARCH64_OPND_SVE_ADDR_RZ:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
+      print_register_offset_address
+       (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+        get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
     case AARCH64_OPND_ADDR_SIMM9:
     case AARCH64_OPND_ADDR_SIMM9_2:
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
     case AARCH64_OPND_ADDR_SIMM9:
     case AARCH64_OPND_ADDR_SIMM9_2:
-      name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
-      if (opnd->addr.writeback)
-       {
-         if (opnd->addr.preind)
-           snprintf (buf, size, "[%s,#%d]!", name, opnd->addr.offset.imm);
-         else
-           snprintf (buf, size, "[%s],#%d", name, opnd->addr.offset.imm);
-       }
-      else
-       {
-         if (opnd->addr.offset.imm)
-           snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
-         else
-           snprintf (buf, size, "[%s]", name);
-       }
+    case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_U6:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x2:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x4:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x8:
+      print_immediate_offset_address
+       (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+      break;
+
+    case AARCH64_OPND_SVE_ADDR_ZI_U5:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
+      print_immediate_offset_address
+       (buf, size, opnd,
+        get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
+    case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
+    case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
+      print_register_offset_address
+       (buf, size, opnd,
+        get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+        get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
@@ -2667,7 +3456,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_DC:
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_DC:
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
-      snprintf (buf, size, "%s", opnd->sysins_op->template);
+      snprintf (buf, size, "%s", opnd->sysins_op->name);
       break;
 
     case AARCH64_OPND_BARRIER:
       break;
 
     case AARCH64_OPND_BARRIER:
@@ -2689,6 +3478,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
        snprintf (buf, size, "#0x%02x", opnd->prfop->value);
       break;
 
        snprintf (buf, size, "#0x%02x", opnd->prfop->value);
       break;
 
+    case AARCH64_OPND_BARRIER_PSB:
+      snprintf (buf, size, "%s", opnd->hint_option->name);
+      break;
+
     default:
       assert (0);
     }
     default:
       assert (0);
     }
@@ -2728,6 +3521,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 #endif
 #define F_ARCHEXT      0x2     /* Architecture dependent system register.  */
 
 #endif
 #define F_ARCHEXT      0x2     /* Architecture dependent system register.  */
 
+#ifdef F_HASXT
+#undef F_HASXT
+#endif
+#define F_HASXT                0x4     /* System instruction register <Xt>
+                                  operand.  */
+
 
 /* TODO there are two more issues need to be resolved
    1. handle read-only and write-only system registers
 
 /* TODO there are two more issues need to be resolved
    1. handle read-only and write-only system registers
@@ -2735,12 +3534,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 const aarch64_sys_reg aarch64_sys_regs [] =
 {
   { "spsr_el1",         CPEN_(0,C0,0), 0 }, /* = spsr_svc */
 const aarch64_sys_reg aarch64_sys_regs [] =
 {
   { "spsr_el1",         CPEN_(0,C0,0), 0 }, /* = spsr_svc */
+  { "spsr_el12",       CPEN_ (5, C0, 0), F_ARCHEXT },
   { "elr_el1",          CPEN_(0,C0,1), 0 },
   { "elr_el1",          CPEN_(0,C0,1), 0 },
+  { "elr_el12",        CPEN_ (5, C0, 1), F_ARCHEXT },
   { "sp_el0",           CPEN_(0,C1,0), 0 },
   { "spsel",            CPEN_(0,C2,0), 0 },
   { "daif",             CPEN_(3,C2,1), 0 },
   { "currentel",        CPEN_(0,C2,2), 0 }, /* RO */
   { "pan",             CPEN_(0,C2,3),  F_ARCHEXT },
   { "sp_el0",           CPEN_(0,C1,0), 0 },
   { "spsel",            CPEN_(0,C2,0), 0 },
   { "daif",             CPEN_(3,C2,1), 0 },
   { "currentel",        CPEN_(0,C2,2), 0 }, /* RO */
   { "pan",             CPEN_(0,C2,3),  F_ARCHEXT },
+  { "uao",             CPEN_ (0, C2, 4), F_ARCHEXT },
   { "nzcv",             CPEN_(3,C2,0), 0 },
   { "fpcr",             CPEN_(3,C4,0), 0 },
   { "fpsr",             CPEN_(3,C4,1), 0 },
   { "nzcv",             CPEN_(3,C2,0), 0 },
   { "fpcr",             CPEN_(3,C4,0), 0 },
   { "fpsr",             CPEN_(3,C4,1), 0 },
@@ -2791,6 +3593,7 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1),    0 }, /* RO */
   { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0),    0 }, /* RO */
   { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1),    0 }, /* RO */
   { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1),    0 }, /* RO */
   { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0),    0 }, /* RO */
   { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1),    0 }, /* RO */
+  { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT }, /* RO */
   { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    0 }, /* RO */
   { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    0 }, /* RO */
   { "clidr_el1",        CPENC(3,1,C0,C0,1),    0 }, /* RO */
   { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    0 }, /* RO */
   { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    0 }, /* RO */
   { "clidr_el1",        CPENC(3,1,C0,C0,1),    0 }, /* RO */
@@ -2800,10 +3603,12 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "sctlr_el1",        CPENC(3,0,C1,C0,0),    0 },
   { "sctlr_el2",        CPENC(3,4,C1,C0,0),    0 },
   { "sctlr_el3",        CPENC(3,6,C1,C0,0),    0 },
   { "sctlr_el1",        CPENC(3,0,C1,C0,0),    0 },
   { "sctlr_el2",        CPENC(3,4,C1,C0,0),    0 },
   { "sctlr_el3",        CPENC(3,6,C1,C0,0),    0 },
+  { "sctlr_el12",      CPENC (3, 5, C1, C0, 0), F_ARCHEXT },
   { "actlr_el1",        CPENC(3,0,C1,C0,1),    0 },
   { "actlr_el2",        CPENC(3,4,C1,C0,1),    0 },
   { "actlr_el3",        CPENC(3,6,C1,C0,1),    0 },
   { "cpacr_el1",        CPENC(3,0,C1,C0,2),    0 },
   { "actlr_el1",        CPENC(3,0,C1,C0,1),    0 },
   { "actlr_el2",        CPENC(3,4,C1,C0,1),    0 },
   { "actlr_el3",        CPENC(3,6,C1,C0,1),    0 },
   { "cpacr_el1",        CPENC(3,0,C1,C0,2),    0 },
+  { "cpacr_el12",      CPENC (3, 5, C1, C0, 2), F_ARCHEXT },
   { "cptr_el2",         CPENC(3,4,C1,C1,2),    0 },
   { "cptr_el3",         CPENC(3,6,C1,C1,2),    0 },
   { "scr_el3",          CPENC(3,6,C1,C1,0),    0 },
   { "cptr_el2",         CPENC(3,4,C1,C1,2),    0 },
   { "cptr_el3",         CPENC(3,6,C1,C1,2),    0 },
   { "scr_el3",          CPENC(3,6,C1,C1,0),    0 },
@@ -2815,36 +3620,56 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "ttbr0_el1",        CPENC(3,0,C2,C0,0),    0 },
   { "ttbr1_el1",        CPENC(3,0,C2,C0,1),    0 },
   { "ttbr0_el2",        CPENC(3,4,C2,C0,0),    0 },
   { "ttbr0_el1",        CPENC(3,0,C2,C0,0),    0 },
   { "ttbr1_el1",        CPENC(3,0,C2,C0,1),    0 },
   { "ttbr0_el2",        CPENC(3,4,C2,C0,0),    0 },
+  { "ttbr1_el2",       CPENC (3, 4, C2, C0, 1), F_ARCHEXT },
   { "ttbr0_el3",        CPENC(3,6,C2,C0,0),    0 },
   { "ttbr0_el3",        CPENC(3,6,C2,C0,0),    0 },
+  { "ttbr0_el12",      CPENC (3, 5, C2, C0, 0), F_ARCHEXT },
+  { "ttbr1_el12",      CPENC (3, 5, C2, C0, 1), F_ARCHEXT },
   { "vttbr_el2",        CPENC(3,4,C2,C1,0),    0 },
   { "tcr_el1",          CPENC(3,0,C2,C0,2),    0 },
   { "tcr_el2",          CPENC(3,4,C2,C0,2),    0 },
   { "tcr_el3",          CPENC(3,6,C2,C0,2),    0 },
   { "vttbr_el2",        CPENC(3,4,C2,C1,0),    0 },
   { "tcr_el1",          CPENC(3,0,C2,C0,2),    0 },
   { "tcr_el2",          CPENC(3,4,C2,C0,2),    0 },
   { "tcr_el3",          CPENC(3,6,C2,C0,2),    0 },
+  { "tcr_el12",                CPENC (3, 5, C2, C0, 2), F_ARCHEXT },
   { "vtcr_el2",         CPENC(3,4,C2,C1,2),    0 },
   { "afsr0_el1",        CPENC(3,0,C5,C1,0),    0 },
   { "afsr1_el1",        CPENC(3,0,C5,C1,1),    0 },
   { "afsr0_el2",        CPENC(3,4,C5,C1,0),    0 },
   { "afsr1_el2",        CPENC(3,4,C5,C1,1),    0 },
   { "afsr0_el3",        CPENC(3,6,C5,C1,0),    0 },
   { "vtcr_el2",         CPENC(3,4,C2,C1,2),    0 },
   { "afsr0_el1",        CPENC(3,0,C5,C1,0),    0 },
   { "afsr1_el1",        CPENC(3,0,C5,C1,1),    0 },
   { "afsr0_el2",        CPENC(3,4,C5,C1,0),    0 },
   { "afsr1_el2",        CPENC(3,4,C5,C1,1),    0 },
   { "afsr0_el3",        CPENC(3,6,C5,C1,0),    0 },
+  { "afsr0_el12",      CPENC (3, 5, C5, C1, 0), F_ARCHEXT },
   { "afsr1_el3",        CPENC(3,6,C5,C1,1),    0 },
   { "afsr1_el3",        CPENC(3,6,C5,C1,1),    0 },
+  { "afsr1_el12",      CPENC (3, 5, C5, C1, 1), F_ARCHEXT },
   { "esr_el1",          CPENC(3,0,C5,C2,0),    0 },
   { "esr_el2",          CPENC(3,4,C5,C2,0),    0 },
   { "esr_el3",          CPENC(3,6,C5,C2,0),    0 },
   { "esr_el1",          CPENC(3,0,C5,C2,0),    0 },
   { "esr_el2",          CPENC(3,4,C5,C2,0),    0 },
   { "esr_el3",          CPENC(3,6,C5,C2,0),    0 },
+  { "esr_el12",                CPENC (3, 5, C5, C2, 0), F_ARCHEXT },
+  { "vsesr_el2",       CPENC (3, 4, C5, C2, 3), F_ARCHEXT }, /* RO */
   { "fpexc32_el2",      CPENC(3,4,C5,C3,0),    0 },
   { "fpexc32_el2",      CPENC(3,4,C5,C3,0),    0 },
+  { "erridr_el1",      CPENC (3, 0, C5, C3, 0), F_ARCHEXT }, /* RO */
+  { "errselr_el1",     CPENC (3, 0, C5, C3, 1), F_ARCHEXT },
+  { "erxfr_el1",       CPENC (3, 0, C5, C4, 0), F_ARCHEXT }, /* RO */
+  { "erxctlr_el1",     CPENC (3, 0, C5, C4, 1), F_ARCHEXT },
+  { "erxstatus_el1",   CPENC (3, 0, C5, C4, 2), F_ARCHEXT },
+  { "erxaddr_el1",     CPENC (3, 0, C5, C4, 3), F_ARCHEXT },
+  { "erxmisc0_el1",    CPENC (3, 0, C5, C5, 0), F_ARCHEXT },
+  { "erxmisc1_el1",    CPENC (3, 0, C5, C5, 1), F_ARCHEXT },
   { "far_el1",          CPENC(3,0,C6,C0,0),    0 },
   { "far_el2",          CPENC(3,4,C6,C0,0),    0 },
   { "far_el3",          CPENC(3,6,C6,C0,0),    0 },
   { "far_el1",          CPENC(3,0,C6,C0,0),    0 },
   { "far_el2",          CPENC(3,4,C6,C0,0),    0 },
   { "far_el3",          CPENC(3,6,C6,C0,0),    0 },
+  { "far_el12",                CPENC (3, 5, C6, C0, 0), F_ARCHEXT },
   { "hpfar_el2",        CPENC(3,4,C6,C0,4),    0 },
   { "par_el1",          CPENC(3,0,C7,C4,0),    0 },
   { "mair_el1",         CPENC(3,0,C10,C2,0),   0 },
   { "mair_el2",         CPENC(3,4,C10,C2,0),   0 },
   { "mair_el3",         CPENC(3,6,C10,C2,0),   0 },
   { "hpfar_el2",        CPENC(3,4,C6,C0,4),    0 },
   { "par_el1",          CPENC(3,0,C7,C4,0),    0 },
   { "mair_el1",         CPENC(3,0,C10,C2,0),   0 },
   { "mair_el2",         CPENC(3,4,C10,C2,0),   0 },
   { "mair_el3",         CPENC(3,6,C10,C2,0),   0 },
+  { "mair_el12",       CPENC (3, 5, C10, C2, 0), F_ARCHEXT },
   { "amair_el1",        CPENC(3,0,C10,C3,0),   0 },
   { "amair_el2",        CPENC(3,4,C10,C3,0),   0 },
   { "amair_el3",        CPENC(3,6,C10,C3,0),   0 },
   { "amair_el1",        CPENC(3,0,C10,C3,0),   0 },
   { "amair_el2",        CPENC(3,4,C10,C3,0),   0 },
   { "amair_el3",        CPENC(3,6,C10,C3,0),   0 },
+  { "amair_el12",      CPENC (3, 5, C10, C3, 0), F_ARCHEXT },
   { "vbar_el1",         CPENC(3,0,C12,C0,0),   0 },
   { "vbar_el2",         CPENC(3,4,C12,C0,0),   0 },
   { "vbar_el3",         CPENC(3,6,C12,C0,0),   0 },
   { "vbar_el1",         CPENC(3,0,C12,C0,0),   0 },
   { "vbar_el2",         CPENC(3,4,C12,C0,0),   0 },
   { "vbar_el3",         CPENC(3,6,C12,C0,0),   0 },
+  { "vbar_el12",       CPENC (3, 5, C12, C0, 0), F_ARCHEXT },
   { "rvbar_el1",        CPENC(3,0,C12,C0,1),   0 }, /* RO */
   { "rvbar_el2",        CPENC(3,4,C12,C0,1),   0 }, /* RO */
   { "rvbar_el3",        CPENC(3,6,C12,C0,1),   0 }, /* RO */
   { "rvbar_el1",        CPENC(3,0,C12,C0,1),   0 }, /* RO */
   { "rvbar_el2",        CPENC(3,4,C12,C0,1),   0 }, /* RO */
   { "rvbar_el3",        CPENC(3,6,C12,C0,1),   0 }, /* RO */
@@ -2852,7 +3677,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "rmr_el2",          CPENC(3,4,C12,C0,2),   0 },
   { "rmr_el3",          CPENC(3,6,C12,C0,2),   0 },
   { "isr_el1",          CPENC(3,0,C12,C1,0),   0 }, /* RO */
   { "rmr_el2",          CPENC(3,4,C12,C0,2),   0 },
   { "rmr_el3",          CPENC(3,6,C12,C0,2),   0 },
   { "isr_el1",          CPENC(3,0,C12,C1,0),   0 }, /* RO */
+  { "disr_el1",                CPENC (3, 0, C12, C1, 1), F_ARCHEXT },
+  { "vdisr_el2",       CPENC (3, 4, C12, C1, 1), F_ARCHEXT },
   { "contextidr_el1",   CPENC(3,0,C13,C0,1),   0 },
   { "contextidr_el1",   CPENC(3,0,C13,C0,1),   0 },
+  { "contextidr_el2",  CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
+  { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
   { "tpidr_el0",        CPENC(3,3,C13,C0,2),   0 },
   { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RO */
   { "tpidr_el1",        CPENC(3,0,C13,C0,4),   0 },
   { "tpidr_el0",        CPENC(3,3,C13,C0,2),   0 },
   { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RO */
   { "tpidr_el1",        CPENC(3,0,C13,C0,4),   0 },
@@ -2864,19 +3693,29 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "cntvct_el0",       CPENC(3,3,C14,C0,2),   0 }, /* RO */
   { "cntvoff_el2",      CPENC(3,4,C14,C0,3),   0 },
   { "cntkctl_el1",      CPENC(3,0,C14,C1,0),   0 },
   { "cntvct_el0",       CPENC(3,3,C14,C0,2),   0 }, /* RO */
   { "cntvoff_el2",      CPENC(3,4,C14,C0,3),   0 },
   { "cntkctl_el1",      CPENC(3,0,C14,C1,0),   0 },
+  { "cntkctl_el12",    CPENC (3, 5, C14, C1, 0), F_ARCHEXT },
   { "cnthctl_el2",      CPENC(3,4,C14,C1,0),   0 },
   { "cntp_tval_el0",    CPENC(3,3,C14,C2,0),   0 },
   { "cnthctl_el2",      CPENC(3,4,C14,C1,0),   0 },
   { "cntp_tval_el0",    CPENC(3,3,C14,C2,0),   0 },
+  { "cntp_tval_el02",  CPENC (3, 5, C14, C2, 0), F_ARCHEXT },
   { "cntp_ctl_el0",     CPENC(3,3,C14,C2,1),   0 },
   { "cntp_ctl_el0",     CPENC(3,3,C14,C2,1),   0 },
+  { "cntp_ctl_el02",   CPENC (3, 5, C14, C2, 1), F_ARCHEXT },
   { "cntp_cval_el0",    CPENC(3,3,C14,C2,2),   0 },
   { "cntp_cval_el0",    CPENC(3,3,C14,C2,2),   0 },
+  { "cntp_cval_el02",  CPENC (3, 5, C14, C2, 2), F_ARCHEXT },
   { "cntv_tval_el0",    CPENC(3,3,C14,C3,0),   0 },
   { "cntv_tval_el0",    CPENC(3,3,C14,C3,0),   0 },
+  { "cntv_tval_el02",  CPENC (3, 5, C14, C3, 0), F_ARCHEXT },
   { "cntv_ctl_el0",     CPENC(3,3,C14,C3,1),   0 },
   { "cntv_ctl_el0",     CPENC(3,3,C14,C3,1),   0 },
+  { "cntv_ctl_el02",   CPENC (3, 5, C14, C3, 1), F_ARCHEXT },
   { "cntv_cval_el0",    CPENC(3,3,C14,C3,2),   0 },
   { "cntv_cval_el0",    CPENC(3,3,C14,C3,2),   0 },
+  { "cntv_cval_el02",  CPENC (3, 5, C14, C3, 2), F_ARCHEXT },
   { "cnthp_tval_el2",   CPENC(3,4,C14,C2,0),   0 },
   { "cnthp_ctl_el2",    CPENC(3,4,C14,C2,1),   0 },
   { "cnthp_cval_el2",   CPENC(3,4,C14,C2,2),   0 },
   { "cntps_tval_el1",   CPENC(3,7,C14,C2,0),   0 },
   { "cntps_ctl_el1",    CPENC(3,7,C14,C2,1),   0 },
   { "cntps_cval_el1",   CPENC(3,7,C14,C2,2),   0 },
   { "cnthp_tval_el2",   CPENC(3,4,C14,C2,0),   0 },
   { "cnthp_ctl_el2",    CPENC(3,4,C14,C2,1),   0 },
   { "cnthp_cval_el2",   CPENC(3,4,C14,C2,2),   0 },
   { "cntps_tval_el1",   CPENC(3,7,C14,C2,0),   0 },
   { "cntps_ctl_el1",    CPENC(3,7,C14,C2,1),   0 },
   { "cntps_cval_el1",   CPENC(3,7,C14,C2,2),   0 },
+  { "cnthv_tval_el2",  CPENC (3, 4, C14, C3, 0), F_ARCHEXT },
+  { "cnthv_ctl_el2",   CPENC (3, 4, C14, C3, 1), F_ARCHEXT },
+  { "cnthv_cval_el2",  CPENC (3, 4, C14, C3, 2), F_ARCHEXT },
   { "dacr32_el2",       CPENC(3,4,C3,C0,0),    0 },
   { "ifsr32_el2",       CPENC(3,4,C5,C0,1),    0 },
   { "teehbr32_el1",     CPENC(2,2,C1,C0,0),    0 },
   { "dacr32_el2",       CPENC(3,4,C3,C0,0),    0 },
   { "ifsr32_el2",       CPENC(3,4,C5,C0,1),    0 },
   { "teehbr32_el1",     CPENC(2,2,C1,C0,0),    0 },
@@ -2963,7 +3802,19 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "dbgclaimset_el1",   CPENC(2,0,C7, C8, 6), 0 },
   { "dbgclaimclr_el1",   CPENC(2,0,C7, C9, 6), 0 },
   { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), 0 },  /* r */
   { "dbgclaimset_el1",   CPENC(2,0,C7, C8, 6), 0 },
   { "dbgclaimclr_el1",   CPENC(2,0,C7, C9, 6), 0 },
   { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), 0 },  /* r */
-
+  { "pmblimitr_el1",    CPENC (3, 0, C9, C10, 0), F_ARCHEXT },  /* rw */
+  { "pmbptr_el1",       CPENC (3, 0, C9, C10, 1), F_ARCHEXT },  /* rw */
+  { "pmbsr_el1",        CPENC (3, 0, C9, C10, 3), F_ARCHEXT },  /* rw */
+  { "pmbidr_el1",       CPENC (3, 0, C9, C10, 7), F_ARCHEXT },  /* ro */
+  { "pmscr_el1",        CPENC (3, 0, C9, C9, 0),  F_ARCHEXT },  /* rw */
+  { "pmsicr_el1",       CPENC (3, 0, C9, C9, 2),  F_ARCHEXT },  /* rw */
+  { "pmsirr_el1",       CPENC (3, 0, C9, C9, 3),  F_ARCHEXT },  /* rw */
+  { "pmsfcr_el1",       CPENC (3, 0, C9, C9, 4),  F_ARCHEXT },  /* rw */
+  { "pmsevfr_el1",      CPENC (3, 0, C9, C9, 5),  F_ARCHEXT },  /* rw */
+  { "pmslatfr_el1",     CPENC (3, 0, C9, C9, 6),  F_ARCHEXT },  /* rw */
+  { "pmsidr_el1",       CPENC (3, 0, C9, C9, 7),  F_ARCHEXT },  /* ro */
+  { "pmscr_el2",        CPENC (3, 4, C9, C9, 0),  F_ARCHEXT },  /* rw */
+  { "pmscr_el12",       CPENC (3, 5, C9, C9, 0),  F_ARCHEXT },  /* rw */
   { "pmcr_el0",          CPENC(3,3,C9,C12, 0), 0 },
   { "pmcntenset_el0",    CPENC(3,3,C9,C12, 1), 0 },
   { "pmcntenclr_el0",    CPENC(3,3,C9,C12, 2), 0 },
   { "pmcr_el0",          CPENC(3,3,C9,C12, 0), 0 },
   { "pmcntenset_el0",    CPENC(3,3,C9,C12, 1), 0 },
   { "pmcntenclr_el0",    CPENC(3,3,C9,C12, 2), 0 },
@@ -3063,6 +3914,98 @@ aarch64_sys_reg_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
     return FALSE;
 
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
     return FALSE;
 
+  /* Virtualization host extensions: system registers.  */
+  if ((reg->value == CPENC (3, 4, C2, C0, 1)
+       || reg->value == CPENC (3, 4, C13, C0, 1)
+       || reg->value == CPENC (3, 4, C14, C3, 0)
+       || reg->value == CPENC (3, 4, C14, C3, 1)
+       || reg->value == CPENC (3, 4, C14, C3, 2))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
+      return FALSE;
+
+  /* Virtualization host extensions: *_el12 names of *_el1 registers.  */
+  if ((reg->value == CPEN_ (5, C0, 0)
+       || reg->value == CPEN_ (5, C0, 1)
+       || reg->value == CPENC (3, 5, C1, C0, 0)
+       || reg->value == CPENC (3, 5, C1, C0, 2)
+       || reg->value == CPENC (3, 5, C2, C0, 0)
+       || reg->value == CPENC (3, 5, C2, C0, 1)
+       || reg->value == CPENC (3, 5, C2, C0, 2)
+       || reg->value == CPENC (3, 5, C5, C1, 0)
+       || reg->value == CPENC (3, 5, C5, C1, 1)
+       || reg->value == CPENC (3, 5, C5, C2, 0)
+       || reg->value == CPENC (3, 5, C6, C0, 0)
+       || reg->value == CPENC (3, 5, C10, C2, 0)
+       || reg->value == CPENC (3, 5, C10, C3, 0)
+       || reg->value == CPENC (3, 5, C12, C0, 0)
+       || reg->value == CPENC (3, 5, C13, C0, 1)
+       || reg->value == CPENC (3, 5, C14, C1, 0))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
+    return FALSE;
+
+  /* Virtualization host extensions: *_el02 names of *_el0 registers.  */
+  if ((reg->value == CPENC (3, 5, C14, C2, 0)
+       || reg->value == CPENC (3, 5, C14, C2, 1)
+       || reg->value == CPENC (3, 5, C14, C2, 2)
+       || reg->value == CPENC (3, 5, C14, C3, 0)
+       || reg->value == CPENC (3, 5, C14, C3, 1)
+       || reg->value == CPENC (3, 5, C14, C3, 2))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
+    return FALSE;
+
+  /* ARMv8.2 features.  */
+
+  /* ID_AA64MMFR2_EL1.  */
+  if (reg->value == CPENC (3, 0, C0, C7, 2)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
+    return FALSE;
+
+  /* PSTATE.UAO.  */
+  if (reg->value == CPEN_ (0, C2, 4)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
+    return FALSE;
+
+  /* RAS extension.  */
+
+  /* ERRIDR_EL1, ERRSELR_EL1, ERXFR_EL1, ERXCTLR_EL1, ERXSTATUS_EL, ERXADDR_EL1,
+     ERXMISC0_EL1 AND ERXMISC1_EL1.  */
+  if ((reg->value == CPENC (3, 0, C5, C3, 0)
+       || reg->value == CPENC (3, 0, C5, C3, 1)
+       || reg->value == CPENC (3, 0, C5, C3, 2)
+       || reg->value == CPENC (3, 0, C5, C3, 3)
+       || reg->value == CPENC (3, 0, C5, C4, 0)
+       || reg->value == CPENC (3, 0, C5, C4, 1)
+       || reg->value == CPENC (3, 0, C5, C4, 2)
+       || reg->value == CPENC (3, 0, C5, C4, 3)
+       || reg->value == CPENC (3, 0, C5, C5, 0)
+       || reg->value == CPENC (3, 0, C5, C5, 1))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RAS))
+    return FALSE;
+
+  /* VSESR_EL2, DISR_EL1 and VDISR_EL2.  */
+  if ((reg->value == CPENC (3, 4, C5, C2, 3)
+       || reg->value == CPENC (3, 0, C12, C1, 1)
+       || reg->value == CPENC (3, 4, C12, C1, 1))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RAS))
+    return FALSE;
+
+  /* Statistical Profiling extension.  */
+  if ((reg->value == CPENC (3, 0, C9, C10, 0)
+       || reg->value == CPENC (3, 0, C9, C10, 1)
+       || reg->value == CPENC (3, 0, C9, C10, 3)
+       || reg->value == CPENC (3, 0, C9, C10, 7)
+       || reg->value == CPENC (3, 0, C9, C9, 0)
+       || reg->value == CPENC (3, 0, C9, C9, 2)
+       || reg->value == CPENC (3, 0, C9, C9, 3)
+       || reg->value == CPENC (3, 0, C9, C9, 4)
+       || reg->value == CPENC (3, 0, C9, C9, 5)
+       || reg->value == CPENC (3, 0, C9, C9, 6)
+       || reg->value == CPENC (3, 0, C9, C9, 7)
+       || reg->value == CPENC (3, 4, C9, C9, 0)
+       || reg->value == CPENC (3, 5, C9, C9, 0))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PROFILE))
+    return FALSE;
+
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -3072,6 +4015,7 @@ const aarch64_sys_reg aarch64_pstatefields [] =
   { "daifset",          0x1e,  0 },
   { "daifclr",          0x1f,  0 },
   { "pan",             0x04,   F_ARCHEXT },
   { "daifset",          0x1e,  0 },
   { "daifclr",          0x1f,  0 },
   { "pan",             0x04,   F_ARCHEXT },
+  { "uao",             0x03,   F_ARCHEXT },
   { 0,          CPENC(0,0,0,0,0), 0 },
 };
 
   { 0,          CPENC(0,0,0,0,0), 0 },
 };
 
@@ -3087,6 +4031,11 @@ aarch64_pstatefield_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
     return FALSE;
 
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
     return FALSE;
 
+  /* UAO.  Values are from aarch64_pstatefields.  */
+  if (reg->value == 0x03
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
+    return FALSE;
+
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -3094,77 +4043,107 @@ const aarch64_sys_ins_reg aarch64_sys_regs_ic[] =
 {
     { "ialluis", CPENS(0,C7,C1,0), 0 },
     { "iallu",   CPENS(0,C7,C5,0), 0 },
 {
     { "ialluis", CPENS(0,C7,C1,0), 0 },
     { "iallu",   CPENS(0,C7,C5,0), 0 },
-    { "ivau",    CPENS(3,C7,C5,1), 1 },
+    { "ivau",    CPENS (3, C7, C5, 1), F_HASXT },
     { 0, CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
 {
     { 0, CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
 {
-    { "zva",        CPENS(3,C7,C4,1),  1 },
-    { "ivac",       CPENS(0,C7,C6,1),  1 },
-    { "isw",        CPENS(0,C7,C6,2),  1 },
-    { "cvac",       CPENS(3,C7,C10,1), 1 },
-    { "csw",        CPENS(0,C7,C10,2), 1 },
-    { "cvau",       CPENS(3,C7,C11,1), 1 },
-    { "civac",      CPENS(3,C7,C14,1), 1 },
-    { "cisw",       CPENS(0,C7,C14,2), 1 },
+    { "zva",       CPENS (3, C7, C4, 1),  F_HASXT },
+    { "ivac",       CPENS (0, C7, C6, 1),  F_HASXT },
+    { "isw",       CPENS (0, C7, C6, 2),  F_HASXT },
+    { "cvac",       CPENS (3, C7, C10, 1), F_HASXT },
+    { "csw",       CPENS (0, C7, C10, 2), F_HASXT },
+    { "cvau",       CPENS (3, C7, C11, 1), F_HASXT },
+    { "cvap",       CPENS (3, C7, C12, 1), F_HASXT | F_ARCHEXT },
+    { "civac",      CPENS (3, C7, C14, 1), F_HASXT },
+    { "cisw",       CPENS (0, C7, C14, 2), F_HASXT },
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_at[] =
 {
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_at[] =
 {
-    { "s1e1r",      CPENS(0,C7,C8,0), 1 },
-    { "s1e1w",      CPENS(0,C7,C8,1), 1 },
-    { "s1e0r",      CPENS(0,C7,C8,2), 1 },
-    { "s1e0w",      CPENS(0,C7,C8,3), 1 },
-    { "s12e1r",     CPENS(4,C7,C8,4), 1 },
-    { "s12e1w",     CPENS(4,C7,C8,5), 1 },
-    { "s12e0r",     CPENS(4,C7,C8,6), 1 },
-    { "s12e0w",     CPENS(4,C7,C8,7), 1 },
-    { "s1e2r",      CPENS(4,C7,C8,0), 1 },
-    { "s1e2w",      CPENS(4,C7,C8,1), 1 },
-    { "s1e3r",      CPENS(6,C7,C8,0), 1 },
-    { "s1e3w",      CPENS(6,C7,C8,1), 1 },
+    { "s1e1r",      CPENS (0, C7, C8, 0), F_HASXT },
+    { "s1e1w",      CPENS (0, C7, C8, 1), F_HASXT },
+    { "s1e0r",      CPENS (0, C7, C8, 2), F_HASXT },
+    { "s1e0w",      CPENS (0, C7, C8, 3), F_HASXT },
+    { "s12e1r",     CPENS (4, C7, C8, 4), F_HASXT },
+    { "s12e1w",     CPENS (4, C7, C8, 5), F_HASXT },
+    { "s12e0r",     CPENS (4, C7, C8, 6), F_HASXT },
+    { "s12e0w",     CPENS (4, C7, C8, 7), F_HASXT },
+    { "s1e2r",      CPENS (4, C7, C8, 0), F_HASXT },
+    { "s1e2w",      CPENS (4, C7, C8, 1), F_HASXT },
+    { "s1e3r",      CPENS (6, C7, C8, 0), F_HASXT },
+    { "s1e3w",      CPENS (6, C7, C8, 1), F_HASXT },
+    { "s1e1rp",     CPENS (0, C7, C9, 0), F_HASXT | F_ARCHEXT },
+    { "s1e1wp",     CPENS (0, C7, C9, 1), F_HASXT | F_ARCHEXT },
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
 {
     { "vmalle1",   CPENS(0,C8,C7,0), 0 },
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
 const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
 {
     { "vmalle1",   CPENS(0,C8,C7,0), 0 },
-    { "vae1",      CPENS(0,C8,C7,1), 1 },
-    { "aside1",    CPENS(0,C8,C7,2), 1 },
-    { "vaae1",     CPENS(0,C8,C7,3), 1 },
+    { "vae1",      CPENS (0, C8, C7, 1), F_HASXT },
+    { "aside1",    CPENS (0, C8, C7, 2), F_HASXT },
+    { "vaae1",     CPENS (0, C8, C7, 3), F_HASXT },
     { "vmalle1is", CPENS(0,C8,C3,0), 0 },
     { "vmalle1is", CPENS(0,C8,C3,0), 0 },
-    { "vae1is",    CPENS(0,C8,C3,1), 1 },
-    { "aside1is",  CPENS(0,C8,C3,2), 1 },
-    { "vaae1is",   CPENS(0,C8,C3,3), 1 },
-    { "ipas2e1is", CPENS(4,C8,C0,1), 1 },
-    { "ipas2le1is",CPENS(4,C8,C0,5), 1 },
-    { "ipas2e1",   CPENS(4,C8,C4,1), 1 },
-    { "ipas2le1",  CPENS(4,C8,C4,5), 1 },
-    { "vae2",      CPENS(4,C8,C7,1), 1 },
-    { "vae2is",    CPENS(4,C8,C3,1), 1 },
+    { "vae1is",    CPENS (0, C8, C3, 1), F_HASXT },
+    { "aside1is",  CPENS (0, C8, C3, 2), F_HASXT },
+    { "vaae1is",   CPENS (0, C8, C3, 3), F_HASXT },
+    { "ipas2e1is", CPENS (4, C8, C0, 1), F_HASXT },
+    { "ipas2le1is",CPENS (4, C8, C0, 5), F_HASXT },
+    { "ipas2e1",   CPENS (4, C8, C4, 1), F_HASXT },
+    { "ipas2le1",  CPENS (4, C8, C4, 5), F_HASXT },
+    { "vae2",      CPENS (4, C8, C7, 1), F_HASXT },
+    { "vae2is",    CPENS (4, C8, C3, 1), F_HASXT },
     { "vmalls12e1",CPENS(4,C8,C7,6), 0 },
     { "vmalls12e1is",CPENS(4,C8,C3,6), 0 },
     { "vmalls12e1",CPENS(4,C8,C7,6), 0 },
     { "vmalls12e1is",CPENS(4,C8,C3,6), 0 },
-    { "vae3",      CPENS(6,C8,C7,1), 1 },
-    { "vae3is",    CPENS(6,C8,C3,1), 1 },
+    { "vae3",      CPENS (6, C8, C7, 1), F_HASXT },
+    { "vae3is",    CPENS (6, C8, C3, 1), F_HASXT },
     { "alle2",     CPENS(4,C8,C7,0), 0 },
     { "alle2is",   CPENS(4,C8,C3,0), 0 },
     { "alle1",     CPENS(4,C8,C7,4), 0 },
     { "alle1is",   CPENS(4,C8,C3,4), 0 },
     { "alle3",     CPENS(6,C8,C7,0), 0 },
     { "alle3is",   CPENS(6,C8,C3,0), 0 },
     { "alle2",     CPENS(4,C8,C7,0), 0 },
     { "alle2is",   CPENS(4,C8,C3,0), 0 },
     { "alle1",     CPENS(4,C8,C7,4), 0 },
     { "alle1is",   CPENS(4,C8,C3,4), 0 },
     { "alle3",     CPENS(6,C8,C7,0), 0 },
     { "alle3is",   CPENS(6,C8,C3,0), 0 },
-    { "vale1is",   CPENS(0,C8,C3,5), 1 },
-    { "vale2is",   CPENS(4,C8,C3,5), 1 },
-    { "vale3is",   CPENS(6,C8,C3,5), 1 },
-    { "vaale1is",  CPENS(0,C8,C3,7), 1 },
-    { "vale1",     CPENS(0,C8,C7,5), 1 },
-    { "vale2",     CPENS(4,C8,C7,5), 1 },
-    { "vale3",     CPENS(6,C8,C7,5), 1 },
-    { "vaale1",    CPENS(0,C8,C7,7), 1 },
+    { "vale1is",   CPENS (0, C8, C3, 5), F_HASXT },
+    { "vale2is",   CPENS (4, C8, C3, 5), F_HASXT },
+    { "vale3is",   CPENS (6, C8, C3, 5), F_HASXT },
+    { "vaale1is",  CPENS (0, C8, C3, 7), F_HASXT },
+    { "vale1",     CPENS (0, C8, C7, 5), F_HASXT },
+    { "vale2",     CPENS (4, C8, C7, 5), F_HASXT },
+    { "vale3",     CPENS (6, C8, C7, 5), F_HASXT },
+    { "vaale1",    CPENS (0, C8, C7, 7), F_HASXT },
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
+bfd_boolean
+aarch64_sys_ins_reg_has_xt (const aarch64_sys_ins_reg *sys_ins_reg)
+{
+  return (sys_ins_reg->flags & F_HASXT) != 0;
+}
+
+extern bfd_boolean
+aarch64_sys_ins_reg_supported_p (const aarch64_feature_set features,
+                                const aarch64_sys_ins_reg *reg)
+{
+  if (!(reg->flags & F_ARCHEXT))
+    return TRUE;
+
+  /* DC CVAP.  Values are from aarch64_sys_regs_dc.  */
+  if (reg->value == CPENS (3, C7, C12, 1)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
+    return FALSE;
+
+  /* AT S1E1RP, AT S1E1WP.  Values are from aarch64_sys_regs_at.  */
+  if ((reg->value == CPENS (0, C7, C9, 0)
+       || reg->value == CPENS (0, C7, C9, 1))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
+    return FALSE;
+
+  return TRUE;
+}
+
 #undef C0
 #undef C1
 #undef C2
 #undef C0
 #undef C1
 #undef C2
@@ -3182,6 +4161,62 @@ const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
 #undef C14
 #undef C15
 
 #undef C14
 #undef C15
 
+#define BIT(INSN,BT)     (((INSN) >> (BT)) & 1)
+#define BITS(INSN,HI,LO) (((INSN) >> (LO)) & ((1 << (((HI) - (LO)) + 1)) - 1))
+
+static bfd_boolean
+verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED,
+             const aarch64_insn insn)
+{
+  int t  = BITS (insn, 4, 0);
+  int n  = BITS (insn, 9, 5);
+  int t2 = BITS (insn, 14, 10);
+
+  if (BIT (insn, 23))
+    {
+      /* Write back enabled.  */
+      if ((t == n || t2 == n) && n != 31)
+       return FALSE;
+    }
+
+  if (BIT (insn, 22))
+    {
+      /* Load */
+      if (t == t2)
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Return true if VALUE cannot be moved into an SVE register using DUP
+   (with any element size, not just ESIZE) and if using DUPM would
+   therefore be OK.  ESIZE is the number of bytes in the immediate.  */
+
+bfd_boolean
+aarch64_sve_dupm_mov_immediate_p (uint64_t uvalue, int esize)
+{
+  int64_t svalue = uvalue;
+  uint64_t upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
+
+  if ((uvalue & ~upper) != uvalue && (uvalue | upper) != uvalue)
+    return FALSE;
+  if (esize <= 4 || (uint32_t) uvalue == (uint32_t) (uvalue >> 32))
+    {
+      svalue = (int32_t) uvalue;
+      if (esize <= 2 || (uint16_t) uvalue == (uint16_t) (uvalue >> 16))
+       {
+         svalue = (int16_t) uvalue;
+         if (esize == 1 || (uint8_t) uvalue == (uint8_t) (uvalue >> 8))
+           return FALSE;
+       }
+    }
+  if ((svalue & 0xff) == 0)
+    svalue /= 256;
+  return svalue < -128 || svalue >= 128;
+}
+
 /* Include the opcode description table as well as the operand description
    table.  */
 /* Include the opcode description table as well as the operand description
    table.  */
+#define VERIFIER(x) verify_##x
 #include "aarch64-tbl.h"
 #include "aarch64-tbl.h"
This page took 0.04679 seconds and 4 git commands to generate.