├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── COPYING ├── Makefile.am ├── README ├── configure.ac ├── src ├── arm.c ├── hwcap-dump.c ├── hwcap.c ├── hwcap.h ├── main.c ├── mock.c ├── platforms.h ├── ppc.c ├── x86-dump.c ├── x86-lib.c ├── x86.c └── x86.h └── tests ├── arm ├── aarch64-aws-a1.txt ├── aarch64-cavium-thunderx.txt ├── aarch64-cavium-thunderx2.txt ├── aarch64-dragonboard.txt ├── aarch64-hp-moonshot-xgene-1.txt ├── aarch64-neoverse-n1.txt ├── aarch64-odroid-n2.txt ├── aarch64-raspberry-4.txt ├── armv5tel-dreamplug.txt ├── armv6l-raspberry-pi1b.txt ├── armv7l-beaglebone.txt ├── armv7l-compulab-utilite-pro.txt ├── armv7l-jhcloos-cheap.txt ├── armv7l-odroid-c1.txt ├── armv7l-raspberry-pi3.txt ├── armv7l-rk3288.txt ├── armv7l-scaleway-c1.txt ├── armv7l-solidrun-cubox.txt └── armv8l-neoverse-n1.txt ├── ppc ├── power8.txt └── power9.txt ├── test.sh └── x86 ├── amd-colfax.txt ├── amd-zen2.txt ├── amd-zen4-ryzen-7-pro-7840u.txt ├── amd-zen4.txt ├── athlon64-windsor.txt ├── i3-ivybridge.txt ├── opteron-6272.txt ├── xeon-e-2176g.txt ├── xeon-platinum-8480plus.txt └── xeon-silver-4410.txt /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout 8 | uses: actions/checkout@v2 9 | - name: Autoreconf 10 | run: autoreconf -vi 11 | - name: Configure 12 | run: ./configure -C 13 | - name: Distcheck 14 | run: make -j$(nproc) distcheck 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.la 2 | *.lo 3 | *.o 4 | *.pc 5 | .deps/ 6 | .dirstamp 7 | .libs/ 8 | /aclocal.m4 9 | /autom4te.cache/ 10 | /build-aux/ 11 | /config.cache 12 | /config.h 13 | /config.h.in 14 | /config.log 15 | /config.status 16 | /configure 17 | /hwcap-dump 18 | /libtool 19 | /m4/ 20 | /cpuid2cpuflags 21 | /stamp-h1 22 | Makefile 23 | Makefile.in 24 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | bin_PROGRAMS = cpuid2cpuflags 4 | EXTRA_PROGRAMS = hwcap-dump x86-dump 5 | check_PROGRAMS = arm-mock ppc-mock x86-mock 6 | 7 | cpuid2cpuflags_SOURCES = \ 8 | src/main.c \ 9 | src/platforms.h \ 10 | src/arm.c \ 11 | src/hwcap.c \ 12 | src/hwcap.h \ 13 | src/ppc.c \ 14 | src/x86.c \ 15 | src/x86-lib.c \ 16 | src/x86.h 17 | 18 | hwcap_dump_SOURCES = \ 19 | src/hwcap-dump.c \ 20 | src/hwcap.c \ 21 | src/hwcap.h 22 | hwcap_dump_CPPFLAGS = -DCPUID_ARM -DCPUID_MOCK 23 | 24 | x86_dump_SOURCES = \ 25 | src/x86-dump.c \ 26 | src/x86-lib.c \ 27 | src/x86.h 28 | 29 | arm_mock_SOURCES = \ 30 | src/hwcap.h \ 31 | src/mock.c \ 32 | src/arm.c 33 | arm_mock_CPPFLAGS = -DCPUID_ARM -DCPUID_MOCK 34 | 35 | ppc_mock_SOURCES = \ 36 | src/hwcap.h \ 37 | src/mock.c \ 38 | src/ppc.c 39 | ppc_mock_CPPFLAGS = -DCPUID_PPC -DCPUID_MOCK 40 | 41 | x86_mock_SOURCES = \ 42 | src/mock.c \ 43 | src/x86.c \ 44 | src/x86.h 45 | x86_mock_CPPFLAGS = -DCPUID_X86 -DCPUID_MOCK 46 | 47 | LOG_COMPILER = sh $(top_srcdir)/tests/test.sh $(builddir) 48 | TESTS = \ 49 | tests/arm/aarch64-aws-a1.txt \ 50 | tests/arm/aarch64-cavium-thunderx.txt \ 51 | tests/arm/aarch64-cavium-thunderx2.txt \ 52 | tests/arm/aarch64-dragonboard.txt \ 53 | tests/arm/aarch64-hp-moonshot-xgene-1.txt \ 54 | tests/arm/aarch64-neoverse-n1.txt \ 55 | tests/arm/aarch64-odroid-n2.txt \ 56 | tests/arm/aarch64-raspberry-4.txt \ 57 | tests/arm/armv5tel-dreamplug.txt \ 58 | tests/arm/armv6l-raspberry-pi1b.txt \ 59 | tests/arm/armv7l-beaglebone.txt \ 60 | tests/arm/armv7l-compulab-utilite-pro.txt \ 61 | tests/arm/armv7l-jhcloos-cheap.txt \ 62 | tests/arm/armv7l-odroid-c1.txt \ 63 | tests/arm/armv7l-raspberry-pi3.txt \ 64 | tests/arm/armv7l-rk3288.txt \ 65 | tests/arm/armv7l-scaleway-c1.txt \ 66 | tests/arm/armv7l-solidrun-cubox.txt \ 67 | tests/arm/armv8l-neoverse-n1.txt \ 68 | tests/ppc/power8.txt \ 69 | tests/ppc/power9.txt \ 70 | tests/x86/amd-colfax.txt \ 71 | tests/x86/amd-zen2.txt \ 72 | tests/x86/athlon64-windsor.txt \ 73 | tests/x86/i3-ivybridge.txt \ 74 | tests/x86/opteron-6272.txt \ 75 | tests/x86/xeon-e-2176g.txt \ 76 | tests/x86/xeon-silver-4410.txt \ 77 | tests/x86/amd-zen4.txt \ 78 | tests/x86/amd-zen4-ryzen-7-pro-7840u.txt \ 79 | tests/x86/xeon-platinum-8480plus.txt 80 | 81 | EXTRA_DIST = $(TESTS) tests/test.sh 82 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | cpuid2cpuflags -- CPU_FLAGS_* generator 2 | (c) 2017-2024 Michał Górny 3 | SPDX-License-Identifier: GPL-2.0-or-later 4 | 5 | 6 | Usage 7 | ~~~~~ 8 | 9 | The program attempts to obtain the identification and capabilities 10 | of the currently used CPU, and print the matching set of CPU_FLAGS_* 11 | flags for Gentoo. To use it, just run it: 12 | 13 | $ cpuid2cpuflags 14 | CPU_FLAGS_X86: 3dnow 3dnowext mmx mmxext sse sse2 sse3 15 | 16 | There are no command-line options. Please note that the program 17 | identifies the apparent CPU capabilities using available CPU calls 18 | or system interfaces, *not* the capabilities indicated by compiler 19 | flags. 20 | 21 | The flag definitions match the flags described in Gentoo profiles/desc 22 | at the time of program release. If additional flags are introduced 23 | in the future, they will be added in a future program release. 24 | 25 | The output format is compatible both with Portage (package.use) 26 | and Paludis (use.conf/options.conf). If you find it useful to 27 | generate/update it automatically, you can use a dedicated file: 28 | 29 | $ mkdir /etc/portage/package.use # if not used yet 30 | $ echo "*/* $(cpuid2cpuflags)" > /etc/portage/package.use/00cpuflags 31 | 32 | 33 | Building 34 | ~~~~~~~~ 35 | 36 | These are the steps necessary to build the ./cpuid2cpuflags program: 37 | 38 | $ autoreconf -vi 39 | $ ./configure 40 | $ make 41 | 42 | 43 | Implementation details 44 | ~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | X86 (incl. x86-64) 47 | ------------------ 48 | 49 | On x86 platforms, cpuid2cpuflags issues the CPUID instruction to obtain 50 | processor capabilities. This should work reliably across different 51 | systems and kernels, unless the system somehow blocks this instruction. 52 | If this is the case, please report a bug. 53 | 54 | 55 | ARM and AArch64 56 | --------------- 57 | 58 | On ARM platforms, the userspace processes are not allowed to obtain 59 | processor information directly. Instead, the program is relying 60 | on kernel identification of the CPU provided via the system interfaces. 61 | Currently, only Linux is supported. 62 | 63 | On Linux, two interfaces are used: uname() to identify the CPU family, 64 | and getauxval(AT_HWCAP*...) to obtain detailed feature flags. 65 | 66 | The textual value obtained from uname (armv* or aarch64) is used 67 | to enable appropriate ARM version flags and some feature flags. It is 68 | also used to determine whether the kernel is 64- or 32-bit since that 69 | affects the interpretation of AT_HWCAP* flags. 70 | 71 | Afterwards, the remaining feature flags are enabled based on either flag 72 | bits provided by AT_HWCAP*, or implicitly based on the subarchitecture 73 | (i.e. currently a number of features is always set on AArch64). 74 | 75 | It should be noted that the program strongly depends on correct 76 | identification of the CPU in the kernel. If you find the results 77 | incorrect, please report a bug but I can't promise I'll be able to find 78 | a good workaround. 79 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.60]) 2 | AC_INIT([cpuid2cpuflags], [16]) 3 | AC_CONFIG_AUX_DIR([build-aux]) 4 | AC_CONFIG_MACRO_DIR([m4]) 5 | AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 parallel-tests subdir-objects -Wall]) 6 | 7 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) 8 | 9 | AC_PROG_CC 10 | AC_USE_SYSTEM_EXTENSIONS 11 | AC_TYPE_UINT32_T 12 | 13 | AC_CONFIG_HEADER([config.h]) 14 | AC_CONFIG_FILES([Makefile]) 15 | AC_OUTPUT 16 | -------------------------------------------------------------------------------- /src/arm.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- ARM/AArch64-specific detection routines 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #ifdef CPUID_ARM 12 | 13 | #include 14 | #include 15 | #ifdef HAVE_STDINT_H 16 | # include 17 | #endif 18 | #include 19 | 20 | #include "hwcap.h" 21 | 22 | /** 23 | * Definition of ARM subarches (vN) as bitmaps indicating which v* flags 24 | * should be enabled. Generally, we expect every next subarch to 25 | * be represented by the next bit, and to imply all previous subarches 26 | * (i.e. be compatible with). 27 | */ 28 | enum cpu_subarch 29 | { 30 | SUBARCH_V4 = (1 << 0), 31 | SUBARCH_V4T = (1 << 1) | SUBARCH_V4, 32 | SUBARCH_V5 = (1 << 2) | SUBARCH_V4T, 33 | SUBARCH_V5T = (1 << 3) | SUBARCH_V5, 34 | SUBARCH_V5TE = (1 << 4) | SUBARCH_V5T, 35 | SUBARCH_V5TEJ = (1 << 5) | SUBARCH_V5TE, 36 | SUBARCH_V6 = (1 << 6) | SUBARCH_V5TEJ, 37 | SUBARCH_V6T2 = (1 << 7) | SUBARCH_V6, 38 | SUBARCH_V7 = (1 << 8) | SUBARCH_V6T2, 39 | SUBARCH_V8 = (1 << 9) | SUBARCH_V7, 40 | SUBARCH_AARCH64 = (1 << 10) | SUBARCH_V8, 41 | 42 | SUBARCH_MAX 43 | }; 44 | 45 | /** 46 | * Mapping of 'uname -m' value to subarch. 47 | */ 48 | struct subarch_info 49 | { 50 | const char* name; 51 | enum cpu_subarch subarch; 52 | }; 53 | 54 | struct subarch_info subarches[] = { 55 | /* grep -Rho string.*cpu_arch_name.*$ arch/arm | sort -u */ 56 | /* start with newest as the most likely */ 57 | { "aarch64", SUBARCH_AARCH64 }, 58 | { "armv8", SUBARCH_V8 }, 59 | { "armv7", SUBARCH_V7 }, 60 | { "armv6", SUBARCH_V6 }, 61 | { "armv5tej", SUBARCH_V5TEJ }, 62 | { "armv5te", SUBARCH_V5TE }, 63 | { "armv5t", SUBARCH_V5T }, 64 | { "armv4t", SUBARCH_V4T }, 65 | { "armv4", SUBARCH_V4 }, 66 | 67 | { 0 } 68 | }; 69 | 70 | /** 71 | * Supported checks: 72 | * 73 | * - CHECK_HWCAP and CHECK_HWCAP2 refer to appropriate values in 32-bit 74 | * ARM AT_HWCAP*, 75 | * - CHECK_AARCH64_HWCAP and CHECK_HWCAP2 refer to appropriate values 76 | * in 64-bit AArch64 AT_HWCAP, 77 | * - CHECK_SUBARCH refers to the subarch determined via 'uname -m'. 78 | */ 79 | enum check_type 80 | { 81 | CHECK_SENTINEL = 0, 82 | 83 | CHECK_HWCAP, 84 | CHECK_HWCAP2, 85 | CHECK_AARCH64_HWCAP, 86 | CHECK_AARCH64_HWCAP2, 87 | CHECK_SUBARCH, 88 | 89 | CHECK_MAX 90 | }; 91 | 92 | struct flag_info 93 | { 94 | const char* name; 95 | enum check_type type; 96 | unsigned long mask; 97 | }; 98 | 99 | struct flag_info flags[] = { 100 | /* arm variant */ 101 | /* copied outta linux/arch/arm/include/uapi/asm/hwcap.h */ 102 | { "edsp", CHECK_HWCAP, (1 << 7) }, 103 | { "iwmmxt", CHECK_HWCAP, (1 << 9) }, 104 | { "neon", CHECK_HWCAP, (1 << 12) }, 105 | { "thumb", CHECK_HWCAP, (1 << 2) }, 106 | { "vfp", CHECK_HWCAP, (1 << 6) }, 107 | { "vfpv3", CHECK_HWCAP, (1 << 13) }, 108 | { "vfpv4", CHECK_HWCAP, (1 << 16) }, 109 | { "vfp-d32", CHECK_HWCAP, (1 << 19) }, 110 | { "asimddp", CHECK_HWCAP, (1 << 24) }, 111 | { "i8mm", CHECK_HWCAP, (1 << 27) }, 112 | { "aes", CHECK_HWCAP2, (1 << 0) }, 113 | { "sha1", CHECK_HWCAP2, (1 << 2) }, 114 | { "sha2", CHECK_HWCAP2, (1 << 3) }, 115 | { "crc32", CHECK_HWCAP2, (1 << 4) }, 116 | 117 | /* aarch64 variant */ 118 | /* copied outta linux/arch/arm64/include/uapi/asm/hwcap.h */ 119 | /* see also sys/arm64/include/elf.h in FreeBSD */ 120 | { "edsp", CHECK_SUBARCH, SUBARCH_AARCH64 }, 121 | { "neon", CHECK_AARCH64_HWCAP, (1 << 1) }, /* HWCAP_ASIMD */ 122 | { "thumb", CHECK_SUBARCH, SUBARCH_AARCH64 }, 123 | { "vfp", CHECK_SUBARCH, SUBARCH_AARCH64 }, 124 | { "vfpv3", CHECK_SUBARCH, SUBARCH_AARCH64 }, 125 | { "vfpv4", CHECK_SUBARCH, SUBARCH_AARCH64 }, 126 | { "vfp-d32", CHECK_SUBARCH, SUBARCH_AARCH64 }, 127 | { "aes", CHECK_AARCH64_HWCAP, (1 << 3) }, 128 | { "sha1", CHECK_AARCH64_HWCAP, (1 << 5) }, 129 | { "sha2", CHECK_AARCH64_HWCAP, (1 << 6) }, 130 | { "crc32", CHECK_AARCH64_HWCAP, (1 << 7) }, 131 | { "sm4", CHECK_AARCH64_HWCAP, (1 << 19) }, 132 | { "asimddp", CHECK_AARCH64_HWCAP, (1 << 20) }, 133 | { "sve", CHECK_AARCH64_HWCAP, (1 << 22) }, 134 | { "sve2", CHECK_AARCH64_HWCAP2, (1 << 1) }, 135 | { "i8mm", CHECK_AARCH64_HWCAP2, (1 << 13) }, 136 | 137 | /* subarches */ 138 | { "v4", CHECK_SUBARCH, SUBARCH_V4 }, 139 | { "v5", CHECK_SUBARCH, SUBARCH_V5 }, 140 | { "v6", CHECK_SUBARCH, SUBARCH_V6 }, 141 | { "v7", CHECK_SUBARCH, SUBARCH_V7 }, 142 | { "v8", CHECK_SUBARCH, SUBARCH_V8 }, 143 | 144 | /* other bits */ 145 | /* TODO: figure out how to detect it better? */ 146 | { "thumb2", CHECK_SUBARCH, SUBARCH_V6T2 }, 147 | 148 | { 0 } 149 | }; 150 | 151 | /** 152 | * Print CPU_FLAGS_ARM based on AT_HWCAP* and 'uname -m'. 153 | * 154 | * Returns exit status (0 on success, non-zero on failure). 155 | */ 156 | int print_flags() 157 | { 158 | unsigned long hwcap, hwcap2, subarch = 0; 159 | char* uname_m; 160 | int i; 161 | 162 | hwcap = get_hwcap(); 163 | hwcap2 = get_hwcap2(); 164 | uname_m = get_uname_machine(); 165 | if (uname_m) 166 | { 167 | size_t len = strlen(uname_m); 168 | /* strip endianness suffix */ 169 | if (len > 0 && (uname_m[len-1] == 'l' || uname_m[len-1] == 'b')) 170 | uname_m[len-1] = '\0'; 171 | 172 | for (i = 0; subarches[i].name; ++i) 173 | { 174 | if (!strcmp(uname_m, subarches[i].name)) 175 | { 176 | subarch = subarches[i].subarch; 177 | break; 178 | } 179 | } 180 | 181 | if (subarch == 0) 182 | { 183 | fprintf(stderr, "Error: unknown ARM architecture '%s'\n", 184 | uname_m); 185 | return 1; 186 | } 187 | } 188 | else 189 | { 190 | perror("Error: uname() failed"); 191 | return 1; 192 | } 193 | 194 | fputs("CPU_FLAGS_ARM:", stdout); 195 | 196 | for (i = 0; flags[i].name; ++i) 197 | { 198 | unsigned long* reg = 0; 199 | 200 | switch (flags[i].type) 201 | { 202 | case CHECK_HWCAP: 203 | if (subarch < SUBARCH_AARCH64) 204 | reg = &hwcap; 205 | break; 206 | case CHECK_HWCAP2: 207 | if (subarch < SUBARCH_AARCH64) 208 | reg = &hwcap2; 209 | break; 210 | case CHECK_AARCH64_HWCAP: 211 | if (subarch >= SUBARCH_AARCH64) 212 | reg = &hwcap; 213 | break; 214 | case CHECK_AARCH64_HWCAP2: 215 | if (subarch >= SUBARCH_AARCH64) 216 | reg = &hwcap2; 217 | break; 218 | case CHECK_SUBARCH: 219 | reg = &subarch; 220 | break; 221 | case CHECK_SENTINEL: 222 | assert(0 && "CHECK_SENTINEL reached"); 223 | case CHECK_MAX: 224 | assert(0 && "CHECK_MAX reached"); 225 | } 226 | assert(flags[i].type <= CHECK_MAX); 227 | 228 | if (reg) 229 | { 230 | if ((*reg & flags[i].mask) == flags[i].mask) 231 | { 232 | fputc(' ', stdout); 233 | fputs(flags[i].name, stdout); 234 | } 235 | } 236 | } 237 | 238 | fputs("\n", stdout); 239 | return 0; 240 | } 241 | 242 | #endif /*CPUID_ARM*/ 243 | -------------------------------------------------------------------------------- /src/hwcap-dump.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- dumping tool for AT_HWCAP* 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #include 12 | #include 13 | 14 | #if LONG_BIT > 64 15 | # error "Surprisingly long LONG_BIT value" 16 | #endif 17 | 18 | #include "hwcap.h" 19 | 20 | /** 21 | * Prints AT_HWCAP* dump suitable for mocking tests. 22 | */ 23 | int main(int argc, char* argv[]) 24 | { 25 | unsigned long val = 0; 26 | const char* uname_m; 27 | 28 | val = get_hwcap(); 29 | printf("hwcap:%016lx\n", val); 30 | val = get_hwcap2(); 31 | printf("hwcap2:%016lx\n", val); 32 | uname_m = get_uname_machine(); 33 | if (uname_m) 34 | printf("machine:%s\n", uname_m); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/hwcap.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- native AT_HWCAP* getters 2 | * (c) 2015-2024 Michał Górny 3 | * (c) 2022 Alexey Dokuchaev 4 | * SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifdef HAVE_CONFIG_H 8 | # include "config.h" 9 | #endif 10 | #include "platforms.h" 11 | 12 | #if defined(CPUID_ARM) || defined(CPUID_PPC) 13 | 14 | #include 15 | #include 16 | #ifdef __FreeBSD__ 17 | # include 18 | #else 19 | # include 20 | #endif 21 | 22 | #ifdef __FreeBSD__ 23 | static unsigned long getauxval(int aux) 24 | { 25 | unsigned long auxval = 0; 26 | elf_aux_info(aux, &auxval, sizeof(auxval)); 27 | return auxval; 28 | } 29 | #endif 30 | 31 | #include "hwcap.h" 32 | 33 | /** 34 | * Returns native AT_HWCAP value. 35 | */ 36 | unsigned long get_hwcap() 37 | { 38 | return getauxval(AT_HWCAP); 39 | } 40 | 41 | /** 42 | * Returns native AT_HWCAP2 value. 43 | */ 44 | unsigned long get_hwcap2() 45 | { 46 | #ifdef AT_HWCAP2 47 | return getauxval(AT_HWCAP2); 48 | #else 49 | return 0; 50 | #endif 51 | } 52 | 53 | /** 54 | * Returns machine name from utsname data, or NULL on failure. 55 | * 56 | * The data is stored in static buffer of undefined length. The caller 57 | * may modify the string, and must not free it. 58 | */ 59 | char* get_uname_machine() 60 | { 61 | #ifdef __FreeBSD__ 62 | /** 63 | * On FreeBSD, `uname -m' is too vague to distinguish between 64 | * particular CPUs, so we return more unique `uname -p' instead. 65 | * Because there is no `uname_res.machine_arch' field, we have 66 | * to call sysctl(3) rather than uname(3). 67 | */ 68 | int mib[] = { CTL_HW, HW_MACHINE_ARCH }; 69 | static char buf[48]; 70 | size_t len = sizeof(buf); 71 | if (sysctl(mib, 2, &buf, &len, NULL, 0) == 0) 72 | return buf; 73 | #else 74 | static struct utsname uname_res; 75 | if (uname(&uname_res) != -1) 76 | return uname_res.machine; 77 | #endif 78 | else 79 | return NULL; 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/hwcap.h: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- AT_HWCAP* routine prototypes 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | unsigned long get_hwcap(); 7 | unsigned long get_hwcap2(); 8 | char* get_uname_machine(); 9 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- main program (mostly option parsing) 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #include 12 | #include 13 | 14 | int print_flags(); 15 | 16 | struct option long_options[] = { 17 | { "help", no_argument, 0, 'h' }, 18 | { "version", no_argument, 0, 'V' }, 19 | { 0, 0, 0, 0 } 20 | }; 21 | 22 | const char* usage = "Usage: %s [options]\n" 23 | "\n" 24 | "Options:\n" 25 | " -h, --help print this help message\n" 26 | " -V, --version print program version\n"; 27 | 28 | int main(int argc, char* argv[]) 29 | { 30 | int opt; 31 | 32 | while ((opt = getopt_long(argc, argv, "hV", long_options, 0)) != -1) 33 | { 34 | switch (opt) 35 | { 36 | case 'h': 37 | printf(usage, argv[0]); 38 | return 0; 39 | case 'V': 40 | puts(PACKAGE_STRING); 41 | return 0; 42 | case '?': 43 | fprintf(stderr, usage, argv[0]); 44 | return 1; 45 | } 46 | } 47 | if (optind != argc) 48 | { 49 | fprintf(stderr, "%s: unexpected position parameter\n", argv[0]); 50 | fprintf(stderr, usage, argv[0]); 51 | return 1; 52 | } 53 | 54 | return print_flags(); 55 | } 56 | -------------------------------------------------------------------------------- /src/mock.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- mocked routines for tests 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | 10 | #include 11 | #include 12 | #ifdef HAVE_INTTYPES_H 13 | # include 14 | #endif 15 | #ifdef HAVE_STDINT_H 16 | # include 17 | #endif 18 | 19 | #include "x86.h" 20 | #include "hwcap.h" 21 | 22 | int print_flags(); 23 | 24 | FILE* mocked_regs_f; 25 | 26 | /** 27 | * Get CPUID value from mocked test description for specified level 28 | * and fill passed register variables (where not NULL). 29 | * 30 | * Returns 1 on sucess, 0 if not present. 31 | */ 32 | int run_cpuid(uint32_t level, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) 33 | { 34 | rewind(mocked_regs_f); 35 | while (!feof(mocked_regs_f) && !ferror(mocked_regs_f)) 36 | { 37 | uint32_t level_, eax_, ebx_, ecx_, edx_; 38 | int ret; 39 | 40 | ret = fscanf(mocked_regs_f, "top:%08" PRIx32 ":%08" PRIx32 41 | ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32, 42 | &level_, &eax_, &ebx_, &ecx_, &edx_); 43 | if (ret > 0 && level_ == level) 44 | { 45 | assert(ret == 5); 46 | if (eax) 47 | *eax = eax_; 48 | if (ebx) 49 | *ebx = ebx_; 50 | if (ecx) 51 | *ecx = ecx_; 52 | if (edx) 53 | *edx = edx_; 54 | return 1; 55 | } 56 | else if (ferror(mocked_regs_f)) 57 | { 58 | perror("Reading mocked register file failed"); 59 | return 0; 60 | } 61 | 62 | /* seek to the next line */ 63 | do 64 | ret = fgetc(mocked_regs_f); 65 | while (ret != '\n' && ret != EOF); 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | /** 72 | * Get CPUID value from mocked test description for specified level 73 | * and subleaf, and fill passed register variables (where not NULL). 74 | * 75 | * Returns 1 on sucess, 0 if not present. 76 | */ 77 | int run_cpuid_sub(uint32_t level, uint32_t sublevel, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) 78 | { 79 | rewind(mocked_regs_f); 80 | while (!feof(mocked_regs_f) && !ferror(mocked_regs_f)) 81 | { 82 | uint32_t level_, sublevel_, eax_, ebx_, ecx_, edx_; 83 | int ret; 84 | 85 | ret = fscanf(mocked_regs_f, "sub:%08" PRIx32 ":%08" PRIx32 86 | ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32, 87 | &level_, &sublevel_, &eax_, &ebx_, &ecx_, &edx_); 88 | if (ret > 0 && level_ == level && sublevel_ == sublevel) 89 | { 90 | assert(ret == 6); 91 | if (eax) 92 | *eax = eax_; 93 | if (ebx) 94 | *ebx = ebx_; 95 | if (ecx) 96 | *ecx = ecx_; 97 | if (edx) 98 | *edx = edx_; 99 | return 1; 100 | } 101 | else if (ferror(mocked_regs_f)) 102 | { 103 | perror("Reading mocked register file failed"); 104 | return 0; 105 | } 106 | 107 | /* seek to the next line */ 108 | do 109 | ret = fgetc(mocked_regs_f); 110 | while (ret != '\n' && ret != EOF); 111 | } 112 | 113 | return 0; 114 | } 115 | 116 | /** 117 | * Returns AT_HWCAP from mocked test description. 118 | */ 119 | unsigned long get_hwcap() 120 | { 121 | rewind(mocked_regs_f); 122 | while (!feof(mocked_regs_f) && !ferror(mocked_regs_f)) 123 | { 124 | unsigned long val_; 125 | int ret; 126 | 127 | ret = fscanf(mocked_regs_f, "hwcap:%016lx", &val_); 128 | if (ret > 0) 129 | { 130 | assert(ret == 1); 131 | return val_; 132 | } 133 | else if (ferror(mocked_regs_f)) 134 | { 135 | perror("Reading mocked register file failed"); 136 | return 0; 137 | } 138 | 139 | /* seek to the next line */ 140 | do 141 | ret = fgetc(mocked_regs_f); 142 | while (ret != '\n' && ret != EOF); 143 | } 144 | 145 | return 0; 146 | } 147 | 148 | /** 149 | * Returns AT_HWCAP2 from mocked test description. 150 | */ 151 | unsigned long get_hwcap2() 152 | { 153 | rewind(mocked_regs_f); 154 | while (!feof(mocked_regs_f) && !ferror(mocked_regs_f)) 155 | { 156 | unsigned long val_; 157 | int ret; 158 | 159 | ret = fscanf(mocked_regs_f, "hwcap2:%016lx", &val_); 160 | if (ret > 0) 161 | { 162 | assert(ret == 1); 163 | return val_; 164 | } 165 | else if (ferror(mocked_regs_f)) 166 | { 167 | perror("Reading mocked register file failed"); 168 | return 0; 169 | } 170 | 171 | /* seek to the next line */ 172 | do 173 | ret = fgetc(mocked_regs_f); 174 | while (ret != '\n' && ret != EOF); 175 | } 176 | 177 | return 0; 178 | } 179 | 180 | /** 181 | * Returns machine name from mocked test description, or NULL if missing. 182 | * 183 | * The data is stored in static buffer of undefined length. The caller 184 | * may modify the string, and must not free it. 185 | */ 186 | char* get_uname_machine() 187 | { 188 | rewind(mocked_regs_f); 189 | while (!feof(mocked_regs_f) && !ferror(mocked_regs_f)) 190 | { 191 | static char buf[64]; 192 | int ret; 193 | 194 | ret = fscanf(mocked_regs_f, "machine:%63s", buf); 195 | if (ret > 0) 196 | { 197 | assert(ret == 1); 198 | return buf; 199 | } 200 | else if (ferror(mocked_regs_f)) 201 | { 202 | perror("Reading mocked register file failed"); 203 | return NULL; 204 | } 205 | 206 | /* seek to the next line */ 207 | do 208 | ret = fgetc(mocked_regs_f); 209 | while (ret != '\n' && ret != EOF); 210 | } 211 | 212 | return NULL; 213 | } 214 | 215 | int main(int argc, char* argv[]) 216 | { 217 | const char* mocked_regs = argv[1]; 218 | 219 | if (!mocked_regs) 220 | { 221 | fprintf(stderr, "Usage: x86-test \n"); 222 | return 1; 223 | } 224 | 225 | mocked_regs_f = fopen(mocked_regs, "r"); 226 | if (!mocked_regs_f) 227 | { 228 | perror("Unable to open mocked register data"); 229 | return 1; 230 | } 231 | 232 | print_flags(); 233 | 234 | fclose(mocked_regs_f); 235 | return 0; 236 | } 237 | -------------------------------------------------------------------------------- /src/platforms.h: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- platform detection 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifndef CPUID_MOCK 7 | /* check for supported platforms */ 8 | # if defined(__x86_64) || defined(__i386) 9 | # define CPUID_X86 10 | # elif defined(__arm__) || defined(__aarch64__) 11 | # define CPUID_ARM 12 | # elif defined(__powerpc__) 13 | # define CPUID_PPC 14 | # else 15 | # error "Unsupported platform, please report" 16 | # endif 17 | #endif 18 | -------------------------------------------------------------------------------- /src/ppc.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- PowerPC-specific detection routines 2 | * (c) 2015-2024 Michał Górny 3 | * (c) 2015-2019 Michał Górny 4 | * (c) 2019 Georgy Yakovlev 5 | * (c) 2019 Shawn Anastasio 6 | * SPDX-License-Identifier: GPL-2.0-or-later 7 | */ 8 | 9 | #ifdef HAVE_CONFIG_H 10 | # include "config.h" 11 | #endif 12 | #include "platforms.h" 13 | 14 | #ifdef CPUID_PPC 15 | 16 | #include 17 | #include 18 | #ifdef HAVE_STDINT_H 19 | # include 20 | #endif 21 | #include 22 | 23 | #include "hwcap.h" 24 | 25 | /** 26 | * Supported checks: 27 | * 28 | * - CHECK_HWCAP and CHECK_HWCAP2 refer to appropriate AT_HWCAP* values. 29 | */ 30 | enum check_type 31 | { 32 | CHECK_SENTINEL = 0, 33 | CHECK_HWCAP, 34 | CHECK_HWCAP2, 35 | CHECK_MAX 36 | }; 37 | 38 | struct flag_info 39 | { 40 | const char* name; 41 | enum check_type type; 42 | unsigned long mask; 43 | }; 44 | 45 | struct flag_info flags[] = { 46 | /* taken from /usr/include/bits/hwcap.h */ 47 | /* PPC_FEATURE_HAS_ALTIVEC */ 48 | { "altivec", CHECK_HWCAP, 0x10000000 }, 49 | /* PPC_FEATURE_HAS_VSX */ 50 | { "vsx", CHECK_HWCAP, 0x00000080 }, 51 | /* PPC_FEATURE2_ARCH_2_07 */ 52 | { "vsx2", CHECK_HWCAP2, 0x80000000 }, 53 | /* PPC_FEATURE2_ARCH_3_00 */ 54 | { "vsx3", CHECK_HWCAP2, 0x00800000 }, 55 | { 0 } 56 | }; 57 | 58 | /** 59 | * Print CPU_FLAGS_PPC based on AT_HWCAP*. 60 | * 61 | * Returns exit status (0 on success, non-zero on failure). 62 | */ 63 | int print_flags() 64 | { 65 | unsigned long hwcap = 0, hwcap2 = 0; 66 | int i; 67 | 68 | hwcap = get_hwcap(); 69 | hwcap2 = get_hwcap2(); 70 | 71 | fputs("CPU_FLAGS_PPC:", stdout); 72 | 73 | for (i = 0; flags[i].name; ++i) 74 | { 75 | unsigned long* reg = 0; 76 | 77 | switch (flags[i].type) 78 | { 79 | case CHECK_HWCAP: 80 | reg = &hwcap; 81 | break; 82 | case CHECK_HWCAP2: 83 | reg = &hwcap2; 84 | break; 85 | case CHECK_SENTINEL: 86 | assert(0 && "CHECK_SENTINEL reached"); 87 | case CHECK_MAX: 88 | assert(0 && "CHECK_MAX reached"); 89 | } 90 | assert(flags[i].type <= CHECK_MAX); 91 | 92 | if (reg) 93 | { 94 | if ((*reg & flags[i].mask) == flags[i].mask) 95 | { 96 | fputc(' ', stdout); 97 | fputs(flags[i].name, stdout); 98 | } 99 | } 100 | } 101 | 102 | fputs("\n", stdout); 103 | return 0; 104 | } 105 | 106 | #endif /*CPUID_PPC*/ 107 | -------------------------------------------------------------------------------- /src/x86-dump.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- X86 CPUID dumping tool 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #include 12 | #ifdef HAVE_INTTYPES_H 13 | # include 14 | #endif 15 | #ifdef HAVE_STDINT_H 16 | # include 17 | #endif 18 | 19 | #include "x86.h" 20 | 21 | /** 22 | * Dump the value of specified CPUID level. 23 | */ 24 | void dump(uint32_t level) 25 | { 26 | uint32_t eax, ebx, ecx, edx; 27 | int ret; 28 | 29 | ret = run_cpuid(level, &eax, &ebx, &ecx, &edx); 30 | 31 | if (ret) 32 | printf("top:%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 33 | ":%08" PRIx32 ":%08" PRIx32 "\n", 34 | level, eax, ebx, ecx, edx); 35 | } 36 | 37 | /** 38 | * Dump the value of specified CPUID level with subleaf. 39 | */ 40 | void dump_leaf(uint32_t level, uint32_t leaf) 41 | { 42 | uint32_t eax, ebx, ecx, edx; 43 | int ret; 44 | 45 | ret = run_cpuid_sub(level, leaf, &eax, &ebx, &ecx, &edx); 46 | 47 | if (ret) 48 | printf("sub:%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 49 | ":%08" PRIx32 ":%08" PRIx32 ":%08" PRIx32 "\n", 50 | level, leaf, eax, ebx, ecx, edx); 51 | } 52 | 53 | /** 54 | * Prints CPUID dump suitable for mocking tests. 55 | */ 56 | int main(int argc, char* argv[]) 57 | { 58 | #ifdef CPUID_X86 59 | /* Intel */ 60 | dump(0x00000001); 61 | /* Intel ext. */ 62 | dump_leaf(0x00000007, 0x00000000); 63 | dump_leaf(0x00000007, 0x00000001); 64 | /* AMD */ 65 | dump(0x80000001); 66 | /* Centaur (VIA) */ 67 | dump(0xC0000001); 68 | #else 69 | fprintf(stderr, "This program works only on x86\n"); 70 | #endif 71 | } 72 | -------------------------------------------------------------------------------- /src/x86-lib.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- X86 CPUID native getter 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #ifdef CPUID_X86 12 | 13 | #include 14 | 15 | #include "x86.h" 16 | 17 | /** 18 | * Run native CPUID for specified level, and fill passed register 19 | * variables (where not NULL). 20 | * 21 | * Returns 1 on sucess, 0 if not supported by the CPU. 22 | */ 23 | int run_cpuid(uint32_t level, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) 24 | { 25 | uint32_t eax_, ebx_, ecx_, edx_; 26 | 27 | /* We can't use __get_cpuid() since it can't do Centaur extended 28 | * flags (it's limited to Intel & AMD namespaces by poor design) */ 29 | 30 | /* TODO: we need to figure out if 0xN0000000 is even valid 31 | * otherwise it will fallback to last supported CPUID... */ 32 | if (__get_cpuid_max(level & 0xf0000000, 0) < level) 33 | return 0; 34 | __cpuid(level, eax_, ebx_, ecx_, edx_); 35 | 36 | if (eax) 37 | *eax = eax_; 38 | if (ebx) 39 | *ebx = ebx_; 40 | if (ecx) 41 | *ecx = ecx_; 42 | if (edx) 43 | *edx = edx_; 44 | return 1; 45 | } 46 | 47 | /** 48 | * Run native CPUID for specified level and subleaf, and fill passed 49 | * register variables (where not NULL). 50 | * 51 | * Returns 1 on sucess, 0 if not supported by the CPU. 52 | */ 53 | int run_cpuid_sub(uint32_t level, uint32_t sublevel, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) 54 | { 55 | uint32_t eax_, ebx_, ecx_, edx_; 56 | 57 | if (__get_cpuid_max(level & 0xf0000000, 0) < level) 58 | return 0; 59 | __cpuid_count(level, sublevel, eax_, ebx_, ecx_, edx_); 60 | 61 | if (eax) 62 | *eax = eax_; 63 | if (ebx) 64 | *ebx = ebx_; 65 | if (ecx) 66 | *ecx = ecx_; 67 | if (edx) 68 | *edx = edx_; 69 | return 1; 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/x86.c: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- X86-specific detection routines 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "config.h" 8 | #endif 9 | #include "platforms.h" 10 | 11 | #ifdef CPUID_X86 12 | 13 | #include 14 | #include 15 | #ifdef HAVE_STDINT_H 16 | # include 17 | #endif 18 | #include 19 | 20 | #include "x86.h" 21 | 22 | /** 23 | * Supported checks: 24 | * 25 | * - INTEL_{ECX,EDX} -- registers of 0x00000001 CPUID. 26 | * - INTEL_SUB0_{EBX,ECX,EDX} -- registers of 0x00000007 / leaf 0 CPUID. 27 | * - INTEL_SUB1_EAX -- registers of 0x00000007 / leaf 1 CPUID. 28 | * - AMD_{ECX,EDX} -- registers of 0x80000001 CPUID. 29 | * - VIA_EDX -- register of 0xC0000001 CPUID. 30 | */ 31 | enum check_type 32 | { 33 | CHECK_SENTINEL = 0, 34 | 35 | INTEL_ECX, 36 | INTEL_EDX, 37 | INTEL_SUB0_EBX, 38 | INTEL_SUB0_ECX, 39 | INTEL_SUB0_EDX, 40 | INTEL_SUB1_EAX, 41 | AMD_ECX, 42 | AMD_EDX, 43 | VIA_EDX, 44 | 45 | CHECK_MAX 46 | }; 47 | 48 | struct flag_info 49 | { 50 | const char* name; 51 | enum check_type type; 52 | uint32_t mask; 53 | }; 54 | 55 | struct flag_info flags[] = { 56 | { "3dnow", AMD_EDX, (1 << 31) }, 57 | { "3dnowext", AMD_EDX, (1 << 30) }, /* 3DNow!+ */ 58 | { "aes", INTEL_ECX, (1 << 25) }, 59 | { "amx_bf16", INTEL_SUB0_EDX, (1 << 22) }, 60 | { "amx_int8", INTEL_SUB0_EDX, (1 << 25) }, 61 | { "amx_tile", INTEL_SUB0_EDX, (1 << 24) }, 62 | { "avx", INTEL_ECX, (1 << 28) }, 63 | { "avx2", INTEL_SUB0_EBX, (1 << 5) }, 64 | { "avx512_4fmaps", INTEL_SUB0_EDX, (1 << 3) }, 65 | { "avx512_4vnniw", INTEL_SUB0_EDX, (1 << 2) }, 66 | { "avx512_bf16", INTEL_SUB1_EAX, (1 << 5) }, 67 | { "avx512_bitalg", INTEL_SUB0_ECX, (1 << 12) }, 68 | { "avx512_fp16", INTEL_SUB0_EDX, (1 << 23) }, 69 | { "avx512_vbmi2", INTEL_SUB0_ECX, (1 << 6) }, 70 | { "avx512_vnni", INTEL_SUB0_ECX, (1 << 11) }, 71 | { "avx512_vp2intersect", INTEL_SUB0_EDX, (1 << 8) }, 72 | { "avx512_vpopcntdq", INTEL_SUB0_ECX, (1 << 14) }, 73 | { "avx512bw", INTEL_SUB0_EBX, (1 << 30) }, 74 | { "avx512cd", INTEL_SUB0_EBX, (1 << 28) }, 75 | { "avx512dq", INTEL_SUB0_EBX, (1 << 17) }, 76 | { "avx512er", INTEL_SUB0_EBX, (1 << 27) }, 77 | { "avx512f", INTEL_SUB0_EBX, (1 << 16) }, 78 | { "avx512ifma", INTEL_SUB0_EBX, (1 << 21) }, 79 | { "avx512pf", INTEL_SUB0_EBX, (1 << 26) }, 80 | { "avx512vbmi", INTEL_SUB0_ECX, (1 << 1) }, 81 | { "avx512vl", INTEL_SUB0_EBX, (1 << 31) }, 82 | { "avx_vnni", INTEL_SUB1_EAX, (1 << 4) }, 83 | { "bmi1", INTEL_SUB0_EBX, (1 << 3) }, 84 | { "bmi2", INTEL_SUB0_EBX, (1 << 8) }, 85 | { "f16c", INTEL_ECX, (1 << 29) }, 86 | { "fma3", INTEL_ECX, (1 << 12) }, 87 | { "fma4", AMD_ECX, (1 << 16) }, 88 | { "mmx", INTEL_EDX, (1 << 23) }, 89 | { "mmxext", AMD_EDX, (1 << 22) }, /* AMD */ 90 | { "mmxext", INTEL_EDX, (1 << 25) }, /* implied by SSE on Intel */ 91 | { "padlock", VIA_EDX, (1 << 10) }, /* PHE */ 92 | { "pclmul", INTEL_ECX, (1 << 1) }, 93 | { "popcnt", AMD_ECX, (1 << 5) }, /* ABM on AMD; XXX: manuals say it's LZCNT */ 94 | { "popcnt", INTEL_ECX, (1 << 23) }, /* Intel */ 95 | { "rdrand", INTEL_ECX, (1 << 30) }, 96 | { "sha", INTEL_SUB0_EBX, (1 << 29) }, 97 | { "sse", INTEL_EDX, (1 << 25) }, 98 | { "sse2", INTEL_EDX, (1 << 26) }, 99 | { "sse3", INTEL_ECX, (1 << 0) }, 100 | { "sse4_1", INTEL_ECX, (1 << 19) }, 101 | { "sse4_2", INTEL_ECX, (1 << 20) }, 102 | { "sse4a", AMD_ECX, (1 << 6) }, 103 | { "ssse3", INTEL_ECX, (1 << 9) }, 104 | { "vpclmulqdq", INTEL_SUB0_ECX, (1 << 10) }, 105 | { "xop", AMD_ECX, (1 << 11) }, 106 | { 0 } 107 | }; 108 | 109 | /** 110 | * Print CPU_FLAGS_X86 based on CPUID. 111 | * 112 | * Returns exit status (0 on success, non-zero on failure). 113 | */ 114 | int print_flags() 115 | { 116 | uint32_t intel_ecx = 0, intel_edx = 0; 117 | uint32_t intel_sub0_ebx = 0, intel_sub0_ecx = 0, intel_sub0_edx = 0; 118 | uint32_t intel_sub1_eax = 0; 119 | uint32_t amd_ecx = 0, amd_edx = 0; 120 | uint32_t centaur_edx = 0; 121 | 122 | int got_intel, got_intel_sub0, got_intel_sub1, got_amd, got_centaur; 123 | 124 | const char* last = ""; 125 | int i; 126 | 127 | /* Intel */ 128 | got_intel = run_cpuid(0x00000001, 0, 0, &intel_ecx, &intel_edx); 129 | /* Intel ext. */ 130 | got_intel_sub0 = run_cpuid_sub(0x00000007, 0x00000000, 131 | 0, &intel_sub0_ebx, &intel_sub0_ecx, &intel_sub0_edx); 132 | got_intel_sub1 = run_cpuid_sub(0x00000007, 0x00000001, 133 | &intel_sub1_eax, 0, 0, 0); 134 | /* AMD */ 135 | got_amd = run_cpuid(0x80000001, 0, 0, &amd_ecx, &amd_edx); 136 | /* Centaur (VIA) */ 137 | got_centaur = run_cpuid(0xC0000001, 0, 0, 0, ¢aur_edx); 138 | 139 | fputs("CPU_FLAGS_X86:", stdout); 140 | 141 | for (i = 0; flags[i].name; ++i) 142 | { 143 | uint32_t* reg = 0; 144 | 145 | switch (flags[i].type) 146 | { 147 | case INTEL_ECX: 148 | if (got_intel) 149 | reg = &intel_ecx; 150 | break; 151 | case INTEL_EDX: 152 | if (got_intel) 153 | reg = &intel_edx; 154 | break; 155 | case INTEL_SUB0_EBX: 156 | if (got_intel_sub0) 157 | reg = &intel_sub0_ebx; 158 | break; 159 | case INTEL_SUB0_ECX: 160 | if (got_intel_sub0) 161 | reg = &intel_sub0_ecx; 162 | break; 163 | case INTEL_SUB0_EDX: 164 | if (got_intel_sub0) 165 | reg = &intel_sub0_edx; 166 | break; 167 | case INTEL_SUB1_EAX: 168 | if (got_intel_sub1) 169 | reg = &intel_sub1_eax; 170 | break; 171 | case AMD_ECX: 172 | if (got_amd) 173 | reg = &amd_ecx; 174 | break; 175 | case AMD_EDX: 176 | if (got_amd) 177 | reg = &amd_edx; 178 | break; 179 | case VIA_EDX: 180 | if (got_centaur) 181 | reg = ¢aur_edx; 182 | break; 183 | case CHECK_SENTINEL: 184 | assert(0 && "CHECK_SENTINEL reached"); 185 | case CHECK_MAX: 186 | assert(0 && "CHECK_MAX reached"); 187 | } 188 | assert(flags[i].type <= CHECK_MAX); 189 | 190 | if (reg) 191 | { 192 | if ((*reg & flags[i].mask) == flags[i].mask) 193 | { 194 | if (strcmp(last, flags[i].name)) 195 | { 196 | fputc(' ', stdout); 197 | fputs(flags[i].name, stdout); 198 | 199 | last = flags[i].name; 200 | } 201 | } 202 | } 203 | } 204 | 205 | fputs("\n", stdout); 206 | return 0; 207 | } 208 | 209 | #endif /*CPUID_X86*/ 210 | -------------------------------------------------------------------------------- /src/x86.h: -------------------------------------------------------------------------------- 1 | /* cpuid2cpuflags -- X86 CPUID routine prototypes 2 | * (c) 2015-2024 Michał Górny 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | #ifdef HAVE_STDINT_H 7 | # include 8 | #endif 9 | 10 | int run_cpuid(uint32_t level, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); 11 | int run_cpuid_sub(uint32_t level, uint32_t sublevel, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); 12 | -------------------------------------------------------------------------------- /tests/arm/aarch64-aws-a1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:00000000000008ff 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-cavium-thunderx.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:00000000000001ff 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-cavium-thunderx2.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:00000000000019ff 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-dragonboard.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:0000000000000087 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-hp-moonshot-xgene-1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:0000000000000007 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-neoverse-n1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 asimddp v4 v5 v6 v7 v8 thumb2 2 | hwcap:0000000010119fff 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-odroid-n2.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:00000000000000ff 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/aarch64-raspberry-4.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:0000000000000887 3 | hwcap2:0000000000000000 4 | machine:aarch64 5 | -------------------------------------------------------------------------------- /tests/arm/armv5tel-dreamplug.txt: -------------------------------------------------------------------------------- 1 | expected:edsp thumb v4 v5 2 | hwcap:0000000000000097 3 | hwcap2:0000000000000000 4 | machine:armv5tel 5 | -------------------------------------------------------------------------------- /tests/arm/armv6l-raspberry-pi1b.txt: -------------------------------------------------------------------------------- 1 | expected:edsp thumb vfp v4 v5 v6 2 | hwcap:00000000000081d6 3 | hwcap2:0000000000000000 4 | machine:armv6l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-beaglebone.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:000000000008b8d6 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-compulab-utilite-pro.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:000000000008b0d6 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-jhcloos-cheap.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:00000000000fb8d7 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-odroid-c1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:000000000009b0d7 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-raspberry-pi3.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 crc32 v4 v5 v6 v7 thumb2 2 | hwcap:00000000003fb0d6 3 | hwcap2:0000000000000010 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-rk3288.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:00000000003fb8d7 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-scaleway-c1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp thumb vfp vfpv3 vfp-d32 v4 v5 v6 v7 thumb2 2 | hwcap:00000000001ea8d6 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv7l-solidrun-cubox.txt: -------------------------------------------------------------------------------- 1 | expected:edsp iwmmxt thumb vfp vfpv3 v4 v5 v6 v7 thumb2 2 | hwcap:000000000004ead6 3 | hwcap2:0000000000000000 4 | machine:armv7l 5 | -------------------------------------------------------------------------------- /tests/arm/armv8l-neoverse-n1.txt: -------------------------------------------------------------------------------- 1 | expected:edsp neon thumb vfp vfpv3 vfpv4 aes sha1 sha2 crc32 v4 v5 v6 v7 v8 thumb2 2 | hwcap:000000000037b0d6 3 | hwcap2:000000000000001f 4 | machine:armv8l 5 | -------------------------------------------------------------------------------- /tests/ppc/power8.txt: -------------------------------------------------------------------------------- 1 | expected:altivec vsx vsx2 2 | hwcap:00000000dc0065c2 3 | hwcap2:00000000be000000 4 | -------------------------------------------------------------------------------- /tests/ppc/power9.txt: -------------------------------------------------------------------------------- 1 | expected:altivec vsx vsx2 vsx3 2 | hwcap:00000000dc0065c2 3 | hwcap2:00000000bee00000 4 | -------------------------------------------------------------------------------- /tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # cpuid2cpuflags 3 | # (c) 2019 Michał Górny 4 | # 2-clause BSD licensed 5 | 6 | BINDIR=${1} 7 | SUITE=${2%/*} 8 | ARCH=${SUITE##*/} 9 | ARCH_UC=$(echo "${ARCH}" | tr '[[:lower:]]' '[[:upper:]]') 10 | MOCK=${BINDIR}/${ARCH}-mock 11 | EXPECTED=$(sed -n -e "s/^expected:/CPU_FLAGS_${ARCH_UC}: /p" "${2}") 12 | 13 | if [ -z "${EXPECTED}" ]; then 14 | echo "expected: not found in test case!" >&2 15 | exit 1 16 | fi 17 | 18 | if [ ! -x "${MOCK}" ]; then 19 | echo "${MOCK} not executable!" >&2 20 | exit 1 21 | fi 22 | 23 | RESULT=$("${MOCK}" "${2}") 24 | RET=${?} 25 | if [ ${RET} -ne 0 ]; then 26 | echo "${MOCK} failed (exit status: ${RET})!" >&2 27 | fi 28 | 29 | echo "Expected: ${EXPECTED}" 30 | echo "Result: ${RESULT}" 31 | if [ "${EXPECTED}" != "${RESULT}" ]; then 32 | echo "Result does not match!" >&2 33 | RET=1 34 | fi 35 | 36 | exit "${RET}" 37 | -------------------------------------------------------------------------------- /tests/x86/amd-colfax.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 2 | top:00000001:00800f82:0b400800:7ed8320b:178bfbff 3 | sub:00000007:00000000:00000000:209c01a9:00000000:00000000 4 | top:80000001:00800f82:70000000:35c233ff:2fd3fbff 5 | -------------------------------------------------------------------------------- /tests/x86/amd-zen2.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 2 | top:00000001:00870f10:050c0800:7ed8320b:178bfbff 3 | sub:00000007:00000000:00000000:219c91a9:00400004:00000000 4 | top:80000001:00870f10:20000000:75c237ff:2fd3fbff 5 | -------------------------------------------------------------------------------- /tests/x86/amd-zen4-ryzen-7-pro-7840u.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 avx512_bf16 avx512_bitalg avx512_vbmi2 avx512_vnni avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 vpclmulqdq 2 | top:00000001:00a70f41:06100800:7ef8320b:178bfbff 3 | sub:00000007:00000000:00000001:f1bf97a9:00405fde:10000000 4 | sub:00000007:00000001:00000020:00000000:00000000:00000000 5 | top:80000001:00a70f41:40000000:75c237ff:2fd3fbff 6 | -------------------------------------------------------------------------------- /tests/x86/amd-zen4.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 avx512_bf16 avx512_bitalg avx512_vbmi2 avx512_vnni avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 vpclmulqdq 2 | top:00000001:00a60f12:1f200800:7ef8320b:178bfbff 3 | sub:00000007:00000000:00000001:f1bf97a9:00405fde:10000010 4 | sub:00000007:00000001:00000020:00000000:00000000:00000000 5 | top:80000001:00a60f12:00000000:75c237ff:2fd3fbff 6 | -------------------------------------------------------------------------------- /tests/x86/athlon64-windsor.txt: -------------------------------------------------------------------------------- 1 | expected:3dnow 3dnowext mmx mmxext sse sse2 sse3 2 | top:00000001:00040fb2:01020800:00002001:178bfbff 3 | top:80000001:00040fb2:0000090d:0000001f:ebd3fbff 4 | -------------------------------------------------------------------------------- /tests/x86/i3-ivybridge.txt: -------------------------------------------------------------------------------- 1 | expected:avx f16c mmx mmxext pclmul popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3 2 | top:00000001:000306a9:01100800:3dbae3bf:bfebfbff 3 | sub:00000007:00000000:00000000:00000281:00000000:00000000 4 | top:80000001:00000000:00000000:00000001:28100800 5 | -------------------------------------------------------------------------------- /tests/x86/opteron-6272.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx fma4 mmx mmxext pclmul popcnt sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 xop 2 | top:00000001:00600f12:06100800:1e98220b:178bfbff 3 | sub:00000007:00000000:00000000:00000000:00000000:00000000 4 | top:80000001:00600f12:30000000:01c9bfff:2fd3fbff 5 | -------------------------------------------------------------------------------- /tests/x86/xeon-e-2176g.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sse sse2 sse3 sse4_1 sse4_2 ssse3 2 | top:00000001:000906ea:07100800:7ffafbff:bfebfbff 3 | sub:00000007:00000000:00000000:029c6fbf:40000000:9c000000 4 | top:80000001:00000000:00000000:00000121:2c100800 5 | -------------------------------------------------------------------------------- /tests/x86/xeon-platinum-8480plus.txt: -------------------------------------------------------------------------------- 1 | expected:aes amx_bf16 amx_int8 amx_tile avx avx2 avx512_bf16 avx512_bitalg avx512_fp16 avx512_vbmi2 avx512_vnni avx512_vpopcntdq avx512bw avx512cd avx512dq avx512f avx512ifma avx512vbmi avx512vl avx_vnni bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sha sse sse2 sse3 sse4_1 sse4_2 ssse3 vpclmulqdq 2 | top:00000001:000806f8:8b800800:7ffefbff:bfebfbff 3 | sub:00000007:00000000:00000002:f3bfb7ef:fb417ffe:ffdd4432 4 | sub:00000007:00000001:00001c30:00000000:00000000:00040000 5 | top:80000001:00000000:00000000:00000121:2c100800 6 | -------------------------------------------------------------------------------- /tests/x86/xeon-silver-4410.txt: -------------------------------------------------------------------------------- 1 | expected:aes avx avx2 avx512bw avx512cd avx512dq avx512f avx512vl bmi1 bmi2 f16c fma3 mmx mmxext pclmul popcnt rdrand sse sse2 sse3 sse4_1 sse4_2 ssse3 2 | top:00000001:00050654:11100800:7ffefbff:bfebfbff 3 | sub:00000007:00000000:00000000:d39ffffb:00000018:9c002400 4 | top:80000001:00000000:00000000:00000121:2c100800 5 | --------------------------------------------------------------------------------