[gas][aarch64] Armv8.6-a option [1/X]
[deliverable/binutils-gdb.git] / gas / config / tc-aarch64.c
index 461c39b104365bc1cc77789a1f787e8da9ee0c92..fb1ec0bcc31116cb320fe2530bdc74995b0bf7dc 100644 (file)
@@ -238,9 +238,6 @@ set_fatal_syntax_error (const char *error)
   set_error (AARCH64_OPDE_FATAL_SYNTAX_ERROR, error);
 }
 \f
-/* Number of littlenums required to hold an extended precision number.  */
-#define MAX_LITTLENUMS 6
-
 /* Return value for certain parsers when the parsing fails; those parsers
    return the information of the parsed result, e.g. register number, on
    success.  */
@@ -449,6 +446,7 @@ get_reg_expected_msg (aarch64_reg_type reg_type)
 
 /* Some well known registers that we refer to directly elsewhere.  */
 #define REG_SP 31
+#define REG_ZR 31
 
 /* Instructions take 4 bytes in the object file.  */
 #define INSN_SIZE      4
@@ -531,7 +529,7 @@ const char EXP_CHARS[] = "eE";
 /* As in 0f12.456  */
 /* or   0d1.2345e12  */
 
-const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+const char FLT_CHARS[] = "rRsSfFdDxXeEpPhH";
 
 /* Prefix character that indicates the start of an immediate value.  */
 #define is_immediate_prefix(C) ((C) == '#')
@@ -1938,6 +1936,28 @@ s_aarch64_elf_cons (int nbytes)
   demand_empty_rest_of_line ();
 }
 
+/* Mark symbol that it follows a variant PCS convention.  */
+
+static void
+s_variant_pcs (int ignored ATTRIBUTE_UNUSED)
+{
+  char *name;
+  char c;
+  symbolS *sym;
+  asymbol *bfdsym;
+  elf_symbol_type *elfsym;
+
+  c = get_symbol_name (&name);
+  if (!*name)
+    as_bad (_("Missing symbol name in directive"));
+  sym = symbol_find_or_make (name);
+  restore_line_pointer (c);
+  demand_empty_rest_of_line ();
+  bfdsym = symbol_get_bfdsym (sym);
+  elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
+  gas_assert (elfsym);
+  elfsym->internal_elf_sym.st_other |= STO_AARCH64_VARIANT_PCS;
+}
 #endif /* OBJ_ELF */
 
 /* Output a 32-bit word, but mark as an instruction.  */
@@ -2084,7 +2104,9 @@ const pseudo_typeS md_pseudo_table[] = {
   {"long", s_aarch64_elf_cons, 4},
   {"xword", s_aarch64_elf_cons, 8},
   {"dword", s_aarch64_elf_cons, 8},
+  {"variant_pcs", s_variant_pcs, 0},
 #endif
+  {"float16", float_cons, 'h'},
   {0, 0, 0}
 };
 \f
@@ -3380,8 +3402,8 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
      [base,Xm,SXTX {#imm}]
      [base,Wm,(S|U)XTW {#imm}]
    Pre-indexed
+     [base]!                    // in ldraa/ldrab exclusive
      [base,#imm]!
-     [base]!                   // in ld/stgv
    Post-indexed
      [base],#imm
      [base],Xm                  // in SIMD ld/st structure
@@ -3394,6 +3416,7 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
      [base,Zm.D,(S|U)XTW {#imm}] // ignores top 32 bits of Zm.D elements
      [Zn.S,#imm]
      [Zn.D,#imm]
+     [Zn.S{, Xm}]
      [Zn.S,Zm.S{,LSL #imm}]      // in ADR
      [Zn.D,Zm.D{,LSL #imm}]      // in ADR
      [Zn.D,Zm.D,(S|U)XTW {#imm}] // in ADR
@@ -3559,6 +3582,7 @@ parse_address_main (char **str, aarch64_opnd_info *operand,
                return FALSE;
            }
          /* We only accept:
+            [base,Xm]  # For vector plus scalar SVE2 indexing.
             [base,Xm{,LSL #imm}]
             [base,Xm,SXTX {#imm}]
             [base,Wm,(S|U)XTW {#imm}]  */
@@ -3572,7 +3596,10 @@ parse_address_main (char **str, aarch64_opnd_info *operand,
                  return FALSE;
                }
              if (aarch64_get_qualifier_esize (*base_qualifier)
-                 != aarch64_get_qualifier_esize (*offset_qualifier))
+                 != aarch64_get_qualifier_esize (*offset_qualifier)
+                 && (operand->type != AARCH64_OPND_SVE_ADDR_ZX
+                     || *base_qualifier != AARCH64_OPND_QLF_S_S
+                     || *offset_qualifier != AARCH64_OPND_QLF_X))
                {
                  set_syntax_error (_("offset has different size from base"));
                  return FALSE;
@@ -3690,20 +3717,43 @@ parse_address_main (char **str, aarch64_opnd_info *operand,
     }
 
   /* If at this point neither .preind nor .postind is set, we have a
-     bare [Rn]{!}; reject [Rn]! except for ld/stgv but accept [Rn]
-     as a shorthand for [Rn,#0].  */
+     bare [Rn]{!}; only accept [Rn]! as a shorthand for [Rn,#0]! for ldraa and
+     ldrab, accept [Rn] as a shorthand for [Rn,#0].
+     For SVE2 vector plus scalar offsets, allow [Zn.<T>] as shorthand for
+     [Zn.<T>, xzr].  */
   if (operand->addr.preind == 0 && operand->addr.postind == 0)
     {
-      if (operand->type != AARCH64_OPND_ADDR_SIMPLE_2 && operand->addr.writeback)
+      if (operand->addr.writeback)
        {
-         /* Reject [Rn]!   */
-         set_syntax_error (_("missing offset in the pre-indexed address"));
-         return FALSE;
+         if (operand->type == AARCH64_OPND_ADDR_SIMM10)
+            {
+              /* Accept [Rn]! as a shorthand for [Rn,#0]!   */
+              operand->addr.offset.is_reg = 0;
+              operand->addr.offset.imm = 0;
+              operand->addr.preind = 1;
+            }
+          else
+           {
+            /* Reject [Rn]!   */
+            set_syntax_error (_("missing offset in the pre-indexed address"));
+            return FALSE;
+          }
+       }
+       else
+       {
+          operand->addr.preind = 1;
+          if (operand->type == AARCH64_OPND_SVE_ADDR_ZX)
+          {
+            operand->addr.offset.is_reg = 1;
+            operand->addr.offset.regno = REG_ZR;
+            *offset_qualifier = AARCH64_OPND_QLF_X;
+          }
+          else
+          {
+            inst.reloc.exp.X_op = O_constant;
+            inst.reloc.exp.X_add_number = 0;
+          }
        }
-
-      operand->addr.preind = 1;
-      inst.reloc.exp.X_op = O_constant;
-      inst.reloc.exp.X_add_number = 0;
     }
 
   *str = p;
@@ -5137,6 +5187,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
     case AARCH64_OPND_Rm:
     case AARCH64_OPND_Rt:
     case AARCH64_OPND_Rt2:
+    case AARCH64_OPND_Rt_SP:
     case AARCH64_OPND_Rs:
     case AARCH64_OPND_Ra:
     case AARCH64_OPND_Rt_SYS:
@@ -5513,6 +5564,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 
        case AARCH64_OPND_Rd_SP:
        case AARCH64_OPND_Rn_SP:
+       case AARCH64_OPND_Rt_SP:
        case AARCH64_OPND_SVE_Rn_SP:
        case AARCH64_OPND_Rm_SP:
          po_int_reg_or_fail (REG_TYPE_R_SP);
@@ -5637,6 +5689,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 
        case AARCH64_OPND_SVE_Zm3_INDEX:
        case AARCH64_OPND_SVE_Zm3_22_INDEX:
+       case AARCH64_OPND_SVE_Zm3_11_INDEX:
+       case AARCH64_OPND_SVE_Zm4_11_INDEX:
        case AARCH64_OPND_SVE_Zm4_INDEX:
        case AARCH64_OPND_SVE_Zn_INDEX:
          reg_type = REG_TYPE_ZN;
@@ -5694,11 +5748,20 @@ parse_operands (char *str, const aarch64_opcode *opcode)
              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;
                }
+
+             if (vectype.width != 0 && *str != ',')
+               {
+                 set_fatal_syntax_error
+                   (_("expected element type rather than vector type"));
+                 goto failure;
+               }
+
              info->reglist.first_regno = (val >> 2) & 0x1f;
              info->reglist.num_regs = (val & 0x3) + 1;
            }
@@ -5752,6 +5815,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_CCMP_IMM:
        case AARCH64_OPND_SIMM5:
        case AARCH64_OPND_FBITS:
+       case AARCH64_OPND_TME_UIMM16:
        case AARCH64_OPND_UIMM4:
        case AARCH64_OPND_UIMM4_ADDG:
        case AARCH64_OPND_UIMM10:
@@ -5766,8 +5830,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_SVE_LIMM_MOV:
        case AARCH64_OPND_SVE_SHLIMM_PRED:
        case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+       case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
        case AARCH64_OPND_SVE_SHRIMM_PRED:
        case AARCH64_OPND_SVE_SHRIMM_UNPRED:
+       case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
        case AARCH64_OPND_SVE_SIMM5:
        case AARCH64_OPND_SVE_SIMM5B:
        case AARCH64_OPND_SVE_SIMM6:
@@ -5781,6 +5847,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_IMM_ROT3:
        case AARCH64_OPND_SVE_IMM_ROT1:
        case AARCH64_OPND_SVE_IMM_ROT2:
+       case AARCH64_OPND_SVE_IMM_ROT3:
          po_imm_nc_or_fail ();
          info->imm.value = val;
          break;
@@ -6148,7 +6215,6 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          break;
 
        case AARCH64_OPND_ADDR_SIMPLE:
-       case AARCH64_OPND_ADDR_SIMPLE_2:
        case AARCH64_OPND_SIMD_ADDR_SIMPLE:
          {
            /* [<Xn|SP>{, #<simm>}]  */
@@ -6158,8 +6224,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
            po_misc_or_fail (parse_address (&str, info));
            if (info->addr.pcrel || info->addr.offset.is_reg
                || !info->addr.preind || info->addr.postind
-               || (info->addr.writeback
-                  && operands[i] != AARCH64_OPND_ADDR_SIMPLE_2))
+               || info->addr.writeback)
              {
                set_syntax_error (_("invalid addressing mode"));
                goto failure;
@@ -6182,8 +6247,6 @@ parse_operands (char *str, const aarch64_opcode *opcode)
                  }
              }
            po_char_or_fail (']');
-           if (operands[i] == AARCH64_OPND_ADDR_SIMPLE_2)
-             po_char_or_fail ('!');
            break;
          }
 
@@ -6420,6 +6483,33 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          info->qualifier = offset_qualifier;
          goto regoff_addr;
 
+       case AARCH64_OPND_SVE_ADDR_ZX:
+         /* [Zn.<T>{, <Xm>}].  */
+         po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+                                             &offset_qualifier));
+         /* Things to check:
+             base_qualifier either S_S or S_D
+             offset_qualifier must be X
+             */
+         if ((base_qualifier != AARCH64_OPND_QLF_S_S
+              && base_qualifier != AARCH64_OPND_QLF_S_D)
+             || offset_qualifier != AARCH64_OPND_QLF_X)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         info->qualifier = base_qualifier;
+         if (!info->addr.offset.is_reg || info->addr.pcrel
+             || !info->addr.preind || info->addr.writeback
+             || info->shifter.operator_present != 0)
+           {
+             set_syntax_error (_("invalid addressing mode"));
+             goto failure;
+           }
+         info->shifter.kind = AARCH64_MOD_LSL;
+         break;
+
+
        case AARCH64_OPND_SVE_ADDR_ZI_U5:
        case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
        case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
@@ -6778,17 +6868,12 @@ warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
           == AARCH64_OPND_CLASS_INT_REG)
          && opnds[0].reg.regno == opnds[1].addr.base_regno
          && opnds[1].addr.base_regno != REG_SP
+         /* Exempt STG/STZG/ST2G/STZ2G.  */
+         && !(opnds[1].type == AARCH64_OPND_ADDR_SIMM13)
          && opnds[1].addr.writeback)
        as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
       break;
 
-    case ldstgv_indexed:
-      /* Load operations must load different registers.  */
-      if ((opcode->opcode & (1 << 22))
-         && opnds[0].reg.regno == opnds[1].addr.base_regno)
-           as_warn (_("unpredictable load of register -- `%s'"), str);
-      break;
-
     case ldstpair_off:
     case ldstnapair_offs:
     case ldstpair_indexed:
@@ -7292,7 +7377,7 @@ aarch64_init_frag (fragS * fragP, int max_chars)
 
   /* PR 21809: Do not set a mapping state for debug sections
      - it just confuses other tools.  */
-  if (bfd_get_section_flags (NULL, now_seg) & SEC_DEBUGGING)
+  if (bfd_section_flags (now_seg) & SEC_DEBUGGING)
     return;
 
   switch (fragP->fr_type)
@@ -8342,15 +8427,18 @@ aarch64_after_parse_args (void)
 const char *
 elf64_aarch64_target_format (void)
 {
-  if (strcmp (TARGET_OS, "cloudabi") == 0)
-    {
-      /* FIXME: What to do for ilp32_p ?  */
-      return target_big_endian ? "elf64-bigaarch64-cloudabi" : "elf64-littleaarch64-cloudabi";
-    }
+#ifdef TE_CLOUDABI
+  /* FIXME: What to do for ilp32_p ?  */
+  if (target_big_endian)
+    return "elf64-bigaarch64-cloudabi";
+  else
+    return "elf64-littleaarch64-cloudabi";
+#else
   if (target_big_endian)
     return ilp32_p ? "elf32-bigaarch64" : "elf64-bigaarch64";
   else
     return ilp32_p ? "elf32-littleaarch64" : "elf64-littleaarch64";
+#endif
 }
 
 void
@@ -8726,6 +8814,8 @@ struct aarch64_cpu_option_table
    recognized by GCC.  */
 static const struct aarch64_cpu_option_table aarch64_cpus[] = {
   {"all", AARCH64_ANY, NULL},
+  {"cortex-a34", AARCH64_FEATURE (AARCH64_ARCH_V8,
+                                 AARCH64_FEATURE_CRC), "Cortex-A34"},
   {"cortex-a35", AARCH64_FEATURE (AARCH64_ARCH_V8,
                                  AARCH64_FEATURE_CRC), "Cortex-A35"},
   {"cortex-a53", AARCH64_FEATURE (AARCH64_ARCH_V8,
@@ -8745,6 +8835,26 @@ static const struct aarch64_cpu_option_table aarch64_cpus[] = {
   {"cortex-a76", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
                                  AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
                                  "Cortex-A76"},
+  {"cortex-a76ae", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                   AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
+                                   | AARCH64_FEATURE_DOTPROD
+                                   | AARCH64_FEATURE_SSBS),
+                                   "Cortex-A76AE"},
+  {"cortex-a77", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                 AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
+                                 | AARCH64_FEATURE_DOTPROD
+                                 | AARCH64_FEATURE_SSBS),
+                                 "Cortex-A77"},
+  {"cortex-a65", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                 AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
+                                 | AARCH64_FEATURE_DOTPROD
+                                 | AARCH64_FEATURE_SSBS),
+                                 "Cortex-A65"},
+  {"cortex-a65ae", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                   AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
+                                   | AARCH64_FEATURE_DOTPROD
+                                   | AARCH64_FEATURE_SSBS),
+                                   "Cortex-A65AE"},
   {"ares", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
                                  AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
                                  | AARCH64_FEATURE_DOTPROD
@@ -8757,6 +8867,16 @@ static const struct aarch64_cpu_option_table aarch64_cpus[] = {
                              AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
                              | AARCH64_FEATURE_RDMA),
    "Qualcomm Falkor"},
+  {"neoverse-e1", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                 AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
+                                 | AARCH64_FEATURE_DOTPROD
+                                 | AARCH64_FEATURE_SSBS),
+                                 "Neoverse E1"},
+  {"neoverse-n1", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+                                 AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
+                                 | AARCH64_FEATURE_DOTPROD
+                                 | AARCH64_FEATURE_PROFILE),
+                                 "Neoverse N1"},
   {"qdf24xx", AARCH64_FEATURE (AARCH64_ARCH_V8,
                               AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
                               | AARCH64_FEATURE_RDMA),
@@ -8798,6 +8918,7 @@ static const struct aarch64_arch_option_table aarch64_archs[] = {
   {"armv8.3-a", AARCH64_ARCH_V8_3},
   {"armv8.4-a", AARCH64_ARCH_V8_4},
   {"armv8.5-a", AARCH64_ARCH_V8_5},
+  {"armv8.6-a", AARCH64_ARCH_V8_6},
   {NULL, AARCH64_ARCH_NONE}
 };
 
@@ -8841,6 +8962,8 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
                        AARCH64_FEATURE (AARCH64_FEATURE_F16
                                         | AARCH64_FEATURE_SIMD
                                         | AARCH64_FEATURE_COMPNUM, 0)},
+  {"tme",              AARCH64_FEATURE (AARCH64_FEATURE_TME, 0),
+                       AARCH64_ARCH_NONE},
   {"compnum",          AARCH64_FEATURE (AARCH64_FEATURE_COMPNUM, 0),
                        AARCH64_FEATURE (AARCH64_FEATURE_F16
                                         | AARCH64_FEATURE_SIMD, 0)},
@@ -8867,6 +8990,19 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
                        AARCH64_ARCH_NONE},
   {"memtag",           AARCH64_FEATURE (AARCH64_FEATURE_MEMTAG, 0),
                        AARCH64_ARCH_NONE},
+  {"sve2",             AARCH64_FEATURE (AARCH64_FEATURE_SVE2, 0),
+                       AARCH64_FEATURE (AARCH64_FEATURE_SVE, 0)},
+  {"sve2-sm4",         AARCH64_FEATURE (AARCH64_FEATURE_SVE2_SM4, 0),
+                       AARCH64_FEATURE (AARCH64_FEATURE_SVE2
+                                        | AARCH64_FEATURE_SM4, 0)},
+  {"sve2-aes",         AARCH64_FEATURE (AARCH64_FEATURE_SVE2_AES, 0),
+                       AARCH64_FEATURE (AARCH64_FEATURE_SVE2
+                                        | AARCH64_FEATURE_AES, 0)},
+  {"sve2-sha3",                AARCH64_FEATURE (AARCH64_FEATURE_SVE2_SHA3, 0),
+                       AARCH64_FEATURE (AARCH64_FEATURE_SVE2
+                                        | AARCH64_FEATURE_SHA3, 0)},
+  {"sve2-bitperm",     AARCH64_FEATURE (AARCH64_FEATURE_SVE2_BITPERM, 0),
+                       AARCH64_FEATURE (AARCH64_FEATURE_SVE2, 0)},
   {NULL,               AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
 };
 
@@ -9331,3 +9467,35 @@ aarch64_copy_symbol_attributes (symbolS * dest, symbolS * src)
 {
   AARCH64_GET_FLAG (dest) = AARCH64_GET_FLAG (src);
 }
+
+#ifdef OBJ_ELF
+/* Same as elf_copy_symbol_attributes, but without copying st_other.
+   This is needed so AArch64 specific st_other values can be independently
+   specified for an IFUNC resolver (that is called by the dynamic linker)
+   and the symbol it resolves (aliased to the resolver).  In particular,
+   if a function symbol has special st_other value set via directives,
+   then attaching an IFUNC resolver to that symbol should not override
+   the st_other setting.  Requiring the directive on the IFUNC resolver
+   symbol would be unexpected and problematic in C code, where the two
+   symbols appear as two independent function declarations.  */
+
+void
+aarch64_elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
+{
+  struct elf_obj_sy *srcelf = symbol_get_obj (src);
+  struct elf_obj_sy *destelf = symbol_get_obj (dest);
+  if (srcelf->size)
+    {
+      if (destelf->size == NULL)
+       destelf->size = XNEW (expressionS);
+      *destelf->size = *srcelf->size;
+    }
+  else
+    {
+      if (destelf->size != NULL)
+       free (destelf->size);
+      destelf->size = NULL;
+    }
+  S_SET_SIZE (dest, S_GET_SIZE (src));
+}
+#endif
This page took 0.031332 seconds and 4 git commands to generate.