[AArch64][SVE 22/32] Add qualifiers for merging and zeroing predication
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:54:30 +0000 (16:54 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:54:30 +0000 (16:54 +0100)
This patch adds qualifiers to represent /z and /m suffixes on
predicate registers.

include/
* opcode/aarch64.h (AARCH64_OPND_QLF_P_Z): New aarch64_opnd_qualifier.
(AARCH64_OPND_QLF_P_M): Likewise.

opcodes/
* aarch64-opc.c (aarch64_opnd_qualifiers): Add entries for
AARCH64_OPND_QLF_P_[ZM].
(aarch64_print_operand): Print /z and /m where appropriate.

gas/
* config/tc-aarch64.c (vector_el_type): Add NT_zero and NT_merge.
(parse_vector_type_for_operand): Assert that the skipped character
is a '.'.
(parse_predication_for_operand): New function.
(parse_typed_reg): Parse /z and /m suffixes for predicate registers.
(vectype_to_qualifier): Handle NT_zero and NT_merge.

gas/ChangeLog
gas/config/tc-aarch64.c
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-opc.c

index ac1bb548b6391519023f7567cf710f689531c4af..589b2cfe152d0d3301f6e76c94d2eab10182c3ad 100644 (file)
@@ -1,3 +1,12 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/tc-aarch64.c (vector_el_type): Add NT_zero and NT_merge.
+       (parse_vector_type_for_operand): Assert that the skipped character
+       is a '.'.
+       (parse_predication_for_operand): New function.
+       (parse_typed_reg): Parse /z and /m suffixes for predicate registers.
+       (vectype_to_qualifier): Handle NT_zero and NT_merge.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
index be88d29da897f3b005734383e7afa77a52f7ba26..f87726244e0e582ebfd5ad53a2a13b45908c3392 100644 (file)
@@ -83,7 +83,9 @@ enum vector_el_type
   NT_h,
   NT_s,
   NT_d,
-  NT_q
+  NT_q,
+  NT_zero,
+  NT_merge
 };
 
 /* Bits for DEFINED field in vector_type_el.  */
@@ -750,6 +752,7 @@ parse_vector_type_for_operand (aarch64_reg_type reg_type,
   enum vector_el_type type;
 
   /* skip '.' */
+  gas_assert (*ptr == '.');
   ptr++;
 
   if (reg_type == REG_TYPE_ZN || reg_type == REG_TYPE_PN || !ISDIGIT (*ptr))
@@ -816,6 +819,38 @@ elt_size:
   return TRUE;
 }
 
+/* *STR contains an SVE zero/merge predication suffix.  Parse it into
+   *PARSED_TYPE and point *STR at the end of the suffix.  */
+
+static bfd_boolean
+parse_predication_for_operand (struct vector_type_el *parsed_type, char **str)
+{
+  char *ptr = *str;
+
+  /* Skip '/'.  */
+  gas_assert (*ptr == '/');
+  ptr++;
+  switch (TOLOWER (*ptr))
+    {
+    case 'z':
+      parsed_type->type = NT_zero;
+      break;
+    case 'm':
+      parsed_type->type = NT_merge;
+      break;
+    default:
+      if (*ptr != '\0' && *ptr != ',')
+       first_error_fmt (_("unexpected character `%c' in predication type"),
+                        *ptr);
+      else
+       first_error (_("missing predication type"));
+      return FALSE;
+    }
+  parsed_type->width = 0;
+  *str = ptr + 1;
+  return TRUE;
+}
+
 /* Parse a register of the type TYPE.
 
    Return PARSE_FAIL if the string pointed by *CCP is not a valid register
@@ -860,10 +895,18 @@ parse_typed_reg (char **ccp, aarch64_reg_type type, aarch64_reg_type *rtype,
   type = reg->type;
 
   if ((type == REG_TYPE_VN || type == REG_TYPE_ZN || type == REG_TYPE_PN)
-      && *str == '.')
+      && (*str == '.' || (type == REG_TYPE_PN && *str == '/')))
     {
-      if (!parse_vector_type_for_operand (type, &parsetype, &str))
-       return PARSE_FAIL;
+      if (*str == '.')
+       {
+         if (!parse_vector_type_for_operand (type, &parsetype, &str))
+           return PARSE_FAIL;
+       }
+      else
+       {
+         if (!parse_predication_for_operand (&parsetype, &str))
+           return PARSE_FAIL;
+       }
 
       /* Register if of the form Vn.[bhsdq].  */
       is_typed_vecreg = TRUE;
@@ -4655,6 +4698,11 @@ vectype_to_qualifier (const struct vector_type_el *vectype)
   if (!vectype->defined || vectype->type == NT_invtype)
     goto vectype_conversion_fail;
 
+  if (vectype->type == NT_zero)
+    return AARCH64_OPND_QLF_P_Z;
+  if (vectype->type == NT_merge)
+    return AARCH64_OPND_QLF_P_M;
+
   gas_assert (vectype->type >= NT_b && vectype->type <= NT_q);
 
   if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH))
index 53d0ba0b176ea6b582b1108a3c5f08bddb734cac..175d1d543339955417c3a28ce7d4a92d9aac40bb 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * opcode/aarch64.h (AARCH64_OPND_QLF_P_Z): New aarch64_opnd_qualifier.
+       (AARCH64_OPND_QLF_P_M): Likewise.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
index b0eb6175d079609c7a203491651386340a0bd675..8eae0b941c97357c19db8256be13146b3f938e70 100644 (file)
@@ -315,6 +315,9 @@ enum aarch64_opnd_qualifier
   AARCH64_OPND_QLF_V_2D,
   AARCH64_OPND_QLF_V_1Q,
 
+  AARCH64_OPND_QLF_P_Z,
+  AARCH64_OPND_QLF_P_M,
+
   /* Constraint on value.  */
   AARCH64_OPND_QLF_imm_0_7,
   AARCH64_OPND_QLF_imm_0_15,
index 463837baa4354d55d5705543124a561feb7ec1a1..5d2ddb1405688f866157d8c76a86622aaea85342 100644 (file)
@@ -1,3 +1,9 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * aarch64-opc.c (aarch64_opnd_qualifiers): Add entries for
+       AARCH64_OPND_QLF_P_[ZM].
+       (aarch64_print_operand): Print /z and /m where appropriate.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
index 56a01693dc9d094e0f384735efd1a99e424eff75..41c058f47aa1ce6b42392ba60c455ea5730bd697 100644 (file)
@@ -603,6 +603,9 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
   {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
   {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
 
+  {0, 0, 0, "z", OQK_OPD_VARIANT},
+  {0, 0, 0, "m", OQK_OPD_VARIANT},
+
   /* Qualifiers constraining the value range.
      First 3 fields:
      Lower bound, higher bound, unused.  */
@@ -2623,6 +2626,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
        snprintf (buf, size, "p%d", opnd->reg.regno);
+      else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
+              || opnd->qualifier == AARCH64_OPND_QLF_P_M)
+       snprintf (buf, size, "p%d/%s", opnd->reg.regno,
+                 aarch64_get_qualifier_name (opnd->qualifier));
       else
        snprintf (buf, size, "p%d.%s", opnd->reg.regno,
                  aarch64_get_qualifier_name (opnd->qualifier));