[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:56:15 +0000 (16:56 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:56:15 +0000 (16:56 +0100)
This patch adds support for addresses of the form:

       [<base>, #<offset>, MUL VL]

This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.

For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, ....  The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.

include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.

opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.

gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.

14 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-tbl.h

index c1f4152d8dddfc8d9f71db7fbd9007533225d9a0..4593a787c823a49b541fa785982a9814d3d6d44d 100644 (file)
@@ -1,3 +1,12 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
+       parse_shift_modes.
+       (parse_shift): Handle SHIFTED_MUL_VL.
+       (parse_address_main): Add an imm_shift_mode parameter.
+       (parse_address, parse_sve_address): Update accordingly.
+       (parse_operands): Handle MUL VL addressing modes.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
index e59333ffbf0fb5c2590297e51309b35f1301ed9f..930b07a00903e06e308d2b761e289aa5861d8c1e 100644 (file)
@@ -2922,6 +2922,7 @@ find_reloc_table_entry (char **str)
 /* Mode argument to parse_shift and parser_shifter_operand.  */
 enum parse_shift_mode
 {
+  SHIFTED_NONE,                        /* no shifter allowed  */
   SHIFTED_ARITH_IMM,           /* "rn{,lsl|lsr|asl|asr|uxt|sxt #n}" or
                                   "#imm{,lsl #n}"  */
   SHIFTED_LOGIC_IMM,           /* "rn{,lsl|lsr|asl|asr|ror #n}" or
@@ -2929,6 +2930,7 @@ enum parse_shift_mode
   SHIFTED_LSL,                 /* bare "lsl #n"  */
   SHIFTED_MUL,                 /* bare "mul #n"  */
   SHIFTED_LSL_MSL,             /* "lsl|msl #n"  */
+  SHIFTED_MUL_VL,              /* "mul vl"  */
   SHIFTED_REG_OFFSET           /* [su]xtw|sxtx {#n} or lsl #n  */
 };
 
@@ -2970,7 +2972,8 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
     }
 
   if (kind == AARCH64_MOD_MUL
-      && mode != SHIFTED_MUL)
+      && mode != SHIFTED_MUL
+      && mode != SHIFTED_MUL_VL)
     {
       set_syntax_error (_("invalid use of 'MUL'"));
       return FALSE;
@@ -3010,6 +3013,22 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
        }
       break;
 
+    case SHIFTED_MUL_VL:
+      /* "MUL VL" consists of two separate tokens.  Require the first
+        token to be "MUL" and look for a following "VL".  */
+      if (kind == AARCH64_MOD_MUL)
+       {
+         skip_whitespace (p);
+         if (strncasecmp (p, "vl", 2) == 0 && !ISALPHA (p[2]))
+           {
+             p += 2;
+             kind = AARCH64_MOD_MUL_VL;
+             break;
+           }
+       }
+      set_syntax_error (_("only 'MUL VL' is permitted"));
+      return FALSE;
+
     case SHIFTED_REG_OFFSET:
       if (kind != AARCH64_MOD_UXTW && kind != AARCH64_MOD_LSL
          && kind != AARCH64_MOD_SXTW && kind != AARCH64_MOD_SXTX)
@@ -3037,7 +3056,7 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
 
   /* Parse shift amount.  */
   exp_has_prefix = 0;
-  if (mode == SHIFTED_REG_OFFSET && *p == ']')
+  if ((mode == SHIFTED_REG_OFFSET && *p == ']') || kind == AARCH64_MOD_MUL_VL)
     exp.X_op = O_absent;
   else
     {
@@ -3048,7 +3067,11 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
        }
       my_get_expression (&exp, &p, GE_NO_PREFIX, 0);
     }
-  if (exp.X_op == O_absent)
+  if (kind == AARCH64_MOD_MUL_VL)
+    /* For consistency, give MUL VL the same shift amount as an implicit
+       MUL #1.  */
+    operand->shifter.amount = 1;
+  else if (exp.X_op == O_absent)
     {
       if (aarch64_extend_operator_p (kind) == FALSE || exp_has_prefix)
        {
@@ -3268,6 +3291,7 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
    PC-relative (literal)
      label
    SVE:
+     [base,#imm,MUL VL]
      [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
@@ -3307,15 +3331,20 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
    corresponding register.
 
    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.  */
+   OFFSET_TYPE says the same for offset registers.  IMM_SHIFT_MODE
+   is the type of shifter that is allowed for immediate offsets,
+   or SHIFTED_NONE if none.
+
+   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,
                    aarch64_opnd_qualifier_t *base_qualifier,
                    aarch64_opnd_qualifier_t *offset_qualifier,
-                   aarch64_reg_type base_type, aarch64_reg_type offset_type)
+                   aarch64_reg_type base_type, aarch64_reg_type offset_type,
+                   enum parse_shift_mode imm_shift_mode)
 {
   char *p = *str;
   const reg_entry *reg;
@@ -3497,12 +3526,19 @@ parse_address_main (char **str, aarch64_opnd_info *operand,
              inst.reloc.type = entry->ldst_type;
              inst.reloc.pc_rel = entry->pc_rel;
            }
-         else if (! my_get_expression (exp, &p, GE_OPT_PREFIX, 1))
+         else
            {
-             set_syntax_error (_("invalid expression in the address"));
-             return FALSE;
+             if (! my_get_expression (exp, &p, GE_OPT_PREFIX, 1))
+               {
+                 set_syntax_error (_("invalid expression in the address"));
+                 return FALSE;
+               }
+             /* [Xn,<expr>  */
+             if (imm_shift_mode != SHIFTED_NONE && skip_past_comma (&p))
+               /* [Xn,<expr>,<shifter>  */
+               if (! parse_shift (&p, operand, imm_shift_mode))
+                 return FALSE;
            }
-         /* [Xn,<expr>  */
        }
     }
 
@@ -3582,10 +3618,10 @@ parse_address (char **str, aarch64_opnd_info *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);
+                            REG_TYPE_R64_SP, REG_TYPE_R_Z, SHIFTED_NONE);
 }
 
-/* Parse an address in which SVE vector registers are allowed.
+/* Parse an address in which SVE vector registers and MUL VL are allowed.
    The arguments have the same meaning as for parse_address_main.
    Return TRUE on success.  */
 static bfd_boolean
@@ -3594,7 +3630,8 @@ parse_sve_address (char **str, aarch64_opnd_info *operand,
                   aarch64_opnd_qualifier_t *offset_qualifier)
 {
   return parse_address_main (str, operand, base_qualifier, offset_qualifier,
-                            REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET);
+                            REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET,
+                            SHIFTED_MUL_VL);
 }
 
 /* Parse an operand for a MOVZ, MOVN or MOVK instruction.
@@ -5938,11 +5975,18 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          /* No qualifier.  */
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
        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}]
+         /* [X<n>{, #imm, MUL VL}]
+            [X<n>{, #imm}]
             but recognizing SVE registers.  */
          po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
                                              &offset_qualifier));
index 71df381d25a3f74f109e428ac0dc7baa9c3ffab5..f28903fa4f6a6e0577dc8f16e459ce931638c0f3 100644 (file)
@@ -1,3 +1,11 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
+       (AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
+       (AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
+       (AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
+       (AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
index e61ac9c03fd59f1f836c84a159b7a993e483a28d..837d6bd7580f5f379ddcbfb40ac8243e856d8386 100644 (file)
@@ -244,6 +244,12 @@ enum aarch64_opnd
   AARCH64_OPND_PRFOP,          /* Prefetch operation.  */
   AARCH64_OPND_BARRIER_PSB,    /* Barrier operand for PSB.  */
 
+  AARCH64_OPND_SVE_ADDR_RI_S4xVL,   /* SVE [<Xn|SP>, #<simm4>, MUL VL].  */
+  AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, /* SVE [<Xn|SP>, #<simm4>*2, MUL VL].  */
+  AARCH64_OPND_SVE_ADDR_RI_S4x3xVL, /* SVE [<Xn|SP>, #<simm4>*3, MUL VL].  */
+  AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, /* SVE [<Xn|SP>, #<simm4>*4, MUL VL].  */
+  AARCH64_OPND_SVE_ADDR_RI_S6xVL,   /* SVE [<Xn|SP>, #<simm6>, MUL VL].  */
+  AARCH64_OPND_SVE_ADDR_RI_S9xVL,   /* SVE [<Xn|SP>, #<simm9>, MUL VL].  */
   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].  */
@@ -786,6 +792,7 @@ enum aarch64_modifier_kind
   AARCH64_MOD_SXTW,
   AARCH64_MOD_SXTX,
   AARCH64_MOD_MUL,
+  AARCH64_MOD_MUL_VL,
 };
 
 bfd_boolean
index 2cedfb929b8806f559d5e5f3dd3907f85c62b593..de052a93540e0375384deb7f1fa7ca91c0bd950e 100644 (file)
@@ -1,3 +1,28 @@
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
+       operands.
+       * aarch64-opc.c (aarch64_operand_modifiers): Initialize
+       the AARCH64_MOD_MUL_VL entry.
+       (value_aligned_p): Cope with non-power-of-two alignments.
+       (operand_general_constraint_met_p): Handle the new MUL VL addresses.
+       (print_immediate_offset_address): Likewise.
+       (aarch64_print_operand): Likewise.
+       * aarch64-opc-2.c: Regenerate.
+       * aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
+       (ins_sve_addr_ri_s9xvl): New inserters.
+       * aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
+       (aarch64_ins_sve_addr_ri_s6xvl): Likewise.
+       (aarch64_ins_sve_addr_ri_s9xvl): Likewise.
+       * aarch64-asm-2.c: Regenerate.
+       * aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
+       (ext_sve_addr_ri_s9xvl): New extractors.
+       * aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
+       (aarch64_ext_sve_addr_ri_s4xvl): Likewise.
+       (aarch64_ext_sve_addr_ri_s6xvl): Likewise.
+       (aarch64_ext_sve_addr_ri_s9xvl): Likewise.
+       * aarch64-dis-2.c: Regenerate.
+
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
index 47a414c5a200a0533291c92379c78df91545ee16..da590cab8d6583425eb615eb6fe28e1677bfa6d5 100644 (file)
@@ -480,12 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
-    case 123:
-    case 124:
-    case 125:
-    case 126:
-    case 127:
-    case 128:
     case 129:
     case 130:
     case 131:
@@ -494,7 +488,13 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 134:
     case 135:
     case 136:
+    case 137:
+    case 138:
     case 139:
+    case 140:
+    case 141:
+    case 142:
+    case 145:
       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 120:
-    case 122:
+    case 126:
+    case 128:
       return aarch64_ins_imm (self, info, code, inst);
     case 38:
     case 39:
@@ -587,46 +587,55 @@ aarch64_insert_operand (const aarch64_operand *self,
     case 90:
     case 91:
     case 92:
-      return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
+      return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst);
     case 93:
+      return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst);
     case 94:
+      return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst);
     case 95:
     case 96:
     case 97:
     case 98:
+      return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
     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:
     case 107:
     case 108:
     case 109:
     case 110:
+      return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
     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);
+      return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
     case 119:
-      return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst);
+    case 120:
     case 121:
+    case 122:
+      return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
+    case 123:
+      return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
+    case 124:
+      return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
+    case 125:
+      return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst);
+    case 127:
       return aarch64_ins_sve_scale (self, info, code, inst);
-    case 137:
+    case 143:
       return aarch64_ins_sve_index (self, info, code, inst);
-    case 138:
-    case 140:
+    case 144:
+    case 146:
       return aarch64_ins_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
index 0d3b2c770e84c824ef4ae2f03ae38375c636f7b4..944a9eba5415bdab4311a710c5f6f96fec67de06 100644 (file)
@@ -745,6 +745,56 @@ aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+/* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
+   where <simm4> is a 4-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm4> is encoded in the SVE_imm4 field.  */
+const char *
+aarch64_ins_sve_addr_ri_s4xvl (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_imm4, code, info->addr.offset.imm / factor, 0);
+  return NULL;
+}
+
+/* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
+   where <simm6> is a 6-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm6> is encoded in the SVE_imm6 field.  */
+const char *
+aarch64_ins_sve_addr_ri_s6xvl (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 [<base>, #<simm9>*<factor>, MUL VL],
+   where <simm9> is a 9-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm9> is encoded in the concatenation of the SVE_imm6
+   and imm3 fields, with imm3 being the less-significant part.  */
+const char *
+aarch64_ins_sve_addr_ri_s9xvl (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_fields (code, info->addr.offset.imm / factor, 0,
+                2, FLD_imm3, FLD_SVE_imm6);
+  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.  */
index b81cfa16d567461c44fb33c142acff7c54d7d5ed..5e13de0483163bb9c1bec302150ee560dddee0e2 100644 (file)
@@ -69,6 +69,9 @@ 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_s4xvl);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_s6xvl);
+AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_s9xvl);
 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);
index 3dd714f4f650e7be63d505787c87b8de373344db..48d6ce7fefd2ee11ec92c520e259adf6c9a7b7cb 100644 (file)
@@ -10426,12 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 27:
     case 35:
     case 36:
-    case 123:
-    case 124:
-    case 125:
-    case 126:
-    case 127:
-    case 128:
     case 129:
     case 130:
     case 131:
@@ -10440,7 +10434,13 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 134:
     case 135:
     case 136:
+    case 137:
+    case 138:
     case 139:
+    case 140:
+    case 141:
+    case 142:
+    case 145:
       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 120:
-    case 122:
+    case 126:
+    case 128:
       return aarch64_ext_imm (self, info, code, inst);
     case 38:
     case 39:
@@ -10540,46 +10540,55 @@ aarch64_extract_operand (const aarch64_operand *self,
     case 90:
     case 91:
     case 92:
-      return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
+      return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst);
     case 93:
+      return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst);
     case 94:
+      return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst);
     case 95:
     case 96:
     case 97:
     case 98:
+      return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
     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:
     case 107:
     case 108:
     case 109:
     case 110:
+      return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
     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);
+      return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
     case 119:
-      return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst);
+    case 120:
     case 121:
+    case 122:
+      return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
+    case 123:
+      return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
+    case 124:
+      return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
+    case 125:
+      return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst);
+    case 127:
       return aarch64_ext_sve_scale (self, info, code, inst);
-    case 137:
+    case 143:
       return aarch64_ext_sve_index (self, info, code, inst);
-    case 138:
-    case 140:
+    case 144:
+    case 146:
       return aarch64_ext_sve_reglist (self, info, code, inst);
     default: assert (0); abort ();
     }
index ed77b4df978ef19752691c98af993c000f25c128..ba6befdb55a4912a45e49a74fbfa5b2eedc2cdfe 100644 (file)
@@ -1186,6 +1186,78 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return 1;
 }
 
+/* Decode an SVE address [<base>, #<offset>*<factor>, MUL VL],
+   where <offset> is given by the OFFSET parameter and where <factor> is
+   1 plus SELF's operand-dependent value.  fields[0] specifies the field
+   that holds <base>.  */
+static int
+aarch64_ext_sve_addr_reg_mul_vl (const aarch64_operand *self,
+                                aarch64_opnd_info *info, aarch64_insn code,
+                                int64_t offset)
+{
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  info->addr.offset.imm = offset * (1 + get_operand_specific_data (self));
+  info->addr.offset.is_reg = FALSE;
+  info->addr.writeback = FALSE;
+  info->addr.preind = TRUE;
+  if (offset != 0)
+    info->shifter.kind = AARCH64_MOD_MUL_VL;
+  info->shifter.amount = 1;
+  info->shifter.operator_present = (info->addr.offset.imm != 0);
+  info->shifter.amount_present = FALSE;
+  return 1;
+}
+
+/* Decode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
+   where <simm4> is a 4-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm4> is encoded in the SVE_imm4 field.  */
+int
+aarch64_ext_sve_addr_ri_s4xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info, aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_field (FLD_SVE_imm4, code, 0);
+  offset = ((offset + 8) & 15) - 8;
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
+/* Decode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
+   where <simm6> is a 6-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm6> is encoded in the SVE_imm6 field.  */
+int
+aarch64_ext_sve_addr_ri_s6xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info, aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_field (FLD_SVE_imm6, code, 0);
+  offset = (((offset + 32) & 63) - 32);
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
+/* Decode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
+   where <simm9> is a 9-bit signed value and where <factor> is 1 plus
+   SELF's operand-dependent value.  fields[0] specifies the field that
+   holds <base>.  <simm9> is encoded in the concatenation of the SVE_imm6
+   and imm3 fields, with imm3 being the less-significant part.  */
+int
+aarch64_ext_sve_addr_ri_s9xvl (const aarch64_operand *self,
+                              aarch64_opnd_info *info,
+                              aarch64_insn code,
+                              const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  offset = extract_fields (code, 0, 2, FLD_SVE_imm6, FLD_imm3);
+  offset = (((offset + 256) & 511) - 256);
+  return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
+}
+
 /* Decode an SVE address [<base>, #<offset> << <shift>], where <offset>
    is given by the OFFSET parameter and where <shift> is SELF's operand-
    dependent value.  fields[0] specifies the base register field <base>.  */
index 0ce2d8930d052370671af914ab740b3d89f7aea9..5619877be540bbc4f49e23c16d893eede7385ed5 100644 (file)
@@ -91,6 +91,9 @@ 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_s4xvl);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_s6xvl);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_s9xvl);
 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);
index ed2b70b9093eadeea800eff09587bf9174593549..a72f577ac77849f77b2dc8a81c57bb210b4f51c1 100644 (file)
@@ -113,6 +113,12 @@ 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_S4xVL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 4-bit signed offset, multiplied by VL"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_S4x2xVL", 1 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 4-bit signed offset, multiplied by 2*VL"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_S4x3xVL", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 4-bit signed offset, multiplied by 3*VL"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_S4x4xVL", 3 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 4-bit signed offset, multiplied by 4*VL"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_S6xVL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 6-bit signed offset, multiplied by VL"},
+  {AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_RI_S9xVL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an address with a 9-bit signed offset, multiplied by VL"},
   {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"},
index 6617e28f2ef11c8a06e5ef66770f5ced5803ca2b..d0959b5b886a4f4621c7124464556bdc88e35cdf 100644 (file)
@@ -365,6 +365,7 @@ const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
     {"sxtw", 0x6},
     {"sxtx", 0x7},
     {"mul", 0x0},
+    {"mul vl", 0x0},
     {NULL, 0},
 };
 
@@ -486,10 +487,11 @@ value_in_range_p (int64_t value, int low, int high)
   return (value >= low && value <= high) ? 1 : 0;
 }
 
+/* Return true if VALUE is a multiple of ALIGN.  */
 static inline int
 value_aligned_p (int64_t value, int align)
 {
-  return ((value & (align - 1)) == 0) ? 1 : 0;
+  return (value % align) == 0;
 }
 
 /* A signed value fits in a field.  */
@@ -1666,6 +1668,49 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
+       case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
+         min_value = -8;
+         max_value = 7;
+       sve_imm_offset_vl:
+         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->addr.offset.imm != 0 && !opnd->shifter.operator_present)
+             || (opnd->shifter.operator_present
+                 && opnd->shifter.kind != AARCH64_MOD_MUL_VL))
+           {
+             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_RI_S6xVL:
+         min_value = -32;
+         max_value = 31;
+         goto sve_imm_offset_vl;
+
+       case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
+         min_value = -256;
+         max_value = 255;
+         goto sve_imm_offset_vl;
+
        case AARCH64_OPND_SVE_ADDR_RI_U6:
        case AARCH64_OPND_SVE_ADDR_RI_U6x2:
        case AARCH64_OPND_SVE_ADDR_RI_U6x4:
@@ -2645,7 +2690,13 @@ print_immediate_offset_address (char *buf, size_t size,
     }
   else
     {
-      if (opnd->addr.offset.imm)
+      if (opnd->shifter.operator_present)
+       {
+         assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
+         snprintf (buf, size, "[%s,#%d,mul vl]",
+                   base, opnd->addr.offset.imm);
+       }
+      else if (opnd->addr.offset.imm)
        snprintf (buf, size, "[%s,#%d]", base, opnd->addr.offset.imm);
       else
        snprintf (buf, size, "[%s]", base);
@@ -3114,6 +3165,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_ADDR_SIMM7:
     case AARCH64_OPND_ADDR_SIMM9:
     case AARCH64_OPND_ADDR_SIMM9_2:
+    case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
+    case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
     case AARCH64_OPND_SVE_ADDR_RI_U6:
     case AARCH64_OPND_SVE_ADDR_RI_U6x2:
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
index aba4b2d2d36e61a66ab89b6d4e5eccd9b3327e6a..986cef6fe31a8da0f2d87b04abe04cfb9835537a 100644 (file)
@@ -2820,6 +2820,24 @@ struct aarch64_opcode aarch64_opcode_table[] =
       "a prefetch operation specifier")                                        \
     Y(SYSTEM, hint, "BARRIER_PSB", 0, F (),                            \
       "the PSB option name CSYNC")                                     \
+    Y(ADDRESS, sve_addr_ri_s4xvl, "SVE_ADDR_RI_S4xVL",                 \
+      0 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 4-bit signed offset, multiplied by VL")       \
+    Y(ADDRESS, sve_addr_ri_s4xvl, "SVE_ADDR_RI_S4x2xVL",               \
+      1 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 4-bit signed offset, multiplied by 2*VL")     \
+    Y(ADDRESS, sve_addr_ri_s4xvl, "SVE_ADDR_RI_S4x3xVL",               \
+      2 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 4-bit signed offset, multiplied by 3*VL")     \
+    Y(ADDRESS, sve_addr_ri_s4xvl, "SVE_ADDR_RI_S4x4xVL",               \
+      3 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 4-bit signed offset, multiplied by 4*VL")     \
+    Y(ADDRESS, sve_addr_ri_s6xvl, "SVE_ADDR_RI_S6xVL",                 \
+      0 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 6-bit signed offset, multiplied by VL")       \
+    Y(ADDRESS, sve_addr_ri_s9xvl, "SVE_ADDR_RI_S9xVL",                 \
+      0 << OPD_F_OD_LSB, F(FLD_Rn),                                    \
+      "an address with a 9-bit signed offset, multiplied by VL")       \
     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,  \