[AArch64][SVE 25/32] Add support for SVE addressing modes
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:55:49 +0000 (16:55 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:55:49 +0000 (16:55 +0100)
This patch adds most of the new SVE addressing modes and associated
operands.  A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.

The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.

include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.

opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.

gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64.  Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters.  Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.

15 files changed:
gas/ChangeLog
gas/config/tc-aarch64.c
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-asm-2.c
opcodes/aarch64-asm.c
opcodes/aarch64-asm.h
opcodes/aarch64-dis-2.c
opcodes/aarch64-dis.c
opcodes/aarch64-dis.h
opcodes/aarch64-opc-2.c
opcodes/aarch64-opc.c
opcodes/aarch64-opc.h
opcodes/aarch64-tbl.h

index 97f1a61d150339cddff1ddbb57741ab32154bc39..c1f4152d8dddfc8d9f71db7fbd9007533225d9a0 100644 (file)
@@ -1,3 +1,18 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
+       register types.
+       (get_reg_expected_msg): Handle them.
+       (aarch64_addr_reg_parse): New function, split out from
+       aarch64_reg_parse_32_64.  Handle Z registers too.
+       (aarch64_reg_parse_32_64): Call it.
+       (parse_address_main): Add base_qualifier, offset_qualifier,
+       base_type and offset_type parameters.  Handle SVE base and offset
+       registers.
+       (parse_address): Update call to parse_address_main.
+       (parse_sve_address): New function.
+       (parse_operands): Parse the new SVE address operands.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
index 79ee0545a738c192b27d74854850be4458631a7c..e59333ffbf0fb5c2590297e51309b35f1301ed9f 100644 (file)
@@ -272,9 +272,16 @@ struct reloc_entry
   BASIC_REG_TYPE(PN)   /* p[0-15] */   \
   /* Typecheck: any 64-bit int reg         (inc SP exc XZR).  */       \
   MULTI_REG_TYPE(R64_SP, REG_TYPE(R_64) | REG_TYPE(SP_64))             \
+  /* Typecheck: same, plus SVE registers.  */                          \
+  MULTI_REG_TYPE(SVE_BASE, REG_TYPE(R_64) | REG_TYPE(SP_64)            \
+                | REG_TYPE(ZN))                                        \
   /* Typecheck: x[0-30], w[0-30] or [xw]zr.  */                                \
   MULTI_REG_TYPE(R_Z, REG_TYPE(R_32) | REG_TYPE(R_64)                  \
                 | REG_TYPE(Z_32) | REG_TYPE(Z_64))                     \
+  /* Typecheck: same, plus SVE registers.  */                          \
+  MULTI_REG_TYPE(SVE_OFFSET, REG_TYPE(R_32) | REG_TYPE(R_64)           \
+                | REG_TYPE(Z_32) | REG_TYPE(Z_64)                      \
+                | REG_TYPE(ZN))                                        \
   /* Typecheck: x[0-30], w[0-30] or {w}sp.  */                         \
   MULTI_REG_TYPE(R_SP, REG_TYPE(R_32) | REG_TYPE(R_64)                 \
                 | REG_TYPE(SP_32) | REG_TYPE(SP_64))                   \
@@ -358,9 +365,15 @@ get_reg_expected_msg (aarch64_reg_type reg_type)
     case REG_TYPE_R64_SP:
       msg = N_("64-bit integer or SP register expected");
       break;
+    case REG_TYPE_SVE_BASE:
+      msg = N_("base register expected");
+      break;
     case REG_TYPE_R_Z:
       msg = N_("integer or zero register expected");
       break;
+    case REG_TYPE_SVE_OFFSET:
+      msg = N_("offset register expected");
+      break;
     case REG_TYPE_R_SP:
       msg = N_("integer or SP register expected");
       break;
@@ -697,14 +710,16 @@ aarch64_check_reg_type (const reg_entry *reg, aarch64_reg_type type)
   return (reg_type_masks[type] & (1 << reg->type)) != 0;
 }
 
-/* Try to parse a base or offset register.  Return the register entry
-   on success, setting *QUALIFIER to the register qualifier.  Return null
-   otherwise.
+/* Try to parse a base or offset register.  Allow SVE base and offset
+   registers if REG_TYPE includes SVE registers.  Return the register
+   entry on success, setting *QUALIFIER to the register qualifier.
+   Return null otherwise.
 
    Note that this function does not issue any diagnostics.  */
 
 static const reg_entry *
-aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
+aarch64_addr_reg_parse (char **ccp, aarch64_reg_type reg_type,
+                       aarch64_opnd_qualifier_t *qualifier)
 {
   char *str = *ccp;
   const reg_entry *reg = parse_reg (&str);
@@ -726,6 +741,24 @@ aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
       *qualifier = AARCH64_OPND_QLF_X;
       break;
 
+    case REG_TYPE_ZN:
+      if ((reg_type_masks[reg_type] & (1 << REG_TYPE_ZN)) == 0
+         || str[0] != '.')
+       return NULL;
+      switch (TOLOWER (str[1]))
+       {
+       case 's':
+         *qualifier = AARCH64_OPND_QLF_S_S;
+         break;
+       case 'd':
+         *qualifier = AARCH64_OPND_QLF_S_D;
+         break;
+       default:
+         return NULL;
+       }
+      str += 2;
+      break;
+
     default:
       return NULL;
     }
@@ -735,6 +768,18 @@ aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
   return reg;
 }
 
+/* Try to parse a base or offset register.  Return the register entry
+   on success, setting *QUALIFIER to the register qualifier.  Return null
+   otherwise.
+
+   Note that this function does not issue any diagnostics.  */
+
+static const reg_entry *
+aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
+{
+  return aarch64_addr_reg_parse (ccp, REG_TYPE_R_Z_SP, qualifier);
+}
+
 /* Parse the qualifier of a vector register or vector element of type
    REG_TYPE.  Fill in *PARSED_TYPE and return TRUE if the parsing
    succeeds; otherwise return FALSE.
@@ -3209,8 +3254,8 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
    The A64 instruction set has the following addressing modes:
 
    Offset
-     [base]                    // in SIMD ld/st structure
-     [base{,#0}]               // in ld/st exclusive
+     [base]                     // in SIMD ld/st structure
+     [base{,#0}]                // in ld/st exclusive
      [base{,#imm}]
      [base,Xm{,LSL #imm}]
      [base,Xm,SXTX {#imm}]
@@ -3219,10 +3264,18 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
      [base,#imm]!
    Post-indexed
      [base],#imm
-     [base],Xm                 // in SIMD ld/st structure
+     [base],Xm                  // in SIMD ld/st structure
    PC-relative (literal)
      label
-     =immediate
+   SVE:
+     [base,Zm.D{,LSL #imm}]
+     [base,Zm.S,(S|U)XTW {#imm}]
+     [base,Zm.D,(S|U)XTW {#imm}] // ignores top 32 bits of Zm.D elements
+     [Zn.S,#imm]
+     [Zn.D,#imm]
+     [Zn.S,Zm.S{,LSL #imm}]      // in ADR
+     [Zn.D,Zm.D{,LSL #imm}]      // in ADR
+     [Zn.D,Zm.D,(S|U)XTW {#imm}] // in ADR
 
    (As a convenience, the notation "=immediate" is permitted in conjunction
    with the pc-relative literal load instructions to automatically place an
@@ -3249,19 +3302,27 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
      .pcrel=1; .preind=1; .postind=0; .writeback=0
 
    The shift/extension information, if any, will be stored in .shifter.
+   The base and offset qualifiers will be stored in *BASE_QUALIFIER and
+   *OFFSET_QUALIFIER respectively, with NIL being used if there's no
+   corresponding register.
 
-   It is the caller's responsibility to check for addressing modes not
+   BASE_TYPE says which types of base register should be accepted and
+   OFFSET_TYPE says the same for offset registers.  In all other respects,
+   it is the caller's responsibility to check for addressing modes not
    supported by the instruction, and to set inst.reloc.type.  */
 
 static bfd_boolean
-parse_address_main (char **str, aarch64_opnd_info *operand)
+parse_address_main (char **str, aarch64_opnd_info *operand,
+                   aarch64_opnd_qualifier_t *base_qualifier,
+                   aarch64_opnd_qualifier_t *offset_qualifier,
+                   aarch64_reg_type base_type, aarch64_reg_type offset_type)
 {
   char *p = *str;
   const reg_entry *reg;
-  aarch64_opnd_qualifier_t base_qualifier;
-  aarch64_opnd_qualifier_t offset_qualifier;
   expressionS *exp = &inst.reloc.exp;
 
+  *base_qualifier = AARCH64_OPND_QLF_NIL;
+  *offset_qualifier = AARCH64_OPND_QLF_NIL;
   if (! skip_past_char (&p, '['))
     {
       /* =immediate or label.  */
@@ -3336,10 +3397,10 @@ parse_address_main (char **str, aarch64_opnd_info *operand)
 
   /* [ */
 
-  reg = aarch64_reg_parse_32_64 (&p, &base_qualifier);
-  if (!reg || !aarch64_check_reg_type (reg, REG_TYPE_R64_SP))
+  reg = aarch64_addr_reg_parse (&p, base_type, base_qualifier);
+  if (!reg || !aarch64_check_reg_type (reg, base_type))
     {
-      set_syntax_error (_(get_reg_expected_msg (REG_TYPE_R64_SP)));
+      set_syntax_error (_(get_reg_expected_msg (base_type)));
       return FALSE;
     }
   operand->addr.base_regno = reg->number;
@@ -3350,12 +3411,12 @@ parse_address_main (char **str, aarch64_opnd_info *operand)
       /* [Xn, */
       operand->addr.preind = 1;
 
-      reg = aarch64_reg_parse_32_64 (&p, &offset_qualifier);
+      reg = aarch64_addr_reg_parse (&p, offset_type, offset_qualifier);
       if (reg)
        {
-         if (!aarch64_check_reg_type (reg, REG_TYPE_R_Z))
+         if (!aarch64_check_reg_type (reg, offset_type))
            {
-             set_syntax_error (_(get_reg_expected_msg (REG_TYPE_R_Z)));
+             set_syntax_error (_(get_reg_expected_msg (offset_type)));
              return FALSE;
            }
 
@@ -3379,13 +3440,19 @@ parse_address_main (char **str, aarch64_opnd_info *operand)
              || operand->shifter.kind == AARCH64_MOD_LSL
              || operand->shifter.kind == AARCH64_MOD_SXTX)
            {
-             if (offset_qualifier == AARCH64_OPND_QLF_W)
+             if (*offset_qualifier == AARCH64_OPND_QLF_W)
                {
                  set_syntax_error (_("invalid use of 32-bit register offset"));
                  return FALSE;
                }
+             if (aarch64_get_qualifier_esize (*base_qualifier)
+                 != aarch64_get_qualifier_esize (*offset_qualifier))
+               {
+                 set_syntax_error (_("offset has different size from base"));
+                 return FALSE;
+               }
            }
-         else if (offset_qualifier == AARCH64_OPND_QLF_X)
+         else if (*offset_qualifier == AARCH64_OPND_QLF_X)
            {
              set_syntax_error (_("invalid use of 64-bit register offset"));
              return FALSE;
@@ -3468,7 +3535,7 @@ parse_address_main (char **str, aarch64_opnd_info *operand)
          return FALSE;
        }
 
-      reg = aarch64_reg_parse_32_64 (&p, &offset_qualifier);
+      reg = aarch64_reg_parse_32_64 (&p, offset_qualifier);
       if (reg)
        {
          /* [Xn],Xm */
@@ -3513,7 +3580,21 @@ parse_address_main (char **str, aarch64_opnd_info *operand)
 static bfd_boolean
 parse_address (char **str, aarch64_opnd_info *operand)
 {
-  return parse_address_main (str, operand);
+  aarch64_opnd_qualifier_t base_qualifier, offset_qualifier;
+  return parse_address_main (str, operand, &base_qualifier, &offset_qualifier,
+                            REG_TYPE_R64_SP, REG_TYPE_R_Z);
+}
+
+/* Parse an address in which SVE vector registers are allowed.
+   The arguments have the same meaning as for parse_address_main.
+   Return TRUE on success.  */
+static bfd_boolean
+parse_sve_address (char **str, aarch64_opnd_info *operand,
+                  aarch64_opnd_qualifier_t *base_qualifier,
+                  aarch64_opnd_qualifier_t *offset_qualifier)
+{
+  return parse_address_main (str, operand, base_qualifier, offset_qualifier,
+                            REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET);
 }
 
 /* Parse an operand for a MOVZ, MOVN or MOVK instruction.
@@ -5123,7 +5204,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
       int comma_skipped_p = 0;
       aarch64_reg_type rtype;
       struct vector_type_el vectype;
-      aarch64_opnd_qualifier_t qualifier;
+      aarch64_opnd_qualifier_t qualifier, base_qualifier, offset_qualifier;
       aarch64_opnd_info *info = &inst.base.operands[i];
       aarch64_reg_type reg_type;
 
@@ -5757,6 +5838,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_ADDR_REGOFF:
          /* [<Xn|SP>, <R><m>{, <extend> {<amount>}}]  */
          po_misc_or_fail (parse_address (&str, info));
+       regoff_addr:
          if (info->addr.pcrel || !info->addr.offset.is_reg
              || !info->addr.preind || info->addr.postind
              || info->addr.writeback)
@@ -5856,6 +5938,123 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          /* No qualifier.  */
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_U6:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x2:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x4:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x8:
+         /* [X<n>{, #imm}]
+            but recognizing SVE registers.  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         if (base_qualifier != AARCH64_OPND_QLF_X)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+       sve_regimm:
+         if (info->addr.pcrel || info->addr.offset.is_reg
+             || !info->addr.preind || info->addr.writeback)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         if (inst.reloc.type != BFD_RELOC_UNUSED
+             || inst.reloc.exp.X_op != O_constant)
+           {
+             /* Make sure this has priority over
+                "invalid addressing mode".  */
+             set_fatal_syntax_error (_("constant offset required"));
+             goto failure;
+           }
+         info->addr.offset.imm = inst.reloc.exp.X_add_number;
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RR:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RX:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL3:
+         /* [<Xn|SP>, <R><m>{, lsl #<amount>}]
+            but recognizing SVE registers.  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         if (base_qualifier != AARCH64_OPND_QLF_X
+             || offset_qualifier != AARCH64_OPND_QLF_X)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         goto regoff_addr;
+
+       case AARCH64_OPND_SVE_ADDR_RZ:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
+         /* [<Xn|SP>, Z<m>.D{, LSL #<amount>}]
+            [<Xn|SP>, Z<m>.<T>, <extend> {#<amount>}]  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         if (base_qualifier != AARCH64_OPND_QLF_X
+             || (offset_qualifier != AARCH64_OPND_QLF_S_S
+                 && offset_qualifier != AARCH64_OPND_QLF_S_D))
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         info->qualifier = offset_qualifier;
+         goto regoff_addr;
+
+       case AARCH64_OPND_SVE_ADDR_ZI_U5:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
+         /* [Z<n>.<T>{, #imm}]  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         if (base_qualifier != AARCH64_OPND_QLF_S_S
+             && base_qualifier != AARCH64_OPND_QLF_S_D)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         info->qualifier = base_qualifier;
+         goto sve_regimm;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
+       case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
+       case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
+         /* [Z<n>.<T>, Z<m>.<T>{, LSL #<amount>}]
+            [Z<n>.D, Z<m>.D, <extend> {#<amount>}]
+
+            We don't reject:
+
+            [Z<n>.S, Z<m>.S, <extend> {#<amount>}]
+
+            here since we get better error messages by leaving it to
+            the qualifier checking routines.  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         if ((base_qualifier != AARCH64_OPND_QLF_S_S
+              && base_qualifier != AARCH64_OPND_QLF_S_D)
+             || offset_qualifier != base_qualifier)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         info->qualifier = base_qualifier;
+         goto regoff_addr;
+
        case AARCH64_OPND_SYSREG:
          if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0))
              == PARSE_FAIL)
index cdac6f56de78c8978e9e28e5854388160e20099b..71df381d25a3f74f109e428ac0dc7baa9c3ffab5 100644 (file)
@@ -1,3 +1,23 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
+       (AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
+       (AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
+       (AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
+       (AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
+       (AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
+       (AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
+       (AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
+       (AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
+       (AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
+       (AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
+       (AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
+       (AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
+       (AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
+       (AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
+       (AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
+       Likewise.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
index 49b4413601c49e8e09914e6fde3c039aec7821a4..e61ac9c03fd59f1f836c84a159b7a993e483a28d 100644 (file)
@@ -244,6 +244,45 @@ enum aarch64_opnd
   AARCH64_OPND_PRFOP,          /* Prefetch operation.  */
   AARCH64_OPND_BARRIER_PSB,    /* Barrier operand for PSB.  */
 
+  AARCH64_OPND_SVE_ADDR_RI_U6,     /* SVE [<Xn|SP>, #<uimm6>].  */
+  AARCH64_OPND_SVE_ADDR_RI_U6x2,    /* SVE [<Xn|SP>, #<uimm6>*2].  */
+  AARCH64_OPND_SVE_ADDR_RI_U6x4,    /* SVE [<Xn|SP>, #<uimm6>*4].  */
+  AARCH64_OPND_SVE_ADDR_RI_U6x8,    /* SVE [<Xn|SP>, #<uimm6>*8].  */
+  AARCH64_OPND_SVE_ADDR_RR,        /* SVE [<Xn|SP>, <Xm|XZR>].  */
+  AARCH64_OPND_SVE_ADDR_RR_LSL1,    /* SVE [<Xn|SP>, <Xm|XZR>, LSL #1].  */
+  AARCH64_OPND_SVE_ADDR_RR_LSL2,    /* SVE [<Xn|SP>, <Xm|XZR>, LSL #2].  */
+  AARCH64_OPND_SVE_ADDR_RR_LSL3,    /* SVE [<Xn|SP>, <Xm|XZR>, LSL #3].  */
+  AARCH64_OPND_SVE_ADDR_RX,        /* SVE [<Xn|SP>, <Xm>].  */
+  AARCH64_OPND_SVE_ADDR_RX_LSL1,    /* SVE [<Xn|SP>, <Xm>, LSL #1].  */
+  AARCH64_OPND_SVE_ADDR_RX_LSL2,    /* SVE [<Xn|SP>, <Xm>, LSL #2].  */
+  AARCH64_OPND_SVE_ADDR_RX_LSL3,    /* SVE [<Xn|SP>, <Xm>, LSL #3].  */
+  AARCH64_OPND_SVE_ADDR_RZ,        /* SVE [<Xn|SP>, Zm.D].  */
+  AARCH64_OPND_SVE_ADDR_RZ_LSL1,    /* SVE [<Xn|SP>, Zm.D, LSL #1].  */
+  AARCH64_OPND_SVE_ADDR_RZ_LSL2,    /* SVE [<Xn|SP>, Zm.D, LSL #2].  */
+  AARCH64_OPND_SVE_ADDR_RZ_LSL3,    /* SVE [<Xn|SP>, Zm.D, LSL #3].  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW_14,  /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW].
+                                      Bit 14 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW_22,  /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW].
+                                      Bit 22 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW1_14, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #1].
+                                      Bit 14 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #1].
+                                      Bit 22 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW2_14, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #2].
+                                      Bit 14 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #2].
+                                      Bit 22 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW3_14, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #3].
+                                      Bit 14 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, /* SVE [<Xn|SP>, Zm.<T>, (S|U)XTW #3].
+                                      Bit 22 controls S/U choice.  */
+  AARCH64_OPND_SVE_ADDR_ZI_U5,     /* SVE [Zn.<T>, #<uimm5>].  */
+  AARCH64_OPND_SVE_ADDR_ZI_U5x2,    /* SVE [Zn.<T>, #<uimm5>*2].  */
+  AARCH64_OPND_SVE_ADDR_ZI_U5x4,    /* SVE [Zn.<T>, #<uimm5>*4].  */
+  AARCH64_OPND_SVE_ADDR_ZI_U5x8,    /* SVE [Zn.<T>, #<uimm5>*8].  */
+  AARCH64_OPND_SVE_ADDR_ZZ_LSL,     /* SVE [Zn.<T>, Zm,<T>, LSL #<msz>].  */
+  AARCH64_OPND_SVE_ADDR_ZZ_SXTW,    /* SVE [Zn.<T>, Zm,<T>, SXTW #<msz>].  */
+  AARCH64_OPND_SVE_ADDR_ZZ_UXTW,    /* SVE [Zn.<T>, Zm,<T>, UXTW #<msz>].  */
   AARCH64_OPND_SVE_PATTERN,    /* SVE vector pattern enumeration.  */
   AARCH64_OPND_SVE_PATTERN_SCALED, /* Likewise, with additional MUL factor.  */
   AARCH64_OPND_SVE_PRFOP,      /* SVE prefetch operation.  */
index 35a10060d5f15f95df3bcf71a348853a9b72c01d..2cedfb929b8806f559d5e5f3dd3907f85c62b593 100644 (file)
@@ -1,3 +1,45 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
+       address operands.
+       * aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
+       (FLD_SVE_xs_22): New aarch64_field_kinds.
+       (OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
+       (get_operand_specific_data): New function.
+       * aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
+       FLD_SVE_xs_14 and FLD_SVE_xs_22.
+       (operand_general_constraint_met_p): Handle the new SVE address
+       operands.
+       (sve_reg): New array.
+       (get_addr_sve_reg_name): New function.
+       (aarch64_print_operand): Handle the new SVE address operands.
+       * aarch64-opc-2.c: Regenerate.
+       * aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
+       (ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
+       (ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
+       * aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
+       (aarch64_ins_sve_addr_rr_lsl): Likewise.
+       (aarch64_ins_sve_addr_rz_xtw): Likewise.
+       (aarch64_ins_sve_addr_zi_u5): Likewise.
+       (aarch64_ins_sve_addr_zz): Likewise.
+       (aarch64_ins_sve_addr_zz_lsl): Likewise.
+       (aarch64_ins_sve_addr_zz_sxtw): Likewise.
+       (aarch64_ins_sve_addr_zz_uxtw): Likewise.
+       * aarch64-asm-2.c: Regenerate.
+       * aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
+       (ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
+       (ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
+       * aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
+       (aarch64_ext_sve_addr_ri_u6): Likewise.
+       (aarch64_ext_sve_addr_rr_lsl): Likewise.
+       (aarch64_ext_sve_addr_rz_xtw): Likewise.
+       (aarch64_ext_sve_addr_zi_u5): Likewise.
+       (aarch64_ext_sve_addr_zz): Likewise.
+       (aarch64_ext_sve_addr_zz_lsl): Likewise.
+       (aarch64_ext_sve_addr_zz_sxtw): Likewise.
+       (aarch64_ext_sve_addr_zz_uxtw): Likewise.
+       * aarch64-dis-2.c: Regenerate.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
index 039b9beac453f623c7aee2e946645f42c08b459c..47a414c5a200a0533291c92379c78df91545ee16 100644 (file)
@@ -480,21 +480,21 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
-    case 92:
-    case 93:
-    case 94:
-    case 95:
-    case 96:
-    case 97:
-    case 98:
-    case 99:
-    case 100:
-    case 101:
-    case 102:
-    case 103:
-    case 104:
-    case 105:
-    case 108:
+    case 123:
+    case 124:
+    case 125:
+    case 126:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+    case 136:
+    case 139:
       return aarch64_ins_regno (self, info, code, inst);
     case 12:
       return aarch64_ins_reg_extended (self, info, code, inst);
@@ -531,8 +531,8 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 68:
     case 69:
     case 70:
-    case 89:
-    case 91:
+    case 120:
+    case 122:
       return aarch64_ins_imm (self, info, code, inst);
     case 38:
     case 39:
@@ -583,12 +583,50 @@ aarch64_insert_operand (const aarch64_operand *self,
       return aarch64_ins_prfop (self, info, code, inst);
     case 88:
       return aarch64_ins_hint (self, info, code, inst);
+    case 89:
     case 90:
-      return aarch64_ins_sve_scale (self, info, code, inst);
+    case 91:
+    case 92:
+      return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+      return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
+    case 105:
     case 106:
-      return aarch64_ins_sve_index (self, info, code, inst);
     case 107:
+    case 108:
     case 109:
+    case 110:
+    case 111:
+    case 112:
+      return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+      return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
+    case 117:
+      return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
+    case 118:
+      return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
+    case 119:
+      return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst);
+    case 121:
+      return aarch64_ins_sve_scale (self, info, code, inst);
+    case 137:
+      return aarch64_ins_sve_index (self, info, code, inst);
+    case 138:
+    case 140:
       return aarch64_ins_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
index 117a3c6f98e8bdc875e9fe28d2f9081076a8d9d4..0d3b2c770e84c824ef4ae2f03ae38375c636f7b4 100644 (file)
@@ -745,6 +745,114 @@ aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_ri_u6 (const aarch64_operand *self,
+                           const aarch64_opnd_info *info, aarch64_insn *code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int factor = 1 << get_operand_specific_data (self);
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+  insert_field (FLD_SVE_imm6, code, info->addr.offset.imm / factor, 0);
+  return NULL;
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_rr_lsl (const aarch64_operand *self,
+                            const aarch64_opnd_info *info, aarch64_insn *code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+  insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+  return NULL;
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_rz_xtw (const aarch64_operand *self,
+                            const aarch64_opnd_info *info, aarch64_insn *code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+  insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+  if (info->shifter.kind == AARCH64_MOD_UXTW)
+    insert_field (self->fields[2], code, 0, 0);
+  else
+    insert_field (self->fields[2], code, 1, 0);
+  return NULL;
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_zi_u5 (const aarch64_operand *self,
+                           const aarch64_opnd_info *info, aarch64_insn *code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int factor = 1 << get_operand_specific_data (self);
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+  insert_field (FLD_imm5, code, info->addr.offset.imm / factor, 0);
+  return NULL;
+}
+
+/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
+   where <modifier> is fixed by the instruction 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 const char *
+aarch64_ext_sve_addr_zz (const aarch64_operand *self,
+                        const aarch64_opnd_info *info, aarch64_insn *code)
+{
+  insert_field (self->fields[0], code, info->addr.base_regno, 0);
+  insert_field (self->fields[1], code, info->addr.offset.regno, 0);
+  insert_field (FLD_SVE_msz, code, info->shifter.amount, 0);
+  return NULL;
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_zz_lsl (const aarch64_operand *self,
+                            const aarch64_opnd_info *info, aarch64_insn *code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code);
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand *self,
+                             const aarch64_opnd_info *info,
+                             aarch64_insn *code,
+                             const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code);
+}
+
+/* Encode 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.  */
+const char *
+aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self,
+                             const aarch64_opnd_info *info,
+                             aarch64_insn *code,
+                             const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code);
+}
+
 /* Encode 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
index ac5faebe193da0feeae63821c7311c10848f7026..b81cfa16d567461c44fb33c142acff7c54d7d5ed 100644 (file)
@@ -69,6 +69,13 @@ AARCH64_DECL_OPD_INSERTER (ins_hint);
 AARCH64_DECL_OPD_INSERTER (ins_prfop);
 AARCH64_DECL_OPD_INSERTER (ins_reg_extended);
 AARCH64_DECL_OPD_INSERTER (ins_reg_shifted);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_u6);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_rr_lsl);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_rz_xtw);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zi_u5);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_lsl);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_sxtw);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_uxtw);
 AARCH64_DECL_OPD_INSERTER (ins_sve_index);
 AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
 AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
index 124385dacf5b93beb18dbc2ec3b786423921f6ee..3dd714f4f650e7be63d505787c87b8de373344db 100644 (file)
@@ -10426,21 +10426,21 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
-    case 92:
-    case 93:
-    case 94:
-    case 95:
-    case 96:
-    case 97:
-    case 98:
-    case 99:
-    case 100:
-    case 101:
-    case 102:
-    case 103:
-    case 104:
-    case 105:
-    case 108:
+    case 123:
+    case 124:
+    case 125:
+    case 126:
+    case 127:
+    case 128:
+    case 129:
+    case 130:
+    case 131:
+    case 132:
+    case 133:
+    case 134:
+    case 135:
+    case 136:
+    case 139:
       return aarch64_ext_regno (self, info, code, inst);
     case 8:
       return aarch64_ext_regrt_sysins (self, info, code, inst);
@@ -10482,8 +10482,8 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 68:
     case 69:
     case 70:
-    case 89:
-    case 91:
+    case 120:
+    case 122:
       return aarch64_ext_imm (self, info, code, inst);
     case 38:
     case 39:
@@ -10536,12 +10536,50 @@ aarch64_extract_operand (const aarch64_operand *self,
       return aarch64_ext_prfop (self, info, code, inst);
     case 88:
       return aarch64_ext_hint (self, info, code, inst);
+    case 89:
     case 90:
-      return aarch64_ext_sve_scale (self, info, code, inst);
+    case 91:
+    case 92:
+      return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+      return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
+    case 105:
     case 106:
-      return aarch64_ext_sve_index (self, info, code, inst);
     case 107:
+    case 108:
     case 109:
+    case 110:
+    case 111:
+    case 112:
+      return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+      return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
+    case 117:
+      return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
+    case 118:
+      return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
+    case 119:
+      return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst);
+    case 121:
+      return aarch64_ext_sve_scale (self, info, code, inst);
+    case 137:
+      return aarch64_ext_sve_index (self, info, code, inst);
+    case 138:
+    case 140:
       return aarch64_ext_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
index 1d00c0aa8c89cfb213a8c1312a6801face1b3c3f..ed77b4df978ef19752691c98af993c000f25c128 100644 (file)
@@ -1186,6 +1186,152 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return 1;
 }
 
+/* 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 int
+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 1;
+}
+
+/* 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.  */
+int
+aarch64_ext_sve_addr_ri_u6 (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int offset = extract_field (FLD_SVE_imm6, code, 0);
+  return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
+}
+
+/* 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.  */
+int
+aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int index;
+
+  index = extract_field (self->fields[1], code, 0);
+  if (index == 31 && (self->flags & OPD_F_NO_ZR) != 0)
+    return 0;
+
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.regno = index;
+  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 1;
+}
+
+/* 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.  */
+int
+aarch64_ext_sve_addr_rz_xtw (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst 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 1;
+}
+
+/* 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.  */
+int
+aarch64_ext_sve_addr_zi_u5 (const aarch64_operand *self,
+                           aarch64_opnd_info *info, aarch64_insn code,
+                           const aarch64_inst *inst 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 int
+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 1;
+}
+
+/* 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.  */
+int
+aarch64_ext_sve_addr_zz_lsl (const aarch64_operand *self,
+                            aarch64_opnd_info *info, aarch64_insn code,
+                            const aarch64_inst *inst 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.  */
+int
+aarch64_ext_sve_addr_zz_sxtw (const aarch64_operand *self,
+                             aarch64_opnd_info *info, aarch64_insn code,
+                             const aarch64_inst *inst 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.  */
+int
+aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
+                             aarch64_opnd_info *info, aarch64_insn code,
+                             const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
+}
+
 /* 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
index 92f5ad43c48a7cd6eb491d850f5527b0cf37faf6..0ce2d8930d052370671af914ab740b3d89f7aea9 100644 (file)
@@ -91,6 +91,13 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_hint);
 AARCH64_DECL_OPD_EXTRACTOR (ext_prfop);
 AARCH64_DECL_OPD_EXTRACTOR (ext_reg_extended);
 AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_u6);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_rr_lsl);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_rz_xtw);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zi_u5);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_lsl);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_sxtw);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_uxtw);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
 AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
index 8f221b893ddc413080d3a4dcbd5c3c3bc2f78667..ed2b70b9093eadeea800eff09587bf9174593549 100644 (file)
@@ -113,6 +113,37 @@ const struct aarch64_operand aarch64_operands[] =
   {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_ISB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the ISB option name SY or an optional 4-bit unsigned immediate"},
   {AARCH64_OPND_CLASS_SYSTEM, "PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a prefetch operation specifier"},
   {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_PSB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the PSB option name CSYNC"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_U6", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 6-bit unsigned offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_U6x2", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 6-bit unsigned offset, multiplied by 2"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_U6x4", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 6-bit unsigned offset, multiplied by 4"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_U6x8", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 6-bit unsigned offset, multiplied by 8"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RR", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RR_LSL1", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RR_LSL2", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RR_LSL3", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RX", (0 << OPD_F_OD_LSB) | OPD_F_NO_ZR | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RX_LSL1", (1 << OPD_F_OD_LSB) | OPD_F_NO_ZR | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RX_LSL2", (2 << OPD_F_OD_LSB) | OPD_F_NO_ZR | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RX_LSL3", (3 << OPD_F_OD_LSB) | OPD_F_NO_ZR | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_Rm}, "an address with a scalar register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_LSL1", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_LSL2", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_LSL3", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW_14", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW_22", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW1_14", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW1_22", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW2_14", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW2_22", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW3_14", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RZ_XTW3_22", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZI_U5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an address with a 5-bit unsigned offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZI_U5x2", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an address with a 5-bit unsigned offset, multiplied by 2"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZI_U5x4", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an address with a 5-bit unsigned offset, multiplied by 4"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZI_U5x8", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an address with a 5-bit unsigned offset, multiplied by 8"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_LSL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_SXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_UXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
   {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
   {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN_SCALED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
   {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_prfop}, "an enumeration value such as PLDL1KEEP"},
index 326b94e71e956980554b22bdaab1247832f2b3c6..6617e28f2ef11c8a06e5ef66770f5ced5803ca2b 100644 (file)
@@ -280,9 +280,13 @@ const aarch64_field fields[] =
     {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
     {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
     { 16,  4 }, /* SVE_imm4: 4-bit immediate field.  */
+    { 16,  6 }, /* SVE_imm6: 6-bit immediate field.  */
+    { 10,  2 }, /* SVE_msz: 2-bit shift amount for ADR.  */
     {  5,  5 }, /* SVE_pattern: vector pattern enumeration.  */
     {  0,  4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD].  */
     { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
+    { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
+    { 22,  1 }  /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
 };
 
 enum aarch64_operand_class
@@ -1368,9 +1372,9 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                                  const aarch64_opcode *opcode,
                                  aarch64_operand_error *mismatch_detail)
 {
-  unsigned num;
+  unsigned num, modifiers;
   unsigned char size;
-  int64_t imm;
+  int64_t imm, min_value, max_value;
   const aarch64_opnd_info *opnd = opnds + idx;
   aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
 
@@ -1662,6 +1666,113 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_U6:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x2:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x4:
+       case AARCH64_OPND_SVE_ADDR_RI_U6x8:
+         min_value = 0;
+         max_value = 63;
+       sve_imm_offset:
+         assert (!opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         num = 1 << get_operand_specific_data (&aarch64_operands[type]);
+         min_value *= num;
+         max_value *= num;
+         if (opnd->shifter.operator_present
+             || opnd->shifter.amount_present)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         if (!value_in_range_p (opnd->addr.offset.imm, min_value, max_value))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx,
+                                            min_value, max_value);
+             return 0;
+           }
+         if (!value_aligned_p (opnd->addr.offset.imm, num))
+           {
+             set_unaligned_error (mismatch_detail, idx, num);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RR:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RX:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RX_LSL3:
+       case AARCH64_OPND_SVE_ADDR_RZ:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
+       case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
+         modifiers = 1 << AARCH64_MOD_LSL;
+       sve_rr_operand:
+         assert (opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         if ((aarch64_operands[type].flags & OPD_F_NO_ZR) != 0
+             && opnd->addr.offset.regno == 31)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("index register xzr is not allowed"));
+             return 0;
+           }
+         if (((1 << opnd->shifter.kind) & modifiers) == 0
+             || (opnd->shifter.amount
+                 != get_operand_specific_data (&aarch64_operands[type])))
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
+       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
+         modifiers = (1 << AARCH64_MOD_SXTW) | (1 << AARCH64_MOD_UXTW);
+         goto sve_rr_operand;
+
+       case AARCH64_OPND_SVE_ADDR_ZI_U5:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
+       case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
+         min_value = 0;
+         max_value = 31;
+         goto sve_imm_offset;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
+         modifiers = 1 << AARCH64_MOD_LSL;
+       sve_zz_operand:
+         assert (opnd->addr.offset.is_reg);
+         assert (opnd->addr.preind);
+         if (((1 << opnd->shifter.kind) & modifiers) == 0
+             || opnd->shifter.amount < 0
+             || opnd->shifter.amount > 3)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid addressing mode"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
+         modifiers = (1 << AARCH64_MOD_SXTW);
+         goto sve_zz_operand;
+
+       case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
+         modifiers = 1 << AARCH64_MOD_UXTW;
+         goto sve_zz_operand;
+
        default:
          break;
        }
@@ -2330,6 +2441,17 @@ static const char *int_reg[2][2][32] = {
 #undef R64
 #undef R32
 };
+
+/* Names of the SVE vector registers, first with .S suffixes,
+   then with .D suffixes.  */
+
+static const char *sve_reg[2][32] = {
+#define ZS(X) "z" #X ".s"
+#define ZD(X) "z" #X ".d"
+  BANK (ZS, ZS (31)), BANK (ZD, ZD (31))
+#undef ZD
+#undef ZS
+};
 #undef BANK
 
 /* Return the integer register name.
@@ -2373,6 +2495,17 @@ get_offset_int_reg_name (const aarch64_opnd_info *opnd)
     }
 }
 
+/* Get the name of the SVE vector offset register in OPND, using the operand
+   qualifier to decide whether the suffix should be .S or .D.  */
+
+static inline const char *
+get_addr_sve_reg_name (int regno, aarch64_opnd_qualifier_t qualifier)
+{
+  assert (qualifier == AARCH64_OPND_QLF_S_S
+         || qualifier == AARCH64_OPND_QLF_S_D);
+  return sve_reg[qualifier == AARCH64_OPND_QLF_S_D][regno];
+}
+
 /* Types for expanding an encoded 8-bit value to a floating-point value.  */
 
 typedef union
@@ -2948,18 +3081,65 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
+    case AARCH64_OPND_SVE_ADDR_RR:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+    case AARCH64_OPND_SVE_ADDR_RX:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
        (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
         get_offset_int_reg_name (opnd));
       break;
 
+    case AARCH64_OPND_SVE_ADDR_RZ:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
+    case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
+    case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
+      print_register_offset_address
+       (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+        get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+      break;
+
     case AARCH64_OPND_ADDR_SIMM7:
     case AARCH64_OPND_ADDR_SIMM9:
     case AARCH64_OPND_ADDR_SIMM9_2:
+    case AARCH64_OPND_SVE_ADDR_RI_U6:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x2:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x4:
+    case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
        (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
       break;
 
+    case AARCH64_OPND_SVE_ADDR_ZI_U5:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
+    case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
+      print_immediate_offset_address
+       (buf, size, opnd,
+        get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
+    case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
+    case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
+      print_register_offset_address
+       (buf, size, opnd,
+        get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+        get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+      break;
+
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
index 3406f6e9f2b4c3897fda8f6f3027e88e8030506e..e823146275531581932f40f0da35a7ee4bb942f6 100644 (file)
@@ -107,9 +107,13 @@ enum aarch64_field_kind
   FLD_SVE_Zn,
   FLD_SVE_Zt,
   FLD_SVE_imm4,
+  FLD_SVE_imm6,
+  FLD_SVE_msz,
   FLD_SVE_pattern,
   FLD_SVE_prfop,
   FLD_SVE_tszh,
+  FLD_SVE_xs_14,
+  FLD_SVE_xs_22,
 };
 
 /* Field description.  */
@@ -156,6 +160,9 @@ extern const aarch64_operand aarch64_operands[];
                                                   value by 2 to get the value
                                                   of an immediate operand.  */
 #define OPD_F_MAYBE_SP         0x00000010      /* May potentially be SP.  */
+#define OPD_F_OD_MASK          0x00000060      /* Operand-dependent data.  */
+#define OPD_F_OD_LSB           5
+#define OPD_F_NO_ZR            0x00000080      /* ZR index not allowed.  */
 
 static inline bfd_boolean
 operand_has_inserter (const aarch64_operand *operand)
@@ -187,6 +194,13 @@ operand_maybe_stack_pointer (const aarch64_operand *operand)
   return (operand->flags & OPD_F_MAYBE_SP) ? TRUE : FALSE;
 }
 
+/* Return the value of the operand-specific data field (OPD_F_OD_MASK).  */
+static inline unsigned int
+get_operand_specific_data (const aarch64_operand *operand)
+{
+  return (operand->flags & OPD_F_OD_MASK) >> OPD_F_OD_LSB;
+}
+
 /* Return the total width of the operand *OPERAND.  */
 static inline unsigned
 get_operand_fields_width (const aarch64_operand *operand)
index 491235f91404bb06e595434ae63601d1feb9e818..aba4b2d2d36e61a66ab89b6d4e5eccd9b3327e6a 100644 (file)
@@ -2818,8 +2818,95 @@ struct aarch64_opcode aarch64_opcode_table[] =
       "the ISB option name SY or an optional 4-bit unsigned immediate")        \
     Y(SYSTEM, prfop, "PRFOP", 0, F(),                                  \
       "a prefetch operation specifier")                                        \
-    Y (SYSTEM, hint, "BARRIER_PSB", 0, F (),                           \
+    Y(SYSTEM, hint, "BARRIER_PSB", 0, F (),                            \
       "the PSB option name CSYNC")                                     \
+    Y(ADDRESS, sve_addr_ri_u6, "SVE_ADDR_RI_U6", 0 << OPD_F_OD_LSB,    \
+      F(FLD_Rn), "an address with a 6-bit unsigned offset")            \
+    Y(ADDRESS, sve_addr_ri_u6, "SVE_ADDR_RI_U6x2", 1 << OPD_F_OD_LSB,  \
+      F(FLD_Rn),                                                       \
+      "an address with a 6-bit unsigned offset, multiplied by 2")      \
+    Y(ADDRESS, sve_addr_ri_u6, "SVE_ADDR_RI_U6x4", 2 << OPD_F_OD_LSB,  \
+      F(FLD_Rn),                                                       \
+      "an address with a 6-bit unsigned offset, multiplied by 4")      \
+    Y(ADDRESS, sve_addr_ri_u6, "SVE_ADDR_RI_U6x8", 3 << OPD_F_OD_LSB,  \
+      F(FLD_Rn),                                                       \
+      "an address with a 6-bit unsigned offset, multiplied by 8")      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RR", 0 << OPD_F_OD_LSB,      \
+      F(FLD_Rn,FLD_Rm), "an address with a scalar register offset")    \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RR_LSL1", 1 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_Rm), "an address with a scalar register offset")    \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RR_LSL2", 2 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_Rm), "an address with a scalar register offset")    \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RR_LSL3", 3 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_Rm), "an address with a scalar register offset")    \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RX",                         \
+      (0 << OPD_F_OD_LSB) | OPD_F_NO_ZR, F(FLD_Rn,FLD_Rm),             \
+      "an address with a scalar register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RX_LSL1",                    \
+      (1 << OPD_F_OD_LSB) | OPD_F_NO_ZR, F(FLD_Rn,FLD_Rm),             \
+      "an address with a scalar register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RX_LSL2",                    \
+      (2 << OPD_F_OD_LSB) | OPD_F_NO_ZR, F(FLD_Rn,FLD_Rm),             \
+      "an address with a scalar register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RX_LSL3",                    \
+      (3 << OPD_F_OD_LSB) | OPD_F_NO_ZR, F(FLD_Rn,FLD_Rm),             \
+      "an address with a scalar register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RZ", 0 << OPD_F_OD_LSB,      \
+      F(FLD_Rn,FLD_SVE_Zm_16),                                         \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RZ_LSL1", 1 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_SVE_Zm_16),                                         \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RZ_LSL2", 2 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_SVE_Zm_16),                                         \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rr_lsl, "SVE_ADDR_RZ_LSL3", 3 << OPD_F_OD_LSB, \
+      F(FLD_Rn,FLD_SVE_Zm_16),                                         \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW_14",                  \
+      0 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW_22",                  \
+      0 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW1_14",                 \
+      1 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW1_22",                 \
+      1 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW2_14",                 \
+      2 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW2_22",                 \
+      2 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW3_14",                 \
+      3 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_14),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_rz_xtw, "SVE_ADDR_RZ_XTW3_22",                 \
+      3 << OPD_F_OD_LSB, F(FLD_Rn,FLD_SVE_Zm_16,FLD_SVE_xs_22),                \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_zi_u5, "SVE_ADDR_ZI_U5", 0 << OPD_F_OD_LSB,    \
+      F(FLD_SVE_Zn), "an address with a 5-bit unsigned offset")                \
+    Y(ADDRESS, sve_addr_zi_u5, "SVE_ADDR_ZI_U5x2", 1 << OPD_F_OD_LSB,  \
+      F(FLD_SVE_Zn),                                                   \
+      "an address with a 5-bit unsigned offset, multiplied by 2")      \
+    Y(ADDRESS, sve_addr_zi_u5, "SVE_ADDR_ZI_U5x4", 2 << OPD_F_OD_LSB,  \
+      F(FLD_SVE_Zn),                                                   \
+      "an address with a 5-bit unsigned offset, multiplied by 4")      \
+    Y(ADDRESS, sve_addr_zi_u5, "SVE_ADDR_ZI_U5x8", 3 << OPD_F_OD_LSB,  \
+      F(FLD_SVE_Zn),                                                   \
+      "an address with a 5-bit unsigned offset, multiplied by 8")      \
+    Y(ADDRESS, sve_addr_zz_lsl, "SVE_ADDR_ZZ_LSL", 0,                  \
+      F(FLD_SVE_Zn,FLD_SVE_Zm_16),                                     \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_zz_sxtw, "SVE_ADDR_ZZ_SXTW", 0,                        \
+      F(FLD_SVE_Zn,FLD_SVE_Zm_16),                                     \
+      "an address with a vector register offset")                      \
+    Y(ADDRESS, sve_addr_zz_uxtw, "SVE_ADDR_ZZ_UXTW", 0,                        \
+      F(FLD_SVE_Zn,FLD_SVE_Zm_16),                                     \
+      "an address with a vector register offset")                      \
     Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern),            \
       "an enumeration value such as POW2")                             \
     Y(IMMEDIATE, sve_scale, "SVE_PATTERN_SCALED", 0,                   \