[AArch64][SVE 21/32] Add Zn and Pn registers
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:53:54 +0000 (16:53 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:53:54 +0000 (16:53 +0100)
This patch adds the Zn and Pn registers, and associated fields and
operands.

include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.

opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length.  Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.

gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn.  Update the
call to parse_vector_type_for_operand.  Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.

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 425c37a7dde8905f69f299d2e4314a26181a4c5a..ac1bb548b6391519023f7567cf710f689531c4af 100644 (file)
@@ -1,3 +1,21 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
+       (AARCH64_REG_TYPES): Add ZN and PN.
+       (get_reg_expected_msg): Handle them.
+       (parse_vector_type_for_operand): Add a reg_type parameter.
+       Skip the width for Zn and Pn registers.
+       (parse_typed_reg): Extend vector handling to Zn and Pn.  Update the
+       call to parse_vector_type_for_operand.  Set HASVARTYPE for Zn and Pn,
+       expecting the width to be 0.
+       (parse_vector_reg_list): Restrict error about [BHSD]nn operands to
+       REG_TYPE_VN.
+       (vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
+       (parse_operands): Handle the new Zn and Pn operands.
+       (REGSET16): New macro, split out from...
+       (REGSET31): ...here.
+       (reg_names): Add Zn and Pn entries.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/tc-aarch64.c (output_operand_error_record): Handle
index 83352303cf0467136c971b3e3a948fc77fd34b79..be88d29da897f3b005734383e7afa77a52f7ba26 100644 (file)
@@ -87,8 +87,9 @@ enum vector_el_type
 };
 
 /* Bits for DEFINED field in vector_type_el.  */
-#define NTA_HASTYPE  1
-#define NTA_HASINDEX 2
+#define NTA_HASTYPE     1
+#define NTA_HASINDEX    2
+#define NTA_HASVARWIDTH 4
 
 struct vector_type_el
 {
@@ -265,6 +266,8 @@ struct reloc_entry
   BASIC_REG_TYPE(FP_Q) /* q[0-31] */   \
   BASIC_REG_TYPE(CN)   /* c[0-7]  */   \
   BASIC_REG_TYPE(VN)   /* v[0-31] */   \
+  BASIC_REG_TYPE(ZN)   /* z[0-31] */   \
+  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: x[0-30], w[0-30] or [xw]zr.  */                                \
@@ -393,6 +396,12 @@ get_reg_expected_msg (aarch64_reg_type reg_type)
     case REG_TYPE_VN:          /* any V reg  */
       msg = N_("vector register expected");
       break;
+    case REG_TYPE_ZN:
+      msg = N_("SVE vector register expected");
+      break;
+    case REG_TYPE_PN:
+      msg = N_("SVE predicate register expected");
+      break;
     default:
       as_fatal (_("invalid register type %d"), reg_type);
     }
@@ -724,15 +733,16 @@ aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
   return reg;
 }
 
-/* Parse the qualifier of a SIMD vector register or a SIMD vector element.
-   Fill in *PARSED_TYPE and return TRUE if the parsing succeeds;
-   otherwise return FALSE.
+/* 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.
 
    Accept only one occurrence of:
    8b 16b 2h 4h 8h 2s 4s 1d 2d
    b h s d q  */
 static bfd_boolean
-parse_vector_type_for_operand (struct vector_type_el *parsed_type, char **str)
+parse_vector_type_for_operand (aarch64_reg_type reg_type,
+                              struct vector_type_el *parsed_type, char **str)
 {
   char *ptr = *str;
   unsigned width;
@@ -742,7 +752,7 @@ parse_vector_type_for_operand (struct vector_type_el *parsed_type, char **str)
   /* skip '.' */
   ptr++;
 
-  if (!ISDIGIT (*ptr))
+  if (reg_type == REG_TYPE_ZN || reg_type == REG_TYPE_PN || !ISDIGIT (*ptr))
     {
       width = 0;
       goto elt_size;
@@ -849,15 +859,23 @@ parse_typed_reg (char **ccp, aarch64_reg_type type, aarch64_reg_type *rtype,
     }
   type = reg->type;
 
-  if (type == REG_TYPE_VN && *str == '.')
+  if ((type == REG_TYPE_VN || type == REG_TYPE_ZN || type == REG_TYPE_PN)
+      && *str == '.')
     {
-      if (!parse_vector_type_for_operand (&parsetype, &str))
+      if (!parse_vector_type_for_operand (type, &parsetype, &str))
        return PARSE_FAIL;
 
       /* Register if of the form Vn.[bhsdq].  */
       is_typed_vecreg = TRUE;
 
-      if (parsetype.width == 0)
+      if (type == REG_TYPE_ZN || type == REG_TYPE_PN)
+       {
+         /* The width is always variable; we don't allow an integer width
+            to be specified.  */
+         gas_assert (parsetype.width == 0);
+         atype.defined |= NTA_HASVARWIDTH | NTA_HASTYPE;
+       }
+      else if (parsetype.width == 0)
        /* Expect index. In the new scheme we cannot have
           Vn.[bhsdq] represent a scalar. Therefore any
           Vn.[bhsdq] should have an index following it.
@@ -1034,7 +1052,7 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type,
          continue;
        }
       /* reject [bhsd]n */
-      if (typeinfo.defined == 0)
+      if (type == REG_TYPE_VN && typeinfo.defined == 0)
        {
          set_first_syntax_error (_("invalid scalar register in list"));
          error = TRUE;
@@ -4639,7 +4657,7 @@ vectype_to_qualifier (const struct vector_type_el *vectype)
 
   gas_assert (vectype->type >= NT_b && vectype->type <= NT_q);
 
-  if (vectype->defined & NTA_HASINDEX)
+  if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH))
     /* Vector element register.  */
     return AARCH64_OPND_QLF_S_B + vectype->type;
   else
@@ -4979,6 +4997,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
       struct vector_type_el vectype;
       aarch64_opnd_qualifier_t qualifier;
       aarch64_opnd_info *info = &inst.base.operands[i];
+      aarch64_reg_type reg_type;
 
       DEBUG_TRACE ("parse operand %d", i);
 
@@ -5061,22 +5080,54 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          info->qualifier = AARCH64_OPND_QLF_S_B + (rtype - REG_TYPE_FP_B);
          break;
 
+       case AARCH64_OPND_SVE_Pd:
+       case AARCH64_OPND_SVE_Pg3:
+       case AARCH64_OPND_SVE_Pg4_5:
+       case AARCH64_OPND_SVE_Pg4_10:
+       case AARCH64_OPND_SVE_Pg4_16:
+       case AARCH64_OPND_SVE_Pm:
+       case AARCH64_OPND_SVE_Pn:
+       case AARCH64_OPND_SVE_Pt:
+         reg_type = REG_TYPE_PN;
+         goto vector_reg;
+
+       case AARCH64_OPND_SVE_Za_5:
+       case AARCH64_OPND_SVE_Za_16:
+       case AARCH64_OPND_SVE_Zd:
+       case AARCH64_OPND_SVE_Zm_5:
+       case AARCH64_OPND_SVE_Zm_16:
+       case AARCH64_OPND_SVE_Zn:
+       case AARCH64_OPND_SVE_Zt:
+         reg_type = REG_TYPE_ZN;
+         goto vector_reg;
+
        case AARCH64_OPND_Vd:
        case AARCH64_OPND_Vn:
        case AARCH64_OPND_Vm:
-         val = aarch64_reg_parse (&str, REG_TYPE_VN, NULL, &vectype);
+         reg_type = REG_TYPE_VN;
+       vector_reg:
+         val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
          if (val == PARSE_FAIL)
            {
-             first_error (_(get_reg_expected_msg (REG_TYPE_VN)));
+             first_error (_(get_reg_expected_msg (reg_type)));
              goto failure;
            }
          if (vectype.defined & NTA_HASINDEX)
            goto failure;
 
          info->reg.regno = val;
-         info->qualifier = vectype_to_qualifier (&vectype);
-         if (info->qualifier == AARCH64_OPND_QLF_NIL)
-           goto failure;
+         if ((reg_type == REG_TYPE_PN || reg_type == REG_TYPE_ZN)
+             && vectype.type == NT_invtype)
+           /* Unqualified Pn and Zn registers are allowed in certain
+              contexts.  Rely on F_STRICT qualifier checking to catch
+              invalid uses.  */
+           info->qualifier = AARCH64_OPND_QLF_NIL;
+         else
+           {
+             info->qualifier = vectype_to_qualifier (&vectype);
+             if (info->qualifier == AARCH64_OPND_QLF_NIL)
+               goto failure;
+           }
          break;
 
        case AARCH64_OPND_VdD1:
@@ -5101,13 +5152,19 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          info->qualifier = AARCH64_OPND_QLF_S_D;
          break;
 
+       case AARCH64_OPND_SVE_Zn_INDEX:
+         reg_type = REG_TYPE_ZN;
+         goto vector_reg_index;
+
        case AARCH64_OPND_Ed:
        case AARCH64_OPND_En:
        case AARCH64_OPND_Em:
-         val = aarch64_reg_parse (&str, REG_TYPE_VN, NULL, &vectype);
+         reg_type = REG_TYPE_VN;
+       vector_reg_index:
+         val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
          if (val == PARSE_FAIL)
            {
-             first_error (_(get_reg_expected_msg (REG_TYPE_VN)));
+             first_error (_(get_reg_expected_msg (reg_type)));
              goto failure;
            }
          if (vectype.type == NT_invtype || !(vectype.defined & NTA_HASINDEX))
@@ -5120,20 +5177,43 @@ parse_operands (char *str, const aarch64_opcode *opcode)
            goto failure;
          break;
 
+       case AARCH64_OPND_SVE_ZnxN:
+       case AARCH64_OPND_SVE_ZtxN:
+         reg_type = REG_TYPE_ZN;
+         goto vector_reg_list;
+
        case AARCH64_OPND_LVn:
        case AARCH64_OPND_LVt:
        case AARCH64_OPND_LVt_AL:
        case AARCH64_OPND_LEt:
-         if ((val = parse_vector_reg_list (&str, REG_TYPE_VN,
-                                           &vectype)) == PARSE_FAIL)
-           goto failure;
-         if (! reg_list_valid_p (val, /* accept_alternate */ 0))
+         reg_type = REG_TYPE_VN;
+       vector_reg_list:
+         if (reg_type == REG_TYPE_ZN
+             && get_opcode_dependent_value (opcode) == 1
+             && *str != '{')
            {
-             set_fatal_syntax_error (_("invalid register list"));
-             goto failure;
+             val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
+             if (val == PARSE_FAIL)
+               {
+                 first_error (_(get_reg_expected_msg (reg_type)));
+                 goto failure;
+               }
+             info->reglist.first_regno = val;
+             info->reglist.num_regs = 1;
+           }
+         else
+           {
+             val = parse_vector_reg_list (&str, reg_type, &vectype);
+             if (val == PARSE_FAIL)
+               goto failure;
+             if (! reg_list_valid_p (val, /* accept_alternate */ 0))
+               {
+                 set_fatal_syntax_error (_("invalid register list"));
+                 goto failure;
+               }
+             info->reglist.first_regno = (val >> 2) & 0x1f;
+             info->reglist.num_regs = (val & 0x3) + 1;
            }
-         info->reglist.first_regno = (val >> 2) & 0x1f;
-         info->reglist.num_regs = (val & 0x3) + 1;
          if (operands[i] == AARCH64_OPND_LEt)
            {
              if (!(vectype.defined & NTA_HASINDEX))
@@ -5141,8 +5221,17 @@ parse_operands (char *str, const aarch64_opcode *opcode)
              info->reglist.has_index = 1;
              info->reglist.index = vectype.index;
            }
-         else if (!(vectype.defined & NTA_HASTYPE))
-           goto failure;
+         else
+           {
+             if (vectype.defined & NTA_HASINDEX)
+               goto failure;
+             if (!(vectype.defined & NTA_HASTYPE))
+               {
+                 if (reg_type == REG_TYPE_ZN)
+                   set_fatal_syntax_error (_("missing type suffix"));
+                 goto failure;
+               }
+           }
          info->qualifier = vectype_to_qualifier (&vectype);
          if (info->qualifier == AARCH64_OPND_QLF_NIL)
            goto failure;
@@ -6157,11 +6246,13 @@ aarch64_canonicalize_symbol_name (char *name)
 
 #define REGDEF(s,n,t) { #s, n, REG_TYPE_##t, TRUE }
 #define REGNUM(p,n,t) REGDEF(p##n, n, t)
-#define REGSET31(p,t) \
+#define REGSET16(p,t) \
   REGNUM(p, 0,t), REGNUM(p, 1,t), REGNUM(p, 2,t), REGNUM(p, 3,t), \
   REGNUM(p, 4,t), REGNUM(p, 5,t), REGNUM(p, 6,t), REGNUM(p, 7,t), \
   REGNUM(p, 8,t), REGNUM(p, 9,t), REGNUM(p,10,t), REGNUM(p,11,t), \
-  REGNUM(p,12,t), REGNUM(p,13,t), REGNUM(p,14,t), REGNUM(p,15,t), \
+  REGNUM(p,12,t), REGNUM(p,13,t), REGNUM(p,14,t), REGNUM(p,15,t)
+#define REGSET31(p,t) \
+  REGSET16(p, t), \
   REGNUM(p,16,t), REGNUM(p,17,t), REGNUM(p,18,t), REGNUM(p,19,t), \
   REGNUM(p,20,t), REGNUM(p,21,t), REGNUM(p,22,t), REGNUM(p,23,t), \
   REGNUM(p,24,t), REGNUM(p,25,t), REGNUM(p,26,t), REGNUM(p,27,t), \
@@ -6201,10 +6292,18 @@ static const reg_entry reg_names[] = {
 
   /* FP/SIMD registers.  */
   REGSET (v, VN), REGSET (V, VN),
+
+  /* SVE vector registers.  */
+  REGSET (z, ZN), REGSET (Z, ZN),
+
+  /* SVE predicate registers.  */
+  REGSET16 (p, PN), REGSET16 (P, PN)
 };
 
 #undef REGDEF
 #undef REGNUM
+#undef REGSET16
+#undef REGSET31
 #undef REGSET
 
 #define N 1
index e6c3dbdf508ee27afd39254192017d0452a7b182..53d0ba0b176ea6b582b1108a3c5f08bddb734cac 100644 (file)
@@ -1,3 +1,16 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
+       aarch64_operand_class.
+       (AARCH64_OPND_CLASS_PRED_REG): Likewise.
+       (AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
+       (AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
+       (AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
+       (AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
+       (AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
+       (AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
+       (AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * opcode/aarch64.h (aarch64_opcode): Add a tied_operand field.
index d39f10d0cfc9050d12cf01684cb26d9a578592c1..b0eb6175d079609c7a203491651386340a0bd675 100644 (file)
@@ -120,6 +120,8 @@ enum aarch64_operand_class
   AARCH64_OPND_CLASS_SISD_REG,
   AARCH64_OPND_CLASS_SIMD_REGLIST,
   AARCH64_OPND_CLASS_CP_REG,
+  AARCH64_OPND_CLASS_SVE_REG,
+  AARCH64_OPND_CLASS_PRED_REG,
   AARCH64_OPND_CLASS_ADDRESS,
   AARCH64_OPND_CLASS_IMMEDIATE,
   AARCH64_OPND_CLASS_SYSTEM,
@@ -241,6 +243,25 @@ enum aarch64_opnd
   AARCH64_OPND_BARRIER_ISB,    /* Barrier operand for ISB.  */
   AARCH64_OPND_PRFOP,          /* Prefetch operation.  */
   AARCH64_OPND_BARRIER_PSB,    /* Barrier operand for PSB.  */
+
+  AARCH64_OPND_SVE_Pd,         /* SVE p0-p15 in Pd.  */
+  AARCH64_OPND_SVE_Pg3,                /* SVE p0-p7 in Pg.  */
+  AARCH64_OPND_SVE_Pg4_5,      /* SVE p0-p15 in Pg, bits [8,5].  */
+  AARCH64_OPND_SVE_Pg4_10,     /* SVE p0-p15 in Pg, bits [13,10].  */
+  AARCH64_OPND_SVE_Pg4_16,     /* SVE p0-p15 in Pg, bits [19,16].  */
+  AARCH64_OPND_SVE_Pm,         /* SVE p0-p15 in Pm.  */
+  AARCH64_OPND_SVE_Pn,         /* SVE p0-p15 in Pn.  */
+  AARCH64_OPND_SVE_Pt,         /* SVE p0-p15 in Pt.  */
+  AARCH64_OPND_SVE_Za_5,       /* SVE vector register in Za, bits [9,5].  */
+  AARCH64_OPND_SVE_Za_16,      /* SVE vector register in Za, bits [20,16].  */
+  AARCH64_OPND_SVE_Zd,         /* SVE vector register in Zd.  */
+  AARCH64_OPND_SVE_Zm_5,       /* SVE vector register in Zm, bits [9,5].  */
+  AARCH64_OPND_SVE_Zm_16,      /* SVE vector register in Zm, bits [20,16].  */
+  AARCH64_OPND_SVE_Zn,         /* SVE vector register in Zn.  */
+  AARCH64_OPND_SVE_Zn_INDEX,   /* Indexed SVE vector register, for DUP.  */
+  AARCH64_OPND_SVE_ZnxN,       /* SVE vector register list in Zn.  */
+  AARCH64_OPND_SVE_Zt,         /* SVE vector register in Zt.  */
+  AARCH64_OPND_SVE_ZtxN,       /* SVE vector register list in Zt.  */
 };
 
 /* Qualifier constrains an operand.  It either specifies a variant of an
index 925ea1eb101eb8fd2bf9ad57759ec9461754ad56..463837baa4354d55d5705543124a561feb7ec1a1 100644 (file)
@@ -1,3 +1,25 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
+       * aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
+       (FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
+       (FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
+       (FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
+       * aarch64-opc.c (fields): Add corresponding entries here.
+       (operand_general_constraint_met_p): Check that SVE register lists
+       have the correct length.  Check the ranges of SVE index registers.
+       Check for cases where p8-p15 are used in 3-bit predicate fields.
+       (aarch64_print_operand): Handle the new SVE operands.
+       * aarch64-opc-2.c: Regenerate.
+       * aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
+       * aarch64-asm.c (aarch64_ins_sve_index): New function.
+       (aarch64_ins_sve_reglist): Likewise.
+       * aarch64-asm-2.c: Regenerate.
+       * aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
+       * aarch64-dis.c (aarch64_ext_sve_index): New function.
+       (aarch64_ext_sve_reglist): Likewise.
+       * aarch64-dis-2.c: Regenerate.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * aarch64-tbl.h (CORE_INSN, __FP_INSN, SIMD_INSN, CRYP_INSN)
index 439dd3d0e80b75833e8bc9d3a746b7bd69e1633f..9c797b2ea5af2ca822a93ac76dbcee7551e18561 100644 (file)
@@ -480,6 +480,21 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 105:
       return aarch64_ins_regno (self, info, code, inst);
     case 12:
       return aarch64_ins_reg_extended (self, info, code, inst);
@@ -566,6 +581,11 @@ 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 103:
+      return aarch64_ins_sve_index (self, info, code, inst);
+    case 104:
+    case 106:
+      return aarch64_ins_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
 }
index f291495992ee9b3c9253927c742050effc5c3dcb..c045f9e4b41ffe8f2c790a2cfee5eaf5d35c02af 100644 (file)
@@ -745,6 +745,33 @@ aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+/* 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
+   significant part.  */
+const char *
+aarch64_ins_sve_index (const aarch64_operand *self,
+                      const aarch64_opnd_info *info, aarch64_insn *code,
+                      const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  unsigned int esize = aarch64_get_qualifier_esize (info->qualifier);
+  insert_field (self->fields[0], code, info->reglane.regno, 0);
+  insert_fields (code, (info->reglane.index * 2 + 1) * esize, 0,
+                2, FLD_imm5, FLD_SVE_tszh);
+  return NULL;
+}
+
+/* Encode {Zn.<T> - Zm.<T>}.  The fields array specifies which field
+   to use for Zn.  */
+const char *
+aarch64_ins_sve_reglist (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->reglist.first_regno, 0);
+  return NULL;
+}
+
 /* Miscellaneous encoding functions.  */
 
 /* Encode size[0], i.e. bit 22, for
index 3211aff99b4c5dd2267f4744053f464fa2f800eb..ede366c00f26b118bf87d0dab98be73ece92981f 100644 (file)
@@ -69,6 +69,8 @@ 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_index);
+AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
 
 #undef AARCH64_DECL_OPD_INSERTER
 
index a86a84ddd596aed46ce9d14bf6e90176c2bffec0..6ea010b3573ff0d7ea3c06c0b7274d96d65e8f70 100644 (file)
@@ -10426,6 +10426,21 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
+    case 89:
+    case 90:
+    case 91:
+    case 92:
+    case 93:
+    case 94:
+    case 95:
+    case 96:
+    case 97:
+    case 98:
+    case 99:
+    case 100:
+    case 101:
+    case 102:
+    case 105:
       return aarch64_ext_regno (self, info, code, inst);
     case 8:
       return aarch64_ext_regrt_sysins (self, info, code, inst);
@@ -10519,6 +10534,11 @@ 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 103:
+      return aarch64_ext_sve_index (self, info, code, inst);
+    case 104:
+    case 106:
+      return aarch64_ext_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
 }
index 4c3b521d0de9f73f5944c7469fe71c2d8997ae19..ab93234e28afd54630199f2ea7ce35f7b948d070 100644 (file)
@@ -1185,6 +1185,40 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
 
   return 1;
 }
+
+/* Decode Zn[MM], where MM has a 7-bit triangular encoding.  The fields
+   array specifies which field to use for Zn.  MM is encoded in the
+   concatenation of imm5 and SVE_tszh, with imm5 being the less
+   significant part.  */
+int
+aarch64_ext_sve_index (const aarch64_operand *self,
+                      aarch64_opnd_info *info, aarch64_insn code,
+                      const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int val;
+
+  info->reglane.regno = extract_field (self->fields[0], code, 0);
+  val = extract_fields (code, 0, 2, FLD_SVE_tszh, FLD_imm5);
+  if ((val & 15) == 0)
+    return 0;
+  while ((val & 1) == 0)
+    val /= 2;
+  info->reglane.index = val / 2;
+  return 1;
+}
+
+/* Decode {Zn.<T> - Zm.<T>}.  The fields array specifies which field
+   to use for Zn.  The opcode-dependent value specifies the number
+   of registers in the list.  */
+int
+aarch64_ext_sve_reglist (const aarch64_operand *self,
+                        aarch64_opnd_info *info, aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  info->reglist.first_regno = extract_field (self->fields[0], code, 0);
+  info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+  return 1;
+}
 \f
 /* Bitfields that are commonly used to encode certain operands' information
    may be partially used as part of the base opcode in some instructions.
index 1f101571b6f275ea625fdb30732ef3c3a075a8b6..5efb9044ba9d2840a663946dca716f2405cacc07 100644 (file)
@@ -91,6 +91,8 @@ 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_index);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
 
 #undef AARCH64_DECL_OPD_EXTRACTOR
 
index b53bb5c3370529d97c8e8ebb15116b55af1891c4..f8a7079c6903723cbc881c398aebd92eb922326b 100644 (file)
@@ -113,6 +113,24 @@ 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_PRED_REG, "SVE_Pd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pd}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg3}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_5}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_10", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_10}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_16}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pm}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pn}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pt}, "an SVE predicate register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_5}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_16}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zd}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zm_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zm_5}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zm_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zm_16}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zn_INDEX", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an indexed SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_ZnxN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "a list of SVE vector registers"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zt}, "an SVE vector register"},
+  {AARCH64_OPND_CLASS_SVE_REG, "SVE_ZtxN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zt}, "a list of SVE vector registers"},
   {AARCH64_OPND_CLASS_NIL, "", 0, {0}, "DUMMY"},
 };
 
index 30501fcc47e53a7fbac9aa24b2eb6bf7a7ccde2c..56a01693dc9d094e0f384735efd1a99e424eff75 100644 (file)
@@ -199,6 +199,22 @@ const aarch64_field fields[] =
     { 31,  1 },        /* b5: in the test bit and branch instructions.  */
     { 19,  5 },        /* b40: in the test bit and branch instructions.  */
     { 10,  6 },        /* scale: in the fixed-point scalar to fp converting inst.  */
+    {  0,  4 }, /* SVE_Pd: p0-p15, bits [3,0].  */
+    { 10,  3 }, /* SVE_Pg3: p0-p7, bits [12,10].  */
+    {  5,  4 }, /* SVE_Pg4_5: p0-p15, bits [8,5].  */
+    { 10,  4 }, /* SVE_Pg4_10: p0-p15, bits [13,10].  */
+    { 16,  4 }, /* SVE_Pg4_16: p0-p15, bits [19,16].  */
+    { 16,  4 }, /* SVE_Pm: p0-p15, bits [19,16].  */
+    {  5,  4 }, /* SVE_Pn: p0-p15, bits [8,5].  */
+    {  0,  4 }, /* SVE_Pt: p0-p15, bits [3,0].  */
+    {  5,  5 }, /* SVE_Za_5: SVE vector register, bits [9,5].  */
+    { 16,  5 }, /* SVE_Za_16: SVE vector register, bits [20,16].  */
+    {  0,  5 }, /* SVE_Zd: SVE vector register. bits [4,0].  */
+    {  5,  5 }, /* SVE_Zm_5: SVE vector register, bits [9,5].  */
+    { 16,  5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
+    {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
+    {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
+    { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
 };
 
 enum aarch64_operand_class
@@ -1332,6 +1348,43 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        }
       break;
 
+    case AARCH64_OPND_CLASS_SVE_REG:
+      switch (type)
+       {
+       case AARCH64_OPND_SVE_Zn_INDEX:
+         size = aarch64_get_qualifier_esize (opnd->qualifier);
+         if (!value_in_range_p (opnd->reglane.index, 0, 64 / size - 1))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx,
+                                              0, 64 / size - 1);
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_SVE_ZnxN:
+       case AARCH64_OPND_SVE_ZtxN:
+         if (opnd->reglist.num_regs != get_opcode_dependent_value (opcode))
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("invalid register list"));
+             return 0;
+           }
+         break;
+
+       default:
+         break;
+       }
+      break;
+
+    case AARCH64_OPND_CLASS_PRED_REG:
+      if (opnd->reg.regno >= 8
+         && get_operand_fields_width (get_operand_from_code (type)) == 3)
+       {
+         set_other_error (mismatch_detail, idx, _("p0-p7 expected"));
+         return 0;
+       }
+      break;
+
     case AARCH64_OPND_CLASS_COND:
       if (type == AARCH64_OPND_COND1
          && (opnds[idx].cond->value & 0xe) == 0xe)
@@ -2560,6 +2613,46 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_list (buf, size, opnd, "v");
       break;
 
+    case AARCH64_OPND_SVE_Pd:
+    case AARCH64_OPND_SVE_Pg3:
+    case AARCH64_OPND_SVE_Pg4_5:
+    case AARCH64_OPND_SVE_Pg4_10:
+    case AARCH64_OPND_SVE_Pg4_16:
+    case AARCH64_OPND_SVE_Pm:
+    case AARCH64_OPND_SVE_Pn:
+    case AARCH64_OPND_SVE_Pt:
+      if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+       snprintf (buf, size, "p%d", opnd->reg.regno);
+      else
+       snprintf (buf, size, "p%d.%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_Za_5:
+    case AARCH64_OPND_SVE_Za_16:
+    case AARCH64_OPND_SVE_Zd:
+    case AARCH64_OPND_SVE_Zm_5:
+    case AARCH64_OPND_SVE_Zm_16:
+    case AARCH64_OPND_SVE_Zn:
+    case AARCH64_OPND_SVE_Zt:
+      if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+       snprintf (buf, size, "z%d", opnd->reg.regno);
+      else
+       snprintf (buf, size, "z%d.%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
+      break;
+
+    case AARCH64_OPND_SVE_ZnxN:
+    case AARCH64_OPND_SVE_ZtxN:
+      print_register_list (buf, size, opnd, "z");
+      break;
+
+    case AARCH64_OPND_SVE_Zn_INDEX:
+      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+               aarch64_get_qualifier_name (opnd->qualifier),
+               opnd->reglane.index);
+      break;
+
     case AARCH64_OPND_Cn:
     case AARCH64_OPND_Cm:
       snprintf (buf, size, "C%d", opnd->reg.regno);
index 08494c678a5503a1ac5b1eda3f399b20996ea623..cc3dbefd6315398945f5d28c2d33763ae9b01487 100644 (file)
@@ -91,6 +91,22 @@ enum aarch64_field_kind
   FLD_b5,
   FLD_b40,
   FLD_scale,
+  FLD_SVE_Pd,
+  FLD_SVE_Pg3,
+  FLD_SVE_Pg4_5,
+  FLD_SVE_Pg4_10,
+  FLD_SVE_Pg4_16,
+  FLD_SVE_Pm,
+  FLD_SVE_Pn,
+  FLD_SVE_Pt,
+  FLD_SVE_Za_5,
+  FLD_SVE_Za_16,
+  FLD_SVE_Zd,
+  FLD_SVE_Zm_5,
+  FLD_SVE_Zm_16,
+  FLD_SVE_Zn,
+  FLD_SVE_Zt,
+  FLD_SVE_tszh,
 };
 
 /* Field description.  */
index 8f1c9b237d98c72a386afb92dd0279054edf3521..9dbe0c0ec5d5946620e47c8f68ffa4985fc0512d 100644 (file)
@@ -2819,4 +2819,40 @@ struct aarch64_opcode aarch64_opcode_table[] =
     Y(SYSTEM, prfop, "PRFOP", 0, F(),                                  \
       "a prefetch operation specifier")                                        \
     Y (SYSTEM, hint, "BARRIER_PSB", 0, F (),                           \
-      "the PSB option name CSYNC")
+      "the PSB option name CSYNC")                                     \
+    Y(PRED_REG, regno, "SVE_Pd", 0, F(FLD_SVE_Pd),                     \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pg3", 0, F(FLD_SVE_Pg3),                   \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pg4_5", 0, F(FLD_SVE_Pg4_5),               \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pg4_10", 0, F(FLD_SVE_Pg4_10),             \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pg4_16", 0, F(FLD_SVE_Pg4_16),             \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pm", 0, F(FLD_SVE_Pm),                     \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pn", 0, F(FLD_SVE_Pn),                     \
+      "an SVE predicate register")                                     \
+    Y(PRED_REG, regno, "SVE_Pt", 0, F(FLD_SVE_Pt),                     \
+      "an SVE predicate register")                                     \
+    Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5),                  \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16),                        \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, regno, "SVE_Zd", 0, F(FLD_SVE_Zd),                      \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, regno, "SVE_Zm_5", 0, F(FLD_SVE_Zm_5),                  \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, regno, "SVE_Zm_16", 0, F(FLD_SVE_Zm_16),                        \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, regno, "SVE_Zn", 0, F(FLD_SVE_Zn),                      \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, sve_index, "SVE_Zn_INDEX", 0, F(FLD_SVE_Zn),            \
+      "an indexed SVE vector register")                                        \
+    Y(SVE_REG, sve_reglist, "SVE_ZnxN", 0, F(FLD_SVE_Zn),              \
+      "a list of SVE vector registers")                                        \
+    Y(SVE_REG, regno, "SVE_Zt", 0, F(FLD_SVE_Zt),                      \
+      "an SVE vector register")                                                \
+    Y(SVE_REG, sve_reglist, "SVE_ZtxN", 0, F(FLD_SVE_Zt),              \
+      "a list of SVE vector registers")