<!-- archs appear in order of significance for blind, de-facto version ordering -->
<!-- SPDX-License-Identifier: GPL-3.0-or-later -->
<!-- SPDX-FileCopyrightText: 2014-2020 Carles Fernandez-Prades <carles.fernandez@cttc.es> -->
<grammar>

<arch name="generic"> <!-- name is required-->
</arch>

<arch name="softfp">
  <flag compiler="gnu">-mfloat-abi=softfp</flag>
  <flag compiler="clang">-mfloat-abi=softfp</flag>
</arch>

<arch name="hardfp">
  <flag compiler="gnu">-mfloat-abi=hard</flag>
  <flag compiler="clang">-mfloat-abi=hard</flag>
</arch>

<arch name="neon">
  <flag compiler="gnu">-funsafe-math-optimizations</flag>
  <flag compiler="clang">-funsafe-math-optimizations</flag>
  <alignment>16</alignment>
  <check name="has_neon"></check>
</arch>

<arch name="neonv7">
  <flag compiler="gnu">-mfpu=neon</flag>
  <flag compiler="gnu">-funsafe-math-optimizations</flag>
  <flag compiler="clang">-mfpu=neon</flag>
  <flag compiler="clang">-funsafe-math-optimizations</flag>
  <alignment>16</alignment>
  <check name="has_neonv7"></check>
</arch>

<arch name="neonv8">
  <flag compiler="gnu">-funsafe-math-optimizations</flag>
  <flag compiler="clang">-funsafe-math-optimizations</flag>
  <alignment>16</alignment>
  <check name="has_neonv8"></check>
</arch>

<arch name="32">
  <flag compiler="gnu">-m32</flag>
  <flag compiler="clang">-m32</flag>
</arch>

<arch name="64">
  <check name="check_extended_cpuid">
      <param>0x80000001</param>
  </check>
  <check name="cpuid_x86_bit">  <!-- checks to see if a bit is set -->
      <param>3</param>          <!-- eax, ebx, ecx, [edx] -->
      <param>0x80000001</param> <!-- cpuid operation -->
      <param>29</param>         <!-- bit shift -->
  </check>
  <flag compiler="gnu">-m64</flag>
  <flag compiler="clang">-m64</flag>
</arch>

<arch name="3dnow">
  <check name="cpuid_x86_bit">
      <param>3</param>
      <param>0x80000001</param>
      <param>31</param>
  </check>
  <flag compiler="gnu">-m3dnow</flag>
  <flag compiler="clang">-m3dnow</flag>
  <alignment>8</alignment>
</arch>

<arch name="abm">
  <check name="cpuid_x86_bit">
      <param>3</param>
      <param>0x80000001</param>
      <param>5</param>
  </check>
  <flag compiler="gnu">-msse4.2</flag>
  <flag compiler="clang">-msse4.2</flag>
  <alignment>16</alignment>
</arch>

<arch name="popcount">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>23</param>
  </check>
  <flag compiler="gnu">-mpopcnt</flag>
  <flag compiler="clang">-mpopcnt</flag>
  <flag compiler="msvc">/arch:AVX</flag>
</arch>

<arch name="mmx">
  <check name="cpuid_x86_bit">
      <param>3</param>
      <param>0x00000001</param>
      <param>23</param>
  </check>
  <flag compiler="gnu">-mmmx</flag>
  <flag compiler="clang">-mmmx</flag>
  <flag compiler="msvc">/arch:SSE</flag>
  <alignment>8</alignment>
</arch>

<arch name="fma">
    <check name="cpuid_x86_bit">
        <param>2</param>
        <param>0x00000001</param>
        <param>12</param>
    </check>
    <flag compiler="gnu">-mfma</flag>
    <flag compiler="clang">-mfma</flag>
    <flag compiler="msvc">/arch:AVX2</flag>
    <alignment>32</alignment>
</arch>

<arch name="sse">
  <check name="cpuid_x86_bit">
      <param>3</param>
      <param>0x00000001</param>
      <param>25</param>
  </check>
  <flag compiler="gnu">-msse</flag>
  <flag compiler="clang">-msse</flag>
  <flag compiler="msvc">/arch:SSE</flag>
  <environment>_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);</environment>
  <include>xmmintrin.h</include>
  <alignment>16</alignment>
</arch>

<arch name="sse2">
  <check name="cpuid_x86_bit">
      <param>3</param>
      <param>0x00000001</param>
      <param>26</param>
  </check>
  <flag compiler="gnu">-msse2</flag>
  <flag compiler="clang">-msse2</flag>
  <flag compiler="msvc">/arch:SSE2</flag>
  <alignment>16</alignment>
</arch>

<arch name="orc">
</arch>

<!-- it's here for overrule stuff. -->
<arch name="norc">
</arch>

<arch name="sse3">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>0</param>
  </check>
  <flag compiler="gnu">-msse3</flag>
  <flag compiler="clang">-msse3</flag>
  <flag compiler="msvc">/arch:AVX</flag>
  <environment>_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);</environment>
  <include>pmmintrin.h</include>
  <alignment>16</alignment>
</arch>

<arch name="ssse3">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>9</param>
  </check>
  <flag compiler="gnu">-mssse3</flag>
  <flag compiler="clang">-mssse3</flag>
  <flag compiler="msvc">/arch:AVX</flag>
  <alignment>16</alignment>
</arch>

<arch name="sse4_a">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x80000001</param>
      <param>6</param>
  </check>
  <flag compiler="gnu">-msse4a</flag>
  <flag compiler="clang">-msse4a</flag>
  <alignment>16</alignment>
</arch>

<arch name="sse4_1">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>19</param>
  </check>
  <flag compiler="gnu">-msse4.1</flag>
  <flag compiler="clang">-msse4.1</flag>
  <flag compiler="msvc">/arch:AVX</flag>
  <alignment>16</alignment>
</arch>

<arch name="sse4_2">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>20</param>
  </check>
  <flag compiler="gnu">-msse4.2</flag>
  <flag compiler="clang">-msse4.2</flag>
  <flag compiler="msvc">/arch:AVX</flag>
  <alignment>16</alignment>
</arch>

<arch name="avx">
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>28</param>
  </check>
  <!-- check to make sure that xgetbv is enabled in OS -->
  <check name="cpuid_x86_bit">
      <param>2</param>
      <param>0x00000001</param>
      <param>27</param>
  </check>
  <!-- check to see that the OS has enabled AVX -->
  <check name="get_avx_enabled"></check>
  <flag compiler="gnu">-mavx</flag>
  <flag compiler="clang">-mavx</flag>
  <flag compiler="msvc">/arch:AVX</flag>
  <alignment>32</alignment>
</arch>

<arch name="avx2">
    <check name="cpuid_count_x86_bit">
        <param>7</param>
        <param>0</param>
        <param>1</param>
        <param>5</param>
    </check>
    <!-- check to make sure that xgetbv is enabled in OS -->
    <check name="cpuid_x86_bit">
        <param>2</param>
        <param>0x00000001</param>
        <param>27</param>
    </check>
    <!-- check to see that the OS has enabled AVX2 -->
    <check name="get_avx2_enabled"></check>
    <flag compiler="gnu">-mavx2</flag>
    <flag compiler="clang">-mavx2</flag>
    <flag compiler="msvc">/arch:AVX2</flag>
    <alignment>32</alignment>
</arch>

<arch name="avx512f">
    <!-- check for AVX512F -->
    <check name="cpuid_count_x86_bit">
        <param>7</param>
        <param>0</param>
        <param>1</param>
        <param>16</param>
    </check>
    <!-- check to make sure that xgetbv is enabled in OS -->
    <check name="cpuid_x86_bit">
        <param>2</param>
        <param>0x00000001</param>
        <param>27</param>
    </check>
    <!-- check to see that the OS has enabled AVX512 -->
    <check name="get_avx512_enabled"></check>
    <flag compiler="gnu">-mavx512f</flag>
    <flag compiler="clang">-mavx512f</flag>
    <flag compiler="msvc">/arch:AVX512F</flag>
    <alignment>64</alignment>
</arch>

<arch name="avx512cd">
    <!-- check for AVX512CD -->
    <check name="cpuid_count_x86_bit">
        <param>7</param>
        <param>0</param>
        <param>1</param>
        <param>28</param>
    </check>
    <!-- check to make sure that xgetbv is enabled in OS -->
    <check name="cpuid_x86_bit">
        <param>2</param>
        <param>0x00000001</param>
        <param>27</param>
    </check>
    <!-- check to see that the OS has enabled AVX512 -->
    <check name="get_avx512_enabled"></check>
    <flag compiler="gnu">-mavx512cd</flag>
    <flag compiler="clang">-mavx512cd</flag>
    <flag compiler="msvc">/arch:AVX512CD</flag>
    <alignment>64</alignment>
</arch>

<arch name="riscv64">
</arch>

<arch name="rvv">
    <flag compiler="gnu">-march=rv64gcv</flag>
    <flag compiler="clang">-march=rv64gcv</flag>
</arch>

<arch name="rvvseg">
    <flag compiler="gnu">-march=rv64gcv</flag>
    <flag compiler="clang">-march=rv64gcv</flag>
    <!-->
        It's unclear how performance portable segmented load/stores are, so the
        default rvv implementations avoid using them.
        This is a pseudo arch for separate segmented load/store implementations,
        and is expected to never be used standalone without "rvv".
    </-->
</arch>

</grammar>
