/* Copyright (C) 2012-2022 Free Software Foundation, Inc.
   Contributed by ARM Ltd.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   GCC is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */

/* This is a list of ISA extentsions in AArch64.

   Before using #include to read this file, define a macro:

      AARCH64_OPT_EXTENSION(NAME, IDENT, REQUIRES, EXPLICIT_ON,
			    EXPLICIT_OFF, FEATURE_STRING)

   - NAME is the name of the extension, represented as a string constant.

   - IDENT is the canonical internal name for this flag.

   - REQUIRES is a list of features that must be enabled whenever this
     feature is enabled.  The relationship is implicitly transitive:
     if A appears in B's REQUIRES and B appears in C's REQUIRES then
     A and B must be enabled whenever C is.  Thus, turning on C also
     turns on A and B, while turning off A or B also turns off C.

   - EXPLICIT_ON is a list of features that are enabled by an explicit
     +NAME specification, in addition to those listed in REQUIRES.
     Usually this is an empty list; comments below explain the exceptions.
     The list is implicitly transitively closed wrt REQUIRES (but *not*
     to EXPLICIT_ON, since NAME is the only thing explicit in +NAME).
     Thus if A is in B's REQUIRES and B is in C's EXPLICIT_ON, +C will
     enable both B and A.  B's EXPLICIT_ON has no effect on +C.

   - EXPLICIT_OFF is a list of features that are disabled by an explicit
     +noNAME specification, in addition to the features that are transitively
     dependent on NAME (according to REQUIRES).  As with EXPLICIT_ON,
     this is usually an empty list; comments below explain the exceptions.
     If a feature A appears in this list then the list implicitly includes
     any features that are transitively dependent on A (according to REQUIRES).

   - FEAT_STRING is a string containing the entries in the 'Features' field of
     /proc/cpuinfo on a GNU/Linux system that correspond to this architecture
     extension being available.  Sometimes multiple entries are needed to enable
     the extension (for example, the 'crypto' extension depends on four
     entries: aes, pmull, sha1, sha2 being present).  In that case this field
     should contain a space (" ") separated list of the strings in 'Features'
     that are required.  Their order is not important.  An empty string means
     do not detect this feature during auto detection.

   The list of features must follow topological order wrt REQUIRES
   and EXPLICIT_ON.  For example, if A is in B's REQUIRES list, A must
   come before B.  This is enforced by aarch64-feature-deps.h.

   NOTE: Any changes to the AARCH64_OPT_EXTENSION macro need to be mirrored in
   config.gcc.  */

AARCH64_OPT_EXTENSION("fp", FP, (), (), (), "fp")

AARCH64_OPT_EXTENSION("simd", SIMD, (FP), (), (), "asimd")

AARCH64_OPT_EXTENSION("crc", CRC, (), (), (), "crc32")

AARCH64_OPT_EXTENSION("lse", LSE, (), (), (), "atomics")

/* +nofp16 disables an implicit F16FML, even though an implicit F16FML
   does not imply F16.  See F16FML for more details.  */
AARCH64_OPT_EXTENSION("fp16", F16, (FP), (), (F16FML), "fphp asimdhp")

AARCH64_OPT_EXTENSION("rcpc", RCPC, (), (), (), "lrcpc")

/* An explicit +rdma implies +simd, but +rdma+nosimd still enables scalar
   RDMA instructions.  */
AARCH64_OPT_EXTENSION("rdma", RDMA, (), (SIMD), (), "asimdrdm")

AARCH64_OPT_EXTENSION("dotprod", DOTPROD, (SIMD), (), (), "asimddp")

AARCH64_OPT_EXTENSION("aes", AES, (SIMD), (), (), "aes")

AARCH64_OPT_EXTENSION("sha2", SHA2, (SIMD), (), (), "sha1 sha2")

/* +nocrypto disables AES, SHA2 and SM4, and anything that depends on them
   (such as SHA3 and the SVE2 crypto extensions).  */
AARCH64_OPT_EXTENSION("crypto", CRYPTO, (AES, SHA2), (), (AES, SHA2, SM4),
		      "aes pmull sha1 sha2")

AARCH64_OPT_EXTENSION("sha3", SHA3, (SHA2), (), (), "sha3 sha512")

AARCH64_OPT_EXTENSION("sm4", SM4, (SIMD), (), (), "sm3 sm4")

/* An explicit +fp16fml implies +fp16, but a dependence on it does not.
   Thus -march=armv8.4-a implies F16FML but not F16.  -march=armv8.4-a+fp16
   and -march=armv8.4-a+fp16fml are equivalent and enable both F16FML and F16.
   -march=armv8.4-a+nofp16+fp16 enables F16 but not F16FML.  */
AARCH64_OPT_EXTENSION("fp16fml", F16FML, (), (F16), (), "asimdfhm")

AARCH64_OPT_EXTENSION("sve", SVE, (SIMD, F16), (), (), "sve")

AARCH64_OPT_EXTENSION("profile", PROFILE, (), (), (), "")

AARCH64_OPT_EXTENSION("rng", RNG, (), (), (), "rng")

AARCH64_OPT_EXTENSION("memtag", MEMTAG, (), (), (), "")

AARCH64_OPT_EXTENSION("sb", SB, (), (), (), "sb")

AARCH64_OPT_EXTENSION("ssbs", SSBS, (), (), (), "ssbs")

AARCH64_OPT_EXTENSION("predres", PREDRES, (), (), (), "")

AARCH64_OPT_EXTENSION("sve2", SVE2, (SVE), (), (), "sve2")

AARCH64_OPT_EXTENSION("sve2-sm4", SVE2_SM4, (SVE2, SM4), (), (), "svesm4")

AARCH64_OPT_EXTENSION("sve2-aes", SVE2_AES, (SVE2, AES), (), (), "sveaes")

AARCH64_OPT_EXTENSION("sve2-sha3", SVE2_SHA3, (SVE2, SHA3), (), (), "svesha3")

AARCH64_OPT_EXTENSION("sve2-bitperm", SVE2_BITPERM, (SVE2), (), (),
		      "svebitperm")

AARCH64_OPT_EXTENSION("tme", TME, (), (), (), "")

AARCH64_OPT_EXTENSION("i8mm", I8MM, (SIMD), (), (), "i8mm")

AARCH64_OPT_EXTENSION("f32mm", F32MM, (SVE), (), (), "f32mm")

AARCH64_OPT_EXTENSION("f64mm", F64MM, (SVE), (), (), "f64mm")

/* An explicit +bf16 implies +simd, but +bf16+nosimd still enables scalar BF16
   instructions.  */
AARCH64_OPT_EXTENSION("bf16", BF16, (FP), (SIMD), (), "bf16")

AARCH64_OPT_EXTENSION("flagm", FLAGM, (), (), (), "flagm")

AARCH64_OPT_EXTENSION("pauth", PAUTH, (), (), (), "paca pacg")

AARCH64_OPT_EXTENSION("ls64", LS64, (), (), (), "")

AARCH64_OPT_EXTENSION("mops", MOPS, (), (), (), "")

#undef AARCH64_OPT_EXTENSION
