ubsan: aarch64: left shift cannot be represented in type 'int64_t'
[deliverable/binutils-gdb.git] / opcodes / aarch64-opc.c
index 7a73c7e409fa01364b143318fcd01dff47d60d87..25665137761e7d114d87a8d8ab871b3608004327 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-opc.c -- AArch64 opcode support.
 /* aarch64-opc.c -- AArch64 opcode support.
-   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 2009-2019 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.
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <stdint.h>
+#include "bfd_stdint.h"
 #include <stdarg.h>
 #include <inttypes.h>
 
 #include "opintl.h"
 #include <stdarg.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.  */
 
@@ -175,7 +240,10 @@ const aarch64_field fields[] =
     { 22,  2 },        /* type: floating point type field in fp data inst.  */
     { 30,  2 },        /* ldst_size: size field in ld/st reg offset inst.  */
     { 10,  6 },        /* imm6: in add/sub reg shifted instructions.  */
     { 22,  2 },        /* type: floating point type field in fp data inst.  */
     { 30,  2 },        /* ldst_size: size field in ld/st reg offset inst.  */
     { 10,  6 },        /* imm6: in add/sub reg shifted instructions.  */
+    { 15,  6 },        /* imm6_2: in rmif instructions.  */
     { 11,  4 },        /* imm4: in advsimd ext and advsimd ins instructions.  */
     { 11,  4 },        /* imm4: in advsimd ext and advsimd ins instructions.  */
+    {  0,  4 },        /* imm4_2: in rmif instructions.  */
+    { 10,  4 },        /* imm4_3: in adddg/subg instructions.  */
     { 16,  5 },        /* imm5: in conditional compare (immediate) instructions.  */
     { 15,  7 },        /* imm7: in load/store pair pre/post index instructions.  */
     { 13,  8 },        /* imm8: in floating-point scalar move immediate inst.  */
     { 16,  5 },        /* imm5: in conditional compare (immediate) instructions.  */
     { 15,  7 },        /* imm7: in load/store pair pre/post index instructions.  */
     { 13,  8 },        /* imm8: in floating-point scalar move immediate inst.  */
@@ -188,6 +256,7 @@ const aarch64_field fields[] =
     { 16,  6 },        /* immr: in bitfield and logical immediate instructions.  */
     { 16,  3 },        /* immb: in advsimd shift by immediate instructions.  */
     { 19,  4 },        /* immh: in advsimd shift by immediate instructions.  */
     { 16,  6 },        /* immr: in bitfield and logical immediate instructions.  */
     { 16,  3 },        /* immb: in advsimd shift by immediate instructions.  */
     { 19,  4 },        /* immh: in advsimd shift by immediate instructions.  */
+    { 22,  1 },        /* S: in LDRAA and LDRAB instructions.  */
     { 22,  1 },        /* N: in logical (immediate) instructions.  */
     { 11,  1 },        /* index: in ld/st inst deciding the pre/post-index.  */
     { 24,  1 },        /* index2: in ld/st pair inst deciding the pre/post-index.  */
     { 22,  1 },        /* N: in logical (immediate) instructions.  */
     { 11,  1 },        /* index: in ld/st inst deciding the pre/post-index.  */
     { 24,  1 },        /* index2: in ld/st pair inst deciding the pre/post-index.  */
@@ -199,6 +268,65 @@ 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.  */
+    { 22,  1 }, /* SVE_i3h: high bit of 3-bit immediate.  */
+    { 11,  1 }, /* SVE_i3l: low bit of 3-bit immediate.  */
+    { 19,  2 }, /* SVE_i3h2: two high bits of 3bit immediate, bits [20,19].  */
+    { 20,  1 }, /* SVE_i2h: high bit of 2bit immediate, bits.  */
+    { 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].  */
+    { 16,  1 }, /* SVE_rot1: 1-bit rotation amount.  */
+    { 10,  2 }, /* SVE_rot2: 2-bit rotation amount.  */
+    { 10,  1 }, /* SVE_rot3: 1-bit rotation amount at bit 10.  */
+    { 22,  1 }, /* SVE_sz: 1-bit element size select.  */
+    { 17,  2 }, /* SVE_size: 2-bit element size, bits [18,17].  */
+    { 30,  1 }, /* SVE_sz2: 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).  */
+    { 11,  2 }, /* rotate1: FCMLA immediate rotate.  */
+    { 13,  2 }, /* rotate2: Indexed element FCMLA immediate rotate.  */
+    { 12,  1 }, /* rotate3: FCADD immediate rotate.  */
+    { 12,  2 }, /* SM3: Indexed element SM3 2 bits index immediate.  */
+    { 22,  1 }, /* sz: 1-bit element size select.  */
 };
 
 enum aarch64_operand_class
 };
 
 enum aarch64_operand_class
@@ -224,18 +352,18 @@ aarch64_get_operand_desc (enum aarch64_opnd type)
 /* Table of all conditional affixes.  */
 const aarch64_cond aarch64_conds[16] =
 {
 /* Table of all conditional affixes.  */
 const aarch64_cond aarch64_conds[16] =
 {
-  {{"eq"}, 0x0},
-  {{"ne"}, 0x1},
-  {{"cs", "hs"}, 0x2},
-  {{"cc", "lo", "ul"}, 0x3},
-  {{"mi"}, 0x4},
-  {{"pl"}, 0x5},
+  {{"eq", "none"}, 0x0},
+  {{"ne", "any"}, 0x1},
+  {{"cs", "hs", "nlast"}, 0x2},
+  {{"cc", "lo", "ul", "last"}, 0x3},
+  {{"mi", "first"}, 0x4},
+  {{"pl", "nfrst"}, 0x5},
   {{"vs"}, 0x6},
   {{"vc"}, 0x7},
   {{"vs"}, 0x6},
   {{"vc"}, 0x7},
-  {{"hi"}, 0x8},
-  {{"ls"}, 0x9},
-  {{"ge"}, 0xa},
-  {{"lt"}, 0xb},
+  {{"hi", "pmore"}, 0x8},
+  {{"ls", "plast"}, 0x9},
+  {{"ge", "tcont"}, 0xa},
+  {{"lt", "tstop"}, 0xb},
   {{"gt"}, 0xc},
   {{"le"}, 0xd},
   {{"al"}, 0xe},
   {{"gt"}, 0xc},
   {{"le"}, 0xd},
   {{"al"}, 0xe},
@@ -276,6 +404,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},
 };
 
@@ -344,8 +474,13 @@ const struct aarch64_name_value_pair aarch64_barrier_options[16] =
 
 const struct aarch64_name_value_pair aarch64_hint_options[] =
 {
 
 const struct aarch64_name_value_pair aarch64_hint_options[] =
 {
-  { "csync", 0x11 },    /* PSB CSYNC.  */
-  { NULL, 0x0 },
+  /* BTI.  This is also the F_DEFAULT entry for AARCH64_OPND_BTI_TARGET.  */
+  { " ",       HINT_ENCODE (HINT_OPD_F_NOPRINT, 0x20) },
+  { "csync",   HINT_OPD_CSYNC },       /* PSB CSYNC.  */
+  { "c",       HINT_OPD_C },           /* BTI C.  */
+  { "j",       HINT_OPD_J },           /* BTI J.  */
+  { "jc",      HINT_OPD_JC },          /* BTI JC.  */
+  { NULL,      HINT_OPD_NULL },
 };
 
 /* op -> op:       load = 0 instruction = 1 store = 2
 };
 
 /* op -> op:       load = 0 instruction = 1 store = 2
@@ -397,10 +532,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.  */
@@ -410,7 +546,7 @@ value_fit_signed_field_p (int64_t value, unsigned width)
   assert (width < 32);
   if (width < sizeof (value) * 8)
     {
   assert (width < 32);
   if (width < sizeof (value) * 8)
     {
-      int64_t lim = (int64_t)1 << (width - 1);
+      int64_t lim = (uint64_t) 1 << (width - 1);
       if (value >= -lim && value < lim)
        return 1;
     }
       if (value >= -lim && value < lim)
        return 1;
     }
@@ -424,7 +560,7 @@ value_fit_unsigned_field_p (int64_t value, unsigned width)
   assert (width < 32);
   if (width < sizeof (value) * 8)
     {
   assert (width < 32);
   if (width < sizeof (value) * 8)
     {
-      int64_t lim = (int64_t)1 << width;
+      int64_t lim = (uint64_t) 1 << width;
       if (value >= 0 && value < lim)
        return 1;
     }
       if (value >= 0 && value < lim)
        return 1;
     }
@@ -575,7 +711,10 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
   {4, 1, 0x2, "s", OQK_OPD_VARIANT},
   {8, 1, 0x3, "d", OQK_OPD_VARIANT},
   {16, 1, 0x4, "q", OQK_OPD_VARIANT},
   {4, 1, 0x2, "s", OQK_OPD_VARIANT},
   {8, 1, 0x3, "d", OQK_OPD_VARIANT},
   {16, 1, 0x4, "q", OQK_OPD_VARIANT},
+  {4, 1, 0x0, "4b", OQK_OPD_VARIANT},
+  {4, 1, 0x0, "2h", OQK_OPD_VARIANT},
 
 
+  {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
   {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
   {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
   {2, 2, 0x0, "2h", OQK_OPD_VARIANT},
   {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
   {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
   {2, 2, 0x0, "2h", OQK_OPD_VARIANT},
@@ -587,10 +726,17 @@ 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},
+
+  /* Qualifier for scaled immediate for Tag granule (stg,st2g,etc).  */
+  {16, 0, 0, "tag", 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.  */
 
+  {0, 15, 0, "CR",       OQK_VALUE_IN_RANGE},
   {0,  7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
   {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
   {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
   {0,  7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
   {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
   {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
@@ -703,6 +849,25 @@ dump_match_qualifiers (const struct aarch64_opnd_info *opnd,
 }
 #endif /* DEBUG_AARCH64 */
 
 }
 #endif /* DEBUG_AARCH64 */
 
+/* This function checks if the given instruction INSN is a destructive
+   instruction based on the usage of the registers.  It does not recognize
+   unary destructive instructions.  */
+bfd_boolean
+aarch64_is_destructive_by_operands (const aarch64_opcode *opcode)
+{
+  int i = 0;
+  const enum aarch64_opnd *opnds = opcode->operands;
+
+  if (opnds[0] == AARCH64_OPND_NIL)
+    return FALSE;
+
+  while (opnds[++i] != AARCH64_OPND_NIL)
+    if (opnds[i] == opnds[0])
+      return TRUE;
+
+  return FALSE;
+}
+
 /* TODO improve this, we can have an extra field at the runtime to
    store the number of operands rather than calculating it every time.  */
 
 /* TODO improve this, we can have an extra field at the runtime to
    store the number of operands rather than calculating it every time.  */
 
@@ -898,7 +1063,7 @@ match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
    amount will be returned in *SHIFT_AMOUNT.  */
 
 bfd_boolean
    amount will be returned in *SHIFT_AMOUNT.  */
 
 bfd_boolean
-aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
+aarch64_wide_constant_p (uint64_t value, int is32, unsigned int *shift_amount)
 {
   int amount;
 
 {
   int amount;
 
@@ -909,22 +1074,21 @@ aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
       /* Allow all zeros or all ones in top 32-bits, so that
         32-bit constant expressions like ~0x80000000 are
         permitted.  */
       /* Allow all zeros or all ones in top 32-bits, so that
         32-bit constant expressions like ~0x80000000 are
         permitted.  */
-      uint64_t ext = value;
-      if (ext >> 32 != 0 && ext >> 32 != (uint64_t) 0xffffffff)
+      if (value >> 32 != 0 && value >> 32 != 0xffffffff)
        /* Immediate out of range.  */
        return FALSE;
        /* Immediate out of range.  */
        return FALSE;
-      value &= (int64_t) 0xffffffff;
+      value &= 0xffffffff;
     }
 
   /* first, try movz then movn */
   amount = -1;
     }
 
   /* first, try movz then movn */
   amount = -1;
-  if ((value & ((int64_t) 0xffff << 0)) == value)
+  if ((value & ((uint64_t) 0xffff << 0)) == value)
     amount = 0;
     amount = 0;
-  else if ((value & ((int64_t) 0xffff << 16)) == value)
+  else if ((value & ((uint64_t) 0xffff << 16)) == value)
     amount = 16;
     amount = 16;
-  else if (!is32 && (value & ((int64_t) 0xffff << 32)) == value)
+  else if (!is32 && (value & ((uint64_t) 0xffff << 32)) == value)
     amount = 32;
     amount = 32;
-  else if (!is32 && (value & ((int64_t) 0xffff << 48)) == value)
+  else if (!is32 && (value & ((uint64_t) 0xffff << 48)) == value)
     amount = 48;
 
   if (amount == -1)
     amount = 48;
 
   if (amount == -1)
@@ -1040,10 +1204,15 @@ build_immediate_table (void)
            switch (log_e)
              {
              case 1: imm = (imm <<  2) | imm;
            switch (log_e)
              {
              case 1: imm = (imm <<  2) | imm;
+               /* Fall through.  */
              case 2: imm = (imm <<  4) | imm;
              case 2: imm = (imm <<  4) | imm;
+               /* Fall through.  */
              case 3: imm = (imm <<  8) | imm;
              case 3: imm = (imm <<  8) | imm;
+               /* Fall through.  */
              case 4: imm = (imm << 16) | imm;
              case 4: imm = (imm << 16) | imm;
+               /* Fall through.  */
              case 5: imm = (imm << 32) | imm;
              case 5: imm = (imm << 32) | imm;
+               /* Fall through.  */
              case 6: break;
              default: abort ();
              }
              case 6: break;
              default: abort ();
              }
@@ -1075,10 +1244,10 @@ aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding)
   uint64_t upper;
   int i;
 
   uint64_t upper;
   int i;
 
-  DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
-              value, is32);
+  DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), esize: %d", value,
+              value, esize);
 
 
-  if (initialized == FALSE)
+  if (!initialized)
     {
       build_immediate_table ();
       initialized = TRUE;
     {
       build_immediate_table ();
       initialized = TRUE;
@@ -1217,6 +1386,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)
@@ -1268,9 +1449,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;
 
@@ -1332,6 +1514,68 @@ 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_Zm3_INDEX:
+       case AARCH64_OPND_SVE_Zm3_22_INDEX:
+       case AARCH64_OPND_SVE_Zm3_11_INDEX:
+       case AARCH64_OPND_SVE_Zm4_11_INDEX:
+       case AARCH64_OPND_SVE_Zm4_INDEX:
+         size = get_operand_fields_width (get_operand_from_code (type));
+         shift = get_operand_specific_data (&aarch64_operands[type]);
+         mask = (1 << shift) - 1;
+         if (opnd->reg.regno > mask)
+           {
+             assert (mask == 7 || mask == 15);
+             set_other_error (mismatch_detail, idx,
+                              mask == 15
+                              ? _("z0-z15 expected")
+                              : _("z0-z7 expected"));
+             return 0;
+           }
+         mask = (1u << (size - shift)) - 1;
+         if (!value_in_range_p (opnd->reglane.index, 0, mask))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, mask);
+             return 0;
+           }
+         break;
+
+       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)
@@ -1357,6 +1601,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
              return 0;
            }
          break;
              return 0;
            }
          break;
+       case ldst_imm10:
+         if (opnd->addr.writeback == 1 && opnd->addr.preind != 1)
+           {
+             set_syntax_error (mismatch_detail, idx,
+                               _("unexpected address writeback"));
+             return 0;
+           }
+         break;
        case ldst_imm9:
        case ldstpair_indexed:
        case asisdlsep:
        case ldst_imm9:
        case ldstpair_indexed:
        case asisdlsep:
@@ -1392,6 +1644,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
              return 0;
            }
          break;
              return 0;
            }
          break;
+       case AARCH64_OPND_ADDR_OFFSET:
        case AARCH64_OPND_ADDR_SIMM9:
          /* Unscaled signed 9 bits immediate offset.  */
          if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
        case AARCH64_OPND_ADDR_SIMM9:
          /* Unscaled signed 9 bits immediate offset.  */
          if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
@@ -1413,6 +1666,50 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                           _("negative or unaligned offset expected"));
          return 0;
 
                           _("negative or unaligned offset expected"));
          return 0;
 
+       case AARCH64_OPND_ADDR_SIMM10:
+         /* Scaled signed 10 bits immediate offset.  */
+         if (!value_in_range_p (opnd->addr.offset.imm, -4096, 4088))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx, -4096, 4088);
+             return 0;
+           }
+         if (!value_aligned_p (opnd->addr.offset.imm, 8))
+           {
+             set_unaligned_error (mismatch_detail, idx, 8);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_ADDR_SIMM11:
+         /* Signed 11 bits immediate offset (multiple of 16).  */
+         if (!value_in_range_p (opnd->addr.offset.imm, -1024, 1008))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx, -1024, 1008);
+             return 0;
+           }
+
+         if (!value_aligned_p (opnd->addr.offset.imm, 16))
+           {
+             set_unaligned_error (mismatch_detail, idx, 16);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_ADDR_SIMM13:
+         /* Signed 13 bits immediate offset (multiple of 16).  */
+         if (!value_in_range_p (opnd->addr.offset.imm, -4096, 4080))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx, -4096, 4080);
+             return 0;
+           }
+
+         if (!value_aligned_p (opnd->addr.offset.imm, 16))
+           {
+             set_unaligned_error (mismatch_detail, idx, 16);
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_SIMD_ADDR_POST:
          /* AdvSIMD load/store multiple structures, post-index.  */
          assert (idx == 1);
        case AARCH64_OPND_SIMD_ADDR_POST:
          /* AdvSIMD load/store multiple structures, post-index.  */
          assert (idx == 1);
@@ -1525,6 +1822,174 @@ 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_RI_S4x16:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x32:
+         min_value = -8;
+         max_value = 7;
+         goto sve_imm_offset;
+
+       case AARCH64_OPND_SVE_ADDR_ZX:
+         /* Everything is already ensured by parse_operands or
+            aarch64_ext_sve_addr_rr_lsl (because this is a very specific
+            argument type).  */
+         assert (opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         assert ((aarch64_operands[type].flags & OPD_F_NO_ZR) == 0);
+         assert (opnd->shifter.kind == AARCH64_MOD_LSL);
+         assert (opnd->shifter.operator_present == 0);
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_R:
+       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;
        }
        default:
          break;
        }
@@ -1598,7 +2063,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          if (opnd->shifter.amount != 0 && opnd->shifter.amount != 12)
            {
              set_other_error (mismatch_detail, idx,
          if (opnd->shifter.amount != 0 && opnd->shifter.amount != 12)
            {
              set_other_error (mismatch_detail, idx,
-                              _("shift amount expected to be 0 or 12"));
+                              _("shift amount must be 0 or 12"));
              return 0;
            }
          if (!value_fit_unsigned_field_p (opnd->imm.value, 12))
              return 0;
            }
          if (!value_fit_unsigned_field_p (opnd->imm.value, 12))
@@ -1621,7 +2086,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          if (!value_aligned_p (opnd->shifter.amount, 16))
            {
              set_other_error (mismatch_detail, idx,
          if (!value_aligned_p (opnd->shifter.amount, 16))
            {
              set_other_error (mismatch_detail, idx,
-                              _("shift amount should be a multiple of 16"));
+                              _("shift amount must be a multiple of 16"));
              return 0;
            }
          if (!value_in_range_p (opnd->shifter.amount, 0, size * 8 - 16))
              return 0;
            }
          if (!value_in_range_p (opnd->shifter.amount, 0, size * 8 - 16))
@@ -1653,7 +2118,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                {
                case OP_MOV_IMM_WIDEN:
                  imm = ~imm;
                {
                case OP_MOV_IMM_WIDEN:
                  imm = ~imm;
-                 /* Fall through...  */
+                 /* Fall through.  */
                case OP_MOV_IMM_WIDE:
                  if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
                    {
                case OP_MOV_IMM_WIDE:
                  if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
                    {
@@ -1680,16 +2145,53 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        case AARCH64_OPND_NZCV:
        case AARCH64_OPND_CCMP_IMM:
        case AARCH64_OPND_EXCEPTION:
        case AARCH64_OPND_NZCV:
        case AARCH64_OPND_CCMP_IMM:
        case AARCH64_OPND_EXCEPTION:
+       case AARCH64_OPND_TME_UIMM16:
        case AARCH64_OPND_UIMM4:
        case AARCH64_OPND_UIMM4:
+       case AARCH64_OPND_UIMM4_ADDG:
        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))
            {
              set_imm_out_of_range_error (mismatch_detail, idx, 0,
          size = get_operand_fields_width (get_operand_from_code (type));
          assert (size < 32);
          if (!value_fit_unsigned_field_p (opnd->imm.value, size))
            {
              set_imm_out_of_range_error (mismatch_detail, idx, 0,
-                                         (1 << size) - 1);
+                                         (1u << size) - 1);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_UIMM10:
+         /* Scaled unsigned 10 bits immediate offset.  */
+         if (!value_in_range_p (opnd->imm.value, 0, 1008))
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx, 0, 1008);
+             return 0;
+           }
+
+         if (!value_aligned_p (opnd->imm.value, 16))
+           {
+             set_unaligned_error (mismatch_detail, idx, 16);
+             return 0;
+           }
+         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;
              return 0;
            }
          break;
@@ -1708,12 +2210,13 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          break;
 
        case AARCH64_OPND_LIMM:
          break;
 
        case AARCH64_OPND_LIMM:
+       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;
          {
            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)
+           if (!aarch64_logical_immediate_p (uimm, esize, NULL))
              {
                set_other_error (mismatch_detail, idx,
                                 _("immediate out of range"));
              {
                set_other_error (mismatch_detail, idx,
                                 _("immediate out of range"));
@@ -1732,6 +2235,31 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
            }
          break;
 
+       case AARCH64_OPND_IMM_ROT1:
+       case AARCH64_OPND_IMM_ROT2:
+       case AARCH64_OPND_SVE_IMM_ROT2:
+         if (opnd->imm.value != 0
+             && opnd->imm.value != 90
+             && opnd->imm.value != 180
+             && opnd->imm.value != 270)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("rotate expected to be 0, 90, 180 or 270"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_IMM_ROT3:
+       case AARCH64_OPND_SVE_IMM_ROT1:
+       case AARCH64_OPND_SVE_IMM_ROT3:
+         if (opnd->imm.value != 90 && opnd->imm.value != 270)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("rotate expected to be 90 or 270"));
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_SHLL_IMM:
          assert (idx == 2);
          size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
        case AARCH64_OPND_SHLL_IMM:
          assert (idx == 2);
          size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
@@ -1837,7 +2365,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
              if (opnd->shifter.amount != 8 && opnd->shifter.amount != 16)
                {
                  set_other_error (mismatch_detail, idx,
              if (opnd->shifter.amount != 8 && opnd->shifter.amount != 16)
                {
                  set_other_error (mismatch_detail, idx,
-                                  _("shift amount expected to be 0 or 16"));
+                                  _("shift amount must be 0 or 16"));
                  return 0;
                }
              break;
                  return 0;
                }
              break;
@@ -1854,6 +2382,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,
@@ -1878,18 +2407,155 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
            }
          break;
 
-       default:
+       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;
          break;
-       }
-      break;
 
 
-    case AARCH64_OPND_CLASS_CP_REG:
-      /* Cn or Cm: 4-bit opcode field named for historical reasons.
-        valid range: C0 - C15.  */
-      if (opnd->reg.regno > 15)
-       {
-         set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
-         return 0;
+       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:
+       case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
+         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:
+       case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
+         num = (type == AARCH64_OPND_SVE_SHRIMM_UNPRED_22) ? 2 : 1;
+         size = aarch64_get_qualifier_esize (opnds[idx - num].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;
        }
       break;
 
        }
       break;
 
@@ -1900,9 +2566,12 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
          /* MSR UAO, #uimm4
             MSR PAN, #uimm4
          assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
          /* MSR UAO, #uimm4
             MSR PAN, #uimm4
+            MSR SSBS,#uimm4
             The immediate must be #0 or #1.  */
          if ((opnd->pstatefield == 0x03        /* UAO.  */
             The immediate must be #0 or #1.  */
          if ((opnd->pstatefield == 0x03        /* UAO.  */
-              || opnd->pstatefield == 0x04)    /* PAN.  */
+              || opnd->pstatefield == 0x04     /* PAN.  */
+              || opnd->pstatefield == 0x19     /* SSBS.  */
+              || opnd->pstatefield == 0x1a)    /* DIT.  */
              && opnds[1].imm.value > 1)
            {
              set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
              && opnds[1].imm.value > 1)
            {
              set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
@@ -1926,7 +2595,16 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
     case AARCH64_OPND_CLASS_SIMD_ELEMENT:
       /* Get the upper bound for the element index.  */
 
     case AARCH64_OPND_CLASS_SIMD_ELEMENT:
       /* Get the upper bound for the element index.  */
-      num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+      if (opcode->op == OP_FCMLA_ELEM)
+       /* FCMLA index range depends on the vector size of other operands
+          and is halfed because complex numbers take two elements.  */
+       num = aarch64_get_qualifier_nelem (opnds[0].qualifier)
+             * aarch64_get_qualifier_esize (opnds[0].qualifier) / 2;
+      else
+       num = 16;
+      num = num / aarch64_get_qualifier_esize (qualifier) - 1;
+      assert (aarch64_get_qualifier_nelem (qualifier) == 1);
+
       /* Index out-of-range.  */
       if (!value_in_range_p (opnd->reglane.index, 0, num))
        {
       /* Index out-of-range.  */
       if (!value_in_range_p (opnd->reglane.index, 0, num))
        {
@@ -1941,7 +2619,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
         01             0:Rm
         10             M:Rm
         11             RESERVED  */
         01             0:Rm
         10             M:Rm
         11             RESERVED  */
-      if (type == AARCH64_OPND_Em && qualifier == AARCH64_OPND_QLF_S_H
+      if (type == AARCH64_OPND_Em16 && qualifier == AARCH64_OPND_QLF_S_H
          && !value_in_range_p (opnd->reglane.regno, 0, 15))
        {
          set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
          && !value_in_range_p (opnd->reglane.regno, 0, 15))
        {
          set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
@@ -1954,7 +2632,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       switch (type)
        {
        case AARCH64_OPND_Rm_EXT:
       switch (type)
        {
        case AARCH64_OPND_Rm_EXT:
-         if (aarch64_extend_operator_p (opnd->shifter.kind) == FALSE
+         if (!aarch64_extend_operator_p (opnd->shifter.kind)
              && opnd->shifter.kind != AARCH64_MOD_LSL)
            {
              set_other_error (mismatch_detail, idx,
              && opnd->shifter.kind != AARCH64_MOD_LSL)
            {
              set_other_error (mismatch_detail, idx,
@@ -2006,7 +2684,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        case AARCH64_OPND_Rm_SFT:
          /* ROR is not available to the shifted register operand in
             arithmetic instructions.  */
        case AARCH64_OPND_Rm_SFT:
          /* ROR is not available to the shifted register operand in
             arithmetic instructions.  */
-         if (aarch64_shift_operator_p (opnd->shifter.kind) == FALSE)
+         if (!aarch64_shift_operator_p (opnd->shifter.kind))
            {
              set_other_error (mismatch_detail, idx,
                               _("shift operator expected"));
            {
              set_other_error (mismatch_detail, idx,
                               _("shift operator expected"));
@@ -2058,6 +2736,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
@@ -2167,6 +2862,17 @@ static const char *int_reg[2][2][32] = {
 #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.
 #undef BANK
 
 /* Return the integer register name.
@@ -2210,6 +2916,17 @@ get_offset_int_reg_name (const aarch64_opnd_info *opnd)
     }
 }
 
     }
 }
 
+/* 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
@@ -2241,7 +2958,7 @@ typedef union
 static uint64_t
 expand_fp_imm (int size, uint32_t imm8)
 {
 static uint64_t
 expand_fp_imm (int size, uint32_t imm8)
 {
-  uint64_t imm;
+  uint64_t imm = 0;
   uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
 
   imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7>   */
   uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
 
   imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7>   */
@@ -2292,7 +3009,8 @@ 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, "[%" PRIi64 "]", opnd->reglist.index);
+    /* PR 21096: The %100 is to silence a warning about possible truncation.  */
+    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
   else
     tb[0] = '\0';
 
   else
     tb[0] = '\0';
 
@@ -2343,14 +3061,25 @@ print_immediate_offset_address (char *buf, size_t size,
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
-       snprintf (buf, size, "[%s,#%d]!", base, opnd->addr.offset.imm);
+        {
+         if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
+            snprintf (buf, size, "[%s]!", base);
+          else
+           snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+        }
       else
       else
-       snprintf (buf, size, "[%s],#%d", base, opnd->addr.offset.imm);
+       snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
     }
   else
     {
     }
   else
     {
-      if (opnd->addr.offset.imm)
-       snprintf (buf, size, "[%s,#%d]", base, opnd->addr.offset.imm);
+      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);
     }
       else
        snprintf (buf, size, "[%s]", base);
     }
@@ -2385,14 +3114,16 @@ 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, sizeof (tb), ",%s #%d", shift_name, opnd->shifter.amount);
+       snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+  /* PR 21096: The %100 is to silence a warning about possible truncation.  */
+                 (opnd->shifter.amount % 100));
       else
       else
-       snprintf (tb, sizeof (tb), ",%s", shift_name);
+       snprintf (tb, sizeof (tb), ", %s", shift_name);
     }
   else
     tb[0] = '\0';
 
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s,%s%s]", base, offset, 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
@@ -2410,13 +3141,13 @@ void
 aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                       const aarch64_opcode *opcode,
                       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                       const aarch64_opcode *opcode,
                       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
-                      bfd_vma *address)
+                      bfd_vma *address, char** notes)
 {
 {
-  int i;
+  unsigned int i, num_conds;
   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)
@@ -2433,14 +3164,19 @@ 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 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
+        the <ic_op>, therefore we use opnd->present to override the
         generic optional-ness information.  */
         generic optional-ness information.  */
-      if (opnd->type == AARCH64_OPND_Rt_SYS && !opnd->present)
-       break;
+      if (opnd->type == AARCH64_OPND_Rt_SYS)
+       {
+         if (!opnd->present)
+           break;
+       }
       /* Omit the operand, e.g. RET.  */
       /* Omit the operand, e.g. RET.  */
-      if (optional_operand_p (opcode, idx)
-         && opnd->reg.regno == get_optional_operand_default_value (opcode))
+      else if (optional_operand_p (opcode, idx)
+              && (opnd->reg.regno
+                  == get_optional_operand_default_value (opcode)))
        break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_X);
        break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_X);
@@ -2450,6 +3186,9 @@ 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_Rt_SP:
+    case AARCH64_OPND_SVE_Rn_SP:
+    case AARCH64_OPND_Rm_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
@@ -2480,7 +3219,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);
@@ -2497,7 +3236,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);
@@ -2512,10 +3251,15 @@ 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;
 
+    case AARCH64_OPND_Va:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
@@ -2526,6 +3270,8 @@ 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:
+    case AARCH64_OPND_Em16:
+    case AARCH64_OPND_SM3_IMM2:
       snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
       snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
@@ -2543,13 +3289,64 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_list (buf, size, opnd, "v");
       break;
 
       print_register_list (buf, size, opnd, "v");
       break;
 
-    case AARCH64_OPND_Cn:
-    case AARCH64_OPND_Cm:
-      snprintf (buf, size, "C%d", opnd->reg.regno);
+    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_Zm3_INDEX:
+    case AARCH64_OPND_SVE_Zm3_22_INDEX:
+    case AARCH64_OPND_SVE_Zm3_11_INDEX:
+    case AARCH64_OPND_SVE_Zm4_11_INDEX:
+    case AARCH64_OPND_SVE_Zm4_INDEX:
+    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_CRn:
+    case AARCH64_OPND_CRm:
+      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
       break;
 
     case AARCH64_OPND_IDX:
       break;
 
     case AARCH64_OPND_IDX:
+    case AARCH64_OPND_MASK:
     case AARCH64_OPND_IMM:
     case AARCH64_OPND_IMM:
+    case AARCH64_OPND_IMM_2:
     case AARCH64_OPND_WIDTH:
     case AARCH64_OPND_UIMM3_OP1:
     case AARCH64_OPND_UIMM3_OP2:
     case AARCH64_OPND_WIDTH:
     case AARCH64_OPND_UIMM3_OP1:
     case AARCH64_OPND_UIMM3_OP2:
@@ -2561,9 +3358,82 @@ 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_TME_UIMM16:
+    case AARCH64_OPND_SIMM5:
+    case AARCH64_OPND_SVE_SHLIMM_PRED:
+    case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+    case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
+    case AARCH64_OPND_SVE_SHRIMM_PRED:
+    case AARCH64_OPND_SVE_SHRIMM_UNPRED:
+    case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
+    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:
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+    case AARCH64_OPND_IMM_ROT3:
+    case AARCH64_OPND_SVE_IMM_ROT1:
+    case AARCH64_OPND_SVE_IMM_ROT2:
+    case AARCH64_OPND_SVE_IMM_ROT3:
       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))
        {
@@ -2588,8 +3458,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);
@@ -2601,13 +3474,23 @@ 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))
        {
        case 2: /* e.g. FMOV <Hd>, #<imm>.  */
       switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
        {
        case 2: /* e.g. FMOV <Hd>, #<imm>.  */
@@ -2639,7 +3522,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_NZCV:
     case AARCH64_OPND_EXCEPTION:
     case AARCH64_OPND_UIMM4:
     case AARCH64_OPND_NZCV:
     case AARCH64_OPND_EXCEPTION:
     case AARCH64_OPND_UIMM4:
+    case AARCH64_OPND_UIMM4_ADDG:
     case AARCH64_OPND_UIMM7:
     case AARCH64_OPND_UIMM7:
+    case AARCH64_OPND_UIMM10:
       if (optional_operand_p (opcode, idx) == TRUE
          && (opnd->imm.value ==
              (int64_t) get_optional_operand_default_value (opcode)))
       if (optional_operand_p (opcode, idx) == TRUE
          && (opnd->imm.value ==
              (int64_t) get_optional_operand_default_value (opcode)))
@@ -2651,6 +3536,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
       snprintf (buf, size, "%s", opnd->cond->names[0]);
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
       snprintf (buf, size, "%s", opnd->cond->names[0]);
+      num_conds = ARRAY_SIZE (opnd->cond->names);
+      for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
+       {
+         size_t len = strlen (buf);
+         if (i == 1)
+           snprintf (buf + len, size - len, "  // %s = %s",
+                     opnd->cond->names[0], opnd->cond->names[i]);
+         else
+           snprintf (buf + len, size - len, ", %s",
+                     opnd->cond->names[i]);
+       }
       break;
 
     case AARCH64_OPND_ADDR_ADRP:
       break;
 
     case AARCH64_OPND_ADDR_ADRP:
@@ -2699,37 +3595,131 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
+    case AARCH64_OPND_SVE_ADDR_R:
+    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;
 
       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_ZX:
+      print_register_offset_address
+       (buf, size, opnd,
+        get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+        get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+      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:
     case AARCH64_OPND_ADDR_SIMM7:
     case AARCH64_OPND_ADDR_SIMM9:
     case AARCH64_OPND_ADDR_SIMM9_2:
+    case AARCH64_OPND_ADDR_SIMM10:
+    case AARCH64_OPND_ADDR_SIMM11:
+    case AARCH64_OPND_ADDR_SIMM13:
+    case AARCH64_OPND_ADDR_OFFSET:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x16:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x32:
+    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;
 
       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:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-       snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
+       snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
       else
        snprintf (buf, size, "[%s]", name);
       break;
 
     case AARCH64_OPND_SYSREG:
       for (i = 0; aarch64_sys_regs[i].name; ++i)
       else
        snprintf (buf, size, "[%s]", name);
       break;
 
     case AARCH64_OPND_SYSREG:
       for (i = 0; aarch64_sys_regs[i].name; ++i)
-       if (aarch64_sys_regs[i].value == opnd->sysreg
-           && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i]))
-         break;
-      if (aarch64_sys_regs[i].name)
-       snprintf (buf, size, "%s", aarch64_sys_regs[i].name);
+       {
+         bfd_boolean exact_match
+           = (aarch64_sys_regs[i].flags & opnd->sysreg.flags)
+              == opnd->sysreg.flags;
+
+         /* Try and find an exact match, But if that fails, return the first
+            partial match that was found.  */
+         if (aarch64_sys_regs[i].value == opnd->sysreg.value
+             && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i])
+             && (name == NULL || exact_match))
+           {
+             name = aarch64_sys_regs[i].name;
+             if (exact_match)
+               {
+                 if (notes)
+                   *notes = NULL;
+                 break;
+               }
+
+             /* If we didn't match exactly, that means the presense of a flag
+                indicates what we didn't want for this instruction.  e.g. If
+                F_REG_READ is there, that means we were looking for a write
+                register.  See aarch64_ext_sysreg.  */
+             if (aarch64_sys_regs[i].flags & F_REG_WRITE)
+               *notes = _("reading from a write-only register");
+             else if (aarch64_sys_regs[i].flags & F_REG_READ)
+               *notes = _("writing to a read-only register");
+           }
+       }
+
+      if (name)
+       snprintf (buf, size, "%s", name);
       else
        {
          /* Implementation defined system register.  */
       else
        {
          /* Implementation defined system register.  */
-         unsigned int value = opnd->sysreg;
+         unsigned int value = opnd->sysreg.value;
          snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
                    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
                    value & 0x7);
          snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
                    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
                    value & 0x7);
@@ -2748,6 +3738,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:
+    case AARCH64_OPND_SYSREG_SR:
       snprintf (buf, size, "%s", opnd->sysins_op->name);
       break;
 
       snprintf (buf, size, "%s", opnd->sysins_op->name);
       break;
 
@@ -2771,7 +3762,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "%s", opnd->hint_option->name);
+    case AARCH64_OPND_BTI_TARGET:
+      if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
+       snprintf (buf, size, "%s", opnd->hint_option->name);
       break;
 
     default:
       break;
 
     default:
@@ -2803,26 +3796,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 #define C14 14
 #define C15 15
 
 #define C14 14
 #define C15 15
 
-#ifdef F_DEPRECATED
-#undef F_DEPRECATED
-#endif
-#define F_DEPRECATED   0x1     /* Deprecated system register.  */
-
-#ifdef F_ARCHEXT
-#undef F_ARCHEXT
-#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
-   2. handle cpu-implementation-defined system registers.  */
+/* TODO there is one more issues need to be resolved
+   1. handle cpu-implementation-defined system registers.  */
 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 */
@@ -2832,10 +3807,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "sp_el0",           CPEN_(0,C1,0), 0 },
   { "spsel",            CPEN_(0,C2,0), 0 },
   { "daif",             CPEN_(3,C2,1), 0 },
   { "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 */
+  { "currentel",        CPEN_(0,C2,2), F_REG_READ }, /* RO */
   { "pan",             CPEN_(0,C2,3),  F_ARCHEXT },
   { "uao",             CPEN_ (0, C2, 4), F_ARCHEXT },
   { "nzcv",             CPEN_(3,C2,0), 0 },
   { "pan",             CPEN_(0,C2,3),  F_ARCHEXT },
   { "uao",             CPEN_ (0, C2, 4), F_ARCHEXT },
   { "nzcv",             CPEN_(3,C2,0), 0 },
+  { "ssbs",            CPEN_(3,C2,6),  F_ARCHEXT },
   { "fpcr",             CPEN_(3,C4,0), 0 },
   { "fpsr",             CPEN_(3,C4,1), 0 },
   { "dspsr_el0",        CPEN_(3,C5,0), 0 },
   { "fpcr",             CPEN_(3,C4,0), 0 },
   { "fpsr",             CPEN_(3,C4,1), 0 },
   { "dspsr_el0",        CPEN_(3,C5,0), 0 },
@@ -2852,44 +3828,46 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "sp_el2",           CPEN_(6,C1,0), 0 },
   { "spsr_svc",         CPEN_(0,C0,0), F_DEPRECATED }, /* = spsr_el1 */
   { "spsr_hyp",         CPEN_(4,C0,0), F_DEPRECATED }, /* = spsr_el2 */
   { "sp_el2",           CPEN_(6,C1,0), 0 },
   { "spsr_svc",         CPEN_(0,C0,0), F_DEPRECATED }, /* = spsr_el1 */
   { "spsr_hyp",         CPEN_(4,C0,0), F_DEPRECATED }, /* = spsr_el2 */
-  { "midr_el1",         CPENC(3,0,C0,C0,0),    0 }, /* RO */
-  { "ctr_el0",          CPENC(3,3,C0,C0,1),    0 }, /* RO */
-  { "mpidr_el1",        CPENC(3,0,C0,C0,5),    0 }, /* RO */
-  { "revidr_el1",       CPENC(3,0,C0,C0,6),    0 }, /* RO */
-  { "aidr_el1",         CPENC(3,1,C0,C0,7),    0 }, /* RO */
-  { "dczid_el0",        CPENC(3,3,C0,C0,7),    0 }, /* RO */
-  { "id_dfr0_el1",      CPENC(3,0,C0,C1,2),    0 }, /* RO */
-  { "id_pfr0_el1",      CPENC(3,0,C0,C1,0),    0 }, /* RO */
-  { "id_pfr1_el1",      CPENC(3,0,C0,C1,1),    0 }, /* RO */
-  { "id_afr0_el1",      CPENC(3,0,C0,C1,3),    0 }, /* RO */
-  { "id_mmfr0_el1",     CPENC(3,0,C0,C1,4),    0 }, /* RO */
-  { "id_mmfr1_el1",     CPENC(3,0,C0,C1,5),    0 }, /* RO */
-  { "id_mmfr2_el1",     CPENC(3,0,C0,C1,6),    0 }, /* RO */
-  { "id_mmfr3_el1",     CPENC(3,0,C0,C1,7),    0 }, /* RO */
-  { "id_mmfr4_el1",     CPENC(3,0,C0,C2,6),    0 }, /* RO */
-  { "id_isar0_el1",     CPENC(3,0,C0,C2,0),    0 }, /* RO */
-  { "id_isar1_el1",     CPENC(3,0,C0,C2,1),    0 }, /* RO */
-  { "id_isar2_el1",     CPENC(3,0,C0,C2,2),    0 }, /* RO */
-  { "id_isar3_el1",     CPENC(3,0,C0,C2,3),    0 }, /* RO */
-  { "id_isar4_el1",     CPENC(3,0,C0,C2,4),    0 }, /* RO */
-  { "id_isar5_el1",     CPENC(3,0,C0,C2,5),    0 }, /* RO */
-  { "mvfr0_el1",        CPENC(3,0,C0,C3,0),    0 }, /* RO */
-  { "mvfr1_el1",        CPENC(3,0,C0,C3,1),    0 }, /* RO */
-  { "mvfr2_el1",        CPENC(3,0,C0,C3,2),    0 }, /* RO */
-  { "ccsidr_el1",       CPENC(3,1,C0,C0,0),    0 }, /* RO */
-  { "id_aa64pfr0_el1",  CPENC(3,0,C0,C4,0),    0 }, /* RO */
-  { "id_aa64pfr1_el1",  CPENC(3,0,C0,C4,1),    0 }, /* RO */
-  { "id_aa64dfr0_el1",  CPENC(3,0,C0,C5,0),    0 }, /* RO */
-  { "id_aa64dfr1_el1",  CPENC(3,0,C0,C5,1),    0 }, /* RO */
-  { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0),    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 */
-  { "csselr_el1",       CPENC(3,2,C0,C0,0),    0 }, /* RO */
+  { "midr_el1",         CPENC(3,0,C0,C0,0),    F_REG_READ }, /* RO */
+  { "ctr_el0",          CPENC(3,3,C0,C0,1),    F_REG_READ }, /* RO */
+  { "mpidr_el1",        CPENC(3,0,C0,C0,5),    F_REG_READ }, /* RO */
+  { "revidr_el1",       CPENC(3,0,C0,C0,6),    F_REG_READ }, /* RO */
+  { "aidr_el1",         CPENC(3,1,C0,C0,7),    F_REG_READ }, /* RO */
+  { "dczid_el0",        CPENC(3,3,C0,C0,7),    F_REG_READ }, /* RO */
+  { "id_dfr0_el1",      CPENC(3,0,C0,C1,2),    F_REG_READ }, /* RO */
+  { "id_pfr0_el1",      CPENC(3,0,C0,C1,0),    F_REG_READ }, /* RO */
+  { "id_pfr1_el1",      CPENC(3,0,C0,C1,1),    F_REG_READ }, /* RO */
+  { "id_pfr2_el1",      CPENC(3,0,C0,C3,4),    F_ARCHEXT | F_REG_READ}, /* RO */
+  { "id_afr0_el1",      CPENC(3,0,C0,C1,3),    F_REG_READ }, /* RO */
+  { "id_mmfr0_el1",     CPENC(3,0,C0,C1,4),    F_REG_READ }, /* RO */
+  { "id_mmfr1_el1",     CPENC(3,0,C0,C1,5),    F_REG_READ }, /* RO */
+  { "id_mmfr2_el1",     CPENC(3,0,C0,C1,6),    F_REG_READ }, /* RO */
+  { "id_mmfr3_el1",     CPENC(3,0,C0,C1,7),    F_REG_READ }, /* RO */
+  { "id_mmfr4_el1",     CPENC(3,0,C0,C2,6),    F_REG_READ }, /* RO */
+  { "id_isar0_el1",     CPENC(3,0,C0,C2,0),    F_REG_READ }, /* RO */
+  { "id_isar1_el1",     CPENC(3,0,C0,C2,1),    F_REG_READ }, /* RO */
+  { "id_isar2_el1",     CPENC(3,0,C0,C2,2),    F_REG_READ }, /* RO */
+  { "id_isar3_el1",     CPENC(3,0,C0,C2,3),    F_REG_READ }, /* RO */
+  { "id_isar4_el1",     CPENC(3,0,C0,C2,4),    F_REG_READ }, /* RO */
+  { "id_isar5_el1",     CPENC(3,0,C0,C2,5),    F_REG_READ }, /* RO */
+  { "mvfr0_el1",        CPENC(3,0,C0,C3,0),    F_REG_READ }, /* RO */
+  { "mvfr1_el1",        CPENC(3,0,C0,C3,1),    F_REG_READ }, /* RO */
+  { "mvfr2_el1",        CPENC(3,0,C0,C3,2),    F_REG_READ }, /* RO */
+  { "ccsidr_el1",       CPENC(3,1,C0,C0,0),    F_REG_READ }, /* RO */
+  { "id_aa64pfr0_el1",  CPENC(3,0,C0,C4,0),    F_REG_READ }, /* RO */
+  { "id_aa64pfr1_el1",  CPENC(3,0,C0,C4,1),    F_REG_READ }, /* RO */
+  { "id_aa64dfr0_el1",  CPENC(3,0,C0,C5,0),    F_REG_READ }, /* RO */
+  { "id_aa64dfr1_el1",  CPENC(3,0,C0,C5,1),    F_REG_READ }, /* RO */
+  { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0),    F_REG_READ }, /* RO */
+  { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    F_REG_READ }, /* RO */
+  { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    F_REG_READ }, /* RO */
+  { "id_aa64zfr0_el1",  CPENC (3, 0, C0, C4, 4), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "clidr_el1",        CPENC(3,1,C0,C0,1),    F_REG_READ }, /* RO */
+  { "csselr_el1",       CPENC(3,2,C0,C0,0),    0 },
   { "vpidr_el2",        CPENC(3,4,C0,C0,0),    0 },
   { "vmpidr_el2",       CPENC(3,4,C0,C0,5),    0 },
   { "sctlr_el1",        CPENC(3,0,C1,C0,0),    0 },
   { "vpidr_el2",        CPENC(3,4,C0,C0,0),    0 },
   { "vmpidr_el2",       CPENC(3,4,C0,C0,5),    0 },
   { "sctlr_el1",        CPENC(3,0,C1,C0,0),    0 },
@@ -2909,6 +3887,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "mdcr_el3",         CPENC(3,6,C1,C3,1),    0 },
   { "hstr_el2",         CPENC(3,4,C1,C1,3),    0 },
   { "hacr_el2",         CPENC(3,4,C1,C1,7),    0 },
   { "mdcr_el3",         CPENC(3,6,C1,C3,1),    0 },
   { "hstr_el2",         CPENC(3,4,C1,C1,3),    0 },
   { "hacr_el2",         CPENC(3,4,C1,C1,7),    0 },
+  { "zcr_el1",          CPENC (3, 0, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el12",         CPENC (3, 5, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el2",          CPENC (3, 4, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el3",          CPENC (3, 6, C1, C2, 0), F_ARCHEXT },
+  { "zidr_el1",         CPENC (3, 0, C0, C0, 7), F_ARCHEXT },
   { "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 },
@@ -2922,6 +3905,16 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "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 },
   { "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 },
+  { "apiakeylo_el1",   CPENC (3, 0, C2, C1, 0), F_ARCHEXT },
+  { "apiakeyhi_el1",   CPENC (3, 0, C2, C1, 1), F_ARCHEXT },
+  { "apibkeylo_el1",   CPENC (3, 0, C2, C1, 2), F_ARCHEXT },
+  { "apibkeyhi_el1",   CPENC (3, 0, C2, C1, 3), F_ARCHEXT },
+  { "apdakeylo_el1",   CPENC (3, 0, C2, C2, 0), F_ARCHEXT },
+  { "apdakeyhi_el1",   CPENC (3, 0, C2, C2, 1), F_ARCHEXT },
+  { "apdbkeylo_el1",   CPENC (3, 0, C2, C2, 2), F_ARCHEXT },
+  { "apdbkeyhi_el1",   CPENC (3, 0, C2, C2, 3), F_ARCHEXT },
+  { "apgakeylo_el1",   CPENC (3, 0, C2, C3, 0), F_ARCHEXT },
+  { "apgakeyhi_el1",   CPENC (3, 0, C2, C3, 1), F_ARCHEXT },
   { "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 },
   { "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 },
@@ -2934,11 +3927,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "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 },
   { "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 */
+  { "vsesr_el2",       CPENC (3, 4, C5, C2, 3), F_ARCHEXT },
   { "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 */
+  { "erridr_el1",      CPENC (3, 0, C5, C3, 0), F_ARCHEXT | F_REG_READ }, /* RO */
   { "errselr_el1",     CPENC (3, 0, C5, C3, 1), F_ARCHEXT },
   { "errselr_el1",     CPENC (3, 0, C5, C3, 1), F_ARCHEXT },
-  { "erxfr_el1",       CPENC (3, 0, C5, C4, 0), F_ARCHEXT }, /* RO */
+  { "erxfr_el1",       CPENC (3, 0, C5, C4, 0), F_ARCHEXT | F_REG_READ }, /* 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 },
   { "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 },
@@ -2962,27 +3955,43 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "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 },
   { "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),   F_REG_READ }, /* RO */
+  { "rvbar_el2",        CPENC(3,4,C12,C0,1),   F_REG_READ }, /* RO */
+  { "rvbar_el3",        CPENC(3,6,C12,C0,1),   F_REG_READ }, /* RO */
   { "rmr_el1",          CPENC(3,0,C12,C0,2),   0 },
   { "rmr_el2",          CPENC(3,4,C12,C0,2),   0 },
   { "rmr_el3",          CPENC(3,6,C12,C0,2),   0 },
   { "rmr_el1",          CPENC(3,0,C12,C0,2),   0 },
   { "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 */
+  { "isr_el1",          CPENC(3,0,C12,C1,0),   F_REG_READ }, /* 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_el2",  CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
   { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
   { "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_el2",  CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
   { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
+  { "rndr",            CPENC(3,3,C2,C4,0), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "rndrrs",          CPENC(3,3,C2,C4,1), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "tco",             CPENC(3,3,C4,C2,7), F_ARCHEXT },
+  { "tfsre0_el1",      CPENC(3,0,C5,C6,1), F_ARCHEXT },
+  { "tfsr_el1",                CPENC(3,0,C5,C6,0), F_ARCHEXT },
+  { "tfsr_el2",                CPENC(3,4,C5,C6,0), F_ARCHEXT },
+  { "tfsr_el3",                CPENC(3,6,C5,C6,0), F_ARCHEXT },
+  { "tfsr_el12",       CPENC(3,5,C5,C6,0), F_ARCHEXT },
+  { "rgsr_el1",                CPENC(3,0,C1,C0,5), F_ARCHEXT },
+  { "gcr_el1",         CPENC(3,0,C1,C0,6), F_ARCHEXT },
+  { "gmid_el1",                CPENC(3,1,C0,C0,4), F_ARCHEXT | F_REG_READ }, /* RO */
   { "tpidr_el0",        CPENC(3,3,C13,C0,2),   0 },
   { "tpidr_el0",        CPENC(3,3,C13,C0,2),   0 },
-  { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RO */
+  { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RW */
   { "tpidr_el1",        CPENC(3,0,C13,C0,4),   0 },
   { "tpidr_el2",        CPENC(3,4,C13,C0,2),   0 },
   { "tpidr_el3",        CPENC(3,6,C13,C0,2),   0 },
   { "tpidr_el1",        CPENC(3,0,C13,C0,4),   0 },
   { "tpidr_el2",        CPENC(3,4,C13,C0,2),   0 },
   { "tpidr_el3",        CPENC(3,6,C13,C0,2),   0 },
+  { "scxtnum_el0",      CPENC(3,3,C13,C0,7), F_ARCHEXT },
+  { "scxtnum_el1",      CPENC(3,0,C13,C0,7), F_ARCHEXT },
+  { "scxtnum_el2",      CPENC(3,4,C13,C0,7), F_ARCHEXT },
+  { "scxtnum_el12",     CPENC(3,5,C13,C0,7), F_ARCHEXT },
+  { "scxtnum_el3",      CPENC(3,6,C13,C0,7), F_ARCHEXT },
   { "teecr32_el1",      CPENC(2,2,C0, C0,0),   0 }, /* See section 3.9.7.1 */
   { "teecr32_el1",      CPENC(2,2,C0, C0,0),   0 }, /* See section 3.9.7.1 */
-  { "cntfrq_el0",       CPENC(3,3,C14,C0,0),   0 }, /* RO */
-  { "cntpct_el0",       CPENC(3,3,C14,C0,1),   0 }, /* RO */
-  { "cntvct_el0",       CPENC(3,3,C14,C0,2),   0 }, /* RO */
+  { "cntfrq_el0",       CPENC(3,3,C14,C0,0),   0 }, /* RW */
+  { "cntpct_el0",       CPENC(3,3,C14,C0,1),   F_REG_READ }, /* RO */
+  { "cntvct_el0",       CPENC(3,3,C14,C0,2),   F_REG_READ }, /* 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 },
   { "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 },
@@ -3013,13 +4022,13 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "teehbr32_el1",     CPENC(2,2,C1,C0,0),    0 },
   { "sder32_el3",       CPENC(3,6,C1,C1,1),    0 },
   { "mdscr_el1",         CPENC(2,0,C0, C2, 2), 0 },
   { "teehbr32_el1",     CPENC(2,2,C1,C0,0),    0 },
   { "sder32_el3",       CPENC(3,6,C1,C1,1),    0 },
   { "mdscr_el1",         CPENC(2,0,C0, C2, 2), 0 },
-  { "mdccsr_el0",        CPENC(2,3,C0, C1, 0), 0 },  /* r */
+  { "mdccsr_el0",        CPENC(2,3,C0, C1, 0), F_REG_READ  },  /* r */
   { "mdccint_el1",       CPENC(2,0,C0, C2, 0), 0 },
   { "dbgdtr_el0",        CPENC(2,3,C0, C4, 0), 0 },
   { "mdccint_el1",       CPENC(2,0,C0, C2, 0), 0 },
   { "dbgdtr_el0",        CPENC(2,3,C0, C4, 0), 0 },
-  { "dbgdtrrx_el0",      CPENC(2,3,C0, C5, 0), 0 },  /* r */
-  { "dbgdtrtx_el0",      CPENC(2,3,C0, C5, 0), 0 },  /* w */
-  { "osdtrrx_el1",       CPENC(2,0,C0, C0, 2), 0 },  /* r */
-  { "osdtrtx_el1",       CPENC(2,0,C0, C3, 2), 0 },  /* w */
+  { "dbgdtrrx_el0",      CPENC(2,3,C0, C5, 0), F_REG_READ  },  /* r */
+  { "dbgdtrtx_el0",      CPENC(2,3,C0, C5, 0), F_REG_WRITE },  /* w */
+  { "osdtrrx_el1",       CPENC(2,0,C0, C0, 2), 0 },
+  { "osdtrtx_el1",       CPENC(2,0,C0, C3, 2), 0 },
   { "oseccr_el1",        CPENC(2,0,C0, C6, 2), 0 },
   { "dbgvcr32_el2",      CPENC(2,4,C0, C7, 0), 0 },
   { "dbgbvr0_el1",       CPENC(2,0,C0, C0, 4), 0 },
   { "oseccr_el1",        CPENC(2,0,C0, C6, 2), 0 },
   { "dbgvcr32_el2",      CPENC(2,4,C0, C7, 0), 0 },
   { "dbgbvr0_el1",       CPENC(2,0,C0, C0, 4), 0 },
@@ -3086,35 +4095,35 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "dbgwcr13_el1",      CPENC(2,0,C0, C13,7), 0 },
   { "dbgwcr14_el1",      CPENC(2,0,C0, C14,7), 0 },
   { "dbgwcr15_el1",      CPENC(2,0,C0, C15,7), 0 },
   { "dbgwcr13_el1",      CPENC(2,0,C0, C13,7), 0 },
   { "dbgwcr14_el1",      CPENC(2,0,C0, C14,7), 0 },
   { "dbgwcr15_el1",      CPENC(2,0,C0, C15,7), 0 },
-  { "mdrar_el1",         CPENC(2,0,C1, C0, 0), 0 },  /* r */
-  { "oslar_el1",         CPENC(2,0,C1, C0, 4), 0 },  /* w */
-  { "oslsr_el1",         CPENC(2,0,C1, C1, 4), 0 },  /* r */
+  { "mdrar_el1",         CPENC(2,0,C1, C0, 0), F_REG_READ  },  /* r */
+  { "oslar_el1",         CPENC(2,0,C1, C0, 4), F_REG_WRITE },  /* w */
+  { "oslsr_el1",         CPENC(2,0,C1, C1, 4), F_REG_READ  },  /* r */
   { "osdlr_el1",         CPENC(2,0,C1, C3, 4), 0 },
   { "dbgprcr_el1",       CPENC(2,0,C1, C4, 4), 0 },
   { "dbgclaimset_el1",   CPENC(2,0,C7, C8, 6), 0 },
   { "dbgclaimclr_el1",   CPENC(2,0,C7, C9, 6), 0 },
   { "osdlr_el1",         CPENC(2,0,C1, C3, 4), 0 },
   { "dbgprcr_el1",       CPENC(2,0,C1, C4, 4), 0 },
   { "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 */
+  { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), F_REG_READ  },  /* 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 */
   { "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 */
+  { "pmbidr_el1",       CPENC (3, 0, C9, C10, 7), F_ARCHEXT | F_REG_READ },  /* 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 */
   { "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 */
+  { "pmsidr_el1",       CPENC (3, 0, C9, C9, 7),  F_ARCHEXT },  /* rw */
   { "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 },
   { "pmovsclr_el0",      CPENC(3,3,C9,C12, 3), 0 },
   { "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 },
   { "pmovsclr_el0",      CPENC(3,3,C9,C12, 3), 0 },
-  { "pmswinc_el0",       CPENC(3,3,C9,C12, 4), 0 },  /* w */
+  { "pmswinc_el0",       CPENC(3,3,C9,C12, 4), F_REG_WRITE },  /* w */
   { "pmselr_el0",        CPENC(3,3,C9,C12, 5), 0 },
   { "pmselr_el0",        CPENC(3,3,C9,C12, 5), 0 },
-  { "pmceid0_el0",       CPENC(3,3,C9,C12, 6), 0 },  /* r */
-  { "pmceid1_el0",       CPENC(3,3,C9,C12, 7), 0 },  /* r */
+  { "pmceid0_el0",       CPENC(3,3,C9,C12, 6), F_REG_READ  },  /* r */
+  { "pmceid1_el0",       CPENC(3,3,C9,C12, 7), F_REG_READ  },  /* r */
   { "pmccntr_el0",       CPENC(3,3,C9,C13, 0), 0 },
   { "pmxevtyper_el0",    CPENC(3,3,C9,C13, 1), 0 },
   { "pmxevcntr_el0",     CPENC(3,3,C9,C13, 2), 0 },
   { "pmccntr_el0",       CPENC(3,3,C9,C13, 0), 0 },
   { "pmxevtyper_el0",    CPENC(3,3,C9,C13, 1), 0 },
   { "pmxevcntr_el0",     CPENC(3,3,C9,C13, 2), 0 },
@@ -3185,6 +4194,18 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "pmevtyper29_el0",   CPENC(3,3,C14,C15,5), 0 },
   { "pmevtyper30_el0",   CPENC(3,3,C14,C15,6), 0 },
   { "pmccfiltr_el0",     CPENC(3,3,C14,C15,7), 0 },
   { "pmevtyper29_el0",   CPENC(3,3,C14,C15,5), 0 },
   { "pmevtyper30_el0",   CPENC(3,3,C14,C15,6), 0 },
   { "pmccfiltr_el0",     CPENC(3,3,C14,C15,7), 0 },
+
+  { "dit",              CPEN_ (3, C2, 5), F_ARCHEXT },
+  { "vstcr_el2",        CPENC(3, 4, C2, C6, 2), F_ARCHEXT },
+  { "vsttbr_el2",       CPENC(3, 4, C2, C6, 0), F_ARCHEXT },
+  { "cnthvs_tval_el2",  CPENC(3, 4, C14, C4, 0), F_ARCHEXT },
+  { "cnthvs_cval_el2",  CPENC(3, 4, C14, C4, 2), F_ARCHEXT },
+  { "cnthvs_ctl_el2",   CPENC(3, 4, C14, C4, 1), F_ARCHEXT },
+  { "cnthps_tval_el2",  CPENC(3, 4, C14, C5, 0), F_ARCHEXT },
+  { "cnthps_cval_el2",  CPENC(3, 4, C14, C5, 2), F_ARCHEXT },
+  { "cnthps_ctl_el2",   CPENC(3, 4, C14, C5, 1), F_ARCHEXT },
+  { "sder32_el2",       CPENC(3, 4, C1, C3, 1), F_ARCHEXT },
+  { "vncr_el2",                 CPENC(3, 4, C2, C2, 0), F_ARCHEXT },
   { 0,          CPENC(0,0,0,0,0),      0 },
 };
 
   { 0,          CPENC(0,0,0,0,0),      0 },
 };
 
@@ -3206,6 +4227,25 @@ 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;
 
+  /* SCXTNUM_ELx registers.  */
+  if ((reg->value == CPENC (3, 3, C13, C0, 7)
+       || reg->value == CPENC (3, 0, C13, C0, 7)
+       || reg->value == CPENC (3, 4, C13, C0, 7)
+       || reg->value == CPENC (3, 6, C13, C0, 7)
+       || reg->value == CPENC (3, 5, C13, C0, 7))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SCXTNUM))
+      return FALSE;
+
+  /* ID_PFR2_EL1 register.  */
+  if (reg->value == CPENC(3, 0, C0, C3, 4)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_ID_PFR2))
+    return FALSE;
+
+  /* SSBS.  Values are from aarch64_sys_regs.  */
+  if (reg->value == CPEN_(3,C2,6)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SSBS))
+    return FALSE;
+
   /* Virtualization host extensions: system registers.  */
   if ((reg->value == CPENC (3, 4, C2, C0, 1)
        || reg->value == CPENC (3, 4, C13, C0, 1)
   /* Virtualization host extensions: system registers.  */
   if ((reg->value == CPENC (3, 4, C2, C0, 1)
        || reg->value == CPENC (3, 4, C13, C0, 1)
@@ -3298,9 +4338,132 @@ aarch64_sys_reg_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PROFILE))
     return FALSE;
 
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PROFILE))
     return FALSE;
 
+  /* ARMv8.3 Pointer authentication keys.  */
+  if ((reg->value == CPENC (3, 0, C2, C1, 0)
+       || reg->value == CPENC (3, 0, C2, C1, 1)
+       || reg->value == CPENC (3, 0, C2, C1, 2)
+       || reg->value == CPENC (3, 0, C2, C1, 3)
+       || reg->value == CPENC (3, 0, C2, C2, 0)
+       || reg->value == CPENC (3, 0, C2, C2, 1)
+       || reg->value == CPENC (3, 0, C2, C2, 2)
+       || reg->value == CPENC (3, 0, C2, C2, 3)
+       || reg->value == CPENC (3, 0, C2, C3, 0)
+       || reg->value == CPENC (3, 0, C2, C3, 1))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_3))
+    return FALSE;
+
+  /* SVE.  */
+  if ((reg->value == CPENC (3, 0, C0, C4, 4)
+       || reg->value == CPENC (3, 0, C1, C2, 0)
+       || reg->value == CPENC (3, 4, C1, C2, 0)
+       || reg->value == CPENC (3, 6, C1, C2, 0)
+       || reg->value == CPENC (3, 5, C1, C2, 0)
+       || reg->value == CPENC (3, 0, C0, C0, 7))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SVE))
+    return FALSE;
+
+  /* ARMv8.4 features.  */
+
+  /* PSTATE.DIT.  */
+  if (reg->value == CPEN_ (3, C2, 5)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* Virtualization extensions.  */
+  if ((reg->value == CPENC(3, 4, C2, C6, 2)
+       || reg->value == CPENC(3, 4, C2, C6, 0)
+       || reg->value == CPENC(3, 4, C14, C4, 0)
+       || reg->value == CPENC(3, 4, C14, C4, 2)
+       || reg->value == CPENC(3, 4, C14, C4, 1)
+       || reg->value == CPENC(3, 4, C14, C5, 0)
+       || reg->value == CPENC(3, 4, C14, C5, 2)
+       || reg->value == CPENC(3, 4, C14, C5, 1)
+       || reg->value == CPENC(3, 4, C1, C3, 1)
+       || reg->value == CPENC(3, 4, C2, C2, 0))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* ARMv8.4 TLB instructions.  */
+  if ((reg->value == CPENS (0, C8, C1, 0)
+       || reg->value == CPENS (0, C8, C1, 1)
+       || reg->value == CPENS (0, C8, C1, 2)
+       || reg->value == CPENS (0, C8, C1, 3)
+       || reg->value == CPENS (0, C8, C1, 5)
+       || reg->value == CPENS (0, C8, C1, 7)
+       || reg->value == CPENS (4, C8, C4, 0)
+       || reg->value == CPENS (4, C8, C4, 4)
+       || reg->value == CPENS (4, C8, C1, 1)
+       || reg->value == CPENS (4, C8, C1, 5)
+       || reg->value == CPENS (4, C8, C1, 6)
+       || reg->value == CPENS (6, C8, C1, 1)
+       || reg->value == CPENS (6, C8, C1, 5)
+       || reg->value == CPENS (4, C8, C1, 0)
+       || reg->value == CPENS (4, C8, C1, 4)
+       || reg->value == CPENS (6, C8, C1, 0)
+       || reg->value == CPENS (0, C8, C6, 1)
+       || reg->value == CPENS (0, C8, C6, 3)
+       || reg->value == CPENS (0, C8, C6, 5)
+       || reg->value == CPENS (0, C8, C6, 7)
+       || reg->value == CPENS (0, C8, C2, 1)
+       || reg->value == CPENS (0, C8, C2, 3)
+       || reg->value == CPENS (0, C8, C2, 5)
+       || reg->value == CPENS (0, C8, C2, 7)
+       || reg->value == CPENS (0, C8, C5, 1)
+       || reg->value == CPENS (0, C8, C5, 3)
+       || reg->value == CPENS (0, C8, C5, 5)
+       || reg->value == CPENS (0, C8, C5, 7)
+       || reg->value == CPENS (4, C8, C0, 2)
+       || reg->value == CPENS (4, C8, C0, 6)
+       || reg->value == CPENS (4, C8, C4, 2)
+       || reg->value == CPENS (4, C8, C4, 6)
+       || reg->value == CPENS (4, C8, C4, 3)
+       || reg->value == CPENS (4, C8, C4, 7)
+       || reg->value == CPENS (4, C8, C6, 1)
+       || reg->value == CPENS (4, C8, C6, 5)
+       || reg->value == CPENS (4, C8, C2, 1)
+       || reg->value == CPENS (4, C8, C2, 5)
+       || reg->value == CPENS (4, C8, C5, 1)
+       || reg->value == CPENS (4, C8, C5, 5)
+       || reg->value == CPENS (6, C8, C6, 1)
+       || reg->value == CPENS (6, C8, C6, 5)
+       || reg->value == CPENS (6, C8, C2, 1)
+       || reg->value == CPENS (6, C8, C2, 5)
+       || reg->value == CPENS (6, C8, C5, 1)
+       || reg->value == CPENS (6, C8, C5, 5))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* Random Number Instructions.  For now they are available
+     (and optional) only with ARMv8.5-A.  */
+  if ((reg->value == CPENC (3, 3, C2, C4, 0)
+       || reg->value == CPENC (3, 3, C2, C4, 1))
+      && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RNG)
+          && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_5)))
+    return FALSE;
+
+  /* System Registers in ARMv8.5-A with AARCH64_FEATURE_MEMTAG.  */
+  if ((reg->value == CPENC (3, 3, C4, C2, 7)
+       || reg->value == CPENC (3, 0, C5, C6, 1)
+       || reg->value == CPENC (3, 0, C5, C6, 0)
+       || reg->value == CPENC (3, 4, C5, C6, 0)
+       || reg->value == CPENC (3, 6, C5, C6, 0)
+       || reg->value == CPENC (3, 5, C5, C6, 0)
+       || reg->value == CPENC (3, 0, C1, C0, 5)
+       || reg->value == CPENC (3, 0, C1, C0, 6)
+       || reg->value == CPENC (3, 1, C0, C0, 4))
+      && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG)))
+    return FALSE;
+
   return TRUE;
 }
 
   return TRUE;
 }
 
+/* The CPENC below is fairly misleading, the fields
+   here are not in CPENC form. They are in op2op1 form. The fields are encoded
+   by ins_pstatefield, which just shifts the value by the width of the fields
+   in a loop. So if you CPENC them only the first value will be set, the rest
+   are masked out to 0. As an example. op2 = 3, op1=2. CPENC would produce a
+   value of 0b110000000001000000 (0x30040) while what you want is
+   0b011010 (0x1a).  */
 const aarch64_sys_reg aarch64_pstatefields [] =
 {
   { "spsel",            0x05,  0 },
 const aarch64_sys_reg aarch64_pstatefields [] =
 {
   { "spsel",            0x05,  0 },
@@ -3308,6 +4471,9 @@ const aarch64_sys_reg aarch64_pstatefields [] =
   { "daifclr",          0x1f,  0 },
   { "pan",             0x04,   F_ARCHEXT },
   { "uao",             0x03,   F_ARCHEXT },
   { "daifclr",          0x1f,  0 },
   { "pan",             0x04,   F_ARCHEXT },
   { "uao",             0x03,   F_ARCHEXT },
+  { "ssbs",            0x19,   F_ARCHEXT },
+  { "dit",             0x1a,   F_ARCHEXT },
+  { "tco",             0x1c,   F_ARCHEXT },
   { 0,          CPENC(0,0,0,0,0), 0 },
 };
 
   { 0,          CPENC(0,0,0,0,0), 0 },
 };
 
@@ -3328,6 +4494,21 @@ aarch64_pstatefield_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
     return FALSE;
 
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
     return FALSE;
 
+  /* SSBS.  Values are from aarch64_pstatefields.  */
+  if (reg->value == 0x19
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SSBS))
+    return FALSE;
+
+  /* DIT.  Values are from aarch64_pstatefields.  */
+  if (reg->value == 0x1a
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* TCO.  Values are from aarch64_pstatefields.  */
+  if (reg->value == 0x1c
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG))
+    return FALSE;
+
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -3342,14 +4523,33 @@ const aarch64_sys_ins_reg aarch64_sys_regs_ic[] =
 const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
 {
     { "zva",       CPENS (3, C7, C4, 1),  F_HASXT },
 const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
 {
     { "zva",       CPENS (3, C7, C4, 1),  F_HASXT },
+    { "gva",       CPENS (3, C7, C4, 3),  F_HASXT | F_ARCHEXT },
+    { "gzva",      CPENS (3, C7, C4, 4),  F_HASXT | F_ARCHEXT },
     { "ivac",       CPENS (0, C7, C6, 1),  F_HASXT },
     { "ivac",       CPENS (0, C7, C6, 1),  F_HASXT },
+    { "igvac",      CPENS (0, C7, C6, 3),  F_HASXT | F_ARCHEXT },
+    { "igsw",       CPENS (0, C7, C6, 4),  F_HASXT | F_ARCHEXT },
     { "isw",       CPENS (0, C7, C6, 2),  F_HASXT },
     { "isw",       CPENS (0, C7, C6, 2),  F_HASXT },
+    { "igdvac",            CPENS (0, C7, C6, 5),  F_HASXT | F_ARCHEXT },
+    { "igdsw",     CPENS (0, C7, C6, 6),  F_HASXT | F_ARCHEXT },
     { "cvac",       CPENS (3, C7, C10, 1), F_HASXT },
     { "cvac",       CPENS (3, C7, C10, 1), F_HASXT },
+    { "cgvac",      CPENS (3, C7, C10, 3), F_HASXT | F_ARCHEXT },
+    { "cgdvac",     CPENS (3, C7, C10, 5), F_HASXT | F_ARCHEXT },
     { "csw",       CPENS (0, C7, C10, 2), F_HASXT },
     { "csw",       CPENS (0, C7, C10, 2), F_HASXT },
+    { "cgsw",       CPENS (0, C7, C10, 4), F_HASXT | F_ARCHEXT },
+    { "cgdsw",     CPENS (0, C7, C10, 6), F_HASXT | F_ARCHEXT },
     { "cvau",       CPENS (3, C7, C11, 1), F_HASXT },
     { "cvap",       CPENS (3, C7, C12, 1), F_HASXT | F_ARCHEXT },
     { "cvau",       CPENS (3, C7, C11, 1), F_HASXT },
     { "cvap",       CPENS (3, C7, C12, 1), F_HASXT | F_ARCHEXT },
+    { "cgvap",      CPENS (3, C7, C12, 3), F_HASXT | F_ARCHEXT },
+    { "cgdvap",     CPENS (3, C7, C12, 5), F_HASXT | F_ARCHEXT },
+    { "cvadp",      CPENS (3, C7, C13, 1), F_HASXT | F_ARCHEXT },
+    { "cgvadp",     CPENS (3, C7, C13, 3), F_HASXT | F_ARCHEXT },
+    { "cgdvadp",    CPENS (3, C7, C13, 5), F_HASXT | F_ARCHEXT },
     { "civac",      CPENS (3, C7, C14, 1), F_HASXT },
     { "civac",      CPENS (3, C7, C14, 1), F_HASXT },
+    { "cigvac",     CPENS (3, C7, C14, 3), F_HASXT | F_ARCHEXT },
+    { "cigdvac",    CPENS (3, C7, C14, 5), F_HASXT | F_ARCHEXT },
     { "cisw",       CPENS (0, C7, C14, 2), F_HASXT },
     { "cisw",       CPENS (0, C7, C14, 2), F_HASXT },
+    { "cigsw",      CPENS (0, C7, C14, 4), F_HASXT | F_ARCHEXT },
+    { "cigdsw",     CPENS (0, C7, C14, 6), F_HASXT | F_ARCHEXT },
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
@@ -3406,6 +4606,66 @@ const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
     { "vale2",     CPENS (4, C8, C7, 5), F_HASXT },
     { "vale3",     CPENS (6, C8, C7, 5), F_HASXT },
     { "vaale1",    CPENS (0, C8, C7, 7), 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 },
+
+    { "vmalle1os",    CPENS (0, C8, C1, 0), F_ARCHEXT },
+    { "vae1os",       CPENS (0, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "aside1os",     CPENS (0, C8, C1, 2), F_HASXT | F_ARCHEXT },
+    { "vaae1os",      CPENS (0, C8, C1, 3), F_HASXT | F_ARCHEXT },
+    { "vale1os",      CPENS (0, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "vaale1os",     CPENS (0, C8, C1, 7), F_HASXT | F_ARCHEXT },
+    { "ipas2e1os",    CPENS (4, C8, C4, 0), F_HASXT | F_ARCHEXT },
+    { "ipas2le1os",   CPENS (4, C8, C4, 4), F_HASXT | F_ARCHEXT },
+    { "vae2os",       CPENS (4, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "vale2os",      CPENS (4, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "vmalls12e1os", CPENS (4, C8, C1, 6), F_ARCHEXT },
+    { "vae3os",       CPENS (6, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "vale3os",      CPENS (6, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "alle2os",      CPENS (4, C8, C1, 0), F_ARCHEXT },
+    { "alle1os",      CPENS (4, C8, C1, 4), F_ARCHEXT },
+    { "alle3os",      CPENS (6, C8, C1, 0), F_ARCHEXT },
+
+    { "rvae1",      CPENS (0, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1",     CPENS (0, C8, C6, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1",     CPENS (0, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1",    CPENS (0, C8, C6, 7), F_HASXT | F_ARCHEXT },
+    { "rvae1is",    CPENS (0, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1is",   CPENS (0, C8, C2, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1is",   CPENS (0, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1is",  CPENS (0, C8, C2, 7), F_HASXT | F_ARCHEXT },
+    { "rvae1os",    CPENS (0, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1os",   CPENS (0, C8, C5, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1os",   CPENS (0, C8, C5, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1os",  CPENS (0, C8, C5, 7), F_HASXT | F_ARCHEXT },
+    { "ripas2e1is", CPENS (4, C8, C0, 2), F_HASXT | F_ARCHEXT },
+    { "ripas2le1is",CPENS (4, C8, C0, 6), F_HASXT | F_ARCHEXT },
+    { "ripas2e1",   CPENS (4, C8, C4, 2), F_HASXT | F_ARCHEXT },
+    { "ripas2le1",  CPENS (4, C8, C4, 6), F_HASXT | F_ARCHEXT },
+    { "ripas2e1os", CPENS (4, C8, C4, 3), F_HASXT | F_ARCHEXT },
+    { "ripas2le1os",CPENS (4, C8, C4, 7), F_HASXT | F_ARCHEXT },
+    { "rvae2",      CPENS (4, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2",     CPENS (4, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvae2is",    CPENS (4, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2is",   CPENS (4, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvae2os",    CPENS (4, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2os",   CPENS (4, C8, C5, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3",      CPENS (6, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3",     CPENS (6, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3is",    CPENS (6, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3is",   CPENS (6, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3os",    CPENS (6, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3os",   CPENS (6, C8, C5, 5), F_HASXT | F_ARCHEXT },
+
+    { 0,       CPENS(0,0,0,0), 0 }
+};
+
+const aarch64_sys_ins_reg aarch64_sys_regs_sr[] =
+{
+    /* RCTX is somewhat unique in a way that it has different values
+       (op2) based on the instruction in which it is used (cfp/dvp/cpp).
+       Thus op2 is masked out and instead encoded directly in the
+       aarch64_opcode_table entries for the respective instructions.  */
+    { "rctx",   CPENS(3,C7,C3,0), F_HASXT | F_ARCHEXT | F_REG_WRITE}, /* WO */
+
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
@@ -3427,12 +4687,44 @@ aarch64_sys_ins_reg_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
     return FALSE;
 
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
     return FALSE;
 
+  /* DC CVADP.  Values are from aarch64_sys_regs_dc.  */
+  if (reg->value == CPENS (3, C7, C13, 1)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_CVADP))
+    return FALSE;
+
+  /* DC <dc_op> for ARMv8.5-A Memory Tagging Extension.  */
+  if ((reg->value == CPENS (0, C7, C6, 3)
+       || reg->value == CPENS (0, C7, C6, 4)
+       || reg->value == CPENS (0, C7, C10, 4)
+       || reg->value == CPENS (0, C7, C14, 4)
+       || reg->value == CPENS (3, C7, C10, 3)
+       || reg->value == CPENS (3, C7, C12, 3)
+       || reg->value == CPENS (3, C7, C13, 3)
+       || reg->value == CPENS (3, C7, C14, 3)
+       || reg->value == CPENS (3, C7, C4, 3)
+       || reg->value == CPENS (0, C7, C6, 5)
+       || reg->value == CPENS (0, C7, C6, 6)
+       || reg->value == CPENS (0, C7, C10, 6)
+       || reg->value == CPENS (0, C7, C14, 6)
+       || reg->value == CPENS (3, C7, C10, 5)
+       || reg->value == CPENS (3, C7, C12, 5)
+       || reg->value == CPENS (3, C7, C13, 5)
+       || reg->value == CPENS (3, C7, C14, 5)
+       || reg->value == CPENS (3, C7, C4, 4))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG))
+    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;
 
   /* 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;
 
+  /* CFP/DVP/CPP RCTX : Value are from aarch64_sys_regs_sr. */
+  if (reg->value == CPENS (3, C7, C3, 0)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PREDRES))
+    return FALSE;
+
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -3456,9 +4748,12 @@ aarch64_sys_ins_reg_supported_p (const aarch64_feature_set features,
 #define BIT(INSN,BT)     (((INSN) >> (BT)) & 1)
 #define BITS(INSN,HI,LO) (((INSN) >> (LO)) & ((1 << (((HI) - (LO)) + 1)) - 1))
 
 #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)
+static enum err_type
+verify_ldpsw (const struct aarch64_inst *inst ATTRIBUTE_UNUSED,
+             const aarch64_insn insn, bfd_vma pc ATTRIBUTE_UNUSED,
+             bfd_boolean encoding ATTRIBUTE_UNUSED,
+             aarch64_operand_error *mismatch_detail ATTRIBUTE_UNUSED,
+             aarch64_instr_sequence *insn_sequence ATTRIBUTE_UNUSED)
 {
   int t  = BITS (insn, 4, 0);
   int n  = BITS (insn, 9, 5);
 {
   int t  = BITS (insn, 4, 0);
   int n  = BITS (insn, 9, 5);
@@ -3468,17 +4763,395 @@ verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED,
     {
       /* Write back enabled.  */
       if ((t == n || t2 == n) && n != 31)
     {
       /* Write back enabled.  */
       if ((t == n || t2 == n) && n != 31)
-       return FALSE;
+       return ERR_UND;
     }
 
   if (BIT (insn, 22))
     {
       /* Load */
       if (t == t2)
     }
 
   if (BIT (insn, 22))
     {
       /* Load */
       if (t == t2)
-       return FALSE;
+       return ERR_UND;
     }
 
     }
 
-  return TRUE;
+  return ERR_OK;
+}
+
+/* Verifier for vector by element 3 operands functions where the
+   conditions `if sz:L == 11 then UNDEFINED` holds.  */
+
+static enum err_type
+verify_elem_sd (const struct aarch64_inst *inst, const aarch64_insn insn,
+               bfd_vma pc ATTRIBUTE_UNUSED, bfd_boolean encoding,
+               aarch64_operand_error *mismatch_detail ATTRIBUTE_UNUSED,
+               aarch64_instr_sequence *insn_sequence ATTRIBUTE_UNUSED)
+{
+  const aarch64_insn undef_pattern = 0x3;
+  aarch64_insn value;
+
+  assert (inst->opcode);
+  assert (inst->opcode->operands[2] == AARCH64_OPND_Em);
+  value = encoding ? inst->value : insn;
+  assert (value);
+
+  if (undef_pattern == extract_fields (value, 0, 2, FLD_sz, FLD_L))
+    return ERR_UND;
+
+  return ERR_OK;
+}
+
+/* Initialize an instruction sequence insn_sequence with the instruction INST.
+   If INST is NULL the given insn_sequence is cleared and the sequence is left
+   uninitialized.  */
+
+void
+init_insn_sequence (const struct aarch64_inst *inst,
+                   aarch64_instr_sequence *insn_sequence)
+{
+  int num_req_entries = 0;
+  insn_sequence->next_insn = 0;
+  insn_sequence->num_insns = num_req_entries;
+  if (insn_sequence->instr)
+    XDELETE (insn_sequence->instr);
+  insn_sequence->instr = NULL;
+
+  if (inst)
+    {
+      insn_sequence->instr = XNEW (aarch64_inst);
+      memcpy (insn_sequence->instr, inst, sizeof (aarch64_inst));
+    }
+
+  /* Handle all the cases here.  May need to think of something smarter than
+     a giant if/else chain if this grows.  At that time, a lookup table may be
+     best.  */
+  if (inst && inst->opcode->constraints & C_SCAN_MOVPRFX)
+    num_req_entries = 1;
+
+  if (insn_sequence->current_insns)
+    XDELETEVEC (insn_sequence->current_insns);
+  insn_sequence->current_insns = NULL;
+
+  if (num_req_entries != 0)
+    {
+      size_t size = num_req_entries * sizeof (aarch64_inst);
+      insn_sequence->current_insns
+       = (aarch64_inst**) XNEWVEC (aarch64_inst, num_req_entries);
+      memset (insn_sequence->current_insns, 0, size);
+    }
+}
+
+
+/*  This function verifies that the instruction INST adheres to its specified
+    constraints.  If it does then ERR_OK is returned, if not then ERR_VFI is
+    returned and MISMATCH_DETAIL contains the reason why verification failed.
+
+    The function is called both during assembly and disassembly.  If assembling
+    then ENCODING will be TRUE, else FALSE.  If dissassembling PC will be set
+    and will contain the PC of the current instruction w.r.t to the section.
+
+    If ENCODING and PC=0 then you are at a start of a section.  The constraints
+    are verified against the given state insn_sequence which is updated as it
+    transitions through the verification.  */
+
+enum err_type
+verify_constraints (const struct aarch64_inst *inst,
+                   const aarch64_insn insn ATTRIBUTE_UNUSED,
+                   bfd_vma pc,
+                   bfd_boolean encoding,
+                   aarch64_operand_error *mismatch_detail,
+                   aarch64_instr_sequence *insn_sequence)
+{
+  assert (inst);
+  assert (inst->opcode);
+
+  const struct aarch64_opcode *opcode = inst->opcode;
+  if (!opcode->constraints && !insn_sequence->instr)
+    return ERR_OK;
+
+  assert (insn_sequence);
+
+  enum err_type res = ERR_OK;
+
+  /* This instruction puts a constraint on the insn_sequence.  */
+  if (opcode->flags & F_SCAN)
+    {
+      if (insn_sequence->instr)
+       {
+         mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+         mismatch_detail->error = _("instruction opens new dependency "
+                                    "sequence without ending previous one");
+         mismatch_detail->index = -1;
+         mismatch_detail->non_fatal = TRUE;
+         res = ERR_VFI;
+       }
+
+      init_insn_sequence (inst, insn_sequence);
+      return res;
+    }
+
+  /* Verify constraints on an existing sequence.  */
+  if (insn_sequence->instr)
+    {
+      const struct aarch64_opcode* inst_opcode = insn_sequence->instr->opcode;
+      /* If we're decoding and we hit PC=0 with an open sequence then we haven't
+        closed a previous one that we should have.  */
+      if (!encoding && pc == 0)
+       {
+         mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+         mismatch_detail->error = _("previous `movprfx' sequence not closed");
+         mismatch_detail->index = -1;
+         mismatch_detail->non_fatal = TRUE;
+         res = ERR_VFI;
+         /* Reset the sequence.  */
+         init_insn_sequence (NULL, insn_sequence);
+         return res;
+       }
+
+      /* Validate C_SCAN_MOVPRFX constraints.  Move this to a lookup table.  */
+      if (inst_opcode->constraints & C_SCAN_MOVPRFX)
+       {
+         /* Check to see if the MOVPRFX SVE instruction is followed by an SVE
+            instruction for better error messages.  */
+         if (!opcode->avariant
+             || !(*opcode->avariant &
+                  (AARCH64_FEATURE_SVE | AARCH64_FEATURE_SVE2)))
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("SVE instruction expected after "
+                                        "`movprfx'");
+             mismatch_detail->index = -1;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+
+         /* Check to see if the MOVPRFX SVE instruction is followed by an SVE
+            instruction that is allowed to be used with a MOVPRFX.  */
+         if (!(opcode->constraints & C_SCAN_MOVPRFX))
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("SVE `movprfx' compatible instruction "
+                                        "expected");
+             mismatch_detail->index = -1;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+
+         /* Next check for usage of the predicate register.  */
+         aarch64_opnd_info blk_dest = insn_sequence->instr->operands[0];
+         aarch64_opnd_info blk_pred, inst_pred;
+         memset (&blk_pred, 0, sizeof (aarch64_opnd_info));
+         memset (&inst_pred, 0, sizeof (aarch64_opnd_info));
+         bfd_boolean predicated = FALSE;
+         assert (blk_dest.type == AARCH64_OPND_SVE_Zd);
+
+         /* Determine if the movprfx instruction used is predicated or not.  */
+         if (insn_sequence->instr->operands[1].type == AARCH64_OPND_SVE_Pg3)
+           {
+             predicated = TRUE;
+             blk_pred = insn_sequence->instr->operands[1];
+           }
+
+         unsigned char max_elem_size = 0;
+         unsigned char current_elem_size;
+         int num_op_used = 0, last_op_usage = 0;
+         int i, inst_pred_idx = -1;
+         int num_ops = aarch64_num_of_operands (opcode);
+         for (i = 0; i < num_ops; i++)
+           {
+             aarch64_opnd_info inst_op = inst->operands[i];
+             switch (inst_op.type)
+               {
+                 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:
+                 case AARCH64_OPND_SVE_Vm:
+                 case AARCH64_OPND_SVE_Vn:
+                 case AARCH64_OPND_Va:
+                 case AARCH64_OPND_Vn:
+                 case AARCH64_OPND_Vm:
+                 case AARCH64_OPND_Sn:
+                 case AARCH64_OPND_Sm:
+                   if (inst_op.reg.regno == blk_dest.reg.regno)
+                     {
+                       num_op_used++;
+                       last_op_usage = i;
+                     }
+                   current_elem_size
+                     = aarch64_get_qualifier_esize (inst_op.qualifier);
+                   if (current_elem_size > max_elem_size)
+                     max_elem_size = current_elem_size;
+                   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:
+                   inst_pred = inst_op;
+                   inst_pred_idx = i;
+                   break;
+                 default:
+                   break;
+               }
+           }
+
+          assert (max_elem_size != 0);
+          aarch64_opnd_info inst_dest = inst->operands[0];
+          /* Determine the size that should be used to compare against the
+             movprfx size.  */
+          current_elem_size
+            = opcode->constraints & C_MAX_ELEM
+              ? max_elem_size
+              : aarch64_get_qualifier_esize (inst_dest.qualifier);
+
+         /* If movprfx is predicated do some extra checks.  */
+         if (predicated)
+           {
+             /* The instruction must be predicated.  */
+             if (inst_pred_idx < 0)
+               {
+                 mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+                 mismatch_detail->error = _("predicated instruction expected "
+                                            "after `movprfx'");
+                 mismatch_detail->index = -1;
+                 mismatch_detail->non_fatal = TRUE;
+                 res = ERR_VFI;
+                 goto done;
+               }
+
+             /* The instruction must have a merging predicate.  */
+             if (inst_pred.qualifier != AARCH64_OPND_QLF_P_M)
+               {
+                 mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+                 mismatch_detail->error = _("merging predicate expected due "
+                                            "to preceding `movprfx'");
+                 mismatch_detail->index = inst_pred_idx;
+                 mismatch_detail->non_fatal = TRUE;
+                 res = ERR_VFI;
+                 goto done;
+               }
+
+             /* The same register must be used in instruction.  */
+             if (blk_pred.reg.regno != inst_pred.reg.regno)
+               {
+                 mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+                 mismatch_detail->error = _("predicate register differs "
+                                            "from that in preceding "
+                                            "`movprfx'");
+                 mismatch_detail->index = inst_pred_idx;
+                 mismatch_detail->non_fatal = TRUE;
+                 res = ERR_VFI;
+                 goto done;
+               }
+           }
+
+         /* Destructive operations by definition must allow one usage of the
+            same register.  */
+         int allowed_usage
+           = aarch64_is_destructive_by_operands (opcode) ? 2 : 1;
+
+         /* Operand is not used at all.  */
+         if (num_op_used == 0)
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("output register of preceding "
+                                        "`movprfx' not used in current "
+                                        "instruction");
+             mismatch_detail->index = 0;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+
+         /* We now know it's used, now determine exactly where it's used.  */
+         if (blk_dest.reg.regno != inst_dest.reg.regno)
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("output register of preceding "
+                                        "`movprfx' expected as output");
+             mismatch_detail->index = 0;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+
+         /* Operand used more than allowed for the specific opcode type.  */
+         if (num_op_used > allowed_usage)
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("output register of preceding "
+                                        "`movprfx' used as input");
+             mismatch_detail->index = last_op_usage;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+
+         /* Now the only thing left is the qualifiers checks.  The register
+            must have the same maximum element size.  */
+         if (inst_dest.qualifier
+             && blk_dest.qualifier
+             && current_elem_size
+                != aarch64_get_qualifier_esize (blk_dest.qualifier))
+           {
+             mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+             mismatch_detail->error = _("register size not compatible with "
+                                        "previous `movprfx'");
+             mismatch_detail->index = 0;
+             mismatch_detail->non_fatal = TRUE;
+             res = ERR_VFI;
+             goto done;
+           }
+       }
+
+done:
+      /* Add the new instruction to the sequence.  */
+      memcpy (insn_sequence->current_insns + insn_sequence->next_insn++,
+             inst, sizeof (aarch64_inst));
+
+      /* Check if sequence is now full.  */
+      if (insn_sequence->next_insn >= insn_sequence->num_insns)
+       {
+         /* Sequence is full, but we don't have anything special to do for now,
+            so clear and reset it.  */
+         init_insn_sequence (NULL, insn_sequence);
+       }
+    }
+
+  return res;
+}
+
+
+/* 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
 }
 
 /* Include the opcode description table as well as the operand description
This page took 0.096679 seconds and 4 git commands to generate.