gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / aarch64-dis.c
index c3670fe78b25df9a0d6ebc8171117ddf3ead175e..6567880efbaaeea5e1f2aa026df99059e9bb7471 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-dis.c -- AArch64 disassembler.
 /* aarch64-dis.c -- AArch64 disassembler.
-   Copyright (C) 2009-2014 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 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 "sysdep.h"
 #include "bfd_stdint.h"
 
 #include "sysdep.h"
 #include "bfd_stdint.h"
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "libiberty.h"
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
 
 #include "libiberty.h"
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
 
-#define ERR_OK   0
-#define ERR_UND -1
-#define ERR_UNP -3
-#define ERR_NYI -5
-
 #define INSNLEN 4
 
 /* Cached mapping symbol state.  */
 #define INSNLEN 4
 
 /* Cached mapping symbol state.  */
@@ -42,11 +37,16 @@ enum map_type
 
 static enum map_type last_type;
 static int last_mapping_sym = -1;
 
 static enum map_type last_type;
 static int last_mapping_sym = -1;
+static bfd_vma last_stop_offset = 0;
 static bfd_vma last_mapping_addr = 0;
 
 /* Other options */
 static int no_aliases = 0;     /* If set disassemble as most general inst.  */
 static bfd_vma last_mapping_addr = 0;
 
 /* Other options */
 static int no_aliases = 0;     /* If set disassemble as most general inst.  */
-\f
+\fstatic int no_notes = 1;      /* If set do not print disassemble notes in the
+                                 output as comments.  */
+
+/* Currently active instruction sequence.  */
+static aarch64_instr_sequence insn_sequence;
 
 static void
 set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
 
 static void
 set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
@@ -69,6 +69,18 @@ parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
       return;
     }
 
       return;
     }
 
+  if (CONST_STRNEQ (option, "no-notes"))
+    {
+      no_notes = 1;
+      return;
+    }
+
+  if (CONST_STRNEQ (option, "notes"))
+    {
+      no_notes = 0;
+      return;
+    }
+
 #ifdef DEBUG_AARCH64
   if (CONST_STRNEQ (option, "debug_dump"))
     {
 #ifdef DEBUG_AARCH64
   if (CONST_STRNEQ (option, "debug_dump"))
     {
@@ -78,7 +90,7 @@ parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
 #endif /* DEBUG_AARCH64 */
 
   /* Invalid option.  */
 #endif /* DEBUG_AARCH64 */
 
   /* Invalid option.  */
-  fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
+  opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
 }
 
 static void
 }
 
 static void
@@ -123,7 +135,7 @@ parse_aarch64_dis_options (const char *options)
    is encoded in H:L:M in some cases, the fields H:L:M should be passed in
    the order of H, L, M.  */
 
    is encoded in H:L:M in some cases, the fields H:L:M should be passed in
    the order of H, L, M.  */
 
-static inline aarch64_insn
+aarch64_insn
 extract_fields (aarch64_insn code, aarch64_insn mask, ...)
 {
   uint32_t num;
 extract_fields (aarch64_insn code, aarch64_insn mask, ...)
 {
   uint32_t num;
@@ -145,19 +157,36 @@ extract_fields (aarch64_insn code, aarch64_insn mask, ...)
   return value;
 }
 
   return value;
 }
 
+/* Extract the value of all fields in SELF->fields from instruction CODE.
+   The least significant bit comes from the final field.  */
+
+static aarch64_insn
+extract_all_fields (const aarch64_operand *self, aarch64_insn code)
+{
+  aarch64_insn value;
+  unsigned int i;
+  enum aarch64_field_kind kind;
+
+  value = 0;
+  for (i = 0; i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i)
+    {
+      kind = self->fields[i];
+      value <<= fields[kind].width;
+      value |= extract_field (kind, code, 0);
+    }
+  return value;
+}
+
 /* Sign-extend bit I of VALUE.  */
 /* Sign-extend bit I of VALUE.  */
-static inline int32_t
+static inline uint64_t
 sign_extend (aarch64_insn value, unsigned i)
 {
 sign_extend (aarch64_insn value, unsigned i)
 {
-  uint32_t ret = value;
+  uint64_t ret, sign;
 
   assert (i < 32);
 
   assert (i < 32);
-  if ((value >> i) & 0x1)
-    {
-      uint32_t val = (uint32_t)(-1) << i;
-      ret = ret | val;
-    }
-  return (int32_t) ret;
+  ret = value;
+  sign = (uint64_t) 1 << i;
+  return ((ret & (sign + sign - 1)) ^ sign) - sign;
 }
 
 /* N.B. the following inline helpfer functions create a dependency on the
 }
 
 /* N.B. the following inline helpfer functions create a dependency on the
@@ -173,12 +202,19 @@ get_greg_qualifier_from_value (aarch64_insn value)
   return qualifier;
 }
 
   return qualifier;
 }
 
-/* Given VALUE, return qualifier for a vector register.  */
+/* Given VALUE, return qualifier for a vector register.  This does not support
+   decoding instructions that accept the 2H vector type.  */
+
 static inline enum aarch64_opnd_qualifier
 get_vreg_qualifier_from_value (aarch64_insn value)
 {
   enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
 
 static inline enum aarch64_opnd_qualifier
 get_vreg_qualifier_from_value (aarch64_insn value)
 {
   enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
 
+  /* Instructions using vector type 2H should not call this function.  Skip over
+     the 2H qualifier.  */
+  if (qualifier >= AARCH64_OPND_QLF_V_2H)
+    qualifier += 1;
+
   assert (value <= 0x8
          && aarch64_get_qualifier_standard_value (qualifier) == value);
   return qualifier;
   assert (value <= 0x8
          && aarch64_get_qualifier_standard_value (qualifier) == value);
   return qualifier;
@@ -215,20 +251,44 @@ get_expected_qualifier (const aarch64_inst *inst, int i)
 
 /* Operand extractors.  */
 
 
 /* Operand extractors.  */
 
-int
+bfd_boolean
+aarch64_ext_none (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                 aarch64_opnd_info *info ATTRIBUTE_UNUSED,
+                 const aarch64_insn code ATTRIBUTE_UNUSED,
+                 const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+bfd_boolean
 aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
                   const aarch64_insn code,
 aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
                   const aarch64_insn code,
-                  const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   info->reg.regno = extract_field (self->fields[0], code, 0);
 {
   info->reg.regno = extract_field (self->fields[0], code, 0);
-  return 1;
+  return TRUE;
+}
+
+bfd_boolean
+aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info,
+                  const aarch64_insn code ATTRIBUTE_UNUSED,
+                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  assert (info->idx == 1
+         || info->idx ==3);
+  info->reg.regno = inst->operands[info->idx - 1].reg.regno + 1;
+  return TRUE;
 }
 
 /* e.g. IC <ic_op>{, <Xt>}.  */
 }
 
 /* e.g. IC <ic_op>{, <Xt>}.  */
-int
+bfd_boolean
 aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
                          const aarch64_insn code,
 aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
                          const aarch64_insn code,
-                         const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                         const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                         aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   info->reg.regno = extract_field (self->fields[0], code, 0);
   assert (info->idx == 1
 {
   info->reg.regno = extract_field (self->fields[0], code, 0);
   assert (info->idx == 1
@@ -237,16 +297,17 @@ aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
   /* This will make the constraint checking happy and more importantly will
      help the disassembler determine whether this operand is optional or
      not.  */
   /* This will make the constraint checking happy and more importantly will
      help the disassembler determine whether this operand is optional or
      not.  */
-  info->present = inst->operands[0].sysins_op->has_xt;
+  info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op);
 
 
-  return 1;
+  return TRUE;
 }
 
 /* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>].  */
 }
 
 /* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>].  */
-int
+bfd_boolean
 aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
                     const aarch64_insn code,
 aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
                     const aarch64_insn code,
-                    const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                    const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                    aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* regno */
   info->reglane.regno = extract_field (self->fields[0], code,
 {
   /* regno */
   info->reglane.regno = extract_field (self->fields[0], code,
@@ -282,11 +343,32 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
          while (++pos <= 3 && (value & 0x1) == 0)
            value >>= 1;
          if (pos > 3)
          while (++pos <= 3 && (value & 0x1) == 0)
            value >>= 1;
          if (pos > 3)
-           return 0;
+           return FALSE;
          info->qualifier = get_sreg_qualifier_from_value (pos);
          info->reglane.index = (unsigned) (value >> 1);
        }
     }
          info->qualifier = get_sreg_qualifier_from_value (pos);
          info->reglane.index = (unsigned) (value >> 1);
        }
     }
+  else if (inst->opcode->iclass == dotproduct)
+    {
+      /* Need information in other operand(s) to help decoding.  */
+      info->qualifier = get_expected_qualifier (inst, info->idx);
+      switch (info->qualifier)
+       {
+       case AARCH64_OPND_QLF_S_4B:
+       case AARCH64_OPND_QLF_S_2H:
+         /* L:H */
+         info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
+         info->reglane.regno &= 0x1f;
+         break;
+       default:
+         return FALSE;
+       }
+    }
+  else if (inst->opcode->iclass == cryptosm3)
+    {
+      /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>].  */
+      info->reglane.index = extract_field (FLD_SM3_imm2, code, 0);
+    }
   else
     {
       /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
   else
     {
       /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
@@ -297,10 +379,18 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
       switch (info->qualifier)
        {
        case AARCH64_OPND_QLF_S_H:
       switch (info->qualifier)
        {
        case AARCH64_OPND_QLF_S_H:
-         /* h:l:m */
-         info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
-                                               FLD_M);
-         info->reglane.regno &= 0xf;
+         if (info->type == AARCH64_OPND_Em16)
+           {
+             /* h:l:m */
+             info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
+                                                   FLD_M);
+             info->reglane.regno &= 0xf;
+           }
+         else
+           {
+             /* h:l */
+             info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
+           }
          break;
        case AARCH64_OPND_QLF_S_S:
          /* h:l */
          break;
        case AARCH64_OPND_QLF_S_S:
          /* h:l */
@@ -311,30 +401,41 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
          info->reglane.index = extract_field (FLD_H, code, 0);
          break;
        default:
          info->reglane.index = extract_field (FLD_H, code, 0);
          break;
        default:
-         return 0;
+         return FALSE;
+       }
+
+      if (inst->opcode->op == OP_FCMLA_ELEM
+         && info->qualifier != AARCH64_OPND_QLF_S_H)
+       {
+         /* Complex operand takes two elements.  */
+         if (info->reglane.index & 1)
+           return FALSE;
+         info->reglane.index /= 2;
        }
     }
 
        }
     }
 
-  return 1;
+  return TRUE;
 }
 
 }
 
-int
+bfd_boolean
 aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
                     const aarch64_insn code,
 aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
                     const aarch64_insn code,
-                    const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                    const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                    aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* R */
   info->reglist.first_regno = extract_field (self->fields[0], code, 0);
   /* len */
   info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
 {
   /* R */
   info->reglist.first_regno = extract_field (self->fields[0], code, 0);
   /* len */
   info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
-  return 1;
+  return TRUE;
 }
 
 /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions.  */
 }
 
 /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions.  */
-int
+bfd_boolean
 aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                          aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                          aarch64_opnd_info *info, const aarch64_insn code,
-                         const aarch64_inst *inst)
+                         const aarch64_inst *inst,
+                         aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn value;
   /* Number of elements in each structure to be loaded/stored.  */
 {
   aarch64_insn value;
   /* Number of elements in each structure to be loaded/stored.  */
@@ -363,19 +464,23 @@ aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
   info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
   /* opcode */
   value = extract_field (FLD_opcode, code, 0);
   info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
   /* opcode */
   value = extract_field (FLD_opcode, code, 0);
+  /* PR 21595: Check for a bogus value.  */
+  if (value >= ARRAY_SIZE (data))
+    return FALSE;
   if (expected_num != data[value].num_elements || data[value].is_reserved)
   if (expected_num != data[value].num_elements || data[value].is_reserved)
-    return 0;
+    return FALSE;
   info->reglist.num_regs = data[value].num_regs;
 
   info->reglist.num_regs = data[value].num_regs;
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all
    lanes instructions.  */
 }
 
 /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all
    lanes instructions.  */
-int
+bfd_boolean
 aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
                            aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
                            aarch64_opnd_info *info, const aarch64_insn code,
-                           const aarch64_inst *inst)
+                           const aarch64_inst *inst,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn value;
 
 {
   aarch64_insn value;
 
@@ -393,15 +498,16 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
   if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
     info->reglist.num_regs = 2;
 
   if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
     info->reglist.num_regs = 2;
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
    load/store single element instructions.  */
 }
 
 /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
    load/store single element instructions.  */
-int
+bfd_boolean
 aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                           aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                           aarch64_opnd_info *info, const aarch64_insn code,
-                          const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                          const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                          aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_field field = {0, 0};
   aarch64_insn QSsize;         /* fields Q:S:size.  */
 {
   aarch64_field field = {0, 0};
   aarch64_insn QSsize;         /* fields Q:S:size.  */
@@ -424,7 +530,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
     case 0x1:
       if (QSsize & 0x1)
        /* UND.  */
     case 0x1:
       if (QSsize & 0x1)
        /* UND.  */
-       return 0;
+       return FALSE;
       info->qualifier = AARCH64_OPND_QLF_S_H;
       /* Index encoded in "Q:S:size<1>".  */
       info->reglist.index = QSsize >> 1;
       info->qualifier = AARCH64_OPND_QLF_S_H;
       /* Index encoded in "Q:S:size<1>".  */
       info->reglist.index = QSsize >> 1;
@@ -432,7 +538,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
     case 0x2:
       if ((QSsize >> 1) & 0x1)
        /* UND.  */
     case 0x2:
       if ((QSsize >> 1) & 0x1)
        /* UND.  */
-       return 0;
+       return FALSE;
       if ((QSsize & 0x1) == 0)
        {
          info->qualifier = AARCH64_OPND_QLF_S_S;
       if ((QSsize & 0x1) == 0)
        {
          info->qualifier = AARCH64_OPND_QLF_S_S;
@@ -443,14 +549,14 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
        {
          if (extract_field (FLD_S, code, 0))
            /* UND */
        {
          if (extract_field (FLD_S, code, 0))
            /* UND */
-           return 0;
+           return FALSE;
          info->qualifier = AARCH64_OPND_QLF_S_D;
          /* Index encoded in "Q".  */
          info->reglist.index = QSsize >> 3;
        }
       break;
     default:
          info->qualifier = AARCH64_OPND_QLF_S_D;
          /* Index encoded in "Q".  */
          info->reglist.index = QSsize >> 3;
        }
       break;
     default:
-      return 0;
+      return FALSE;
     }
 
   info->reglist.has_index = 1;
     }
 
   info->reglist.has_index = 1;
@@ -460,17 +566,18 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
   info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
   assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
 
   info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
   assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode fields immh:immb and/or Q for e.g.
    SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
    or SSHR <V><d>, <V><n>, #<shift>.  */
 
 }
 
 /* Decode fields immh:immb and/or Q for e.g.
    SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
    or SSHR <V><d>, <V><n>, #<shift>.  */
 
-int
+bfd_boolean
 aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
                               aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
                               aarch64_opnd_info *info, const aarch64_insn code,
-                              const aarch64_inst *inst)
+                              const aarch64_inst *inst,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   int pos;
   aarch64_insn Q, imm, immh;
 {
   int pos;
   aarch64_insn Q, imm, immh;
@@ -478,7 +585,7 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
 
   immh = extract_field (FLD_immh, code, 0);
   if (immh == 0)
 
   immh = extract_field (FLD_immh, code, 0);
   if (immh == 0)
-    return 0;
+    return FALSE;
   imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb);
   pos = 4;
   /* Get highest set bit in immh.  */
   imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb);
   pos = 4;
   /* Get highest set bit in immh.  */
@@ -526,14 +633,15 @@ aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
        1xxx    (UInt(immh:immb)-64)  */
     info->imm.value = imm - (8 << pos);
 
        1xxx    (UInt(immh:immb)-64)  */
     info->imm.value = imm - (8 << pos);
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode shift immediate for e.g. sshr (imm).  */
 }
 
 /* Decode shift immediate for e.g. sshr (imm).  */
-int
+bfd_boolean
 aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
                      aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
                      aarch64_opnd_info *info, const aarch64_insn code,
-                     const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                     const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                     aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   int64_t imm;
   aarch64_insn val;
 {
   int64_t imm;
   aarch64_insn val;
@@ -543,64 +651,60 @@ aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
     case 0: imm = 8; break;
     case 1: imm = 16; break;
     case 2: imm = 32; break;
     case 0: imm = 8; break;
     case 1: imm = 16; break;
     case 2: imm = 32; break;
-    default: return 0;
+    default: return FALSE;
     }
   info->imm.value = imm;
     }
   info->imm.value = imm;
-  return 1;
+  return TRUE;
 }
 
 /* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>.
    value in the field(s) will be extracted as unsigned immediate value.  */
 }
 
 /* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>.
    value in the field(s) will be extracted as unsigned immediate value.  */
-int
+bfd_boolean
 aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
                 const aarch64_insn code,
 aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
                 const aarch64_insn code,
-                const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
 {
-  int64_t imm;
-  /* Maximum of two fields to extract.  */
-  assert (self->fields[2] == FLD_NIL);
-
-  if (self->fields[1] == FLD_NIL)
-    imm = extract_field (self->fields[0], code, 0);
-  else
-    /* e.g. TBZ b5:b40.  */
-    imm = extract_fields (code, 0, 2, self->fields[0], self->fields[1]);
+  uint64_t imm;
 
 
-  if (info->type == AARCH64_OPND_FPIMM)
-    info->imm.is_fp = 1;
+  imm = extract_all_fields (self, code);
 
   if (operand_need_sign_extension (self))
     imm = sign_extend (imm, get_operand_fields_width (self) - 1);
 
   if (operand_need_shift_by_two (self))
     imm <<= 2;
 
   if (operand_need_sign_extension (self))
     imm = sign_extend (imm, get_operand_fields_width (self) - 1);
 
   if (operand_need_shift_by_two (self))
     imm <<= 2;
+  else if (operand_need_shift_by_four (self))
+    imm <<= 4;
 
   if (info->type == AARCH64_OPND_ADDR_ADRP)
     imm <<= 12;
 
   info->imm.value = imm;
 
   if (info->type == AARCH64_OPND_ADDR_ADRP)
     imm <<= 12;
 
   info->imm.value = imm;
-  return 1;
+  return TRUE;
 }
 
 /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}.  */
 }
 
 /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}.  */
-int
+bfd_boolean
 aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
                      const aarch64_insn code,
 aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
                      const aarch64_insn code,
-                     const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                     const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                     aarch64_operand_error *errors)
 {
 {
-  aarch64_ext_imm (self, info, code, inst);
+  aarch64_ext_imm (self, info, code, inst, errors);
   info->shifter.kind = AARCH64_MOD_LSL;
   info->shifter.amount = extract_field (FLD_hw, code, 0) << 4;
   info->shifter.kind = AARCH64_MOD_LSL;
   info->shifter.amount = extract_field (FLD_hw, code, 0) << 4;
-  return 1;
+  return TRUE;
 }
 
 /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g.
      MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}.  */
 }
 
 /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g.
      MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}.  */
-int
+bfd_boolean
 aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
                                  aarch64_opnd_info *info,
                                  const aarch64_insn code,
 aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
                                  aarch64_opnd_info *info,
                                  const aarch64_insn code,
-                                 const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                                 const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   uint64_t imm;
   enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
 {
   uint64_t imm;
   enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
@@ -644,7 +748,7 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
        case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */
        case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */
        case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */
        case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */
        case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */
        case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */
-       default: assert (0); return 0;
+       default: assert (0); return FALSE;
        }
       /* 00: 0; 01: 8; 10:16; 11:24.  */
       info->shifter.amount = extract_field_2 (&field, code, 0) << 3;
        }
       /* 00: 0; 01: 8; 10:16; 11:24.  */
       info->shifter.amount = extract_field_2 (&field, code, 0) << 3;
@@ -657,28 +761,68 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
       break;
     default:
       assert (0);
       break;
     default:
       assert (0);
-      return 0;
+      return FALSE;
     }
 
     }
 
-  return 1;
+  return TRUE;
+}
+
+/* Decode an 8-bit floating-point immediate.  */
+bfd_boolean
+aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info,
+                  const aarch64_insn code,
+                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->imm.value = extract_all_fields (self, code);
+  info->imm.is_fp = 1;
+  return TRUE;
+}
+
+/* Decode a 1-bit rotate immediate (#90 or #270).  */
+bfd_boolean
+aarch64_ext_imm_rotate1 (const aarch64_operand *self, aarch64_opnd_info *info,
+                        const aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  uint64_t rot = extract_field (self->fields[0], code, 0);
+  assert (rot < 2U);
+  info->imm.value = rot * 180 + 90;
+  return TRUE;
+}
+
+/* Decode a 2-bit rotate immediate (#0, #90, #180 or #270).  */
+bfd_boolean
+aarch64_ext_imm_rotate2 (const aarch64_operand *self, aarch64_opnd_info *info,
+                        const aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  uint64_t rot = extract_field (self->fields[0], code, 0);
+  assert (rot < 4U);
+  info->imm.value = rot * 90;
+  return TRUE;
 }
 
 /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>.  */
 }
 
 /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>.  */
-int
+bfd_boolean
 aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
                   aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
                   aarch64_opnd_info *info, const aarch64_insn code,
-                  const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                  const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   info->imm.value = 64- extract_field (FLD_scale, code, 0);
 {
   info->imm.value = 64- extract_field (FLD_scale, code, 0);
-  return 1;
+  return TRUE;
 }
 
 /* Decode arithmetic immediate for e.g.
      SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}.  */
 }
 
 /* Decode arithmetic immediate for e.g.
      SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}.  */
-int
+bfd_boolean
 aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
                  aarch64_opnd_info *info, const aarch64_insn code,
 aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
                  aarch64_opnd_info *info, const aarch64_insn code,
-                 const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                 const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn value;
 
 {
   aarch64_insn value;
 
@@ -686,40 +830,29 @@ aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
   /* shift */
   value = extract_field (FLD_shift, code, 0);
   if (value >= 2)
   /* shift */
   value = extract_field (FLD_shift, code, 0);
   if (value >= 2)
-    return 0;
+    return FALSE;
   info->shifter.amount = value ? 12 : 0;
   /* imm12 (unsigned) */
   info->imm.value = extract_field (FLD_imm12, code, 0);
 
   info->shifter.amount = value ? 12 : 0;
   /* imm12 (unsigned) */
   info->imm.value = extract_field (FLD_imm12, code, 0);
 
-  return 1;
+  return TRUE;
 }
 
 }
 
-/* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>.  */
-
-int
-aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
-                 aarch64_opnd_info *info, const aarch64_insn code,
-                 const aarch64_inst *inst ATTRIBUTE_UNUSED)
+/* Return true if VALUE is a valid logical immediate encoding, storing the
+   decoded value in *RESULT if so.  ESIZE is the number of bytes in the
+   decoded immediate.  */
+static bfd_boolean
+decode_limm (uint32_t esize, aarch64_insn value, int64_t *result)
 {
   uint64_t imm, mask;
 {
   uint64_t imm, mask;
-  uint32_t sf;
   uint32_t N, R, S;
   unsigned simd_size;
   uint32_t N, R, S;
   unsigned simd_size;
-  aarch64_insn value;
-
-  value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
-  assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W
-         || inst->operands[0].qualifier == AARCH64_OPND_QLF_X);
-  sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;
 
   /* value is N:immr:imms.  */
   S = value & 0x3f;
   R = (value >> 6) & 0x3f;
   N = (value >> 12) & 0x1;
 
 
   /* value is N:immr:imms.  */
   S = value & 0x3f;
   R = (value >> 6) & 0x3f;
   N = (value >> 12) & 0x1;
 
-  if (sf == 0 && N == 1)
-    return 0;
-
   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
      (in other words, right rotated by R), then replicated.  */
   if (N != 0)
   /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
      (in other words, right rotated by R), then replicated.  */
   if (N != 0)
@@ -736,15 +869,19 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
        case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
        case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
        case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
        case 0x30 ... 0x37: /* 110xxx */ simd_size =  8; S &= 0x7; break;
        case 0x38 ... 0x3b: /* 1110xx */ simd_size =  4; S &= 0x3; break;
        case 0x3c ... 0x3d: /* 11110x */ simd_size =  2; S &= 0x1; break;
-       default: return 0;
+       default: return FALSE;
        }
       mask = (1ull << simd_size) - 1;
       /* Top bits are IGNORED.  */
       R &= simd_size - 1;
     }
        }
       mask = (1ull << simd_size) - 1;
       /* Top bits are IGNORED.  */
       R &= simd_size - 1;
     }
+
+  if (simd_size > esize * 8)
+    return FALSE;
+
   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
   if (S == simd_size - 1)
   /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected.  */
   if (S == simd_size - 1)
-    return 0;
+    return FALSE;
   /* S+1 consecutive bits to 1.  */
   /* NOTE: S can't be 63 due to detection above.  */
   imm = (1ull << (S + 1)) - 1;
   /* S+1 consecutive bits to 1.  */
   /* NOTE: S can't be 63 due to detection above.  */
   imm = (1ull << (S + 1)) - 1;
@@ -755,25 +892,60 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
   switch (simd_size)
     {
     case  2: imm = (imm <<  2) | imm;
   switch (simd_size)
     {
     case  2: imm = (imm <<  2) | imm;
+      /* Fall through.  */
     case  4: imm = (imm <<  4) | imm;
     case  4: imm = (imm <<  4) | imm;
+      /* Fall through.  */
     case  8: imm = (imm <<  8) | imm;
     case  8: imm = (imm <<  8) | imm;
+      /* Fall through.  */
     case 16: imm = (imm << 16) | imm;
     case 16: imm = (imm << 16) | imm;
+      /* Fall through.  */
     case 32: imm = (imm << 32) | imm;
     case 32: imm = (imm << 32) | imm;
+      /* Fall through.  */
     case 64: break;
     default: assert (0); return 0;
     }
 
     case 64: break;
     default: assert (0); return 0;
     }
 
-  info->imm.value = sf ? imm : imm & 0xffffffff;
+  *result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4));
 
 
-  return 1;
+  return TRUE;
+}
+
+/* Decode a logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>.  */
+bfd_boolean
+aarch64_ext_limm (const aarch64_operand *self,
+                 aarch64_opnd_info *info, const aarch64_insn code,
+                 const aarch64_inst *inst,
+                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  uint32_t esize;
+  aarch64_insn value;
+
+  value = extract_fields (code, 0, 3, self->fields[0], self->fields[1],
+                         self->fields[2]);
+  esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
+  return decode_limm (esize, value, &info->imm.value);
+}
+
+/* Decode a logical immediate for the BIC alias of AND (etc.).  */
+bfd_boolean
+aarch64_ext_inv_limm (const aarch64_operand *self,
+                     aarch64_opnd_info *info, const aarch64_insn code,
+                     const aarch64_inst *inst,
+                     aarch64_operand_error *errors)
+{
+  if (!aarch64_ext_limm (self, info, code, inst, errors))
+    return FALSE;
+  info->imm.value = ~info->imm.value;
+  return TRUE;
 }
 
 /* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
    or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>.  */
 }
 
 /* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
    or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>.  */
-int
+bfd_boolean
 aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
                aarch64_opnd_info *info,
 aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
                aarch64_opnd_info *info,
-               const aarch64_insn code, const aarch64_inst *inst)
+               const aarch64_insn code, const aarch64_inst *inst,
+               aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn value;
 
 {
   aarch64_insn value;
 
@@ -793,7 +965,7 @@ aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
        case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
        case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
        case 2: qualifier = AARCH64_OPND_QLF_S_Q; break;
        case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
        case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
        case 2: qualifier = AARCH64_OPND_QLF_S_Q; break;
-       default: return 0;
+       default: return FALSE;
        }
       info->qualifier = qualifier;
     }
        }
       info->qualifier = qualifier;
     }
@@ -802,31 +974,56 @@ aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
       /* opc1:size */
       value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size);
       if (value > 0x4)
       /* opc1:size */
       value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size);
       if (value > 0x4)
-       return 0;
+       return FALSE;
       info->qualifier = get_sreg_qualifier_from_value (value);
     }
 
       info->qualifier = get_sreg_qualifier_from_value (value);
     }
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}].  */
 }
 
 /* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}].  */
-int
+bfd_boolean
 aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info,
                         aarch64_insn code,
 aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info,
                         aarch64_insn code,
-                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* Rn */
   info->addr.base_regno = extract_field (FLD_Rn, code, 0);
 {
   /* Rn */
   info->addr.base_regno = extract_field (FLD_Rn, code, 0);
-  return 1;
+  return TRUE;
+}
+
+/* Decode the address operand for e.g.
+     stlur <Xt>, [<Xn|SP>{, <amount>}].  */
+bfd_boolean
+aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                        aarch64_opnd_info *info,
+                        aarch64_insn code, const aarch64_inst *inst,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->qualifier = get_expected_qualifier (inst, info->idx);
+
+  /* Rn */
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+
+  /* simm9 */
+  aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]);
+  info->addr.offset.imm = sign_extend (imm, 8);
+  if (extract_field (self->fields[2], code, 0) == 1) {
+    info->addr.writeback = 1;
+    info->addr.preind = 1;
+  }
+  return TRUE;
 }
 
 /* Decode the address operand for e.g.
      STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
 }
 
 /* Decode the address operand for e.g.
      STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
-int
+bfd_boolean
 aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info,
 aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info,
-                        aarch64_insn code, const aarch64_inst *inst)
+                        aarch64_insn code, const aarch64_inst *inst,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn S, value;
 
 {
   aarch64_insn S, value;
 
@@ -862,13 +1059,14 @@ aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
       info->shifter.amount_present = 1;
     }
 
       info->shifter.amount_present = 1;
     }
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>.  */
 }
 
 /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>.  */
-int
+bfd_boolean
 aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
 aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
-                      aarch64_insn code, const aarch64_inst *inst)
+                      aarch64_insn code, const aarch64_inst *inst,
+                      aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn imm;
   info->qualifier = get_expected_qualifier (inst, info->idx);
 {
   aarch64_insn imm;
   info->qualifier = get_expected_qualifier (inst, info->idx);
@@ -878,7 +1076,8 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
   /* simm (imm9 or imm7)  */
   imm = extract_field (self->fields[0], code, 0);
   info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1);
   /* simm (imm9 or imm7)  */
   imm = extract_field (self->fields[0], code, 0);
   info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1);
-  if (self->fields[0] == FLD_imm7)
+  if (self->fields[0] == FLD_imm7
+      || info->qualifier == AARCH64_OPND_QLF_imm_tag)
     /* scaled immediate in ld/st pair instructions.  */
     info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier);
   /* qualifier */
     /* scaled immediate in ld/st pair instructions.  */
     info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier);
   /* qualifier */
@@ -897,14 +1096,15 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
        info->addr.postind = 1;
     }
 
        info->addr.postind = 1;
     }
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}].  */
 }
 
 /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}].  */
-int
+bfd_boolean
 aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
                         aarch64_insn code,
 aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
                         aarch64_insn code,
-                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   int shift;
   info->qualifier = get_expected_qualifier (inst, info->idx);
 {
   int shift;
   info->qualifier = get_expected_qualifier (inst, info->idx);
@@ -913,15 +1113,38 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
   info->addr.base_regno = extract_field (self->fields[0], code, 0);
   /* uimm12 */
   info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift;
   info->addr.base_regno = extract_field (self->fields[0], code, 0);
   /* uimm12 */
   info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift;
-  return 1;
+  return TRUE;
+}
+
+/* Decode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}].  */
+bfd_boolean
+aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info,
+                        aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  aarch64_insn imm;
+
+  info->qualifier = get_expected_qualifier (inst, info->idx);
+  /* Rn */
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  /* simm10 */
+  imm = extract_fields (code, 0, 2, self->fields[1], self->fields[2]);
+  info->addr.offset.imm = sign_extend (imm, 9) << 3;
+  if (extract_field (self->fields[3], code, 0) == 1) {
+    info->addr.writeback = 1;
+    info->addr.preind = 1;
+  }
+  return TRUE;
 }
 
 /* Decode the address operand for e.g.
      LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>.  */
 }
 
 /* Decode the address operand for e.g.
      LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>.  */
-int
+bfd_boolean
 aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
                            aarch64_opnd_info *info,
 aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
                            aarch64_opnd_info *info,
-                           aarch64_insn code, const aarch64_inst *inst)
+                           aarch64_insn code, const aarch64_inst *inst,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* The opcode dependent area stores the number of elements in
      each structure to be loaded/stored.  */
 {
   /* The opcode dependent area stores the number of elements in
      each structure to be loaded/stored.  */
@@ -947,57 +1170,76 @@ aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
     info->addr.offset.is_reg = 1;
   info->addr.writeback = 1;
 
     info->addr.offset.is_reg = 1;
   info->addr.writeback = 1;
 
-  return 1;
+  return TRUE;
 }
 
 /* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>.  */
 }
 
 /* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>.  */
-int
+bfd_boolean
 aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
                  aarch64_opnd_info *info,
 aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
                  aarch64_opnd_info *info,
-                 aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                 aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   aarch64_insn value;
   /* cond */
   value = extract_field (FLD_cond, code, 0);
   info->cond = get_cond_from_value (value);
 {
   aarch64_insn value;
   /* cond */
   value = extract_field (FLD_cond, code, 0);
   info->cond = get_cond_from_value (value);
-  return 1;
+  return TRUE;
 }
 
 /* Decode the system register operand for e.g. MRS <Xt>, <systemreg>.  */
 }
 
 /* Decode the system register operand for e.g. MRS <Xt>, <systemreg>.  */
-int
+bfd_boolean
 aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
                    aarch64_opnd_info *info,
                    aarch64_insn code,
 aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
                    aarch64_opnd_info *info,
                    aarch64_insn code,
-                   const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                   const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                   aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* op0:op1:CRn:CRm:op2 */
 {
   /* op0:op1:CRn:CRm:op2 */
-  info->sysreg = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
-                                FLD_CRm, FLD_op2);
-  return 1;
+  info->sysreg.value = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
+                                      FLD_CRm, FLD_op2);
+  info->sysreg.flags = 0;
+
+  /* If a system instruction, check which restrictions should be on the register
+     value during decoding, these will be enforced then.  */
+  if (inst->opcode->iclass == ic_system)
+    {
+      /* Check to see if it's read-only, else check if it's write only.
+        if it's both or unspecified don't care.  */
+      if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) == F_SYS_READ)
+       info->sysreg.flags = F_REG_READ;
+      else if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE))
+              == F_SYS_WRITE)
+       info->sysreg.flags = F_REG_WRITE;
+    }
+
+  return TRUE;
 }
 
 /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>.  */
 }
 
 /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>.  */
-int
+bfd_boolean
 aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info, aarch64_insn code,
 aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
                         aarch64_opnd_info *info, aarch64_insn code,
-                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   int i;
   /* op1:op2 */
   info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2);
   for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
     if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield)
 {
   int i;
   /* op1:op2 */
   info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2);
   for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
     if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield)
-      return 1;
+      return TRUE;
   /* Reserved value in <pstatefield>.  */
   /* Reserved value in <pstatefield>.  */
-  return 0;
+  return FALSE;
 }
 
 /* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>.  */
 }
 
 /* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>.  */
-int
+bfd_boolean
 aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
                       aarch64_opnd_info *info,
                       aarch64_insn code,
 aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
                       aarch64_opnd_info *info,
                       aarch64_insn code,
-                      const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                      const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                      aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   int i;
   aarch64_insn value;
 {
   int i;
   aarch64_insn value;
@@ -1013,110 +1255,602 @@ aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
     case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break;
     case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break;
     case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
     case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break;
     case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break;
     case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
-    default: assert (0); return 0;
+    case AARCH64_OPND_SYSREG_SR:
+       sysins_ops = aarch64_sys_regs_sr;
+        /* Let's remove op2 for rctx.  Refer to comments in the definition of
+           aarch64_sys_regs_sr[].  */
+       value = value & ~(0x7);
+       break;
+    default: assert (0); return FALSE;
     }
 
     }
 
-  for (i = 0; sysins_ops[i].template != NULL; ++i)
+  for (i = 0; sysins_ops[i].name != NULL; ++i)
     if (sysins_ops[i].value == value)
       {
        info->sysins_op = sysins_ops + i;
        DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.",
     if (sysins_ops[i].value == value)
       {
        info->sysins_op = sysins_ops + i;
        DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.",
-                    info->sysins_op->template,
+                    info->sysins_op->name,
                     (unsigned)info->sysins_op->value,
                     (unsigned)info->sysins_op->value,
-                    info->sysins_op->has_xt, i);
-       return 1;
+                    aarch64_sys_ins_reg_has_xt (info->sysins_op), i);
+       return TRUE;
       }
 
       }
 
-  return 0;
+  return FALSE;
 }
 
 /* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>.  */
 
 }
 
 /* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>.  */
 
-int
+bfd_boolean
 aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
                     aarch64_opnd_info *info,
                     aarch64_insn code,
 aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
                     aarch64_opnd_info *info,
                     aarch64_insn code,
-                    const aarch64_inst *inst ATTRIBUTE_UNUSED)
+                    const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                    aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   /* CRm */
   info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0);
 {
   /* CRm */
   info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0);
-  return 1;
+  return TRUE;
+}
+
+/* Decode the prefetch operation option operand for e.g.
+     PRFM <prfop>, [<Xn|SP>{, #<pimm>}].  */
+
+bfd_boolean
+aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                  aarch64_opnd_info *info,
+                  aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                  aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  /* prfop in Rt */
+  info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0);
+  return TRUE;
+}
+
+/* Decode the hint number for an alias taking an operand.  Set info->hint_option
+   to the matching name/value pair in aarch64_hint_options.  */
+
+bfd_boolean
+aarch64_ext_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                 aarch64_opnd_info *info,
+                 aarch64_insn code,
+                 const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  /* CRm:op2.  */
+  unsigned hint_number;
+  int i;
+
+  hint_number = extract_fields (code, 0, 2, FLD_CRm, FLD_op2);
+
+  for (i = 0; aarch64_hint_options[i].name != NULL; i++)
+    {
+      if (hint_number == HINT_VAL (aarch64_hint_options[i].value))
+       {
+         info->hint_option = &(aarch64_hint_options[i]);
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+/* Decode the extended register operand for e.g.
+     STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
+bfd_boolean
+aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                         aarch64_opnd_info *info,
+                         aarch64_insn code,
+                         const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                         aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  aarch64_insn value;
+
+  /* Rm */
+  info->reg.regno = extract_field (FLD_Rm, code, 0);
+  /* option */
+  value = extract_field (FLD_option, code, 0);
+  info->shifter.kind =
+    aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
+  /* imm3 */
+  info->shifter.amount = extract_field (FLD_imm3, code,  0);
+
+  /* This makes the constraint checking happy.  */
+  info->shifter.operator_present = 1;
+
+  /* Assume inst->operands[0].qualifier has been resolved.  */
+  assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
+  info->qualifier = AARCH64_OPND_QLF_W;
+  if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
+      && (info->shifter.kind == AARCH64_MOD_UXTX
+         || info->shifter.kind == AARCH64_MOD_SXTX))
+    info->qualifier = AARCH64_OPND_QLF_X;
+
+  return TRUE;
+}
+
+/* Decode the shifted register operand for e.g.
+     SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}.  */
+bfd_boolean
+aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                        aarch64_opnd_info *info,
+                        aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  aarch64_insn value;
+
+  /* Rm */
+  info->reg.regno = extract_field (FLD_Rm, code, 0);
+  /* shift */
+  value = extract_field (FLD_shift, code, 0);
+  info->shifter.kind =
+    aarch64_get_operand_modifier_from_value (value, FALSE /* extend_p */);
+  if (info->shifter.kind == AARCH64_MOD_ROR
+      && inst->opcode->iclass != log_shift)
+    /* ROR is not available for the shifted register operand in arithmetic
+       instructions.  */
+    return FALSE;
+  /* imm6 */
+  info->shifter.amount = extract_field (FLD_imm6, code,  0);
+
+  /* This makes the constraint checking happy.  */
+  info->shifter.operator_present = 1;
+
+  return TRUE;
+}
+
+/* Decode an SVE address [<base>, #<offset>*<factor>, MUL VL],
+   where <offset> is given by the OFFSET parameter and where <factor> is
+   1 plus SELF's operand-dependent value.  fields[0] specifies the field
+   that holds <base>.  */
+static bfd_boolean
+aarch64_ext_sve_addr_reg_mul_vl (const aarch64_operand *self,
+                                aarch64_opnd_info *info, aarch64_insn code,
+                                int64_t offset)
+{
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.imm = offset * (1 + get_operand_specific_data (self));
+  info->addr.offset.is_reg = FALSE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  if (offset != 0)
+    info->shifter.kind = AARCH64_MOD_MUL_VL;
+  info->shifter.amount = 1;
+  info->shifter.operator_present = (info->addr.offset.imm != 0);
+  info->shifter.amount_present = FALSE;
+  return TRUE;
+}
+
+/* Decode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
+   where <simm4> is a 4-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm4> is encoded in the SVE_imm4 field.  */
+bfd_boolean
+aarch64_ext_sve_addr_ri_s4xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info, aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_field (FLD_SVE_imm4, code, 0);
+  offset = ((offset + 8) & 15) - 8;
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
+/* Decode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
+   where <simm6> is a 6-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm6> is encoded in the SVE_imm6 field.  */
+bfd_boolean
+aarch64_ext_sve_addr_ri_s6xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info, aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_field (FLD_SVE_imm6, code, 0);
+  offset = (((offset + 32) & 63) - 32);
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
+/* Decode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
+   where <simm9> is a 9-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm9> is encoded in the concatenation of the SVE_imm6
+   and imm3 fields, with imm3 being the less-significant part.  */
+bfd_boolean
+aarch64_ext_sve_addr_ri_s9xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info,
+                              aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                              aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_fields (code, 0, 2, FLD_SVE_imm6, FLD_imm3);
+  offset = (((offset + 256) & 511) - 256);
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
+/* Decode an SVE address [<base>, #<offset> << <shift>], where <offset>
+   is given by the OFFSET parameter and where <shift> is SELF's operand-
+   dependent value.  fields[0] specifies the base register field <base>.  */
+static bfd_boolean
+aarch64_ext_sve_addr_reg_imm (const aarch64_operand *self,
+                             aarch64_opnd_info *info, aarch64_insn code,
+                             int64_t offset)
+{
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.imm = offset * (1 << get_operand_specific_data (self));
+  info->addr.offset.is_reg = FALSE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  info->shifter.operator_present = FALSE;
+  info->shifter.amount_present = FALSE;
+  return TRUE;
+}
+
+/* Decode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
+   is a 4-bit signed number and where <shift> is SELF's operand-dependent
+   value.  fields[0] specifies the base register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_ri_s4 (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset = sign_extend (extract_field (FLD_SVE_imm4, code, 0), 3);
+  return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
+}
+
+/* Decode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
+   is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
+   value.  fields[0] specifies the base register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_ri_u6 (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset = extract_field (FLD_SVE_imm6, code, 0);
+  return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
 }
 
 }
 
-/* Decode the prefetch operation option operand for e.g.
-     PRFM <prfop>, [<Xn|SP>{, #<pimm>}].  */
+/* Decode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
+   is SELF's operand-dependent value.  fields[0] specifies the base
+   register field and fields[1] specifies the offset register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                            aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int index_regno;
+
+  index_regno = extract_field (self->fields[1], code, 0);
+  if (index_regno == 31 && (self->flags & OPD_F_NO_ZR) != 0)
+    return FALSE;
+
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.regno = index_regno;
+  info->addr.offset.is_reg = TRUE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  info->shifter.kind = AARCH64_MOD_LSL;
+  info->shifter.amount = get_operand_specific_data (self);
+  info->shifter.operator_present = (info->shifter.amount != 0);
+  info->shifter.amount_present = (info->shifter.amount != 0);
+  return TRUE;
+}
+
+/* Decode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
+   <shift> is SELF's operand-dependent value.  fields[0] specifies the
+   base register field, fields[1] specifies the offset register field and
+   fields[2] is a single-bit field that selects SXTW over UXTW.  */
+bfd_boolean
+aarch64_ext_sve_addr_rz_xtw (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                            aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.regno = extract_field (self->fields[1], code, 0);
+  info->addr.offset.is_reg = TRUE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  if (extract_field (self->fields[2], code, 0))
+    info->shifter.kind = AARCH64_MOD_SXTW;
+  else
+    info->shifter.kind = AARCH64_MOD_UXTW;
+  info->shifter.amount = get_operand_specific_data (self);
+  info->shifter.operator_present = TRUE;
+  info->shifter.amount_present = (info->shifter.amount != 0);
+  return TRUE;
+}
+
+/* Decode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
+   5-bit unsigned number and where <shift> is SELF's operand-dependent value.
+   fields[0] specifies the base register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_zi_u5 (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int offset = extract_field (FLD_imm5, code, 0);
+  return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
+   where <modifier> is given by KIND and where <msz> is a 2-bit unsigned
+   number.  fields[0] specifies the base register field and fields[1]
+   specifies the offset register field.  */
+static bfd_boolean
+aarch64_ext_sve_addr_zz (const aarch64_operand *self, aarch64_opnd_info *info,
+                        aarch64_insn code, enum aarch64_modifier_kind kind)
+{
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.regno = extract_field (self->fields[1], code, 0);
+  info->addr.offset.is_reg = TRUE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  info->shifter.kind = kind;
+  info->shifter.amount = extract_field (FLD_SVE_msz, code, 0);
+  info->shifter.operator_present = (kind != AARCH64_MOD_LSL
+                                   || info->shifter.amount != 0);
+  info->shifter.amount_present = (info->shifter.amount != 0);
+  return TRUE;
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
+   <msz> is a 2-bit unsigned number.  fields[0] specifies the base register
+   field and fields[1] specifies the offset register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_zz_lsl (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                            aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_LSL);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
+   <msz> is a 2-bit unsigned number.  fields[0] specifies the base register
+   field and fields[1] specifies the offset register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_zz_sxtw (const aarch64_operand *self,
+                             aarch64_opnd_info *info, aarch64_insn code,
+                             const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                             aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_SXTW);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
+   <msz> is a 2-bit unsigned number.  fields[0] specifies the base register
+   field and fields[1] specifies the offset register field.  */
+bfd_boolean
+aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
+                             aarch64_opnd_info *info, aarch64_insn code,
+                             const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                             aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
+}
+
+/* Finish decoding an SVE arithmetic immediate, given that INFO already
+   has the raw field value and that the low 8 bits decode to VALUE.  */
+static bfd_boolean
+decode_sve_aimm (aarch64_opnd_info *info, int64_t value)
+{
+  info->shifter.kind = AARCH64_MOD_LSL;
+  info->shifter.amount = 0;
+  if (info->imm.value & 0x100)
+    {
+      if (value == 0)
+       /* Decode 0x100 as #0, LSL #8.  */
+       info->shifter.amount = 8;
+      else
+       value *= 256;
+    }
+  info->shifter.operator_present = (info->shifter.amount != 0);
+  info->shifter.amount_present = (info->shifter.amount != 0);
+  info->imm.value = value;
+  return TRUE;
+}
+
+/* Decode an SVE ADD/SUB immediate.  */
+bfd_boolean
+aarch64_ext_sve_aimm (const aarch64_operand *self,
+                     aarch64_opnd_info *info, const aarch64_insn code,
+                     const aarch64_inst *inst,
+                     aarch64_operand_error *errors)
+{
+  return (aarch64_ext_imm (self, info, code, inst, errors)
+         && decode_sve_aimm (info, (uint8_t) info->imm.value));
+}
+
+/* Decode an SVE CPY/DUP immediate.  */
+bfd_boolean
+aarch64_ext_sve_asimm (const aarch64_operand *self,
+                      aarch64_opnd_info *info, const aarch64_insn code,
+                      const aarch64_inst *inst,
+                      aarch64_operand_error *errors)
+{
+  return (aarch64_ext_imm (self, info, code, inst, errors)
+         && decode_sve_aimm (info, (int8_t) info->imm.value));
+}
+
+/* Decode a single-bit immediate that selects between #0.5 and #1.0.
+   The fields array specifies which field to use.  */
+bfd_boolean
+aarch64_ext_sve_float_half_one (const aarch64_operand *self,
+                               aarch64_opnd_info *info, aarch64_insn code,
+                               const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                               aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  if (extract_field (self->fields[0], code, 0))
+    info->imm.value = 0x3f800000;
+  else
+    info->imm.value = 0x3f000000;
+  info->imm.is_fp = TRUE;
+  return TRUE;
+}
+
+/* Decode a single-bit immediate that selects between #0.5 and #2.0.
+   The fields array specifies which field to use.  */
+bfd_boolean
+aarch64_ext_sve_float_half_two (const aarch64_operand *self,
+                               aarch64_opnd_info *info, aarch64_insn code,
+                               const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                               aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  if (extract_field (self->fields[0], code, 0))
+    info->imm.value = 0x40000000;
+  else
+    info->imm.value = 0x3f000000;
+  info->imm.is_fp = TRUE;
+  return TRUE;
+}
+
+/* Decode a single-bit immediate that selects between #0.0 and #1.0.
+   The fields array specifies which field to use.  */
+bfd_boolean
+aarch64_ext_sve_float_zero_one (const aarch64_operand *self,
+                               aarch64_opnd_info *info, aarch64_insn code,
+                               const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                               aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  if (extract_field (self->fields[0], code, 0))
+    info->imm.value = 0x3f800000;
+  else
+    info->imm.value = 0x0;
+  info->imm.is_fp = TRUE;
+  return TRUE;
+}
+
+/* Decode Zn[MM], where MM has a 7-bit triangular encoding.  The fields
+   array specifies which field to use for Zn.  MM is encoded in the
+   concatenation of imm5 and SVE_tszh, with imm5 being the less
+   significant part.  */
+bfd_boolean
+aarch64_ext_sve_index (const aarch64_operand *self,
+                      aarch64_opnd_info *info, aarch64_insn code,
+                      const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                      aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  int val;
+
+  info->reglane.regno = extract_field (self->fields[0], code, 0);
+  val = extract_fields (code, 0, 2, FLD_SVE_tszh, FLD_imm5);
+  if ((val & 31) == 0)
+    return 0;
+  while ((val & 1) == 0)
+    val /= 2;
+  info->reglane.index = val / 2;
+  return TRUE;
+}
 
 
-int
-aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
-                  aarch64_opnd_info *info,
-                  aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+/* Decode a logical immediate for the MOV alias of SVE DUPM.  */
+bfd_boolean
+aarch64_ext_sve_limm_mov (const aarch64_operand *self,
+                         aarch64_opnd_info *info, const aarch64_insn code,
+                         const aarch64_inst *inst,
+                         aarch64_operand_error *errors)
 {
 {
-  /* prfop in Rt */
-  info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0);
-  return 1;
+  int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
+  return (aarch64_ext_limm (self, info, code, inst, errors)
+         && aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize));
 }
 
 }
 
-/* Decode the extended register operand for e.g.
-     STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
-int
-aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
-                         aarch64_opnd_info *info,
-                         aarch64_insn code,
-                         const aarch64_inst *inst ATTRIBUTE_UNUSED)
+/* Decode Zn[MM], where Zn occupies the least-significant part of the field
+   and where MM occupies the most-significant part.  The operand-dependent
+   value specifies the number of bits in Zn.  */
+bfd_boolean
+aarch64_ext_sve_quad_index (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
 {
-  aarch64_insn value;
+  unsigned int reg_bits = get_operand_specific_data (self);
+  unsigned int val = extract_all_fields (self, code);
+  info->reglane.regno = val & ((1 << reg_bits) - 1);
+  info->reglane.index = val >> reg_bits;
+  return TRUE;
+}
 
 
-  /* Rm */
-  info->reg.regno = extract_field (FLD_Rm, code, 0);
-  /* option */
-  value = extract_field (FLD_option, code, 0);
-  info->shifter.kind =
-    aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
-  /* imm3 */
-  info->shifter.amount = extract_field (FLD_imm3, code,  0);
+/* Decode {Zn.<T> - Zm.<T>}.  The fields array specifies which field
+   to use for Zn.  The opcode-dependent value specifies the number
+   of registers in the list.  */
+bfd_boolean
+aarch64_ext_sve_reglist (const aarch64_operand *self,
+                        aarch64_opnd_info *info, aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED,
+                        aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+  info->reglist.first_regno = extract_field (self->fields[0], code, 0);
+  info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+  return TRUE;
+}
 
 
-  /* This makes the constraint checking happy.  */
-  info->shifter.operator_present = 1;
+/* Decode <pattern>{, MUL #<amount>}.  The fields array specifies which
+   fields to use for <pattern>.  <amount> - 1 is encoded in the SVE_imm4
+   field.  */
+bfd_boolean
+aarch64_ext_sve_scale (const aarch64_operand *self,
+                      aarch64_opnd_info *info, aarch64_insn code,
+                      const aarch64_inst *inst, aarch64_operand_error *errors)
+{
+  int val;
 
 
-  /* Assume inst->operands[0].qualifier has been resolved.  */
-  assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
-  info->qualifier = AARCH64_OPND_QLF_W;
-  if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
-      && (info->shifter.kind == AARCH64_MOD_UXTX
-         || info->shifter.kind == AARCH64_MOD_SXTX))
-    info->qualifier = AARCH64_OPND_QLF_X;
+  if (!aarch64_ext_imm (self, info, code, inst, errors))
+    return FALSE;
+  val = extract_field (FLD_SVE_imm4, code, 0);
+  info->shifter.kind = AARCH64_MOD_MUL;
+  info->shifter.amount = val + 1;
+  info->shifter.operator_present = (val != 0);
+  info->shifter.amount_present = (val != 0);
+  return TRUE;
+}
 
 
-  return 1;
+/* Return the top set bit in VALUE, which is expected to be relatively
+   small.  */
+static uint64_t
+get_top_bit (uint64_t value)
+{
+  while ((value & -value) != value)
+    value -= value & -value;
+  return value;
 }
 
 }
 
-/* Decode the shifted register operand for e.g.
-     SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}.  */
-int
-aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
-                        aarch64_opnd_info *info,
-                        aarch64_insn code,
-                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+/* Decode an SVE shift-left immediate.  */
+bfd_boolean
+aarch64_ext_sve_shlimm (const aarch64_operand *self,
+                       aarch64_opnd_info *info, const aarch64_insn code,
+                       const aarch64_inst *inst, aarch64_operand_error *errors)
 {
 {
-  aarch64_insn value;
+  if (!aarch64_ext_imm (self, info, code, inst, errors)
+      || info->imm.value == 0)
+    return FALSE;
 
 
-  /* Rm */
-  info->reg.regno = extract_field (FLD_Rm, code, 0);
-  /* shift */
-  value = extract_field (FLD_shift, code, 0);
-  info->shifter.kind =
-    aarch64_get_operand_modifier_from_value (value, FALSE /* extend_p */);
-  if (info->shifter.kind == AARCH64_MOD_ROR
-      && inst->opcode->iclass != log_shift)
-    /* ROR is not available for the shifted register operand in arithmetic
-       instructions.  */
-    return 0;
-  /* imm6 */
-  info->shifter.amount = extract_field (FLD_imm6, code,  0);
+  info->imm.value -= get_top_bit (info->imm.value);
+  return TRUE;
+}
 
 
-  /* This makes the constraint checking happy.  */
-  info->shifter.operator_present = 1;
+/* Decode an SVE shift-right immediate.  */
+bfd_boolean
+aarch64_ext_sve_shrimm (const aarch64_operand *self,
+                       aarch64_opnd_info *info, const aarch64_insn code,
+                       const aarch64_inst *inst, aarch64_operand_error *errors)
+{
+  if (!aarch64_ext_imm (self, info, code, inst, errors)
+      || info->imm.value == 0)
+    return FALSE;
 
 
-  return 1;
+  info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value;
+  return TRUE;
 }
 \f
 /* Bitfields that are commonly used to encode certain operands' information
 }
 \f
 /* Bitfields that are commonly used to encode certain operands' information
@@ -1317,17 +2051,59 @@ decode_fcvt (aarch64_inst *inst)
 static int
 do_misc_decoding (aarch64_inst *inst)
 {
 static int
 do_misc_decoding (aarch64_inst *inst)
 {
+  unsigned int value;
   switch (inst->opcode->op)
     {
     case OP_FCVT:
       return decode_fcvt (inst);
   switch (inst->opcode->op)
     {
     case OP_FCVT:
       return decode_fcvt (inst);
+
     case OP_FCVTN:
     case OP_FCVTN2:
     case OP_FCVTL:
     case OP_FCVTL2:
       return decode_asimd_fcvt (inst);
     case OP_FCVTN:
     case OP_FCVTN2:
     case OP_FCVTL:
     case OP_FCVTL2:
       return decode_asimd_fcvt (inst);
+
     case OP_FCVTXN_S:
       return decode_asisd_fcvtxn (inst);
     case OP_FCVTXN_S:
       return decode_asisd_fcvtxn (inst);
+
+    case OP_MOV_P_P:
+    case OP_MOVS_P_P:
+      value = extract_field (FLD_SVE_Pn, inst->value, 0);
+      return (value == extract_field (FLD_SVE_Pm, inst->value, 0)
+             && value == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
+
+    case OP_MOV_Z_P_Z:
+      return (extract_field (FLD_SVE_Zd, inst->value, 0)
+             == extract_field (FLD_SVE_Zm_16, inst->value, 0));
+
+    case OP_MOV_Z_V:
+      /* Index must be zero.  */
+      value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
+      return value > 0 && value <= 16 && value == (value & -value);
+
+    case OP_MOV_Z_Z:
+      return (extract_field (FLD_SVE_Zn, inst->value, 0)
+             == extract_field (FLD_SVE_Zm_16, inst->value, 0));
+
+    case OP_MOV_Z_Zi:
+      /* Index must be nonzero.  */
+      value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
+      return value > 0 && value != (value & -value);
+
+    case OP_MOVM_P_P_P:
+      return (extract_field (FLD_SVE_Pd, inst->value, 0)
+             == extract_field (FLD_SVE_Pm, inst->value, 0));
+
+    case OP_MOVZS_P_P_P:
+    case OP_MOVZ_P_P_P:
+      return (extract_field (FLD_SVE_Pn, inst->value, 0)
+             == extract_field (FLD_SVE_Pm, inst->value, 0));
+
+    case OP_NOTS_P_P_P_Z:
+    case OP_NOT_P_P_P_Z:
+      return (extract_field (FLD_SVE_Pm, inst->value, 0)
+             == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
+
     default:
       return 0;
     }
     default:
       return 0;
     }
@@ -1360,6 +2136,13 @@ do_special_decoding (aarch64_inst *inst)
          && extract_field (FLD_N, inst->value, 0) != value)
        return 0;
     }
          && extract_field (FLD_N, inst->value, 0) != value)
        return 0;
     }
+  /* 'sf' field.  */
+  if (inst->opcode->flags & F_LSE_SZ)
+    {
+      idx = select_operand_for_sf_field_coding (inst->opcode);
+      value = extract_field (FLD_lse_sz, inst->value, 0);
+      inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
+    }
   /* size:Q fields.  */
   if (inst->opcode->flags & F_SIZEQ)
     return decode_sizeq (inst);
   /* size:Q fields.  */
   if (inst->opcode->flags & F_SIZEQ)
     return decode_sizeq (inst);
@@ -1582,6 +2365,45 @@ convert_bfm_to_bfi (aarch64_inst *inst)
   return 0;
 }
 
   return 0;
 }
 
+/* The instruction written:
+     BFC <Xd>, #<lsb>, #<width>
+   is equivalent to:
+     BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1).  */
+
+static int
+convert_bfm_to_bfc (aarch64_inst *inst)
+{
+  int64_t immr, imms, val;
+
+  /* Should have been assured by the base opcode value.  */
+  assert (inst->operands[1].reg.regno == 0x1f);
+
+  immr = inst->operands[2].imm.value;
+  imms = inst->operands[3].imm.value;
+  val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
+  if (imms < immr)
+    {
+      /* Drop XZR from the second operand.  */
+      copy_operand_info (inst, 1, 2);
+      copy_operand_info (inst, 2, 3);
+      inst->operands[3].type = AARCH64_OPND_NIL;
+
+      /* Recalculate the immediates.  */
+      inst->operands[1].imm.value = (val - immr) & (val - 1);
+      inst->operands[2].imm.value = imms + 1;
+
+      /* The two opcodes have different qualifiers for the operands; reset to
+        help the checking.  */
+      reset_operand_qualifier (inst, 1);
+      reset_operand_qualifier (inst, 2);
+      reset_operand_qualifier (inst, 3);
+
+      return 1;
+    }
+
+  return 0;
+}
+
 /* The instruction written:
      LSL <Xd>, <Xn>, #<shift>
    is equivalent to:
 /* The instruction written:
      LSL <Xd>, <Xn>, #<shift>
    is equivalent to:
@@ -1672,7 +2494,7 @@ convert_movewide_to_mov (aarch64_inst *inst)
       int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
       value = ~value;
       /* A MOVN has an immediate that could be encoded by MOVZ.  */
       int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
       value = ~value;
       /* A MOVN has an immediate that could be encoded by MOVZ.  */
-      if (aarch64_wide_constant_p (value, is32, NULL) == TRUE)
+      if (aarch64_wide_constant_p (value, is32, NULL))
        return 0;
     }
   inst->operands[1].imm.value = value;
        return 0;
     }
   inst->operands[1].imm.value = value;
@@ -1705,8 +2527,8 @@ convert_movebitmask_to_mov (aarch64_inst *inst)
   /* ORR has an immediate that could be generated by a MOVZ or MOVN
      instruction.  */
   if (inst->operands[0].reg.regno != 0x1f
   /* ORR has an immediate that could be generated by a MOVZ or MOVN
      instruction.  */
   if (inst->operands[0].reg.regno != 0x1f
-      && (aarch64_wide_constant_p (value, is32, NULL) == TRUE
-         || aarch64_wide_constant_p (~value, is32, NULL) == TRUE))
+      && (aarch64_wide_constant_p (value, is32, NULL)
+         || aarch64_wide_constant_p (~value, is32, NULL)))
     return 0;
 
   inst->operands[2].type = AARCH64_OPND_NIL;
     return 0;
 
   inst->operands[2].type = AARCH64_OPND_NIL;
@@ -1741,6 +2563,8 @@ convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias)
     case OP_BFI:
     case OP_UBFIZ:
       return convert_bfm_to_bfi (inst);
     case OP_BFI:
     case OP_UBFIZ:
       return convert_bfm_to_bfi (inst);
+    case OP_BFC:
+      return convert_bfm_to_bfc (inst);
     case OP_MOV_V:
       return convert_orr_to_mov (inst);
     case OP_MOV_IMM_WIDE:
     case OP_MOV_V:
       return convert_orr_to_mov (inst);
     case OP_MOV_IMM_WIDE:
@@ -1760,8 +2584,9 @@ convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias)
     }
 }
 
     }
 }
 
-static int aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
-                                 aarch64_inst *, int);
+static bfd_boolean
+aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
+                      aarch64_inst *, int, aarch64_operand_error *errors);
 
 /* Given the instruction information in *INST, check if the instruction has
    any alias form that can be used to represent *INST.  If the answer is yes,
 
 /* Given the instruction information in *INST, check if the instruction has
    any alias form that can be used to represent *INST.  If the answer is yes,
@@ -1817,7 +2642,8 @@ static int aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
    aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help.  */
 
 static void
    aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help.  */
 
 static void
-determine_disassembling_preference (struct aarch64_inst *inst)
+determine_disassembling_preference (struct aarch64_inst *inst,
+                                   aarch64_operand_error *errors)
 {
   const aarch64_opcode *opcode;
   const aarch64_opcode *alias;
 {
   const aarch64_opcode *opcode;
   const aarch64_opcode *alias;
@@ -1825,7 +2651,7 @@ determine_disassembling_preference (struct aarch64_inst *inst)
   opcode = inst->opcode;
 
   /* This opcode does not have an alias, so use itself.  */
   opcode = inst->opcode;
 
   /* This opcode does not have an alias, so use itself.  */
-  if (opcode_has_alias (opcode) == FALSE)
+  if (!opcode_has_alias (opcode))
     return;
 
   alias = aarch64_find_alias_opcode (opcode);
     return;
 
   alias = aarch64_find_alias_opcode (opcode);
@@ -1848,7 +2674,7 @@ determine_disassembling_preference (struct aarch64_inst *inst)
   for (; alias; alias = aarch64_find_next_alias_opcode (alias))
     {
       DEBUG_TRACE ("try %s", alias->name);
   for (; alias; alias = aarch64_find_next_alias_opcode (alias))
     {
       DEBUG_TRACE ("try %s", alias->name);
-      assert (alias_opcode_p (alias));
+      assert (alias_opcode_p (alias) || opcode_has_alias (opcode));
 
       /* An alias can be a pseudo opcode which will never be used in the
         disassembly, e.g. BIC logical immediate is such a pseudo opcode
 
       /* An alias can be a pseudo opcode which will never be used in the
         disassembly, e.g. BIC logical immediate is such a pseudo opcode
@@ -1892,7 +2718,7 @@ determine_disassembling_preference (struct aarch64_inst *inst)
          /* Directly decode the alias opcode.  */
          aarch64_inst temp;
          memset (&temp, '\0', sizeof (aarch64_inst));
          /* Directly decode the alias opcode.  */
          aarch64_inst temp;
          memset (&temp, '\0', sizeof (aarch64_inst));
-         if (aarch64_opcode_decode (alias, inst->value, &temp, 1) == 1)
+         if (aarch64_opcode_decode (alias, inst->value, &temp, 1, errors) == 1)
            {
              DEBUG_TRACE ("succeed with %s via direct decoding", alias->name);
              memcpy (inst, &temp, sizeof (aarch64_inst));
            {
              DEBUG_TRACE ("succeed with %s via direct decoding", alias->name);
              memcpy (inst, &temp, sizeof (aarch64_inst));
@@ -1902,6 +2728,159 @@ determine_disassembling_preference (struct aarch64_inst *inst)
     }
 }
 
     }
 }
 
+/* Some instructions (including all SVE ones) use the instruction class
+   to describe how a qualifiers_list index is represented in the instruction
+   encoding.  If INST is such an instruction, decode the appropriate fields
+   and fill in the operand qualifiers accordingly.  Return true if no
+   problems are found.  */
+
+static bfd_boolean
+aarch64_decode_variant_using_iclass (aarch64_inst *inst)
+{
+  int i, variant;
+
+  variant = 0;
+  switch (inst->opcode->iclass)
+    {
+    case sve_cpy:
+      variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14);
+      break;
+
+    case sve_index:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
+      if ((i & 31) == 0)
+       return FALSE;
+      while ((i & 1) == 0)
+       {
+         i >>= 1;
+         variant += 1;
+       }
+      break;
+
+    case sve_limm:
+      /* Pick the smallest applicable element size.  */
+      if ((inst->value & 0x20600) == 0x600)
+       variant = 0;
+      else if ((inst->value & 0x20400) == 0x400)
+       variant = 1;
+      else if ((inst->value & 0x20000) == 0)
+       variant = 2;
+      else
+       variant = 3;
+      break;
+
+    case sve_misc:
+      /* sve_misc instructions have only a single variant.  */
+      break;
+
+    case sve_movprfx:
+      variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16);
+      break;
+
+    case sve_pred_zm:
+      variant = extract_field (FLD_SVE_M_4, inst->value, 0);
+      break;
+
+    case sve_shift_pred:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8);
+    sve_shift:
+      if (i == 0)
+       return FALSE;
+      while (i != 1)
+       {
+         i >>= 1;
+         variant += 1;
+       }
+      break;
+
+    case sve_shift_unpred:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
+      goto sve_shift;
+
+    case sve_size_bhs:
+      variant = extract_field (FLD_size, inst->value, 0);
+      if (variant >= 3)
+       return FALSE;
+      break;
+
+    case sve_size_bhsd:
+      variant = extract_field (FLD_size, inst->value, 0);
+      break;
+
+    case sve_size_hsd:
+      i = extract_field (FLD_size, inst->value, 0);
+      if (i < 1)
+       return FALSE;
+      variant = i - 1;
+      break;
+
+    case sve_size_bh:
+    case sve_size_sd:
+      variant = extract_field (FLD_SVE_sz, inst->value, 0);
+      break;
+
+    case sve_size_sd2:
+      variant = extract_field (FLD_SVE_sz2, inst->value, 0);
+      break;
+
+    case sve_size_hsd2:
+      i = extract_field (FLD_SVE_size, inst->value, 0);
+      if (i < 1)
+       return FALSE;
+      variant = i - 1;
+      break;
+
+    case sve_size_13:
+      /* Ignore low bit of this field since that is set in the opcode for
+        instructions of this iclass.  */
+      i = (extract_field (FLD_size, inst->value, 0) & 2);
+      variant = (i >> 1);
+      break;
+
+    case sve_shift_tsz_bhsd:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
+      if (i == 0)
+       return FALSE;
+      while (i != 1)
+       {
+         i >>= 1;
+         variant += 1;
+       }
+      break;
+
+    case sve_size_tsz_bhs:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19);
+      if (i == 0)
+       return FALSE;
+      while (i != 1)
+       {
+         if (i & 1)
+           return FALSE;
+         i >>= 1;
+         variant += 1;
+       }
+      break;
+
+    case sve_shift_tsz_hsd:
+      i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19);
+      if (i == 0)
+       return FALSE;
+      while (i != 1)
+       {
+         i >>= 1;
+         variant += 1;
+       }
+      break;
+
+    default:
+      /* No mapping between instruction class and qualifiers.  */
+      return TRUE;
+    }
+
+  for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+    inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i];
+  return TRUE;
+}
 /* Decode the CODE according to OPCODE; fill INST.  Return 0 if the decoding
    fails, which meanes that CODE is not an instruction of OPCODE; otherwise
    return 1.
 /* Decode the CODE according to OPCODE; fill INST.  Return 0 if the decoding
    fails, which meanes that CODE is not an instruction of OPCODE; otherwise
    return 1.
@@ -1910,9 +2889,10 @@ determine_disassembling_preference (struct aarch64_inst *inst)
    determined and used to disassemble CODE; this is done just before the
    return.  */
 
    determined and used to disassemble CODE; this is done just before the
    return.  */
 
-static int
+static bfd_boolean
 aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
 aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
-                      aarch64_inst *inst, int noaliases_p)
+                      aarch64_inst *inst, int noaliases_p,
+                      aarch64_operand_error *errors)
 {
   int i;
 
 {
   int i;
 
@@ -1920,6 +2900,9 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
 
   assert (opcode && inst);
 
 
   assert (opcode && inst);
 
+  /* Clear inst.  */
+  memset (inst, '\0', sizeof (aarch64_inst));
+
   /* Check the base opcode.  */
   if ((code & opcode->mask) != (opcode->opcode & opcode->mask))
     {
   /* Check the base opcode.  */
   if ((code & opcode->mask) != (opcode->opcode & opcode->mask))
     {
@@ -1927,9 +2910,6 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
       goto decode_fail;
     }
 
       goto decode_fail;
     }
 
-  /* Clear inst.  */
-  memset (inst, '\0', sizeof (aarch64_inst));
-
   inst->opcode = opcode;
   inst->value = code;
 
   inst->opcode = opcode;
   inst->value = code;
 
@@ -1949,23 +2929,41 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
       goto decode_fail;
     }
 
       goto decode_fail;
     }
 
+  /* Possibly use the instruction class to determine the correct
+     qualifier.  */
+  if (!aarch64_decode_variant_using_iclass (inst))
+    {
+      DEBUG_TRACE ("iclass-based decoder FAIL");
+      goto decode_fail;
+    }
+
   /* Call operand decoders.  */
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       const aarch64_operand *opnd;
       enum aarch64_opnd type;
   /* Call operand decoders.  */
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       const aarch64_operand *opnd;
       enum aarch64_opnd type;
+
       type = opcode->operands[i];
       if (type == AARCH64_OPND_NIL)
        break;
       opnd = &aarch64_operands[type];
       if (operand_has_extractor (opnd)
       type = opcode->operands[i];
       if (type == AARCH64_OPND_NIL)
        break;
       opnd = &aarch64_operands[type];
       if (operand_has_extractor (opnd)
-         && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst)))
+         && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst,
+                                        errors)))
        {
          DEBUG_TRACE ("operand decoder FAIL at operand %d", i);
          goto decode_fail;
        }
     }
 
        {
          DEBUG_TRACE ("operand decoder FAIL at operand %d", i);
          goto decode_fail;
        }
     }
 
+  /* If the opcode has a verifier, then check it now.  */
+  if (opcode->verifier
+      && opcode->verifier (inst, code, 0, FALSE, errors, NULL) != ERR_OK)
+    {
+      DEBUG_TRACE ("operand verifier FAIL");
+      goto decode_fail;
+    }
+
   /* Match the qualifiers.  */
   if (aarch64_match_operands_constraint (inst, NULL) == 1)
     {
   /* Match the qualifiers.  */
   if (aarch64_match_operands_constraint (inst, NULL) == 1)
     {
@@ -1975,17 +2973,17 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
         alias and should be disassembled in the form of its alias instead.
         If the answer is yes, *INST will be updated.  */
       if (!noaliases_p)
         alias and should be disassembled in the form of its alias instead.
         If the answer is yes, *INST will be updated.  */
       if (!noaliases_p)
-       determine_disassembling_preference (inst);
+       determine_disassembling_preference (inst, errors);
       DEBUG_TRACE ("SUCCESS");
       DEBUG_TRACE ("SUCCESS");
-      return 1;
+      return TRUE;
     }
   else
     {
       DEBUG_TRACE ("constraint matching FAIL");
     }
 
     }
   else
     {
       DEBUG_TRACE ("constraint matching FAIL");
     }
 
-decode_fail:
-  return 0;
+ decode_fail:
+  return FALSE;
 }
 \f
 /* This does some user-friendly fix-up to *INST.  It is currently focus on
 }
 \f
 /* This does some user-friendly fix-up to *INST.  It is currently focus on
@@ -2011,11 +3009,14 @@ user_friendly_fixup (aarch64_inst *inst)
     }
 }
 
     }
 }
 
-/* Decode INSN and fill in *INST the instruction information.  */
+/* Decode INSN and fill in *INST the instruction information.  An alias
+   opcode may be filled in *INSN if NOALIASES_P is FALSE.  Return zero on
+   success.  */
 
 
-static int
-disas_aarch64_insn (uint64_t pc ATTRIBUTE_UNUSED, uint32_t insn,
-                   aarch64_inst *inst)
+enum err_type
+aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
+                    bfd_boolean noaliases_p,
+                    aarch64_operand_error *errors)
 {
   const aarch64_opcode *opcode = aarch64_opcode_lookup (insn);
 
 {
   const aarch64_opcode *opcode = aarch64_opcode_lookup (insn);
 
@@ -2042,7 +3043,7 @@ disas_aarch64_insn (uint64_t pc ATTRIBUTE_UNUSED, uint32_t insn,
     {
       /* But only one opcode can be decoded successfully for, as the
         decoding routine will check the constraint carefully.  */
     {
       /* But only one opcode can be decoded successfully for, as the
         decoding routine will check the constraint carefully.  */
-      if (aarch64_opcode_decode (opcode, insn, inst, no_aliases) == 1)
+      if (aarch64_opcode_decode (opcode, insn, inst, noaliases_p, errors) == 1)
        return ERR_OK;
       opcode = aarch64_find_next_opcode (opcode);
     }
        return ERR_OK;
       opcode = aarch64_find_next_opcode (opcode);
     }
@@ -2054,13 +3055,14 @@ disas_aarch64_insn (uint64_t pc ATTRIBUTE_UNUSED, uint32_t insn,
 
 static void
 print_operands (bfd_vma pc, const aarch64_opcode *opcode,
 
 static void
 print_operands (bfd_vma pc, const aarch64_opcode *opcode,
-               const aarch64_opnd_info *opnds, struct disassemble_info *info)
+               const aarch64_opnd_info *opnds, struct disassemble_info *info,
+               bfd_boolean *has_notes)
 {
 {
+  char *notes = NULL;
   int i, pcrel_p, num_printed;
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
   int i, pcrel_p, num_printed;
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
-      const size_t size = 128;
-      char str[size];
+      char str[128];
       /* We regard the opcode operand info more, however we also look into
         the inst->operands to support the disassembling of the optional
         operand.
       /* We regard the opcode operand info more, however we also look into
         the inst->operands to support the disassembling of the optional
         operand.
@@ -2071,8 +3073,8 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
        break;
 
       /* Generate the operand string in STR.  */
        break;
 
       /* Generate the operand string in STR.  */
-      aarch64_print_operand (str, size, pc, opcode, opnds, i, &pcrel_p,
-                            &info->target);
+      aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
+                            &info->target, &notes);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
@@ -2085,6 +3087,28 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       else
        (*info->fprintf_func) (info->stream, "%s", str);
     }
       else
        (*info->fprintf_func) (info->stream, "%s", str);
     }
+
+    if (notes && !no_notes)
+      {
+       *has_notes = TRUE;
+       (*info->fprintf_func) (info->stream, "  // note: %s", notes);
+      }
+}
+
+/* Set NAME to a copy of INST's mnemonic with the "." suffix removed.  */
+
+static void
+remove_dot_suffix (char *name, const aarch64_inst *inst)
+{
+  char *ptr;
+  size_t len;
+
+  ptr = strchr (inst->opcode->name, '.');
+  assert (ptr && inst->cond);
+  len = ptr - inst->opcode->name;
+  assert (len < 8);
+  strncpy (name, inst->opcode->name, len);
+  name[len] = '\0';
 }
 
 /* Print the instruction mnemonic name.  */
 }
 
 /* Print the instruction mnemonic name.  */
@@ -2097,29 +3121,92 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       /* For instructions that are truly conditionally executed, e.g. b.cond,
         prepare the full mnemonic name with the corresponding condition
         suffix.  */
       /* For instructions that are truly conditionally executed, e.g. b.cond,
         prepare the full mnemonic name with the corresponding condition
         suffix.  */
-      char name[8], *ptr;
-      size_t len;
-
-      ptr = strchr (inst->opcode->name, '.');
-      assert (ptr && inst->cond);
-      len = ptr - inst->opcode->name;
-      assert (len < 8);
-      strncpy (name, inst->opcode->name, len);
-      name [len] = '\0';
+      char name[8];
+
+      remove_dot_suffix (name, inst);
       (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
     }
   else
     (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
 }
 
       (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
     }
   else
     (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
 }
 
+/* Decide whether we need to print a comment after the operands of
+   instruction INST.  */
+
+static void
+print_comment (const aarch64_inst *inst, struct disassemble_info *info)
+{
+  if (inst->opcode->flags & F_COND)
+    {
+      char name[8];
+      unsigned int i, num_conds;
+
+      remove_dot_suffix (name, inst);
+      num_conds = ARRAY_SIZE (inst->cond->names);
+      for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
+       (*info->fprintf_func) (info->stream, "%s %s.%s",
+                              i == 1 ? "  //" : ",",
+                              name, inst->cond->names[i]);
+    }
+}
+
+/* Build notes from verifiers into a string for printing.  */
+
+static void
+print_verifier_notes (aarch64_operand_error *detail,
+                     struct disassemble_info *info)
+{
+  if (no_notes)
+    return;
+
+  /* The output of the verifier cannot be a fatal error, otherwise the assembly
+     would not have succeeded.  We can safely ignore these.  */
+  assert (detail->non_fatal);
+  assert (detail->error);
+
+  /* If there are multiple verifier messages, concat them up to 1k.  */
+  (*info->fprintf_func) (info->stream, "  // note: %s", detail->error);
+  if (detail->index >= 0)
+     (*info->fprintf_func) (info->stream, " at operand %d", detail->index + 1);
+}
+
 /* Print the instruction according to *INST.  */
 
 static void
 print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
 /* Print the instruction according to *INST.  */
 
 static void
 print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
-                   struct disassemble_info *info)
+                   const aarch64_insn code,
+                   struct disassemble_info *info,
+                   aarch64_operand_error *mismatch_details)
 {
 {
+  bfd_boolean has_notes = FALSE;
+
   print_mnemonic_name (inst, info);
   print_mnemonic_name (inst, info);
-  print_operands (pc, inst->opcode, inst->operands, info);
+  print_operands (pc, inst->opcode, inst->operands, info, &has_notes);
+  print_comment (inst, info);
+
+  /* We've already printed a note, not enough space to print more so exit.
+     Usually notes shouldn't overlap so it shouldn't happen that we have a note
+     from a register and instruction at the same time.  */
+  if (has_notes)
+    return;
+
+  /* Always run constraint verifiers, this is needed because constraints need to
+     maintain a global state regardless of whether the instruction has the flag
+     set or not.  */
+  enum err_type result = verify_constraints (inst, code, pc, FALSE,
+                                            mismatch_details, &insn_sequence);
+  switch (result)
+    {
+    case ERR_UND:
+    case ERR_UNP:
+    case ERR_NYI:
+      assert (0);
+    case ERR_VFI:
+      print_verifier_notes (mismatch_details, info);
+      break;
+    default:
+      break;
+    }
 }
 
 /* Entry-point of the instruction disassembler and printer.  */
 }
 
 /* Entry-point of the instruction disassembler and printer.  */
@@ -2127,17 +3214,18 @@ print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
 static void
 print_insn_aarch64_word (bfd_vma pc,
                         uint32_t word,
 static void
 print_insn_aarch64_word (bfd_vma pc,
                         uint32_t word,
-                        struct disassemble_info *info)
+                        struct disassemble_info *info,
+                        aarch64_operand_error *errors)
 {
 {
-  static const char *err_msg[6] =
+  static const char *err_msg[ERR_NR_ENTRIES+1] =
     {
     {
-      [ERR_OK]   = "_",
-      [-ERR_UND] = "undefined",
-      [-ERR_UNP] = "unpredictable",
-      [-ERR_NYI] = "NYI"
+      [ERR_OK]  = "_",
+      [ERR_UND] = "undefined",
+      [ERR_UNP] = "unpredictable",
+      [ERR_NYI] = "NYI"
     };
 
     };
 
-  int ret;
+  enum err_type ret;
   aarch64_inst inst;
 
   info->insn_info_valid = 1;
   aarch64_inst inst;
 
   info->insn_info_valid = 1;
@@ -2154,7 +3242,7 @@ print_insn_aarch64_word (bfd_vma pc,
        addresses, since the addend is not currently pc-relative.  */
     pc = 0;
 
        addresses, since the addend is not currently pc-relative.  */
     pc = 0;
 
-  ret = disas_aarch64_insn (pc, word, &inst);
+  ret = aarch64_decode_insn (word, &inst, no_aliases, errors);
 
   if (((word >> 21) & 0x3ff) == 1)
     {
 
   if (((word >> 21) & 0x3ff) == 1)
     {
@@ -2171,11 +3259,11 @@ print_insn_aarch64_word (bfd_vma pc,
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
       (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
       (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-                            word, err_msg[-ret]);
+                            word, err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
-      print_aarch64_insn (pc, &inst, info);
+      print_aarch64_insn (pc, &inst, word, info, errors);
       break;
     default:
       abort ();
       break;
     default:
       abort ();
@@ -2207,7 +3295,8 @@ aarch64_symbol_is_valid (asymbol * sym,
 static void
 print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
                 uint32_t word,
 static void
 print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
                 uint32_t word,
-                struct disassemble_info *info)
+                struct disassemble_info *info,
+                aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   switch (info->bytes_per_chunk)
     {
 {
   switch (info->bytes_per_chunk)
     {
@@ -2236,6 +3325,10 @@ get_sym_code_type (struct disassemble_info *info, int n,
   unsigned int type;
   const char *name;
 
   unsigned int type;
   const char *name;
 
+  /* If the symbol is in a different section, ignore it.  */
+  if (info->section != NULL && info->section != info->symtab[n]->section)
+    return FALSE;
+
   es = *(elf_symbol_type **)(info->symtab + n);
   type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
   es = *(elf_symbol_type **)(info->symtab + n);
   type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
@@ -2267,10 +3360,12 @@ print_insn_aarch64 (bfd_vma pc,
 {
   bfd_byte     buffer[INSNLEN];
   int          status;
 {
   bfd_byte     buffer[INSNLEN];
   int          status;
-  void         (*printer) (bfd_vma, uint32_t, struct disassemble_info *);
+  void         (*printer) (bfd_vma, uint32_t, struct disassemble_info *,
+                           aarch64_operand_error *);
   bfd_boolean   found = FALSE;
   unsigned int size = 4;
   unsigned long        data;
   bfd_boolean   found = FALSE;
   unsigned int size = 4;
   unsigned long        data;
+  aarch64_operand_error errors;
 
   if (info->disassembler_options)
     {
 
   if (info->disassembler_options)
     {
@@ -2285,14 +3380,26 @@ print_insn_aarch64 (bfd_vma pc,
   /* Aarch64 instructions are always little-endian */
   info->endian_code = BFD_ENDIAN_LITTLE;
 
   /* Aarch64 instructions are always little-endian */
   info->endian_code = BFD_ENDIAN_LITTLE;
 
+  /* Default to DATA.  A text section is required by the ABI to contain an
+     INSN mapping symbol at the start.  A data section has no such
+     requirement, hence if no mapping symbol is found the section must
+     contain only data.  This however isn't very useful if the user has
+     fully stripped the binaries.  If this is the case use the section
+     attributes to determine the default.  If we have no section default to
+     INSN as well, as we may be disassembling some raw bytes on a baremetal
+     HEX file or similar.  */
+  enum map_type type = MAP_DATA;
+  if ((info->section && info->section->flags & SEC_CODE) || !info->section)
+    type = MAP_INSN;
+
   /* First check the full symtab for a mapping symbol, even if there
      are no usable non-mapping symbols for this address.  */
   if (info->symtab_size != 0
       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
     {
   /* First check the full symtab for a mapping symbol, even if there
      are no usable non-mapping symbols for this address.  */
   if (info->symtab_size != 0
       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
     {
-      enum map_type type = MAP_INSN;
       int last_sym = -1;
       int last_sym = -1;
-      bfd_vma addr;
+      bfd_vma addr, section_vma = 0;
+      bfd_boolean can_use_search_opt_p;
       int n;
 
       if (pc <= last_mapping_addr)
       int n;
 
       if (pc <= last_mapping_addr)
@@ -2301,18 +3408,26 @@ print_insn_aarch64 (bfd_vma pc,
       /* Start scanning at the start of the function, or wherever
         we finished last time.  */
       n = info->symtab_pos + 1;
       /* Start scanning at the start of the function, or wherever
         we finished last time.  */
       n = info->symtab_pos + 1;
-      if (n < last_mapping_sym)
+
+      /* If the last stop offset is different from the current one it means we
+        are disassembling a different glob of bytes.  As such the optimization
+        would not be safe and we should start over.  */
+      can_use_search_opt_p = last_mapping_sym >= 0
+                            && info->stop_offset == last_stop_offset;
+
+      if (n >= last_mapping_sym && can_use_search_opt_p)
        n = last_mapping_sym;
 
        n = last_mapping_sym;
 
-      /* Scan up to the location being disassembled.  */
+      /* Look down while we haven't passed the location being disassembled.
+        The reason for this is that there's no defined order between a symbol
+        and an mapping symbol that may be at the same address.  We may have to
+        look at least one position ahead.  */
       for (; n < info->symtab_size; n++)
        {
          addr = bfd_asymbol_value (info->symtab[n]);
          if (addr > pc)
            break;
       for (; n < info->symtab_size; n++)
        {
          addr = bfd_asymbol_value (info->symtab[n]);
          if (addr > pc)
            break;
-         if ((info->section == NULL
-              || info->section == info->symtab[n]->section)
-             && get_sym_code_type (info, n, &type))
+         if (get_sym_code_type (info, n, &type))
            {
              last_sym = n;
              found = TRUE;
            {
              last_sym = n;
              found = TRUE;
@@ -2322,13 +3437,24 @@ print_insn_aarch64 (bfd_vma pc,
       if (!found)
        {
          n = info->symtab_pos;
       if (!found)
        {
          n = info->symtab_pos;
-         if (n < last_mapping_sym)
+         if (n >= last_mapping_sym && can_use_search_opt_p)
            n = last_mapping_sym;
 
          /* No mapping symbol found at this address.  Look backwards
            n = last_mapping_sym;
 
          /* No mapping symbol found at this address.  Look backwards
-            for a preceeding one.  */
+            for a preceeding one, but don't go pass the section start
+            otherwise a data section with no mapping symbol can pick up
+            a text mapping symbol of a preceeding section.  The documentation
+            says section can be NULL, in which case we will seek up all the
+            way to the top.  */
+         if (info->section)
+           section_vma = info->section->vma;
+
          for (; n >= 0; n--)
            {
          for (; n >= 0; n--)
            {
+             addr = bfd_asymbol_value (info->symtab[n]);
+             if (addr < section_vma)
+               break;
+
              if (get_sym_code_type (info, n, &type))
                {
                  last_sym = n;
              if (get_sym_code_type (info, n, &type))
                {
                  last_sym = n;
@@ -2340,6 +3466,7 @@ print_insn_aarch64 (bfd_vma pc,
 
       last_mapping_sym = last_sym;
       last_type = type;
 
       last_mapping_sym = last_sym;
       last_type = type;
+      last_stop_offset = info->stop_offset;
 
       /* Look a little bit ahead to see if we should print out
         less than four bytes of data.  If there's a symbol,
 
       /* Look a little bit ahead to see if we should print out
         less than four bytes of data.  If there's a symbol,
@@ -2365,8 +3492,11 @@ print_insn_aarch64 (bfd_vma pc,
            size = (pc & 1) ? 1 : 2;
        }
     }
            size = (pc & 1) ? 1 : 2;
        }
     }
+  else
+    last_type = type;
 
 
-  if (last_type == MAP_DATA)
+  /* PR 10263: Disassemble data if requested to do so by the user.  */
+  if (last_type == MAP_DATA && ((info->flags & DISASSEMBLE_DATA) == 0))
     {
       /* size was set above.  */
       info->bytes_per_chunk = size;
     {
       /* size was set above.  */
       info->bytes_per_chunk = size;
@@ -2390,7 +3520,7 @@ print_insn_aarch64 (bfd_vma pc,
   data = bfd_get_bits (buffer, size * 8,
                       info->display_endian == BFD_ENDIAN_BIG);
 
   data = bfd_get_bits (buffer, size * 8,
                       info->display_endian == BFD_ENDIAN_BIG);
 
-  (*printer) (pc, data, info);
+  (*printer) (pc, data, info, &errors);
 
   return size;
 }
 
   return size;
 }
@@ -2408,6 +3538,12 @@ with the -M switch (multiple options should be separated by commas):\n"));
   fprintf (stream, _("\n\
   aliases            Do print instruction aliases.\n"));
 
   fprintf (stream, _("\n\
   aliases            Do print instruction aliases.\n"));
 
+  fprintf (stream, _("\n\
+  no-notes         Don't print instruction notes.\n"));
+
+  fprintf (stream, _("\n\
+  notes            Do print instruction notes.\n"));
+
 #ifdef DEBUG_AARCH64
   fprintf (stream, _("\n\
   debug_dump         Temp switch for debug trace.\n"));
 #ifdef DEBUG_AARCH64
   fprintf (stream, _("\n\
   debug_dump         Temp switch for debug trace.\n"));
This page took 0.105505 seconds and 4 git commands to generate.