Modify AArch64 Assembly and disassembly functions to be able to fail and report why.
[deliverable/binutils-gdb.git] / opcodes / aarch64-opc.c
index 8e89b5b22ccb332e730560ae7d938dc6af761c39..c688b7c7745b8d7f9b6f74ee74ec3e9887a26364 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-opc.c -- AArch64 opcode support.
-   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of the GNU opcodes library.
@@ -240,7 +240,9 @@ const aarch64_field fields[] =
     { 22,  2 },        /* type: floating point type field in fp data inst.  */
     { 30,  2 },        /* ldst_size: size field in ld/st reg offset inst.  */
     { 10,  6 },        /* imm6: in add/sub reg shifted instructions.  */
+    { 15,  6 },        /* imm6_2: in rmif instructions.  */
     { 11,  4 },        /* imm4: in advsimd ext and advsimd ins instructions.  */
+    {  0,  4 },        /* imm4_2: in rmif instructions.  */
     { 16,  5 },        /* imm5: in conditional compare (immediate) instructions.  */
     { 15,  7 },        /* imm7: in load/store pair pre/post index instructions.  */
     { 13,  8 },        /* imm8: in floating-point scalar move immediate inst.  */
@@ -253,6 +255,7 @@ const aarch64_field fields[] =
     { 16,  6 },        /* immr: in bitfield and logical immediate instructions.  */
     { 16,  3 },        /* immb: in advsimd shift by immediate instructions.  */
     { 19,  4 },        /* immh: in advsimd shift by immediate instructions.  */
+    { 22,  1 },        /* S: in LDRAA and LDRAB instructions.  */
     { 22,  1 },        /* N: in logical (immediate) instructions.  */
     { 11,  1 },        /* index: in ld/st inst deciding the pre/post-index.  */
     { 24,  1 },        /* index2: in ld/st pair inst deciding the pre/post-index.  */
@@ -289,6 +292,7 @@ const aarch64_field fields[] =
     {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
     {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
     {  5,  1 }, /* SVE_i1: single-bit immediate.  */
+    { 22,  1 }, /* SVE_i3h: high bit of 3-bit immediate.  */
     { 16,  3 }, /* SVE_imm3: 3-bit immediate field.  */
     { 16,  4 }, /* SVE_imm4: 4-bit immediate field.  */
     {  5,  5 }, /* SVE_imm5: 5-bit immediate field.  */
@@ -302,13 +306,19 @@ const aarch64_field fields[] =
     { 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].  */
+    { 16,  1 }, /* SVE_rot1: 1-bit rotation amount.  */
+    { 10,  2 }, /* SVE_rot2: 2-bit rotation amount.  */
     { 22,  1 }, /* SVE_sz: 1-bit element size select.  */
     { 16,  4 }, /* SVE_tsz: triangular size select.  */
     { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
     {  8,  2 }, /* SVE_tszl_8: triangular size select low, bits [9,8].  */
     { 19,  2 }, /* SVE_tszl_19: triangular size select low, bits [20,19].  */
     { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
-    { 22,  1 }  /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
+    { 22,  1 }, /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
+    { 11,  2 }, /* rotate1: FCMLA immediate rotate.  */
+    { 13,  2 }, /* rotate2: Indexed element FCMLA immediate rotate.  */
+    { 12,  1 }, /* rotate3: FCADD immediate rotate.  */
+    { 12,  2 }, /* SM3: Indexed element SM3 2 bits index immediate.  */
 };
 
 enum aarch64_operand_class
@@ -688,7 +698,9 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
   {4, 1, 0x2, "s", OQK_OPD_VARIANT},
   {8, 1, 0x3, "d", OQK_OPD_VARIANT},
   {16, 1, 0x4, "q", OQK_OPD_VARIANT},
+  {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
 
+  {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
   {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
   {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
   {2, 2, 0x0, "2h", OQK_OPD_VARIANT},
@@ -707,6 +719,7 @@ struct operand_qualifier_data aarch64_opnd_qualifiers[] =
      First 3 fields:
      Lower bound, higher bound, unused.  */
 
+  {0, 15, 0, "CR",       OQK_VALUE_IN_RANGE},
   {0,  7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
   {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
   {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
@@ -1196,10 +1209,10 @@ aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding)
   uint64_t upper;
   int i;
 
-  DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
-              value, is32);
+  DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), esize: %d", value,
+              value, esize);
 
-  if (initialized == FALSE)
+  if (!initialized)
     {
       build_immediate_table ();
       initialized = TRUE;
@@ -1469,6 +1482,29 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
     case AARCH64_OPND_CLASS_SVE_REG:
       switch (type)
        {
+       case AARCH64_OPND_SVE_Zm3_INDEX:
+       case AARCH64_OPND_SVE_Zm3_22_INDEX:
+       case AARCH64_OPND_SVE_Zm4_INDEX:
+         size = get_operand_fields_width (get_operand_from_code (type));
+         shift = get_operand_specific_data (&aarch64_operands[type]);
+         mask = (1 << shift) - 1;
+         if (opnd->reg.regno > mask)
+           {
+             assert (mask == 7 || mask == 15);
+             set_other_error (mismatch_detail, idx,
+                              mask == 15
+                              ? _("z0-z15 expected")
+                              : _("z0-z7 expected"));
+             return 0;
+           }
+         mask = (1 << (size - shift)) - 1;
+         if (!value_in_range_p (opnd->reglane.index, 0, mask))
+           {
+             set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, mask);
+             return 0;
+           }
+         break;
+
        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))
@@ -1528,6 +1564,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
              return 0;
            }
          break;
+       case ldst_imm10:
+         if (opnd->addr.writeback == 1 && opnd->addr.preind != 1)
+           {
+             set_syntax_error (mismatch_detail, idx,
+                               _("unexpected address writeback"));
+             return 0;
+           }
+         break;
        case ldst_imm9:
        case ldstpair_indexed:
        case asisdlsep:
@@ -1563,6 +1607,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
              return 0;
            }
          break;
+       case AARCH64_OPND_ADDR_OFFSET:
        case AARCH64_OPND_ADDR_SIMM9:
          /* Unscaled signed 9 bits immediate offset.  */
          if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
@@ -1584,6 +1629,20 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                           _("negative or unaligned offset expected"));
          return 0;
 
+       case AARCH64_OPND_ADDR_SIMM10:
+         /* Scaled signed 10 bits immediate offset.  */
+         if (!value_in_range_p (opnd->addr.offset.imm, -4096, 4088))
+           {
+             set_offset_out_of_range_error (mismatch_detail, idx, -4096, 4088);
+             return 0;
+           }
+         if (!value_aligned_p (opnd->addr.offset.imm, 8))
+           {
+             set_unaligned_error (mismatch_detail, idx, 8);
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_SIMD_ADDR_POST:
          /* AdvSIMD load/store multiple structures, post-index.  */
          assert (idx == 1);
@@ -1771,6 +1830,12 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_SVE_ADDR_RI_S4x16:
+         min_value = -8;
+         max_value = 7;
+         goto sve_imm_offset;
+
+       case AARCH64_OPND_SVE_ADDR_R:
        case AARCH64_OPND_SVE_ADDR_RR:
        case AARCH64_OPND_SVE_ADDR_RR_LSL1:
        case AARCH64_OPND_SVE_ADDR_RR_LSL2:
@@ -2055,7 +2120,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            uint64_t uimm = opnd->imm.value;
            if (opcode->op == OP_BIC)
              uimm = ~uimm;
-           if (aarch64_logical_immediate_p (uimm, esize, NULL) == FALSE)
+           if (!aarch64_logical_immediate_p (uimm, esize, NULL))
              {
                set_other_error (mismatch_detail, idx,
                                 _("immediate out of range"));
@@ -2074,6 +2139,30 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_IMM_ROT1:
+       case AARCH64_OPND_IMM_ROT2:
+       case AARCH64_OPND_SVE_IMM_ROT2:
+         if (opnd->imm.value != 0
+             && opnd->imm.value != 90
+             && opnd->imm.value != 180
+             && opnd->imm.value != 270)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("rotate expected to be 0, 90, 180 or 270"));
+             return 0;
+           }
+         break;
+
+       case AARCH64_OPND_IMM_ROT3:
+       case AARCH64_OPND_SVE_IMM_ROT1:
+         if (opnd->imm.value != 90 && opnd->imm.value != 270)
+           {
+             set_other_error (mismatch_detail, idx,
+                              _("rotate expected to be 90 or 270"));
+             return 0;
+           }
+         break;
+
        case AARCH64_OPND_SHLL_IMM:
          assert (idx == 2);
          size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
@@ -2370,16 +2459,6 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        }
       break;
 
-    case AARCH64_OPND_CLASS_CP_REG:
-      /* Cn or Cm: 4-bit opcode field named for historical reasons.
-        valid range: C0 - C15.  */
-      if (opnd->reg.regno > 15)
-       {
-         set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
-         return 0;
-       }
-      break;
-
     case AARCH64_OPND_CLASS_SYSTEM:
       switch (type)
        {
@@ -2389,7 +2468,8 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
             MSR PAN, #uimm4
             The immediate must be #0 or #1.  */
          if ((opnd->pstatefield == 0x03        /* UAO.  */
-              || opnd->pstatefield == 0x04)    /* PAN.  */
+              || opnd->pstatefield == 0x04     /* PAN.  */
+              || opnd->pstatefield == 0x1a)    /* DIT.  */
              && opnds[1].imm.value > 1)
            {
              set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
@@ -2413,7 +2493,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
     case AARCH64_OPND_CLASS_SIMD_ELEMENT:
       /* Get the upper bound for the element index.  */
-      num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+      if (opcode->op == OP_FCMLA_ELEM)
+       /* FCMLA index range depends on the vector size of other operands
+          and is halfed because complex numbers take two elements.  */
+       num = aarch64_get_qualifier_nelem (opnds[0].qualifier)
+             * aarch64_get_qualifier_esize (opnds[0].qualifier) / 2;
+      else
+       num = 16;
+      num = num / aarch64_get_qualifier_esize (qualifier) - 1;
+
       /* Index out-of-range.  */
       if (!value_in_range_p (opnd->reglane.index, 0, num))
        {
@@ -2441,7 +2529,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       switch (type)
        {
        case AARCH64_OPND_Rm_EXT:
-         if (aarch64_extend_operator_p (opnd->shifter.kind) == FALSE
+         if (!aarch64_extend_operator_p (opnd->shifter.kind)
              && opnd->shifter.kind != AARCH64_MOD_LSL)
            {
              set_other_error (mismatch_detail, idx,
@@ -2493,7 +2581,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
        case AARCH64_OPND_Rm_SFT:
          /* ROR is not available to the shifted register operand in
             arithmetic instructions.  */
-         if (aarch64_shift_operator_p (opnd->shifter.kind) == FALSE)
+         if (!aarch64_shift_operator_p (opnd->shifter.kind))
            {
              set_other_error (mismatch_detail, idx,
                               _("shift operator expected"));
@@ -2767,7 +2855,7 @@ typedef union
 static uint64_t
 expand_fp_imm (int size, uint32_t imm8)
 {
-  uint64_t imm;
+  uint64_t imm = 0;
   uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
 
   imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7>   */
@@ -2818,7 +2906,8 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
-    snprintf (tb, 8, "[%" PRIi64 "]", opnd->reglist.index);
+    /* PR 21096: The %100 is to silence a warning about possible truncation.  */
+    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
   else
     tb[0] = '\0';
 
@@ -2918,7 +3007,8 @@ print_register_offset_address (char *buf, size_t size,
     {
       if (print_amount_p)
        snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
-                 opnd->shifter.amount);
+  /* PR 21096: The %100 is to silence a warning about possible truncation.  */
+                 (opnd->shifter.amount % 100));
       else
        snprintf (tb, sizeof (tb), ", %s", shift_name);
     }
@@ -2968,7 +3058,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_PAIRREG:
     case AARCH64_OPND_SVE_Rm:
       /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
-        the <ic_op>, therefore we we use opnd->present to override the
+        the <ic_op>, therefore we use opnd->present to override the
         generic optional-ness information.  */
       if (opnd->type == AARCH64_OPND_Rt_SYS)
        {
@@ -2989,6 +3079,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Rd_SP:
     case AARCH64_OPND_Rn_SP:
     case AARCH64_OPND_SVE_Rn_SP:
+    case AARCH64_OPND_Rm_SP:
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_WSP
              || opnd->qualifier == AARCH64_OPND_QLF_X
@@ -3059,6 +3150,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                opnd->reg.regno);
       break;
 
+    case AARCH64_OPND_Va:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
@@ -3069,6 +3161,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Ed:
     case AARCH64_OPND_En:
     case AARCH64_OPND_Em:
+    case AARCH64_OPND_SM3_IMM2:
       snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
                aarch64_get_qualifier_name (opnd->qualifier),
                opnd->reglane.index);
@@ -3124,19 +3217,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_list (buf, size, opnd, "z");
       break;
 
+    case AARCH64_OPND_SVE_Zm3_INDEX:
+    case AARCH64_OPND_SVE_Zm3_22_INDEX:
+    case AARCH64_OPND_SVE_Zm4_INDEX:
     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);
+    case AARCH64_OPND_CRn:
+    case AARCH64_OPND_CRm:
+      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
       break;
 
     case AARCH64_OPND_IDX:
+    case AARCH64_OPND_MASK:
     case AARCH64_OPND_IMM:
+    case AARCH64_OPND_IMM_2:
     case AARCH64_OPND_WIDTH:
     case AARCH64_OPND_UIMM3_OP1:
     case AARCH64_OPND_UIMM3_OP2:
@@ -3161,6 +3259,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_UIMM7:
     case AARCH64_OPND_SVE_UIMM8:
     case AARCH64_OPND_SVE_UIMM8_53:
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+    case AARCH64_OPND_IMM_ROT3:
+    case AARCH64_OPND_SVE_IMM_ROT1:
+    case AARCH64_OPND_SVE_IMM_ROT2:
       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
       break;
 
@@ -3374,6 +3477,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
+    case AARCH64_OPND_SVE_ADDR_R:
     case AARCH64_OPND_SVE_ADDR_RR:
     case AARCH64_OPND_SVE_ADDR_RR_LSL1:
     case AARCH64_OPND_SVE_ADDR_RR_LSL2:
@@ -3407,6 +3511,9 @@ 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_ADDR_SIMM10:
+    case AARCH64_OPND_ADDR_OFFSET:
+    case AARCH64_OPND_SVE_ADDR_RI_S4x16:
     case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
     case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
     case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
@@ -3449,7 +3556,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_SYSREG:
       for (i = 0; aarch64_sys_regs[i].name; ++i)
-       if (aarch64_sys_regs[i].value == opnd->sysreg
+       if (aarch64_sys_regs[i].value == opnd->sysreg.value
            && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i]))
          break;
       if (aarch64_sys_regs[i].name)
@@ -3457,7 +3564,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       else
        {
          /* Implementation defined system register.  */
-         unsigned int value = opnd->sysreg;
+         unsigned int value = opnd->sysreg.value;
          snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
                    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
                    value & 0x7);
@@ -3616,6 +3723,7 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT }, /* RO */
   { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    0 }, /* RO */
   { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    0 }, /* RO */
+  { "id_aa64zfr0_el1",  CPENC (3, 0, C0, C4, 4), F_ARCHEXT }, /* RO */
   { "clidr_el1",        CPENC(3,1,C0,C0,1),    0 }, /* RO */
   { "csselr_el1",       CPENC(3,2,C0,C0,0),    0 }, /* RO */
   { "vpidr_el2",        CPENC(3,4,C0,C0,0),    0 },
@@ -3637,6 +3745,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "mdcr_el3",         CPENC(3,6,C1,C3,1),    0 },
   { "hstr_el2",         CPENC(3,4,C1,C1,3),    0 },
   { "hacr_el2",         CPENC(3,4,C1,C1,7),    0 },
+  { "zcr_el1",          CPENC (3, 0, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el12",         CPENC (3, 5, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el2",          CPENC (3, 4, C1, C2, 0), F_ARCHEXT },
+  { "zcr_el3",          CPENC (3, 6, C1, C2, 0), F_ARCHEXT },
+  { "zidr_el1",         CPENC (3, 0, C0, C0, 7), F_ARCHEXT },
   { "ttbr0_el1",        CPENC(3,0,C2,C0,0),    0 },
   { "ttbr1_el1",        CPENC(3,0,C2,C0,1),    0 },
   { "ttbr0_el2",        CPENC(3,4,C2,C0,0),    0 },
@@ -3923,6 +4036,18 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "pmevtyper29_el0",   CPENC(3,3,C14,C15,5), 0 },
   { "pmevtyper30_el0",   CPENC(3,3,C14,C15,6), 0 },
   { "pmccfiltr_el0",     CPENC(3,3,C14,C15,7), 0 },
+
+  { "dit",              CPEN_ (3, C2, 5), F_ARCHEXT },
+  { "vstcr_el2",        CPENC(3, 4, C2, C6, 2), F_ARCHEXT },
+  { "vsttbr_el2",       CPENC(3, 4, C2, C6, 0), F_ARCHEXT },
+  { "cnthvs_tval_el2",  CPENC(3, 4, C14, C4, 0), F_ARCHEXT },
+  { "cnthvs_cval_el2",  CPENC(3, 4, C14, C4, 2), F_ARCHEXT },
+  { "cnthvs_ctl_el2",   CPENC(3, 4, C14, C4, 1), F_ARCHEXT },
+  { "cnthps_tval_el2",  CPENC(3, 4, C14, C5, 0), F_ARCHEXT },
+  { "cnthps_cval_el2",  CPENC(3, 4, C14, C5, 2), F_ARCHEXT },
+  { "cnthps_ctl_el2",   CPENC(3, 4, C14, C5, 1), F_ARCHEXT },
+  { "sder32_el2",       CPENC(3, 4, C1, C3, 1), F_ARCHEXT },
+  { "vncr_el2",                 CPENC(3, 4, C2, C2, 0), F_ARCHEXT },
   { 0,          CPENC(0,0,0,0,0),      0 },
 };
 
@@ -4050,9 +4175,97 @@ aarch64_sys_reg_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_3))
     return FALSE;
 
+  /* SVE.  */
+  if ((reg->value == CPENC (3, 0, C0, C4, 4)
+       || reg->value == CPENC (3, 0, C1, C2, 0)
+       || reg->value == CPENC (3, 4, C1, C2, 0)
+       || reg->value == CPENC (3, 6, C1, C2, 0)
+       || reg->value == CPENC (3, 5, C1, C2, 0)
+       || reg->value == CPENC (3, 0, C0, C0, 7))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SVE))
+    return FALSE;
+
+  /* ARMv8.4 features.  */
+
+  /* PSTATE.DIT.  */
+  if (reg->value == CPEN_ (3, C2, 5)
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* Virtualization extensions.  */
+  if ((reg->value == CPENC(3, 4, C2, C6, 2)
+       || reg->value == CPENC(3, 4, C2, C6, 0)
+       || reg->value == CPENC(3, 4, C14, C4, 0)
+       || reg->value == CPENC(3, 4, C14, C4, 2)
+       || reg->value == CPENC(3, 4, C14, C4, 1)
+       || reg->value == CPENC(3, 4, C14, C5, 0)
+       || reg->value == CPENC(3, 4, C14, C5, 2)
+       || reg->value == CPENC(3, 4, C14, C5, 1)
+       || reg->value == CPENC(3, 4, C1, C3, 1)
+       || reg->value == CPENC(3, 4, C2, C2, 0))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
+  /* ARMv8.4 TLB instructions.  */
+  if ((reg->value == CPENS (0, C8, C1, 0)
+       || reg->value == CPENS (0, C8, C1, 1)
+       || reg->value == CPENS (0, C8, C1, 2)
+       || reg->value == CPENS (0, C8, C1, 3)
+       || reg->value == CPENS (0, C8, C1, 5)
+       || reg->value == CPENS (0, C8, C1, 7)
+       || reg->value == CPENS (4, C8, C4, 0)
+       || reg->value == CPENS (4, C8, C4, 4)
+       || reg->value == CPENS (4, C8, C1, 1)
+       || reg->value == CPENS (4, C8, C1, 5)
+       || reg->value == CPENS (4, C8, C1, 6)
+       || reg->value == CPENS (6, C8, C1, 1)
+       || reg->value == CPENS (6, C8, C1, 5)
+       || reg->value == CPENS (4, C8, C1, 0)
+       || reg->value == CPENS (4, C8, C1, 4)
+       || reg->value == CPENS (6, C8, C1, 0)
+       || reg->value == CPENS (0, C8, C6, 1)
+       || reg->value == CPENS (0, C8, C6, 3)
+       || reg->value == CPENS (0, C8, C6, 5)
+       || reg->value == CPENS (0, C8, C6, 7)
+       || reg->value == CPENS (0, C8, C2, 1)
+       || reg->value == CPENS (0, C8, C2, 3)
+       || reg->value == CPENS (0, C8, C2, 5)
+       || reg->value == CPENS (0, C8, C2, 7)
+       || reg->value == CPENS (0, C8, C5, 1)
+       || reg->value == CPENS (0, C8, C5, 3)
+       || reg->value == CPENS (0, C8, C5, 5)
+       || reg->value == CPENS (0, C8, C5, 7)
+       || reg->value == CPENS (4, C8, C0, 2)
+       || reg->value == CPENS (4, C8, C0, 6)
+       || reg->value == CPENS (4, C8, C4, 2)
+       || reg->value == CPENS (4, C8, C4, 6)
+       || reg->value == CPENS (4, C8, C4, 3)
+       || reg->value == CPENS (4, C8, C4, 7)
+       || reg->value == CPENS (4, C8, C6, 1)
+       || reg->value == CPENS (4, C8, C6, 5)
+       || reg->value == CPENS (4, C8, C2, 1)
+       || reg->value == CPENS (4, C8, C2, 5)
+       || reg->value == CPENS (4, C8, C5, 1)
+       || reg->value == CPENS (4, C8, C5, 5)
+       || reg->value == CPENS (6, C8, C6, 1)
+       || reg->value == CPENS (6, C8, C6, 5)
+       || reg->value == CPENS (6, C8, C2, 1)
+       || reg->value == CPENS (6, C8, C2, 5)
+       || reg->value == CPENS (6, C8, C5, 1)
+       || reg->value == CPENS (6, C8, C5, 5))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
   return TRUE;
 }
 
+/* The CPENC below is fairly misleading, the fields
+   here are not in CPENC form. They are in op2op1 form. The fields are encoded
+   by ins_pstatefield, which just shifts the value by the width of the fields
+   in a loop. So if you CPENC them only the first value will be set, the rest
+   are masked out to 0. As an example. op2 = 3, op1=2. CPENC would produce a
+   value of 0b110000000001000000 (0x30040) while what you want is
+   0b011010 (0x1a).  */
 const aarch64_sys_reg aarch64_pstatefields [] =
 {
   { "spsel",            0x05,  0 },
@@ -4060,6 +4273,7 @@ const aarch64_sys_reg aarch64_pstatefields [] =
   { "daifclr",          0x1f,  0 },
   { "pan",             0x04,   F_ARCHEXT },
   { "uao",             0x03,   F_ARCHEXT },
+  { "dit",             0x1a,   F_ARCHEXT },
   { 0,          CPENC(0,0,0,0,0), 0 },
 };
 
@@ -4080,6 +4294,11 @@ aarch64_pstatefield_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
     return FALSE;
 
+  /* DIT.  Values are from aarch64_pstatefields.  */
+  if (reg->value == 0x1a
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
+    return FALSE;
+
   return TRUE;
 }
 
@@ -4158,6 +4377,55 @@ const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
     { "vale2",     CPENS (4, C8, C7, 5), F_HASXT },
     { "vale3",     CPENS (6, C8, C7, 5), F_HASXT },
     { "vaale1",    CPENS (0, C8, C7, 7), F_HASXT },
+
+    { "vmalle1os",    CPENS (0, C8, C1, 0), F_ARCHEXT },
+    { "vae1os",       CPENS (0, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "aside1os",     CPENS (0, C8, C1, 2), F_HASXT | F_ARCHEXT },
+    { "vaae1os",      CPENS (0, C8, C1, 3), F_HASXT | F_ARCHEXT },
+    { "vale1os",      CPENS (0, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "vaale1os",     CPENS (0, C8, C1, 7), F_HASXT | F_ARCHEXT },
+    { "ipas2e1os",    CPENS (4, C8, C4, 0), F_HASXT | F_ARCHEXT },
+    { "ipas2le1os",   CPENS (4, C8, C4, 4), F_HASXT | F_ARCHEXT },
+    { "vae2os",       CPENS (4, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "vale2os",      CPENS (4, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "vmalls12e1os", CPENS (4, C8, C1, 6), F_ARCHEXT },
+    { "vae3os",       CPENS (6, C8, C1, 1), F_HASXT | F_ARCHEXT },
+    { "vale3os",      CPENS (6, C8, C1, 5), F_HASXT | F_ARCHEXT },
+    { "alle2os",      CPENS (4, C8, C1, 0), F_ARCHEXT },
+    { "alle1os",      CPENS (4, C8, C1, 4), F_ARCHEXT },
+    { "alle3os",      CPENS (6, C8, C1, 0), F_ARCHEXT },
+
+    { "rvae1",      CPENS (0, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1",     CPENS (0, C8, C6, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1",     CPENS (0, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1",    CPENS (0, C8, C6, 7), F_HASXT | F_ARCHEXT },
+    { "rvae1is",    CPENS (0, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1is",   CPENS (0, C8, C2, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1is",   CPENS (0, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1is",  CPENS (0, C8, C2, 7), F_HASXT | F_ARCHEXT },
+    { "rvae1os",    CPENS (0, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvaae1os",   CPENS (0, C8, C5, 3), F_HASXT | F_ARCHEXT },
+    { "rvale1os",   CPENS (0, C8, C5, 5), F_HASXT | F_ARCHEXT },
+    { "rvaale1os",  CPENS (0, C8, C5, 7), F_HASXT | F_ARCHEXT },
+    { "ripas2e1is", CPENS (4, C8, C0, 2), F_HASXT | F_ARCHEXT },
+    { "ripas2le1is",CPENS (4, C8, C0, 6), F_HASXT | F_ARCHEXT },
+    { "ripas2e1",   CPENS (4, C8, C4, 2), F_HASXT | F_ARCHEXT },
+    { "ripas2le1",  CPENS (4, C8, C4, 6), F_HASXT | F_ARCHEXT },
+    { "ripas2e1os", CPENS (4, C8, C4, 3), F_HASXT | F_ARCHEXT },
+    { "ripas2le1os",CPENS (4, C8, C4, 7), F_HASXT | F_ARCHEXT },
+    { "rvae2",      CPENS (4, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2",     CPENS (4, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvae2is",    CPENS (4, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2is",   CPENS (4, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvae2os",    CPENS (4, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvale2os",   CPENS (4, C8, C5, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3",      CPENS (6, C8, C6, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3",     CPENS (6, C8, C6, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3is",    CPENS (6, C8, C2, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3is",   CPENS (6, C8, C2, 5), F_HASXT | F_ARCHEXT },
+    { "rvae3os",    CPENS (6, C8, C5, 1), F_HASXT | F_ARCHEXT },
+    { "rvale3os",   CPENS (6, C8, C5, 5), F_HASXT | F_ARCHEXT },
+
     { 0,       CPENS(0,0,0,0), 0 }
 };
 
This page took 0.03168 seconds and 4 git commands to generate.