LoongArch: Deprecate $v[01], $fv[01] and $x names per spec
[binutils-gdb.git] / opcodes / aarch64-opc.c
index 4df1dc2cda8afa31244e6ec29f76ebbadca00f12..ba2aa8a6c13bb5cb60fb49276cde9898792cac74 100644 (file)
@@ -99,6 +99,24 @@ const char *const aarch64_sve_prfop_array[16] = {
   0
 };
 
+/* The enumeration strings associated with each value of a 6-bit RPRFM
+   operation.  */
+const char *const aarch64_rprfmop_array[64] = {
+  "pldkeep",
+  "pstkeep",
+  0,
+  0,
+  "pldstrm",
+  "pststrm"
+};
+
+/* Vector length multiples for a predicate-as-counter operand.  Used in things
+   like AARCH64_OPND_SME_VLxN_10.  */
+const char *const aarch64_sme_vlxn_array[2] = {
+  "vlx2",
+  "vlx4"
+};
+
 /* Helper functions to determine which operand to be used to encode/decode
    the size:Q fields for AdvSIMD instructions.  */
 
@@ -220,15 +238,32 @@ const aarch64_field fields[] =
     { 10,  5 },        /* Rt2: in load/store pair instructions.  */
     { 12,  1 },        /* S: in load/store reg offset instructions.  */
     { 12,  2 }, /* SM3_imm2: Indexed element SM3 2 bits index immediate.  */
+    {  1,  3 }, /* SME_Pdx2: predicate register, multiple of 2, [3:1].  */
     { 13,  3 }, /* SME_Pm: second source scalable predicate register P0-P7.  */
+    {  0,  3 }, /* SME_PNd3: PN0-PN7, bits [2:0].  */
+    {  5,  3 }, /* SME_PNn3: PN0-PN7, bits [7:5].  */
     { 16,  1 }, /* SME_Q: Q class bit, bit 16.  */
     { 16,  2 }, /* SME_Rm: index base register W12-W15 [17:16].  */
     { 13,  2 }, /* SME_Rv: vector select register W12-W15, bits [14:13].  */
     { 15,  1 }, /* SME_V: (horizontal / vertical tiles), bit 15.  */
+    { 10,  1 }, /* SME_VL_10: VLx2 or VLx4, bit [10].  */
+    { 13,  1 }, /* SME_VL_13: VLx2 or VLx4, bit [13].  */
     {  0,  2 }, /* SME_ZAda_2b: tile ZA0-ZA3.  */
     {  0,  3 }, /* SME_ZAda_3b: tile ZA0-ZA7.  */
+    {  1,  4 }, /* SME_Zdn2: Z0-Z31, multiple of 2, bits [4:1].  */
+    {  2,  3 }, /* SME_Zdn4: Z0-Z31, multiple of 4, bits [4:2].  */
+    { 16,  4 }, /* SME_Zm: Z0-Z15, bits [19:16].  */
+    { 17,  4 }, /* SME_Zm2: Z0-Z31, multiple of 2, bits [20:17].  */
+    { 18,  3 }, /* SME_Zm4: Z0-Z31, multiple of 4, bits [20:18].  */
+    {  6,  4 }, /* SME_Zn2: Z0-Z31, multiple of 2, bits [9:6].  */
+    {  7,  3 }, /* SME_Zn4: Z0-Z31, multiple of 4, bits [9:7].  */
+    {  4,  1 }, /* SME_ZtT: upper bit of Zt, bit [4].  */
+    {  0,  3 }, /* SME_Zt3: lower 3 bits of Zt, bits [2:0].  */
+    {  0,  2 }, /* SME_Zt2: lower 2 bits of Zt, bits [1:0].  */
     { 23,  1 }, /* SME_i1: immediate field, bit 23.  */
+    { 12,  2 }, /* SME_size_12: bits [13:12].  */
     { 22,  2 }, /* SME_size_22: size<1>, size<0> class field, [23:22].  */
+    { 23,  1 }, /* SME_sz_23: bit [23].  */
     { 22,  1 }, /* SME_tszh: immediate and qualifier field, bit 22.  */
     { 18,  3 }, /* SME_tszl: immediate and qualifier field, bits [20:18].  */
     { 0,   8 }, /* SME_zero_mask: list of up to 8 tile names separated by commas [7:0].  */
@@ -296,11 +331,31 @@ const aarch64_field fields[] =
     {  0,  4 },        /* cond2: condition in truly conditional-executed inst.  */
     {  5,  5 },        /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate.  */
     { 21,  2 },        /* hw: in move wide constant instructions.  */
+    {  0,  1 },        /* imm1_0: general immediate in bits [0].  */
+    {  2,  1 },        /* imm1_2: general immediate in bits [2].  */
+    {  8,  1 },        /* imm1_8: general immediate in bits [8].  */
+    { 10,  1 },        /* imm1_10: general immediate in bits [10].  */
+    { 15,  1 },        /* imm1_15: general immediate in bits [15].  */
+    { 16,  1 },        /* imm1_16: general immediate in bits [16].  */
+    {  0,  2 },        /* imm2_0: general immediate in bits [1:0].  */
+    {  1,  2 },        /* imm2_1: general immediate in bits [2:1].  */
+    {  8,  2 },        /* imm2_8: general immediate in bits [9:8].  */
+    { 10,  2 }, /* imm2_10: 2-bit immediate, bits [11:10] */
+    { 12,  2 }, /* imm2_12: 2-bit immediate, bits [13:12] */
+    { 15,  2 }, /* imm2_15: 2-bit immediate, bits [16:15] */
+    { 16,  2 }, /* imm2_16: 2-bit immediate, bits [17:16] */
+    { 19,  2 }, /* imm2_19: 2-bit immediate, bits [20:19] */
+    {  0,  3 },        /* imm3_0: general immediate in bits [2:0].  */
+    {  5,  3 },        /* imm3_5: general immediate in bits [7:5].  */
     { 10,  3 },        /* imm3_10: in add/sub extended reg instructions.  */
+    { 12,  3 },        /* imm3_12: general immediate in bits [14:12].  */
+    { 14,  3 },        /* imm3_14: general immediate in bits [16:14].  */
+    { 15,  3 },        /* imm3_15: general immediate in bits [17:15].  */
     {  0,  4 },        /* imm4_0: in rmif instructions.  */
     {  5,  4 }, /* imm4_5: in SME instructions.  */
     { 10,  4 },        /* imm4_10: in adddg/subg instructions.  */
     { 11,  4 },        /* imm4_11: in advsimd ext and advsimd ins instructions.  */
+    { 14,  4 },        /* imm4_14: general immediate in bits [17:14].  */
     { 16,  5 },        /* imm5: in conditional compare (immediate) instructions.  */
     { 10,  6 },        /* imm6_10: in add/sub reg shifted instructions.  */
     { 15,  6 },        /* imm6_15: in rmif instructions.  */
@@ -1546,6 +1601,10 @@ check_za_access (const aarch64_opnd_info *opnd,
        set_other_error (mismatch_detail, idx,
                         _("expected a selection register in the"
                           " range w12-w15"));
+      else if (min_wreg == 8)
+       set_other_error (mismatch_detail, idx,
+                        _("expected a selection register in the"
+                          " range w8-w11"));
       else
        abort ();
       return false;
@@ -1574,6 +1633,12 @@ check_za_access (const aarch64_opnd_info *opnd,
        set_other_error (mismatch_detail, idx,
                         _("expected a single offset rather than"
                           " a range"));
+      else if (range_size == 2)
+       set_other_error (mismatch_detail, idx,
+                        _("expected a range of two offsets"));
+      else if (range_size == 4)
+       set_other_error (mismatch_detail, idx,
+                        _("expected a range of four offsets"));
       else
        abort ();
       return false;
@@ -1683,6 +1748,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        {
        case AARCH64_OPND_SVE_Zm3_INDEX:
        case AARCH64_OPND_SVE_Zm3_22_INDEX:
+       case AARCH64_OPND_SVE_Zm3_19_INDEX:
        case AARCH64_OPND_SVE_Zm3_11_INDEX:
        case AARCH64_OPND_SVE_Zm4_11_INDEX:
        case AARCH64_OPND_SVE_Zm4_INDEX:
@@ -1701,6 +1767,47 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            return 0;
          break;
 
+       case AARCH64_OPND_SME_PNn3_INDEX1:
+       case AARCH64_OPND_SME_PNn3_INDEX2:
+         size = get_operand_field_width (get_operand_from_code (type), 1);
+         if (!check_reglane (opnd, mismatch_detail, idx, "pn", 8, 15,
+                             0, (1 << size) - 1))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_Zn_INDEX1_16:
+       case AARCH64_OPND_SME_Zn_INDEX2_15:
+       case AARCH64_OPND_SME_Zn_INDEX2_16:
+       case AARCH64_OPND_SME_Zn_INDEX3_14:
+       case AARCH64_OPND_SME_Zn_INDEX3_15:
+       case AARCH64_OPND_SME_Zn_INDEX4_14:
+         size = get_operand_fields_width (get_operand_from_code (type)) - 5;
+         if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 31,
+                             0, (1 << size) - 1))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_Zm_INDEX1:
+       case AARCH64_OPND_SME_Zm_INDEX2:
+       case AARCH64_OPND_SME_Zm_INDEX3_1:
+       case AARCH64_OPND_SME_Zm_INDEX3_2:
+       case AARCH64_OPND_SME_Zm_INDEX3_10:
+       case AARCH64_OPND_SME_Zm_INDEX4_1:
+       case AARCH64_OPND_SME_Zm_INDEX4_10:
+         size = get_operand_fields_width (get_operand_from_code (type)) - 4;
+         if (!check_reglane (opnd, mismatch_detail, idx, "z", 0, 15,
+                             0, (1 << size) - 1))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_Zm:
+         if (opnd->reg.regno > 15)
+           {
+             set_invalid_regno_error (mismatch_detail, idx, "z", 0, 15);
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_SME_PnT_Wm_imm:
          size = aarch64_get_qualifier_esize (opnd->qualifier);
          max_value = 16 / size - 1;
@@ -1715,9 +1822,53 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       break;
 
     case AARCH64_OPND_CLASS_SVE_REGLIST:
-      num = get_opcode_dependent_value (opcode);
-      if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
-       return 0;
+      switch (type)
+       {
+       case AARCH64_OPND_SME_Pdx2:
+       case AARCH64_OPND_SME_Zdnx2:
+       case AARCH64_OPND_SME_Zdnx4:
+       case AARCH64_OPND_SME_Zmx2:
+       case AARCH64_OPND_SME_Zmx4:
+       case AARCH64_OPND_SME_Znx2:
+       case AARCH64_OPND_SME_Znx4:
+         num = get_operand_specific_data (&aarch64_operands[type]);
+         if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
+           return 0;
+         if ((opnd->reglist.first_regno % num) != 0)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("start register out of range"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SME_Ztx2_STRIDED:
+       case AARCH64_OPND_SME_Ztx4_STRIDED:
+         /* 2-register lists have a stride of 8 and 4-register lists
+            have a stride of 4.  */
+         num = get_operand_specific_data (&aarch64_operands[type]);
+         if (!check_reglist (opnd, mismatch_detail, idx, num, 16 / num))
+           return 0;
+         num = 16 | (opnd->reglist.stride - 1);
+         if ((opnd->reglist.first_regno & ~num) != 0)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("start register out of range"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SME_PdxN:
+       case AARCH64_OPND_SVE_ZnxN:
+       case AARCH64_OPND_SVE_ZtxN:
+         num = get_opcode_dependent_value (opcode);
+         if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
+           return 0;
+         break;
+
+       default:
+         abort ();
+       }
       break;
 
     case AARCH64_OPND_CLASS_ZA_ACCESS:
@@ -1739,17 +1890,74 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            return 0;
          break;
 
+       case AARCH64_OPND_SME_ZA_array_off3_0:
+       case AARCH64_OPND_SME_ZA_array_off3_5:
+         if (!check_za_access (opnd, mismatch_detail, idx, 8, 7, 1,
+                               get_opcode_dependent_value (opcode)))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_ZA_array_off1x4:
+         if (!check_za_access (opnd, mismatch_detail, idx, 8, 1, 4,
+                               get_opcode_dependent_value (opcode)))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_ZA_array_off2x2:
+         if (!check_za_access (opnd, mismatch_detail, idx, 8, 3, 2,
+                               get_opcode_dependent_value (opcode)))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_ZA_array_off2x4:
+         if (!check_za_access (opnd, mismatch_detail, idx, 8, 3, 4,
+                               get_opcode_dependent_value (opcode)))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_ZA_array_off3x2:
+         if (!check_za_access (opnd, mismatch_detail, idx, 8, 7, 2,
+                               get_opcode_dependent_value (opcode)))
+           return 0;
+         break;
+
+       case AARCH64_OPND_SME_ZA_HV_idx_srcxN:
+       case AARCH64_OPND_SME_ZA_HV_idx_destxN:
+         size = aarch64_get_qualifier_esize (opnd->qualifier);
+         num = get_opcode_dependent_value (opcode);
+         max_value = 16 / num / size;
+         if (max_value > 0)
+           max_value -= 1;
+         if (!check_za_access (opnd, mismatch_detail, idx,
+                               12, max_value, num, 0))
+           return 0;
+         break;
+
        default:
          abort ();
        }
       break;
 
     case AARCH64_OPND_CLASS_PRED_REG:
-      if (opnd->reg.regno >= 8
-         && get_operand_fields_width (get_operand_from_code (type)) == 3)
+      switch (type)
        {
-         set_invalid_regno_error (mismatch_detail, idx, "p", 0, 7);
-         return 0;
+       case AARCH64_OPND_SME_PNd3:
+       case AARCH64_OPND_SME_PNg3:
+         if (opnd->reg.regno < 8)
+           {
+             set_invalid_regno_error (mismatch_detail, idx, "pn", 8, 15);
+             return 0;
+           }
+         break;
+
+       default:
+         if (opnd->reg.regno >= 8
+             && get_operand_fields_width (get_operand_from_code (type)) == 3)
+           {
+             set_invalid_regno_error (mismatch_detail, idx, "p", 0, 7);
+             return 0;
+           }
+         break;
        }
       break;
 
@@ -2730,6 +2938,16 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_SME_SHRIMM4:
+         size = 1 << get_operand_fields_width (get_operand_from_code (type));
+         if (!value_in_range_p (opnd->imm.value, 1, size))
+           {
+             set_imm_out_of_range_error (mismatch_detail, idx, 1, size);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SME_SHRIMM5:
        case AARCH64_OPND_SVE_SHRIMM_PRED:
        case AARCH64_OPND_SVE_SHRIMM_UNPRED:
        case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
@@ -2742,6 +2960,20 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_SME_ZT0_INDEX:
+         if (!value_in_range_p (opnd->imm.value, 0, 56))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, 56);
+             return 0;
+           }
+         if (opnd->imm.value % 8 != 0)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("byte index must be a multiple of 8"));
+             return 0;
+           }
+         break;
+
        default:
          break;
        }
@@ -2947,23 +3179,38 @@ aarch64_match_operands_constraint (aarch64_inst *inst,
           break;
 
         default:
-          /* Check for cases where a source register needs to be the same as the
-             destination register.  Do this before matching qualifiers since if
-             an instruction has both invalid tying and invalid qualifiers,
-             the error about qualifiers would suggest several alternative
-             instructions that also have invalid tying.  */
-          if (inst->operands[0].reg.regno
-              != inst->operands[i].reg.regno)
-            {
-              if (mismatch_detail)
-                {
-                  mismatch_detail->kind = AARCH64_OPDE_UNTIED_OPERAND;
-                  mismatch_detail->index = i;
-                  mismatch_detail->error = NULL;
-                }
-              return 0;
-            }
-          break;
+         {
+           /* Check for cases where a source register needs to be the
+              same as the destination register.  Do this before
+              matching qualifiers since if an instruction has both
+              invalid tying and invalid qualifiers, the error about
+              qualifiers would suggest several alternative instructions
+              that also have invalid tying.  */
+           enum aarch64_operand_class op_class1
+              = aarch64_get_operand_class (inst->operands[0].type);
+           enum aarch64_operand_class op_class2
+              = aarch64_get_operand_class (inst->operands[i].type);
+           assert (op_class1 == op_class2);
+           if (op_class1 == AARCH64_OPND_CLASS_SVE_REGLIST
+               ? ((inst->operands[0].reglist.first_regno
+                   != inst->operands[i].reglist.first_regno)
+                  || (inst->operands[0].reglist.num_regs
+                      != inst->operands[i].reglist.num_regs)
+                  || (inst->operands[0].reglist.stride
+                      != inst->operands[i].reglist.stride))
+               : (inst->operands[0].reg.regno
+                  != inst->operands[i].reg.regno))
+             {
+               if (mismatch_detail)
+                 {
+                   mismatch_detail->kind = AARCH64_OPDE_UNTIED_OPERAND;
+                   mismatch_detail->index = i;
+                   mismatch_detail->error = NULL;
+                 }
+               return 0;
+             }
+           break;
+         }
         }
     }
 
@@ -3275,10 +3522,11 @@ static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
                     const char *prefix, struct aarch64_styler *styler)
 {
+  const int mask = (prefix[0] == 'p' ? 15 : 31);
   const int num_regs = opnd->reglist.num_regs;
   const int stride = opnd->reglist.stride;
   const int first_reg = opnd->reglist.first_regno;
-  const int last_reg = (first_reg + (num_regs - 1) * stride) & 0x1f;
+  const int last_reg = (first_reg + (num_regs - 1) * stride) & mask;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
   char tb[16]; /* Temporary buffer.  */
 
@@ -3303,9 +3551,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   else
     {
       const int reg0 = first_reg;
-      const int reg1 = (first_reg + stride) & 0x1f;
-      const int reg2 = (first_reg + stride * 2) & 0x1f;
-      const int reg3 = (first_reg + stride * 3) & 0x1f;
+      const int reg1 = (first_reg + stride) & mask;
+      const int reg2 = (first_reg + stride * 2) & mask;
+      const int reg3 = (first_reg + stride * 3) & mask;
 
       switch (num_regs)
        {
@@ -3679,6 +3927,39 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                             aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
+    case AARCH64_OPND_SVE_PNd:
+    case AARCH64_OPND_SVE_PNg4_10:
+    case AARCH64_OPND_SVE_PNn:
+    case AARCH64_OPND_SVE_PNt:
+    case AARCH64_OPND_SME_PNd3:
+    case AARCH64_OPND_SME_PNg3:
+    case AARCH64_OPND_SME_PNn:
+      if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+       snprintf (buf, size, "%s",
+                 style_reg (styler, "pn%d", opnd->reg.regno));
+      else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
+              || opnd->qualifier == AARCH64_OPND_QLF_P_M)
+       snprintf (buf, size, "%s",
+                 style_reg (styler, "pn%d/%s", opnd->reg.regno,
+                            aarch64_get_qualifier_name (opnd->qualifier)));
+      else
+       snprintf (buf, size, "%s",
+                 style_reg (styler, "pn%d.%s", opnd->reg.regno,
+                            aarch64_get_qualifier_name (opnd->qualifier)));
+      break;
+
+    case AARCH64_OPND_SME_Pdx2:
+    case AARCH64_OPND_SME_PdxN:
+      print_register_list (buf, size, opnd, "p", styler);
+      break;
+
+    case AARCH64_OPND_SME_PNn3_INDEX1:
+    case AARCH64_OPND_SME_PNn3_INDEX2:
+      snprintf (buf, size, "%s[%s]",
+               style_reg (styler, "pn%d", opnd->reglane.regno),
+               style_imm (styler, "%" PRIi64, opnd->reglane.index));
+      break;
+
     case AARCH64_OPND_SVE_Za_5:
     case AARCH64_OPND_SVE_Za_16:
     case AARCH64_OPND_SVE_Zd:
@@ -3686,6 +3967,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm_16:
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
+    case AARCH64_OPND_SME_Zm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
        snprintf (buf, size, "%s", style_reg (styler, "z%d", opnd->reg.regno));
       else
@@ -3696,18 +3978,42 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
+    case AARCH64_OPND_SME_Zdnx2:
+    case AARCH64_OPND_SME_Zdnx4:
+    case AARCH64_OPND_SME_Zmx2:
+    case AARCH64_OPND_SME_Zmx4:
+    case AARCH64_OPND_SME_Znx2:
+    case AARCH64_OPND_SME_Znx4:
+    case AARCH64_OPND_SME_Ztx2_STRIDED:
+    case AARCH64_OPND_SME_Ztx4_STRIDED:
       print_register_list (buf, size, opnd, "z", styler);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
     case AARCH64_OPND_SVE_Zm3_22_INDEX:
+    case AARCH64_OPND_SVE_Zm3_19_INDEX:
     case AARCH64_OPND_SVE_Zm3_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
+    case AARCH64_OPND_SME_Zm_INDEX1:
+    case AARCH64_OPND_SME_Zm_INDEX2:
+    case AARCH64_OPND_SME_Zm_INDEX3_1:
+    case AARCH64_OPND_SME_Zm_INDEX3_2:
+    case AARCH64_OPND_SME_Zm_INDEX3_10:
+    case AARCH64_OPND_SME_Zm_INDEX4_1:
+    case AARCH64_OPND_SME_Zm_INDEX4_10:
+    case AARCH64_OPND_SME_Zn_INDEX1_16:
+    case AARCH64_OPND_SME_Zn_INDEX2_15:
+    case AARCH64_OPND_SME_Zn_INDEX2_16:
+    case AARCH64_OPND_SME_Zn_INDEX3_14:
+    case AARCH64_OPND_SME_Zn_INDEX3_15:
+    case AARCH64_OPND_SME_Zn_INDEX4_14:
       snprintf (buf, size, "%s[%s]",
-               style_reg (styler, "z%d.%s", opnd->reglane.regno,
-                          aarch64_get_qualifier_name (opnd->qualifier)),
+               (opnd->qualifier == AARCH64_OPND_QLF_NIL
+                ? style_reg (styler, "z%d", opnd->reglane.regno)
+                : style_reg (styler, "z%d.%s", opnd->reglane.regno,
+                             aarch64_get_qualifier_name (opnd->qualifier))),
                style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
@@ -3719,7 +4025,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_SME_ZA_HV_idx_src:
+    case AARCH64_OPND_SME_ZA_HV_idx_srcxN:
     case AARCH64_OPND_SME_ZA_HV_idx_dest:
+    case AARCH64_OPND_SME_ZA_HV_idx_destxN:
     case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
       snprintf (buf, size, "%s%s[%s, %s%s%s%s%s]%s",
                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
@@ -3747,9 +4055,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_sme_za_list (buf, size, opnd->reg.regno, styler);
       break;
 
+    case AARCH64_OPND_SME_ZA_array_off1x4:
+    case AARCH64_OPND_SME_ZA_array_off2x2:
+    case AARCH64_OPND_SME_ZA_array_off2x4:
+    case AARCH64_OPND_SME_ZA_array_off3_0:
+    case AARCH64_OPND_SME_ZA_array_off3_5:
+    case AARCH64_OPND_SME_ZA_array_off3x2:
     case AARCH64_OPND_SME_ZA_array_off4:
       snprintf (buf, size, "%s[%s, %s%s%s%s%s]",
-               style_reg (styler, "za"),
+               style_reg (styler, "za%s%s",
+                          opnd->qualifier == AARCH64_OPND_QLF_NIL ? "" : ".",
+                          (opnd->qualifier == AARCH64_OPND_QLF_NIL
+                           ? ""
+                           : aarch64_get_qualifier_name (opnd->qualifier))),
                style_reg (styler, "w%d", opnd->indexed_za.index.regno),
                style_imm (styler, "%" PRIi64, opnd->indexed_za.index.imm),
                opnd->indexed_za.index.countm1 ? ":" : "",
@@ -3778,6 +4096,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                style_imm (styler, "%" PRIi64, opnd->indexed_za.index.imm));
       break;
 
+    case AARCH64_OPND_SME_VLxN_10:
+    case AARCH64_OPND_SME_VLxN_13:
+      enum_value = opnd->imm.value;
+      assert (enum_value < ARRAY_SIZE (aarch64_sme_vlxn_array));
+      snprintf (buf, size, "%s",
+               style_sub_mnem (styler, aarch64_sme_vlxn_array[enum_value]));
+      break;
+
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
       snprintf (buf, size, "%s",
@@ -3802,6 +4128,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_FBITS:
     case AARCH64_OPND_TME_UIMM16:
     case AARCH64_OPND_SIMM5:
+    case AARCH64_OPND_SME_SHRIMM4:
+    case AARCH64_OPND_SME_SHRIMM5:
     case AARCH64_OPND_SVE_SHLIMM_PRED:
     case AARCH64_OPND_SVE_SHLIMM_UNPRED:
     case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
@@ -4268,10 +4596,34 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                                              opnd->prfop->value));
       break;
 
+    case AARCH64_OPND_RPRFMOP:
+      enum_value = opnd->imm.value;
+      if (enum_value < ARRAY_SIZE (aarch64_rprfmop_array)
+         && aarch64_rprfmop_array[enum_value])
+       snprintf (buf, size, "%s",
+                 style_reg (styler, aarch64_rprfmop_array[enum_value]));
+      else
+       snprintf (buf, size, "%s",
+                 style_imm (styler, "#%" PRIi64, opnd->imm.value));
+      break;
+
     case AARCH64_OPND_BARRIER_PSB:
       snprintf (buf, size, "%s", style_sub_mnem (styler, "csync"));
       break;
 
+    case AARCH64_OPND_SME_ZT0:
+      snprintf (buf, size, "%s", style_reg (styler, "zt0"));
+      break;
+
+    case AARCH64_OPND_SME_ZT0_INDEX:
+      snprintf (buf, size, "%s[%s]", style_reg (styler, "zt0"),
+               style_imm (styler, "%d", (int) opnd->imm.value));
+      break;
+
+    case AARCH64_OPND_SME_ZT0_LIST:
+      snprintf (buf, size, "{%s}", style_reg (styler, "zt0"));
+      break;
+
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
        snprintf (buf, size, "%s",
@@ -6268,6 +6620,18 @@ aarch64_cpu_supports_inst_p (uint64_t cpu_variant, aarch64_inst *inst)
       || !AARCH64_CPU_HAS_ALL_FEATURES (cpu_variant, *inst->opcode->avariant))
     return false;
 
+  if (inst->opcode->iclass == sme_fp_sd
+      && inst->operands[0].qualifier == AARCH64_OPND_QLF_S_D
+      && !AARCH64_CPU_HAS_ALL_FEATURES (cpu_variant,
+                                       AARCH64_FEATURE_SME_F64F64))
+    return false;
+
+  if (inst->opcode->iclass == sme_int_sd
+      && inst->operands[0].qualifier == AARCH64_OPND_QLF_S_D
+      && !AARCH64_CPU_HAS_ALL_FEATURES (cpu_variant,
+                                       AARCH64_FEATURE_SME_I16I64))
+    return false;
+
   return true;
 }