Update year range in copyright notice of all files.
[external/binutils.git] / opcodes / aarch64-opc.c
index adc34e2..eea76c8 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-opc.c -- AArch64 opcode support.
-   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of the GNU opcodes library.
@@ -253,6 +253,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.  */
@@ -308,7 +309,10 @@ const aarch64_field fields[] =
     {  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.  */
 };
 
 enum aarch64_operand_class
@@ -707,6 +711,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},
@@ -1156,10 +1161,15 @@ build_immediate_table (void)
            switch (log_e)
              {
              case 1: imm = (imm <<  2) | imm;
+               /* Fall through.  */
              case 2: imm = (imm <<  4) | imm;
+               /* Fall through.  */
              case 3: imm = (imm <<  8) | imm;
+               /* Fall through.  */
              case 4: imm = (imm << 16) | imm;
+               /* Fall through.  */
              case 5: imm = (imm << 32) | imm;
+               /* Fall through.  */
              case 6: break;
              default: abort ();
              }
@@ -1523,6 +1533,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:
@@ -1579,6 +1597,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);
@@ -1969,7 +2001,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                {
                case OP_MOV_IMM_WIDEN:
                  imm = ~imm;
-                 /* Fall through...  */
+                 /* Fall through.  */
                case OP_MOV_IMM_WIDE:
                  if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
                    {
@@ -2069,6 +2101,28 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
            }
          break;
 
+       case AARCH64_OPND_IMM_ROT1:
+       case AARCH64_OPND_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:
+         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);
@@ -2365,16 +2419,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)
        {
@@ -2408,7 +2452,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))
        {
@@ -2965,11 +3017,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       /* 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
         generic optional-ness information.  */
-      if (opnd->type == AARCH64_OPND_Rt_SYS && !opnd->present)
-       break;
+      if (opnd->type == AARCH64_OPND_Rt_SYS)
+       {
+         if (!opnd->present)
+           break;
+       }
       /* Omit the operand, e.g. RET.  */
-      if (optional_operand_p (opcode, idx)
-         && opnd->reg.regno == get_optional_operand_default_value (opcode))
+      else if (optional_operand_p (opcode, idx)
+              && (opnd->reg.regno
+                  == get_optional_operand_default_value (opcode)))
        break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
              || opnd->qualifier == AARCH64_OPND_QLF_X);
@@ -2980,6 +3036,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
@@ -3121,9 +3178,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
                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:
@@ -3152,6 +3209,9 @@ 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:
       snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
       break;
 
@@ -3398,6 +3458,7 @@ 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_SVE_ADDR_RI_S4xVL:
     case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
     case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
@@ -3641,6 +3702,16 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "tcr_el3",          CPENC(3,6,C2,C0,2),    0 },
   { "tcr_el12",                CPENC (3, 5, C2, C0, 2), F_ARCHEXT },
   { "vtcr_el2",         CPENC(3,4,C2,C1,2),    0 },
+  { "apiakeylo_el1",   CPENC (3, 0, C2, C1, 0), F_ARCHEXT },
+  { "apiakeyhi_el1",   CPENC (3, 0, C2, C1, 1), F_ARCHEXT },
+  { "apibkeylo_el1",   CPENC (3, 0, C2, C1, 2), F_ARCHEXT },
+  { "apibkeyhi_el1",   CPENC (3, 0, C2, C1, 3), F_ARCHEXT },
+  { "apdakeylo_el1",   CPENC (3, 0, C2, C2, 0), F_ARCHEXT },
+  { "apdakeyhi_el1",   CPENC (3, 0, C2, C2, 1), F_ARCHEXT },
+  { "apdbkeylo_el1",   CPENC (3, 0, C2, C2, 2), F_ARCHEXT },
+  { "apdbkeyhi_el1",   CPENC (3, 0, C2, C2, 3), F_ARCHEXT },
+  { "apgakeylo_el1",   CPENC (3, 0, C2, C3, 0), F_ARCHEXT },
+  { "apgakeyhi_el1",   CPENC (3, 0, C2, C3, 1), F_ARCHEXT },
   { "afsr0_el1",        CPENC(3,0,C5,C1,0),    0 },
   { "afsr1_el1",        CPENC(3,0,C5,C1,1),    0 },
   { "afsr0_el2",        CPENC(3,4,C5,C1,0),    0 },
@@ -4017,6 +4088,20 @@ aarch64_sys_reg_supported_p (const aarch64_feature_set features,
       && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PROFILE))
     return FALSE;
 
+  /* ARMv8.3 Pointer authentication keys.  */
+  if ((reg->value == CPENC (3, 0, C2, C1, 0)
+       || reg->value == CPENC (3, 0, C2, C1, 1)
+       || reg->value == CPENC (3, 0, C2, C1, 2)
+       || reg->value == CPENC (3, 0, C2, C1, 3)
+       || reg->value == CPENC (3, 0, C2, C2, 0)
+       || reg->value == CPENC (3, 0, C2, C2, 1)
+       || reg->value == CPENC (3, 0, C2, C2, 2)
+       || reg->value == CPENC (3, 0, C2, C2, 3)
+       || reg->value == CPENC (3, 0, C2, C3, 0)
+       || reg->value == CPENC (3, 0, C2, C3, 1))
+      && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_3))
+    return FALSE;
+
   return TRUE;
 }