mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-10 16:12:41 +01:00
Use no-SIMD engine version when needed
If the CPU does not support the required SIMD instructions, use the stockfish_nosimd engine version instead.
This commit is contained in:
@@ -1,14 +1,6 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include src/main/cpp/nativeutil/Android.mk
|
||||||
|
|
||||||
LOCAL_MODULE := nativeutil
|
|
||||||
LOCAL_SRC_FILES := nativeutil.cpp
|
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include src/main/cpp/stockfish/Android.mk
|
include src/main/cpp/stockfish/Android.mk
|
||||||
|
|
||||||
include src/main/cpp/gtb/Android.mk
|
include src/main/cpp/gtb/Android.mk
|
||||||
|
|
||||||
include src/main/cpp/rtb/Android.mk
|
include src/main/cpp/rtb/Android.mk
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
APP_PLATFORM := android-14
|
|
||||||
APP_ABI := all
|
APP_ABI := all
|
||||||
APP_STL := c++_static
|
APP_STL := c++_static
|
||||||
APP_OPTIM := release
|
APP_OPTIM := release
|
||||||
|
|||||||
34
DroidFishApp/src/main/cpp/nativeutil/Android.mk
Normal file
34
DroidFishApp/src/main/cpp/nativeutil/Android.mk
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
UTIL_SRC_FILES := nativeutil.cpp
|
||||||
|
|
||||||
|
CPU_FEATS := cpu_features
|
||||||
|
CPU_FEATS_SRC_FILES += $(CPU_FEATS)/src/filesystem.c \
|
||||||
|
$(CPU_FEATS)/src/stack_line_reader.c \
|
||||||
|
$(CPU_FEATS)/src/string_view.c \
|
||||||
|
$(CPU_FEATS)/src/hwcaps.c \
|
||||||
|
$(CPU_FEATS)/src/unix_features_aggregator.c
|
||||||
|
|
||||||
|
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||||
|
UTIL_SRC_FILES += $(CPU_FEATS_SRC_FILES) $(CPU_FEATS)/src/cpuinfo_arm.c
|
||||||
|
endif
|
||||||
|
#ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||||
|
# UTIL_SRC_FILES += $(CPU_FEATS_SRC_FILES) $(CPU_FEATS)/src/cpuinfo_aarch64.c
|
||||||
|
#endif
|
||||||
|
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||||
|
UTIL_SRC_FILES += $(CPU_FEATS_SRC_FILES) $(CPU_FEATS)/src/cpuinfo_x86.c
|
||||||
|
endif
|
||||||
|
#ifeq ($(TARGET_ARCH_ABI),x86_64)
|
||||||
|
# UTIL_SRC_FILES += $(CPU_FEATS_SRC_FILES) $(CPU_FEATS)/src/cpuinfo_x86.c
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LOCAL_MODULE := nativeutil
|
||||||
|
LOCAL_SRC_FILES := $(UTIL_SRC_FILES)
|
||||||
|
LOCAL_CFLAGS := -I$(LOCAL_PATH)/$(CPU_FEATS)/include \
|
||||||
|
-I$(LOCAL_PATH)/$(CPU_FEATS)/include/internal \
|
||||||
|
-DHAVE_DLFCN_H=1 -DSTACK_LINE_READER_BUFFER_SIZE=1024 \
|
||||||
|
-fPIC -s
|
||||||
|
LOCAL_LDFLAGS := -fPIC -s
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
230
DroidFishApp/src/main/cpp/nativeutil/cpu_features/LICENSE
Normal file
230
DroidFishApp/src/main/cpp/nativeutil/cpu_features/LICENSE
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
For files in the `ndk_compat` folder:
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (C) 2010 The Android Open Source Project
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
174
DroidFishApp/src/main/cpp/nativeutil/cpu_features/README.md
Normal file
174
DroidFishApp/src/main/cpp/nativeutil/cpu_features/README.md
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# cpu_features [](https://travis-ci.org/google/cpu_features) [](https://ci.appveyor.com/project/gchatelet/cpu-features/branch/master)
|
||||||
|
|
||||||
|
A cross-platform C library to retrieve CPU features (such as available
|
||||||
|
instructions) at runtime.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Design Rationale](#rationale)
|
||||||
|
- [Code samples](#codesample)
|
||||||
|
- [Running sample code](#usagesample)
|
||||||
|
- [What's supported](#support)
|
||||||
|
- [Android NDK's drop in replacement](#ndk)
|
||||||
|
- [License](#license)
|
||||||
|
- [Build with cmake](#cmake)
|
||||||
|
|
||||||
|
<a name="rationale"></a>
|
||||||
|
## Design Rationale
|
||||||
|
|
||||||
|
- **Simple to use.** See the snippets below for examples.
|
||||||
|
- **Extensible.** Easy to add missing features or architectures.
|
||||||
|
- **Compatible with old compilers** and available on many architectures so it
|
||||||
|
can be used widely. To ensure that cpu_features works on as many platforms
|
||||||
|
as possible, we implemented it in a highly portable version of C: C99.
|
||||||
|
- **Sandbox-compatible.** The library uses a variety of strategies to cope
|
||||||
|
with sandboxed environments or when `cpuid` is unavailable. This is useful
|
||||||
|
when running integration tests in hermetic environments.
|
||||||
|
- **Thread safe, no memory allocation, and raises no exceptions.**
|
||||||
|
cpu_features is suitable for implementing fundamental libc functions like
|
||||||
|
`malloc`, `memcpy`, and `memcmp`.
|
||||||
|
- **Unit tested.**
|
||||||
|
|
||||||
|
<a name="codesample"></a>
|
||||||
|
### Checking features at runtime
|
||||||
|
|
||||||
|
Here's a simple example that executes a codepath if the CPU supports both the
|
||||||
|
AES and the SSE4.2 instruction sets:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
static const X86Features features = GetX86Info().features;
|
||||||
|
|
||||||
|
void Compute(void) {
|
||||||
|
if (features.aes && features.sse4_2) {
|
||||||
|
// Run optimized code.
|
||||||
|
} else {
|
||||||
|
// Run standard code.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Caching for faster evaluation of complex checks
|
||||||
|
|
||||||
|
If you wish, you can read all the features at once into a global variable, and
|
||||||
|
then query for the specific features you care about. Below, we store all the ARM
|
||||||
|
features and then check whether AES and NEON are supported.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_arm.h"
|
||||||
|
|
||||||
|
static const ArmFeatures features = GetArmInfo().features;
|
||||||
|
static const bool has_aes_and_neon = features.aes && features.neon;
|
||||||
|
|
||||||
|
// use has_aes_and_neon.
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a good approach to take if you're checking for combinations of features
|
||||||
|
when using a compiler that is slow to extract individual bits from bit-packed
|
||||||
|
structures.
|
||||||
|
|
||||||
|
### Checking compile time flags
|
||||||
|
|
||||||
|
The following code determines whether the compiler was told to use the AVX
|
||||||
|
instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
static const X86Features features = GetX86Info().features;
|
||||||
|
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
|
||||||
|
|
||||||
|
// use has_avx.
|
||||||
|
```
|
||||||
|
|
||||||
|
`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to
|
||||||
|
use AVX and 0 otherwise, combining compile time and runtime knowledge.
|
||||||
|
|
||||||
|
### Rejecting poor hardware implementations based on microarchitecture
|
||||||
|
|
||||||
|
On x86, the first incarnation of a feature in a microarchitecture might not be
|
||||||
|
the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve
|
||||||
|
the underlying microarchitecture so you can decide whether to use it.
|
||||||
|
|
||||||
|
Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction
|
||||||
|
set—but only if it's not Sandy Bridge.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
static const X86Info info = GetX86Info();
|
||||||
|
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
|
||||||
|
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
|
||||||
|
|
||||||
|
// use has_fast_avx.
|
||||||
|
```
|
||||||
|
|
||||||
|
This feature is currently available only for x86 microarchitectures.
|
||||||
|
|
||||||
|
<a name="usagesample"></a>
|
||||||
|
### Running sample code
|
||||||
|
|
||||||
|
Building `cpu_features` brings a small executable to test the library.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
% ./build/list_cpu_features
|
||||||
|
arch : x86
|
||||||
|
brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz
|
||||||
|
family : 6 (0x06)
|
||||||
|
model : 45 (0x2D)
|
||||||
|
stepping : 7 (0x07)
|
||||||
|
uarch : INTEL_SNB
|
||||||
|
flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
% ./build/list_cpu_features --json
|
||||||
|
{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="support"></a>
|
||||||
|
## What's supported
|
||||||
|
|
||||||
|
| | x86³ | ARM | AArch64 | MIPS⁴ | POWER |
|
||||||
|
|---------|:----:|:-------:|:-------:|:------:|:-------:|
|
||||||
|
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A |
|
||||||
|
| iOS | N/A | not yet | not yet | N/A | N/A |
|
||||||
|
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ |
|
||||||
|
| MacOs | yes² | N/A | not yet | N/A | no |
|
||||||
|
| Windows | yes² | not yet | not yet | N/A | N/A |
|
||||||
|
|
||||||
|
1. **Features revealed from Linux.** We gather data from several sources
|
||||||
|
depending on availability:
|
||||||
|
+ from glibc's
|
||||||
|
[getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html)
|
||||||
|
+ by parsing `/proc/self/auxv`
|
||||||
|
+ by parsing `/proc/cpuinfo`
|
||||||
|
2. **Features revealed from CPU.** features are retrieved by using the `cpuid`
|
||||||
|
instruction.
|
||||||
|
3. **Microarchitecture detection.** On x86 some features are not always
|
||||||
|
implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the
|
||||||
|
microarchitecture allows the client to reject particular microarchitectures.
|
||||||
|
4. All flavors of Mips are supported, little and big endian as well as 32/64
|
||||||
|
bits.
|
||||||
|
|
||||||
|
<a name="ndk"></a>
|
||||||
|
## Android NDK's drop in replacement
|
||||||
|
|
||||||
|
[cpu_features](https://github.com/google/cpu_features) is now officially
|
||||||
|
supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h)
|
||||||
|
, see [ndk_compat](ndk_compat) folder for details.
|
||||||
|
|
||||||
|
<a name="license"></a>
|
||||||
|
## License
|
||||||
|
|
||||||
|
The cpu_features library is licensed under the terms of the Apache license.
|
||||||
|
See [LICENSE](LICENSE) for more information.
|
||||||
|
|
||||||
|
<a name="cmake"></a>
|
||||||
|
## Build with CMake
|
||||||
|
|
||||||
|
Please check the [CMake build instructions](cmake/README.md).
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CPU_FEATURE_CACHE_NULL = 0,
|
||||||
|
CPU_FEATURE_CACHE_DATA = 1,
|
||||||
|
CPU_FEATURE_CACHE_INSTRUCTION = 2,
|
||||||
|
CPU_FEATURE_CACHE_UNIFIED = 3,
|
||||||
|
CPU_FEATURE_CACHE_TLB = 4,
|
||||||
|
CPU_FEATURE_CACHE_DTLB = 5,
|
||||||
|
CPU_FEATURE_CACHE_STLB = 6,
|
||||||
|
CPU_FEATURE_CACHE_PREFETCH = 7
|
||||||
|
} CacheType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int level;
|
||||||
|
CacheType cache_type;
|
||||||
|
int cache_size; // Cache size in bytes
|
||||||
|
int ways; // Associativity, 0 undefined, 0xFF fully associative
|
||||||
|
int line_size; // Cache line size in bytes
|
||||||
|
int tlb_entries; // number of entries for TLB
|
||||||
|
int partitioning; // number of lines per sector
|
||||||
|
} CacheLevelInfo;
|
||||||
|
|
||||||
|
// Increase this value if more cache levels are needed.
|
||||||
|
#ifndef CPU_FEATURES_MAX_CACHE_LEVEL
|
||||||
|
#define CPU_FEATURES_MAX_CACHE_LEVEL 10
|
||||||
|
#endif
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL];
|
||||||
|
} CacheInfo;
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Architectures
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__pnacl__) || defined(__CLR_VER)
|
||||||
|
#define CPU_FEATURES_ARCH_VM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM)
|
||||||
|
#define CPU_FEATURES_ARCH_X86_32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM)
|
||||||
|
#define CPU_FEATURES_ARCH_X86_64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64)
|
||||||
|
#define CPU_FEATURES_ARCH_X86
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__arm__) || defined(_M_ARM))
|
||||||
|
#define CPU_FEATURES_ARCH_ARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
#define CPU_FEATURES_ARCH_AARCH64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM))
|
||||||
|
#define CPU_FEATURES_ARCH_ANY_ARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__mips64)
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__mips__) && !defined(__mips64) // mips64 also declares __mips__
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64)
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__powerpc__)
|
||||||
|
#define CPU_FEATURES_ARCH_PPC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Os
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define CPU_FEATURES_OS_LINUX_OR_ANDROID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#define CPU_FEATURES_OS_ANDROID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_WIN64) || defined(_WIN32))
|
||||||
|
#define CPU_FEATURES_OS_WINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Compilers
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define CPU_FEATURES_COMPILER_CLANG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#define CPU_FEATURES_COMPILER_GCC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define CPU_FEATURES_COMPILER_MSC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cpp
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#define CPU_FEATURES_START_CPP_NAMESPACE \
|
||||||
|
namespace cpu_features { \
|
||||||
|
extern "C" {
|
||||||
|
#define CPU_FEATURES_END_CPP_NAMESPACE \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
#define CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Compiler flags
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Use the following to check if a feature is known to be available at
|
||||||
|
// compile time. See README.md for an example.
|
||||||
|
#if defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
|
||||||
|
#if defined(__AES__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AES 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AES 0
|
||||||
|
#endif // defined(__AES__)
|
||||||
|
|
||||||
|
#if defined(__F16C__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_F16C 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_F16C 0
|
||||||
|
#endif // defined(__F16C__)
|
||||||
|
|
||||||
|
#if defined(__BMI__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI 0
|
||||||
|
#endif // defined(__BMI__)
|
||||||
|
|
||||||
|
#if defined(__BMI2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI2 0
|
||||||
|
#endif // defined(__BMI2__)
|
||||||
|
|
||||||
|
#if (defined(__SSE__) || (_M_IX86_FP >= 1))
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE2 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__SSE3__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE3 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE3 0
|
||||||
|
#endif // defined(__SSE3__)
|
||||||
|
|
||||||
|
#if defined(__SSSE3__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSSE3 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSSE3 0
|
||||||
|
#endif // defined(__SSSE3__)
|
||||||
|
|
||||||
|
#if defined(__SSE4_1__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
|
||||||
|
#endif // defined(__SSE4_1__)
|
||||||
|
|
||||||
|
#if defined(__SSE4_2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
|
||||||
|
#endif // defined(__SSE4_2__)
|
||||||
|
|
||||||
|
#if defined(__AVX__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX 0
|
||||||
|
#endif // defined(__AVX__)
|
||||||
|
|
||||||
|
#if defined(__AVX2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX2 0
|
||||||
|
#endif // defined(__AVX2__)
|
||||||
|
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
|
#if defined(__ARM_NEON__)
|
||||||
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
|
||||||
|
#endif // defined(__ARM_NEON__)
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_MIPS)
|
||||||
|
#if defined(__mips_msa)
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MSA 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MSA 0
|
||||||
|
#endif // defined(__mips_msa)
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_MIPS)
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
#include "cpu_features_cache_info.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int fp : 1; // Floating-point.
|
||||||
|
int asimd : 1; // Advanced SIMD.
|
||||||
|
int evtstrm : 1; // Generic timer generated events.
|
||||||
|
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
|
||||||
|
int pmull : 1; // Polynomial multiply long.
|
||||||
|
int sha1 : 1; // Hardware-accelerated SHA1.
|
||||||
|
int sha2 : 1; // Hardware-accelerated SHA2-256.
|
||||||
|
int crc32 : 1; // Hardware-accelerated CRC-32.
|
||||||
|
int atomics : 1; // Armv8.1 atomic instructions.
|
||||||
|
int fphp : 1; // Half-precision floating point support.
|
||||||
|
int asimdhp : 1; // Advanced SIMD half-precision support.
|
||||||
|
int cpuid : 1; // Access to certain ID registers.
|
||||||
|
int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
|
||||||
|
int jscvt : 1; // Support for JavaScript conversion.
|
||||||
|
int fcma : 1; // Floating point complex numbers.
|
||||||
|
int lrcpc : 1; // Support for weaker release consistency.
|
||||||
|
int dcpop : 1; // Data persistence writeback.
|
||||||
|
int sha3 : 1; // Hardware-accelerated SHA3.
|
||||||
|
int sm3 : 1; // Hardware-accelerated SM3.
|
||||||
|
int sm4 : 1; // Hardware-accelerated SM4.
|
||||||
|
int asimddp : 1; // Dot product instruction.
|
||||||
|
int sha512 : 1; // Hardware-accelerated SHA512.
|
||||||
|
int sve : 1; // Scalable Vector Extension.
|
||||||
|
int asimdfhm : 1; // Additional half-precision instructions.
|
||||||
|
int dit : 1; // Data independent timing.
|
||||||
|
int uscat : 1; // Unaligned atomics support.
|
||||||
|
int ilrcpc : 1; // Additional support for weaker release consistency.
|
||||||
|
int flagm : 1; // Flag manipulation instructions.
|
||||||
|
int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
|
||||||
|
int sb : 1; // Speculation barrier.
|
||||||
|
int paca : 1; // Address authentication.
|
||||||
|
int pacg : 1; // Generic authentication.
|
||||||
|
|
||||||
|
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
|
||||||
|
} Aarch64Features;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Aarch64Features features;
|
||||||
|
int implementer;
|
||||||
|
int variant;
|
||||||
|
int part;
|
||||||
|
int revision;
|
||||||
|
} Aarch64Info;
|
||||||
|
|
||||||
|
Aarch64Info GetAarch64Info(void);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AARCH64_FP,
|
||||||
|
AARCH64_ASIMD,
|
||||||
|
AARCH64_EVTSTRM,
|
||||||
|
AARCH64_AES,
|
||||||
|
AARCH64_PMULL,
|
||||||
|
AARCH64_SHA1,
|
||||||
|
AARCH64_SHA2,
|
||||||
|
AARCH64_CRC32,
|
||||||
|
AARCH64_ATOMICS,
|
||||||
|
AARCH64_FPHP,
|
||||||
|
AARCH64_ASIMDHP,
|
||||||
|
AARCH64_CPUID,
|
||||||
|
AARCH64_ASIMDRDM,
|
||||||
|
AARCH64_JSCVT,
|
||||||
|
AARCH64_FCMA,
|
||||||
|
AARCH64_LRCPC,
|
||||||
|
AARCH64_DCPOP,
|
||||||
|
AARCH64_SHA3,
|
||||||
|
AARCH64_SM3,
|
||||||
|
AARCH64_SM4,
|
||||||
|
AARCH64_ASIMDDP,
|
||||||
|
AARCH64_SHA512,
|
||||||
|
AARCH64_SVE,
|
||||||
|
AARCH64_ASIMDFHM,
|
||||||
|
AARCH64_DIT,
|
||||||
|
AARCH64_USCAT,
|
||||||
|
AARCH64_ILRCPC,
|
||||||
|
AARCH64_FLAGM,
|
||||||
|
AARCH64_SSBS,
|
||||||
|
AARCH64_SB,
|
||||||
|
AARCH64_PACA,
|
||||||
|
AARCH64_PACG,
|
||||||
|
AARCH64_LAST_,
|
||||||
|
} Aarch64FeaturesEnum;
|
||||||
|
|
||||||
|
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
|
||||||
|
Aarch64FeaturesEnum value);
|
||||||
|
|
||||||
|
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#if !defined(CPU_FEATURES_ARCH_AARCH64)
|
||||||
|
#error "Including cpuinfo_aarch64.h from a non-aarch64 target."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
|
||||||
|
|
||||||
|
#include <stdint.h> // uint32_t
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
#include "cpu_features_cache_info.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int swp : 1; // SWP instruction (atomic read-modify-write)
|
||||||
|
int half : 1; // Half-word loads and stores
|
||||||
|
int thumb : 1; // Thumb (16-bit instruction set)
|
||||||
|
int _26bit : 1; // "26 Bit" Model (Processor status register folded into program counter)
|
||||||
|
int fastmult : 1; // 32x32->64-bit multiplication
|
||||||
|
int fpa : 1; // Floating point accelerator
|
||||||
|
int vfp : 1; // Vector Floating Point.
|
||||||
|
int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)
|
||||||
|
int java : 1; // Jazelle (Java bytecode accelerator)
|
||||||
|
int iwmmxt : 1; // Intel Wireless MMX Technology.
|
||||||
|
int crunch : 1; // MaverickCrunch coprocessor
|
||||||
|
int thumbee : 1; // ThumbEE
|
||||||
|
int neon : 1; // Advanced SIMD.
|
||||||
|
int vfpv3 : 1; // VFP version 3
|
||||||
|
int vfpv3d16 : 1; // VFP version 3 with 16 D-registers
|
||||||
|
int tls : 1; // TLS register
|
||||||
|
int vfpv4 : 1; // VFP version 4 with fast context switching
|
||||||
|
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
|
||||||
|
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
|
||||||
|
int vfpd32 : 1; // VFP with 32 D-registers
|
||||||
|
int lpae : 1; // Large Physical Address Extension (>4GB physical memory on 32-bit architecture)
|
||||||
|
int evtstrm : 1; // kernel event stream using generic architected timer
|
||||||
|
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
|
||||||
|
int pmull : 1; // Polynomial multiply long.
|
||||||
|
int sha1 : 1; // Hardware-accelerated SHA1.
|
||||||
|
int sha2 : 1; // Hardware-accelerated SHA2-256.
|
||||||
|
int crc32 : 1; // Hardware-accelerated CRC-32.
|
||||||
|
|
||||||
|
// Make sure to update ArmFeaturesEnum below if you add a field here.
|
||||||
|
} ArmFeatures;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ArmFeatures features;
|
||||||
|
int implementer;
|
||||||
|
int architecture;
|
||||||
|
int variant;
|
||||||
|
int part;
|
||||||
|
int revision;
|
||||||
|
} ArmInfo;
|
||||||
|
|
||||||
|
// TODO(user): Add macros to know which features are present at compile
|
||||||
|
// time.
|
||||||
|
|
||||||
|
ArmInfo GetArmInfo(void);
|
||||||
|
|
||||||
|
// Compute CpuId from ArmInfo.
|
||||||
|
uint32_t GetArmCpuId(const ArmInfo* const info);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ARM_SWP,
|
||||||
|
ARM_HALF,
|
||||||
|
ARM_THUMB,
|
||||||
|
ARM_26BIT,
|
||||||
|
ARM_FASTMULT,
|
||||||
|
ARM_FPA,
|
||||||
|
ARM_VFP,
|
||||||
|
ARM_EDSP,
|
||||||
|
ARM_JAVA,
|
||||||
|
ARM_IWMMXT,
|
||||||
|
ARM_CRUNCH,
|
||||||
|
ARM_THUMBEE,
|
||||||
|
ARM_NEON,
|
||||||
|
ARM_VFPV3,
|
||||||
|
ARM_VFPV3D16,
|
||||||
|
ARM_TLS,
|
||||||
|
ARM_VFPV4,
|
||||||
|
ARM_IDIVA,
|
||||||
|
ARM_IDIVT,
|
||||||
|
ARM_VFPD32,
|
||||||
|
ARM_LPAE,
|
||||||
|
ARM_EVTSTRM,
|
||||||
|
ARM_AES,
|
||||||
|
ARM_PMULL,
|
||||||
|
ARM_SHA1,
|
||||||
|
ARM_SHA2,
|
||||||
|
ARM_CRC32,
|
||||||
|
ARM_LAST_,
|
||||||
|
} ArmFeaturesEnum;
|
||||||
|
|
||||||
|
int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value);
|
||||||
|
|
||||||
|
const char* GetArmFeaturesEnumName(ArmFeaturesEnum);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#if !defined(CPU_FEATURES_ARCH_ARM)
|
||||||
|
#error "Including cpuinfo_arm.h from a non-arm target."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
|
||||||
|
|
||||||
|
#include "cpu_features_cache_info.h"
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features.
|
||||||
|
// The field names are based on the short name provided in the wikipedia tables.
|
||||||
|
typedef struct {
|
||||||
|
int fpu : 1;
|
||||||
|
int tsc : 1;
|
||||||
|
int cx8 : 1;
|
||||||
|
int clfsh : 1;
|
||||||
|
int mmx : 1;
|
||||||
|
int aes : 1;
|
||||||
|
int erms : 1;
|
||||||
|
int f16c : 1;
|
||||||
|
int fma4 : 1;
|
||||||
|
int fma3 : 1;
|
||||||
|
int vaes : 1;
|
||||||
|
int vpclmulqdq : 1;
|
||||||
|
int bmi1 : 1;
|
||||||
|
int hle : 1;
|
||||||
|
int bmi2 : 1;
|
||||||
|
int rtm : 1;
|
||||||
|
int rdseed : 1;
|
||||||
|
int clflushopt : 1;
|
||||||
|
int clwb : 1;
|
||||||
|
|
||||||
|
int sse : 1;
|
||||||
|
int sse2 : 1;
|
||||||
|
int sse3 : 1;
|
||||||
|
int ssse3 : 1;
|
||||||
|
int sse4_1 : 1;
|
||||||
|
int sse4_2 : 1;
|
||||||
|
int sse4a : 1;
|
||||||
|
|
||||||
|
int avx : 1;
|
||||||
|
int avx2 : 1;
|
||||||
|
|
||||||
|
int avx512f : 1;
|
||||||
|
int avx512cd : 1;
|
||||||
|
int avx512er : 1;
|
||||||
|
int avx512pf : 1;
|
||||||
|
int avx512bw : 1;
|
||||||
|
int avx512dq : 1;
|
||||||
|
int avx512vl : 1;
|
||||||
|
int avx512ifma : 1;
|
||||||
|
int avx512vbmi : 1;
|
||||||
|
int avx512vbmi2 : 1;
|
||||||
|
int avx512vnni : 1;
|
||||||
|
int avx512bitalg : 1;
|
||||||
|
int avx512vpopcntdq : 1;
|
||||||
|
int avx512_4vnniw : 1;
|
||||||
|
int avx512_4vbmi2 : 1;
|
||||||
|
|
||||||
|
int pclmulqdq : 1;
|
||||||
|
int smx : 1;
|
||||||
|
int sgx : 1;
|
||||||
|
int cx16 : 1; // aka. CMPXCHG16B
|
||||||
|
int sha : 1;
|
||||||
|
int popcnt : 1;
|
||||||
|
int movbe : 1;
|
||||||
|
int rdrnd : 1;
|
||||||
|
|
||||||
|
int dca : 1;
|
||||||
|
int ss : 1;
|
||||||
|
// Make sure to update X86FeaturesEnum below if you add a field here.
|
||||||
|
} X86Features;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
X86Features features;
|
||||||
|
int family;
|
||||||
|
int model;
|
||||||
|
int stepping;
|
||||||
|
char vendor[13]; // 0 terminated string
|
||||||
|
} X86Info;
|
||||||
|
|
||||||
|
// Calls cpuid and returns an initialized X86info.
|
||||||
|
// This function is guaranteed to be malloc, memset and memcpy free.
|
||||||
|
X86Info GetX86Info(void);
|
||||||
|
|
||||||
|
// Returns cache hierarchy informations.
|
||||||
|
// Can call cpuid multiple times.
|
||||||
|
// Only works on Intel CPU at the moment.
|
||||||
|
// This function is guaranteed to be malloc, memset and memcpy free.
|
||||||
|
CacheInfo GetX86CacheInfo(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
X86_UNKNOWN,
|
||||||
|
INTEL_CORE, // CORE
|
||||||
|
INTEL_PNR, // PENRYN
|
||||||
|
INTEL_NHM, // NEHALEM
|
||||||
|
INTEL_ATOM_BNL, // BONNELL
|
||||||
|
INTEL_WSM, // WESTMERE
|
||||||
|
INTEL_SNB, // SANDYBRIDGE
|
||||||
|
INTEL_IVB, // IVYBRIDGE
|
||||||
|
INTEL_ATOM_SMT, // SILVERMONT
|
||||||
|
INTEL_HSW, // HASWELL
|
||||||
|
INTEL_BDW, // BROADWELL
|
||||||
|
INTEL_SKL, // SKYLAKE
|
||||||
|
INTEL_ATOM_GMT, // GOLDMONT
|
||||||
|
INTEL_KBL, // KABY LAKE
|
||||||
|
INTEL_CFL, // COFFEE LAKE
|
||||||
|
INTEL_WHL, // WHISKEY LAKE
|
||||||
|
INTEL_CNL, // CANNON LAKE
|
||||||
|
INTEL_ICL, // ICE LAKE
|
||||||
|
AMD_HAMMER, // K8
|
||||||
|
AMD_K10, // K10
|
||||||
|
AMD_BOBCAT, // K14
|
||||||
|
AMD_BULLDOZER, // K15
|
||||||
|
AMD_JAGUAR, // K16
|
||||||
|
AMD_ZEN, // K17
|
||||||
|
} X86Microarchitecture;
|
||||||
|
|
||||||
|
// Returns the underlying microarchitecture by looking at X86Info's vendor,
|
||||||
|
// family and model.
|
||||||
|
X86Microarchitecture GetX86Microarchitecture(const X86Info* info);
|
||||||
|
|
||||||
|
// Calls cpuid and fills the brand_string.
|
||||||
|
// - brand_string *must* be of size 49 (beware of array decaying).
|
||||||
|
// - brand_string will be zero terminated.
|
||||||
|
// - This function calls memcpy.
|
||||||
|
void FillX86BrandString(char brand_string[49]);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
X86_FPU,
|
||||||
|
X86_TSC,
|
||||||
|
X86_CX8,
|
||||||
|
X86_CLFSH,
|
||||||
|
X86_MMX,
|
||||||
|
X86_AES,
|
||||||
|
X86_ERMS,
|
||||||
|
X86_F16C,
|
||||||
|
X86_FMA4,
|
||||||
|
X86_FMA3,
|
||||||
|
X86_VAES,
|
||||||
|
X86_VPCLMULQDQ,
|
||||||
|
X86_BMI1,
|
||||||
|
X86_HLE,
|
||||||
|
X86_BMI2,
|
||||||
|
X86_RTM,
|
||||||
|
X86_RDSEED,
|
||||||
|
X86_CLFLUSHOPT,
|
||||||
|
X86_CLWB,
|
||||||
|
X86_SSE,
|
||||||
|
X86_SSE2,
|
||||||
|
X86_SSE3,
|
||||||
|
X86_SSSE3,
|
||||||
|
X86_SSE4_1,
|
||||||
|
X86_SSE4_2,
|
||||||
|
X86_SSE4A,
|
||||||
|
X86_AVX,
|
||||||
|
X86_AVX2,
|
||||||
|
X86_AVX512F,
|
||||||
|
X86_AVX512CD,
|
||||||
|
X86_AVX512ER,
|
||||||
|
X86_AVX512PF,
|
||||||
|
X86_AVX512BW,
|
||||||
|
X86_AVX512DQ,
|
||||||
|
X86_AVX512VL,
|
||||||
|
X86_AVX512IFMA,
|
||||||
|
X86_AVX512VBMI,
|
||||||
|
X86_AVX512VBMI2,
|
||||||
|
X86_AVX512VNNI,
|
||||||
|
X86_AVX512BITALG,
|
||||||
|
X86_AVX512VPOPCNTDQ,
|
||||||
|
X86_AVX512_4VNNIW,
|
||||||
|
X86_AVX512_4VBMI2,
|
||||||
|
X86_PCLMULQDQ,
|
||||||
|
X86_SMX,
|
||||||
|
X86_SGX,
|
||||||
|
X86_CX16,
|
||||||
|
X86_SHA,
|
||||||
|
X86_POPCNT,
|
||||||
|
X86_MOVBE,
|
||||||
|
X86_RDRND,
|
||||||
|
X86_DCA,
|
||||||
|
X86_SS,
|
||||||
|
X86_LAST_,
|
||||||
|
} X86FeaturesEnum;
|
||||||
|
|
||||||
|
int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value);
|
||||||
|
|
||||||
|
const char* GetX86FeaturesEnumName(X86FeaturesEnum);
|
||||||
|
|
||||||
|
const char* GetX86MicroarchitectureName(X86Microarchitecture);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#if !defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
#error "Including cpuinfo_x86.h from a non-x86 target."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
inline static bool IsBitSet(uint32_t reg, uint32_t bit) {
|
||||||
|
return (reg >> bit) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb,
|
||||||
|
uint32_t lsb) {
|
||||||
|
const uint64_t bits = msb - lsb + 1ULL;
|
||||||
|
const uint64_t mask = (1ULL << bits) - 1ULL;
|
||||||
|
assert(msb >= lsb);
|
||||||
|
return (reg >> lsb) & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// A struct to hold the result of a call to cpuid.
|
||||||
|
typedef struct {
|
||||||
|
uint32_t eax, ebx, ecx, edx;
|
||||||
|
} Leaf;
|
||||||
|
|
||||||
|
Leaf CpuIdEx(uint32_t leaf_id, int ecx);
|
||||||
|
|
||||||
|
// Returns the eax value of the XCR0 register.
|
||||||
|
uint32_t GetXCR0Eax(void);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// An interface for the filesystem that allows mocking the filesystem in
|
||||||
|
// unittests.
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// Same as linux "open(filename, O_RDONLY)", retries automatically on EINTR.
|
||||||
|
int CpuFeatures_OpenFile(const char* filename);
|
||||||
|
|
||||||
|
// Same as linux "read(file_descriptor, buffer, buffer_size)", retries
|
||||||
|
// automatically on EINTR.
|
||||||
|
int CpuFeatures_ReadFile(int file_descriptor, void* buffer, size_t buffer_size);
|
||||||
|
|
||||||
|
// Same as linux "close(file_descriptor)".
|
||||||
|
void CpuFeatures_CloseFile(int file_descriptor);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Interface to retrieve hardware capabilities. It relies on Linux's getauxval
|
||||||
|
// or `/proc/self/auxval` under the hood.
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// To avoid depending on the linux kernel we reproduce the architecture specific
|
||||||
|
// constants here.
|
||||||
|
|
||||||
|
// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
|
||||||
|
#define AARCH64_HWCAP_FP (1UL << 0)
|
||||||
|
#define AARCH64_HWCAP_ASIMD (1UL << 1)
|
||||||
|
#define AARCH64_HWCAP_EVTSTRM (1UL << 2)
|
||||||
|
#define AARCH64_HWCAP_AES (1UL << 3)
|
||||||
|
#define AARCH64_HWCAP_PMULL (1UL << 4)
|
||||||
|
#define AARCH64_HWCAP_SHA1 (1UL << 5)
|
||||||
|
#define AARCH64_HWCAP_SHA2 (1UL << 6)
|
||||||
|
#define AARCH64_HWCAP_CRC32 (1UL << 7)
|
||||||
|
#define AARCH64_HWCAP_ATOMICS (1UL << 8)
|
||||||
|
#define AARCH64_HWCAP_FPHP (1UL << 9)
|
||||||
|
#define AARCH64_HWCAP_ASIMDHP (1UL << 10)
|
||||||
|
#define AARCH64_HWCAP_CPUID (1UL << 11)
|
||||||
|
#define AARCH64_HWCAP_ASIMDRDM (1UL << 12)
|
||||||
|
#define AARCH64_HWCAP_JSCVT (1UL << 13)
|
||||||
|
#define AARCH64_HWCAP_FCMA (1UL << 14)
|
||||||
|
#define AARCH64_HWCAP_LRCPC (1UL << 15)
|
||||||
|
#define AARCH64_HWCAP_DCPOP (1UL << 16)
|
||||||
|
#define AARCH64_HWCAP_SHA3 (1UL << 17)
|
||||||
|
#define AARCH64_HWCAP_SM3 (1UL << 18)
|
||||||
|
#define AARCH64_HWCAP_SM4 (1UL << 19)
|
||||||
|
#define AARCH64_HWCAP_ASIMDDP (1UL << 20)
|
||||||
|
#define AARCH64_HWCAP_SHA512 (1UL << 21)
|
||||||
|
#define AARCH64_HWCAP_SVE (1UL << 22)
|
||||||
|
#define AARCH64_HWCAP_ASIMDFHM (1UL << 23)
|
||||||
|
#define AARCH64_HWCAP_DIT (1UL << 24)
|
||||||
|
#define AARCH64_HWCAP_USCAT (1UL << 25)
|
||||||
|
#define AARCH64_HWCAP_ILRCPC (1UL << 26)
|
||||||
|
#define AARCH64_HWCAP_FLAGM (1UL << 27)
|
||||||
|
#define AARCH64_HWCAP_SSBS (1UL << 28)
|
||||||
|
#define AARCH64_HWCAP_SB (1UL << 29)
|
||||||
|
#define AARCH64_HWCAP_PACA (1UL << 30)
|
||||||
|
#define AARCH64_HWCAP_PACG (1UL << 31)
|
||||||
|
|
||||||
|
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
|
||||||
|
#define ARM_HWCAP_SWP (1UL << 0)
|
||||||
|
#define ARM_HWCAP_HALF (1UL << 1)
|
||||||
|
#define ARM_HWCAP_THUMB (1UL << 2)
|
||||||
|
#define ARM_HWCAP_26BIT (1UL << 3)
|
||||||
|
#define ARM_HWCAP_FAST_MULT (1UL << 4)
|
||||||
|
#define ARM_HWCAP_FPA (1UL << 5)
|
||||||
|
#define ARM_HWCAP_VFP (1UL << 6)
|
||||||
|
#define ARM_HWCAP_EDSP (1UL << 7)
|
||||||
|
#define ARM_HWCAP_JAVA (1UL << 8)
|
||||||
|
#define ARM_HWCAP_IWMMXT (1UL << 9)
|
||||||
|
#define ARM_HWCAP_CRUNCH (1UL << 10)
|
||||||
|
#define ARM_HWCAP_THUMBEE (1UL << 11)
|
||||||
|
#define ARM_HWCAP_NEON (1UL << 12)
|
||||||
|
#define ARM_HWCAP_VFPV3 (1UL << 13)
|
||||||
|
#define ARM_HWCAP_VFPV3D16 (1UL << 14)
|
||||||
|
#define ARM_HWCAP_TLS (1UL << 15)
|
||||||
|
#define ARM_HWCAP_VFPV4 (1UL << 16)
|
||||||
|
#define ARM_HWCAP_IDIVA (1UL << 17)
|
||||||
|
#define ARM_HWCAP_IDIVT (1UL << 18)
|
||||||
|
#define ARM_HWCAP_VFPD32 (1UL << 19)
|
||||||
|
#define ARM_HWCAP_LPAE (1UL << 20)
|
||||||
|
#define ARM_HWCAP_EVTSTRM (1UL << 21)
|
||||||
|
#define ARM_HWCAP2_AES (1UL << 0)
|
||||||
|
#define ARM_HWCAP2_PMULL (1UL << 1)
|
||||||
|
#define ARM_HWCAP2_SHA1 (1UL << 2)
|
||||||
|
#define ARM_HWCAP2_SHA2 (1UL << 3)
|
||||||
|
#define ARM_HWCAP2_CRC32 (1UL << 4)
|
||||||
|
|
||||||
|
// http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/hwcap.h
|
||||||
|
#define MIPS_HWCAP_R6 (1UL << 0)
|
||||||
|
#define MIPS_HWCAP_MSA (1UL << 1)
|
||||||
|
#define MIPS_HWCAP_CRC32 (1UL << 2)
|
||||||
|
|
||||||
|
// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h
|
||||||
|
#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H
|
||||||
|
/* in AT_HWCAP */
|
||||||
|
#define PPC_FEATURE_32 0x80000000
|
||||||
|
#define PPC_FEATURE_64 0x40000000
|
||||||
|
#define PPC_FEATURE_601_INSTR 0x20000000
|
||||||
|
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
|
||||||
|
#define PPC_FEATURE_HAS_FPU 0x08000000
|
||||||
|
#define PPC_FEATURE_HAS_MMU 0x04000000
|
||||||
|
#define PPC_FEATURE_HAS_4xxMAC 0x02000000
|
||||||
|
#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
|
||||||
|
#define PPC_FEATURE_HAS_SPE 0x00800000
|
||||||
|
#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
|
||||||
|
#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
|
||||||
|
#define PPC_FEATURE_NO_TB 0x00100000
|
||||||
|
#define PPC_FEATURE_POWER4 0x00080000
|
||||||
|
#define PPC_FEATURE_POWER5 0x00040000
|
||||||
|
#define PPC_FEATURE_POWER5_PLUS 0x00020000
|
||||||
|
#define PPC_FEATURE_CELL 0x00010000
|
||||||
|
#define PPC_FEATURE_BOOKE 0x00008000
|
||||||
|
#define PPC_FEATURE_SMT 0x00004000
|
||||||
|
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
|
||||||
|
#define PPC_FEATURE_ARCH_2_05 0x00001000
|
||||||
|
#define PPC_FEATURE_PA6T 0x00000800
|
||||||
|
#define PPC_FEATURE_HAS_DFP 0x00000400
|
||||||
|
#define PPC_FEATURE_POWER6_EXT 0x00000200
|
||||||
|
#define PPC_FEATURE_ARCH_2_06 0x00000100
|
||||||
|
#define PPC_FEATURE_HAS_VSX 0x00000080
|
||||||
|
|
||||||
|
#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040
|
||||||
|
|
||||||
|
/* Reserved - do not use 0x00000004 */
|
||||||
|
#define PPC_FEATURE_TRUE_LE 0x00000002
|
||||||
|
#define PPC_FEATURE_PPC_LE 0x00000001
|
||||||
|
|
||||||
|
/* in AT_HWCAP2 */
|
||||||
|
#define PPC_FEATURE2_ARCH_2_07 0x80000000
|
||||||
|
#define PPC_FEATURE2_HTM 0x40000000
|
||||||
|
#define PPC_FEATURE2_DSCR 0x20000000
|
||||||
|
#define PPC_FEATURE2_EBB 0x10000000
|
||||||
|
#define PPC_FEATURE2_ISEL 0x08000000
|
||||||
|
#define PPC_FEATURE2_TAR 0x04000000
|
||||||
|
#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
|
||||||
|
#define PPC_FEATURE2_HTM_NOSC 0x01000000
|
||||||
|
#define PPC_FEATURE2_ARCH_3_00 0x00800000
|
||||||
|
#define PPC_FEATURE2_HAS_IEEE128 0x00400000
|
||||||
|
#define PPC_FEATURE2_DARN 0x00200000
|
||||||
|
#define PPC_FEATURE2_SCV 0x00100000
|
||||||
|
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long hwcaps;
|
||||||
|
unsigned long hwcaps2;
|
||||||
|
} HardwareCapabilities;
|
||||||
|
|
||||||
|
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char platform[64]; // 0 terminated string
|
||||||
|
char base_platform[64]; // 0 terminated string
|
||||||
|
} PlatformType;
|
||||||
|
|
||||||
|
PlatformType CpuFeatures_GetPlatformType(void);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Reads a file line by line and stores the data on the stack. This allows
|
||||||
|
// parsing files in one go without allocating.
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buffer[STACK_LINE_READER_BUFFER_SIZE];
|
||||||
|
StringView view;
|
||||||
|
int fd;
|
||||||
|
bool skip_mode;
|
||||||
|
} StackLineReader;
|
||||||
|
|
||||||
|
// Initializes a StackLineReader.
|
||||||
|
void StackLineReader_Initialize(StackLineReader* reader, int fd);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
StringView line; // A view of the line.
|
||||||
|
bool eof; // Nothing more to read, we reached EOF.
|
||||||
|
bool full_line; // If false the line was truncated to
|
||||||
|
// STACK_LINE_READER_BUFFER_SIZE.
|
||||||
|
} LineResult;
|
||||||
|
|
||||||
|
// Reads the file pointed to by fd and tries to read a full line.
|
||||||
|
LineResult StackLineReader_NextLine(StackLineReader* reader);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// A view over a piece of string. The view is not 0 terminated.
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* ptr;
|
||||||
|
size_t size;
|
||||||
|
} StringView;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
static const StringView kEmptyStringView = {NULL, 0};
|
||||||
|
#else
|
||||||
|
static const StringView kEmptyStringView;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Returns a StringView from the provided string.
|
||||||
|
// Passing NULL is valid only if size is 0.
|
||||||
|
static inline StringView view(const char* str, const size_t size) {
|
||||||
|
StringView view;
|
||||||
|
view.ptr = str;
|
||||||
|
view.size = size;
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline StringView str(const char* str) { return view(str, strlen(str)); }
|
||||||
|
|
||||||
|
// Returns the index of the first occurrence of c in view or -1 if not found.
|
||||||
|
int CpuFeatures_StringView_IndexOfChar(const StringView view, char c);
|
||||||
|
|
||||||
|
// Returns the index of the first occurrence of sub_view in view or -1 if not
|
||||||
|
// found.
|
||||||
|
int CpuFeatures_StringView_IndexOf(const StringView view,
|
||||||
|
const StringView sub_view);
|
||||||
|
|
||||||
|
// Returns whether a is equal to b (same content).
|
||||||
|
bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b);
|
||||||
|
|
||||||
|
// Returns whether a starts with b.
|
||||||
|
bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b);
|
||||||
|
|
||||||
|
// Removes count characters from the beginning of view or kEmptyStringView if
|
||||||
|
// count if greater than view.size.
|
||||||
|
StringView CpuFeatures_StringView_PopFront(const StringView str_view,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
|
// Removes count characters from the end of view or kEmptyStringView if count if
|
||||||
|
// greater than view.size.
|
||||||
|
StringView CpuFeatures_StringView_PopBack(const StringView str_view,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
|
// Keeps the count first characters of view or view if count if greater than
|
||||||
|
// view.size.
|
||||||
|
StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
|
||||||
|
size_t count);
|
||||||
|
|
||||||
|
// Retrieves the first character of view. If view is empty the behavior is
|
||||||
|
// undefined.
|
||||||
|
char CpuFeatures_StringView_Front(const StringView view);
|
||||||
|
|
||||||
|
// Retrieves the last character of view. If view is empty the behavior is
|
||||||
|
// undefined.
|
||||||
|
char CpuFeatures_StringView_Back(const StringView view);
|
||||||
|
|
||||||
|
// Removes leading and tailing space characters.
|
||||||
|
StringView CpuFeatures_StringView_TrimWhitespace(StringView view);
|
||||||
|
|
||||||
|
// Convert StringView to positive integer. e.g. "42", "0x2a".
|
||||||
|
// Returns -1 on error.
|
||||||
|
int CpuFeatures_StringView_ParsePositiveNumber(const StringView view);
|
||||||
|
|
||||||
|
// Copies src StringView to dst buffer.
|
||||||
|
void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
|
||||||
|
size_t dst_size);
|
||||||
|
|
||||||
|
// Checks if line contains the specified whitespace separated word.
|
||||||
|
bool CpuFeatures_StringView_HasWord(const StringView line,
|
||||||
|
const char* const word);
|
||||||
|
|
||||||
|
// Get key/value from line. key and value are separated by ": ".
|
||||||
|
// key and value are cleaned up from leading and trailing whitespaces.
|
||||||
|
bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
|
||||||
|
StringView* key,
|
||||||
|
StringView* value);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// CapabilityConfig provides a way to map cpu features to hardware caps and
|
||||||
|
// /proc/cpuinfo flags. We then provide functions to update capabilities from
|
||||||
|
// either source.
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
#include "internal/hwcaps.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
// Use the following macro to declare setter functions to be used in
|
||||||
|
// CapabilityConfig.
|
||||||
|
#define DECLARE_SETTER(FeatureType, FeatureName) \
|
||||||
|
static void set_##FeatureName(void* const features, bool value) { \
|
||||||
|
((FeatureType*)features)->FeatureName = value; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the following macro to declare getter functions to be used in
|
||||||
|
// CapabilityConfig.
|
||||||
|
#define DECLARE_GETTER(FeatureType, FeatureName) \
|
||||||
|
static int get_##FeatureName(void* const features) { \
|
||||||
|
return ((FeatureType*)features)->FeatureName; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \
|
||||||
|
DECLARE_SETTER(FeatureType, FeatureName) \
|
||||||
|
DECLARE_GETTER(FeatureType, FeatureName)
|
||||||
|
|
||||||
|
// Describes the relationship between hardware caps and /proc/cpuinfo flags.
|
||||||
|
typedef struct {
|
||||||
|
const HardwareCapabilities hwcaps_mask;
|
||||||
|
const char* const proc_cpuinfo_flag;
|
||||||
|
void (*set_bit)(void* const, bool); // setter for the corresponding bit.
|
||||||
|
int (*get_bit)(void* const); // getter for the corresponding bit.
|
||||||
|
} CapabilityConfig;
|
||||||
|
|
||||||
|
// For every config, looks into flags_line for the presence of the
|
||||||
|
// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly.
|
||||||
|
// Note: features is a pointer to the underlying Feature struct.
|
||||||
|
void CpuFeatures_SetFromFlags(const size_t configs_size,
|
||||||
|
const CapabilityConfig* configs,
|
||||||
|
const StringView flags_line,
|
||||||
|
void* const features);
|
||||||
|
|
||||||
|
// For every config, looks into hwcaps for the presence of the feature. Calls
|
||||||
|
// `set_bit` with true if the hardware capability is found.
|
||||||
|
// Note: features is a pointer to the underlying Feature struct.
|
||||||
|
void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
|
||||||
|
const CapabilityConfig* configs,
|
||||||
|
const HardwareCapabilities hwcaps,
|
||||||
|
void* const features);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "cpuinfo_aarch64.h"
|
||||||
|
|
||||||
|
#include "internal/filesystem.h"
|
||||||
|
#include "internal/hwcaps.h"
|
||||||
|
#include "internal/stack_line_reader.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
#include "internal/unix_features_aggregator.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, fp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, aes)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sve)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, dit)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, sb)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, paca)
|
||||||
|
DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg)
|
||||||
|
|
||||||
|
static const CapabilityConfig kConfigs[] = {
|
||||||
|
[AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp, &get_fp},
|
||||||
|
[AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd, &get_asimd},
|
||||||
|
[AARCH64_EVTSTRM] = {{AARCH64_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm},
|
||||||
|
[AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes, &get_aes},
|
||||||
|
[AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull, &get_pmull},
|
||||||
|
[AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1, &get_sha1},
|
||||||
|
[AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2, &get_sha2},
|
||||||
|
[AARCH64_CRC32] = {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32, &get_crc32},
|
||||||
|
[AARCH64_ATOMICS] = {{AARCH64_HWCAP_ATOMICS, 0}, "atomics", &set_atomics, &get_atomics},
|
||||||
|
[AARCH64_FPHP] = {{AARCH64_HWCAP_FPHP, 0}, "fphp", &set_fphp, &get_fphp},
|
||||||
|
[AARCH64_ASIMDHP] = {{AARCH64_HWCAP_ASIMDHP, 0}, "asimdhp", &set_asimdhp, &get_asimdhp},
|
||||||
|
[AARCH64_CPUID] = {{AARCH64_HWCAP_CPUID, 0}, "cpuid", &set_cpuid, &get_cpuid},
|
||||||
|
[AARCH64_ASIMDRDM] = {{AARCH64_HWCAP_ASIMDRDM, 0}, "asimdrdm", &set_asimdrdm, &get_asimdrdm},
|
||||||
|
[AARCH64_JSCVT] = {{AARCH64_HWCAP_JSCVT, 0}, "jscvt", &set_jscvt, &get_jscvt},
|
||||||
|
[AARCH64_FCMA] = {{AARCH64_HWCAP_FCMA, 0}, "fcma", &set_fcma, &get_fcma},
|
||||||
|
[AARCH64_LRCPC] = {{AARCH64_HWCAP_LRCPC, 0}, "lrcpc", &set_lrcpc, &get_lrcpc},
|
||||||
|
[AARCH64_DCPOP] = {{AARCH64_HWCAP_DCPOP, 0}, "dcpop", &set_dcpop, &get_dcpop},
|
||||||
|
[AARCH64_SHA3] = {{AARCH64_HWCAP_SHA3, 0}, "sha3", &set_sha3, &get_sha3},
|
||||||
|
[AARCH64_SM3] = {{AARCH64_HWCAP_SM3, 0}, "sm3", &set_sm3, &get_sm3},
|
||||||
|
[AARCH64_SM4] = {{AARCH64_HWCAP_SM4, 0}, "sm4", &set_sm4, &get_sm4},
|
||||||
|
[AARCH64_ASIMDDP] = {{AARCH64_HWCAP_ASIMDDP, 0}, "asimddp", &set_asimddp, &get_asimddp},
|
||||||
|
[AARCH64_SHA512] = {{AARCH64_HWCAP_SHA512, 0}, "sha512", &set_sha512, &get_sha512},
|
||||||
|
[AARCH64_SVE] = {{AARCH64_HWCAP_SVE, 0}, "sve", &set_sve, &get_sve},
|
||||||
|
[AARCH64_ASIMDFHM] = {{AARCH64_HWCAP_ASIMDFHM, 0}, "asimdfhm", &set_asimdfhm, &get_asimdfhm},
|
||||||
|
[AARCH64_DIT] = {{AARCH64_HWCAP_DIT, 0}, "dit", &set_dit, &get_dit},
|
||||||
|
[AARCH64_USCAT] = {{AARCH64_HWCAP_USCAT, 0}, "uscat", &set_uscat, &get_uscat},
|
||||||
|
[AARCH64_ILRCPC] = {{AARCH64_HWCAP_ILRCPC, 0}, "ilrcpc", &set_ilrcpc, &get_ilrcpc},
|
||||||
|
[AARCH64_FLAGM] = {{AARCH64_HWCAP_FLAGM, 0}, "flagm", &set_flagm, &get_flagm},
|
||||||
|
[AARCH64_SSBS] = {{AARCH64_HWCAP_SSBS, 0}, "ssbs", &set_ssbs, &get_ssbs},
|
||||||
|
[AARCH64_SB] = {{AARCH64_HWCAP_SB, 0}, "sb", &set_sb, &get_sb},
|
||||||
|
[AARCH64_PACA] = {{AARCH64_HWCAP_PACA, 0}, "paca", &set_paca, &get_paca},
|
||||||
|
[AARCH64_PACG] = {{AARCH64_HWCAP_PACG, 0}, "pacg", &set_pacg, &get_pacg},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
||||||
|
|
||||||
|
static bool HandleAarch64Line(const LineResult result,
|
||||||
|
Aarch64Info* const info) {
|
||||||
|
StringView line = result.line;
|
||||||
|
StringView key, value;
|
||||||
|
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
|
||||||
|
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
|
||||||
|
CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
|
||||||
|
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
|
||||||
|
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
|
||||||
|
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
|
||||||
|
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !result.eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillProcCpuInfoData(Aarch64Info* const info) {
|
||||||
|
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
|
||||||
|
if (fd >= 0) {
|
||||||
|
StackLineReader reader;
|
||||||
|
StackLineReader_Initialize(&reader, fd);
|
||||||
|
for (;;) {
|
||||||
|
if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuFeatures_CloseFile(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Aarch64Info kEmptyAarch64Info;
|
||||||
|
|
||||||
|
Aarch64Info GetAarch64Info(void) {
|
||||||
|
assert(kConfigsSize == AARCH64_LAST_);
|
||||||
|
|
||||||
|
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
||||||
|
// have some information if the executable is sandboxed (aka no access to
|
||||||
|
// /proc/cpuinfo).
|
||||||
|
Aarch64Info info = kEmptyAarch64Info;
|
||||||
|
|
||||||
|
FillProcCpuInfoData(&info);
|
||||||
|
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
||||||
|
CpuFeatures_GetHardwareCapabilities(),
|
||||||
|
&info.features);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
|
||||||
|
Aarch64FeaturesEnum value) {
|
||||||
|
if(value >= kConfigsSize)
|
||||||
|
return false;
|
||||||
|
return kConfigs[value].get_bit((Aarch64Features*)features);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
|
||||||
|
if(value >= kConfigsSize)
|
||||||
|
return "unknown feature";
|
||||||
|
return kConfigs[value].proc_cpuinfo_flag;
|
||||||
|
}
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "cpuinfo_arm.h"
|
||||||
|
|
||||||
|
#include "internal/bit_utils.h"
|
||||||
|
#include "internal/filesystem.h"
|
||||||
|
#include "internal/hwcaps.h"
|
||||||
|
#include "internal/stack_line_reader.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
#include "internal/unix_features_aggregator.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, swp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, half)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, java)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, neon)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, tls)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, aes)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2)
|
||||||
|
DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32)
|
||||||
|
|
||||||
|
static const CapabilityConfig kConfigs[] = {
|
||||||
|
[ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp, &get_swp}, //
|
||||||
|
[ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half, &get_half}, //
|
||||||
|
[ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb, &get_thumb}, //
|
||||||
|
[ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit, &get__26bit}, //
|
||||||
|
[ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult, &get_fastmult}, //
|
||||||
|
[ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa, &get_fpa}, //
|
||||||
|
[ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp, &get_vfp}, //
|
||||||
|
[ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp, &get_edsp}, //
|
||||||
|
[ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java, &get_java}, //
|
||||||
|
[ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt, &get_iwmmxt}, //
|
||||||
|
[ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch, &get_crunch}, //
|
||||||
|
[ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee, &get_thumbee}, //
|
||||||
|
[ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon, &get_neon}, //
|
||||||
|
[ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3, &get_vfpv3}, //
|
||||||
|
[ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16, &get_vfpv3d16}, //
|
||||||
|
[ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls, &get_tls}, //
|
||||||
|
[ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4, &get_vfpv4}, //
|
||||||
|
[ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva, &get_idiva}, //
|
||||||
|
[ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt, &get_idivt}, //
|
||||||
|
[ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32, &get_vfpd32}, //
|
||||||
|
[ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae, &get_lpae}, //
|
||||||
|
[ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, //
|
||||||
|
[ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes, &get_aes}, //
|
||||||
|
[ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull, &get_pmull}, //
|
||||||
|
[ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1, &get_sha1}, //
|
||||||
|
[ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2, &get_sha2}, //
|
||||||
|
[ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32, &get_crc32}, //
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool processor_reports_armv6;
|
||||||
|
bool hardware_reports_goldfish;
|
||||||
|
} ProcCpuInfoData;
|
||||||
|
|
||||||
|
static int IndexOfNonDigit(StringView str) {
|
||||||
|
size_t index = 0;
|
||||||
|
while (str.size && isdigit(CpuFeatures_StringView_Front(str))) {
|
||||||
|
str = CpuFeatures_StringView_PopFront(str, 1);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HandleArmLine(const LineResult result, ArmInfo* const info,
|
||||||
|
ProcCpuInfoData* const proc_info) {
|
||||||
|
StringView line = result.line;
|
||||||
|
StringView key, value;
|
||||||
|
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
|
||||||
|
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
|
||||||
|
CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
|
||||||
|
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
|
||||||
|
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
|
||||||
|
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
|
||||||
|
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU architecture"))) {
|
||||||
|
// CPU architecture is a number that may be followed by letters. e.g.
|
||||||
|
// "6TEJ", "7".
|
||||||
|
const StringView digits =
|
||||||
|
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
|
||||||
|
info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("Processor"))
|
||||||
|
|| CpuFeatures_StringView_IsEquals(key, str("model name")) ) {
|
||||||
|
// Android reports this in a non-Linux standard "Processor" but sometimes
|
||||||
|
// also in "model name", Linux reports it only in "model name"
|
||||||
|
// see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases
|
||||||
|
proc_info->processor_reports_armv6 =
|
||||||
|
CpuFeatures_StringView_IndexOf(value, str("(v6l)")) >= 0;
|
||||||
|
} else if (CpuFeatures_StringView_IsEquals(key, str("Hardware"))) {
|
||||||
|
proc_info->hardware_reports_goldfish =
|
||||||
|
CpuFeatures_StringView_IsEquals(value, str("Goldfish"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !result.eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetArmCpuId(const ArmInfo* const info) {
|
||||||
|
return (ExtractBitRange(info->implementer, 7, 0) << 24) |
|
||||||
|
(ExtractBitRange(info->variant, 3, 0) << 20) |
|
||||||
|
(ExtractBitRange(info->part, 11, 0) << 4) |
|
||||||
|
(ExtractBitRange(info->revision, 3, 0) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FixErrors(ArmInfo* const info,
|
||||||
|
ProcCpuInfoData* const proc_cpu_info_data) {
|
||||||
|
// Fixing Samsung kernel reporting invalid cpu architecture.
|
||||||
|
// http://code.google.com/p/android/issues/detail?id=10812
|
||||||
|
if (proc_cpu_info_data->processor_reports_armv6 && info->architecture >= 7) {
|
||||||
|
info->architecture = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle kernel configuration bugs that prevent the correct reporting of CPU
|
||||||
|
// features.
|
||||||
|
switch (GetArmCpuId(info)) {
|
||||||
|
case 0x4100C080:
|
||||||
|
// Special case: The emulator-specific Android 4.2 kernel fails to report
|
||||||
|
// support for the 32-bit ARM IDIV instruction. Technically, this is a
|
||||||
|
// feature of the virtual CPU implemented by the emulator. Note that it
|
||||||
|
// could also support Thumb IDIV in the future, and this will have to be
|
||||||
|
// slightly updated.
|
||||||
|
if (info->architecture >= 7 &&
|
||||||
|
proc_cpu_info_data->hardware_reports_goldfish) {
|
||||||
|
info->features.idiva = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x511004D0:
|
||||||
|
// https://crbug.com/341598.
|
||||||
|
info->features.neon = false;
|
||||||
|
break;
|
||||||
|
case 0x510006F2:
|
||||||
|
case 0x510006F3:
|
||||||
|
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report
|
||||||
|
// IDIV support.
|
||||||
|
info->features.idiva = true;
|
||||||
|
info->features.idivt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Propagate cpu features.
|
||||||
|
if (info->features.vfpv4) info->features.vfpv3 = true;
|
||||||
|
if (info->features.neon) info->features.vfpv3 = true;
|
||||||
|
if (info->features.vfpv3) info->features.vfp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillProcCpuInfoData(ArmInfo* const info,
|
||||||
|
ProcCpuInfoData* proc_cpu_info_data) {
|
||||||
|
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
|
||||||
|
if (fd >= 0) {
|
||||||
|
StackLineReader reader;
|
||||||
|
StackLineReader_Initialize(&reader, fd);
|
||||||
|
for (;;) {
|
||||||
|
if (!HandleArmLine(StackLineReader_NextLine(&reader), info,
|
||||||
|
proc_cpu_info_data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuFeatures_CloseFile(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ArmInfo kEmptyArmInfo;
|
||||||
|
|
||||||
|
static const ProcCpuInfoData kEmptyProcCpuInfoData;
|
||||||
|
|
||||||
|
ArmInfo GetArmInfo(void) {
|
||||||
|
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
||||||
|
// have some information if the executable is sandboxed (aka no access to
|
||||||
|
// /proc/cpuinfo).
|
||||||
|
ArmInfo info = kEmptyArmInfo;
|
||||||
|
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
|
||||||
|
|
||||||
|
FillProcCpuInfoData(&info, &proc_cpu_info_data);
|
||||||
|
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
||||||
|
CpuFeatures_GetHardwareCapabilities(),
|
||||||
|
&info.features);
|
||||||
|
|
||||||
|
FixErrors(&info, &proc_cpu_info_data);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
int GetArmFeaturesEnumValue(const ArmFeatures* features,
|
||||||
|
ArmFeaturesEnum value) {
|
||||||
|
if(value >= kConfigsSize)
|
||||||
|
return false;
|
||||||
|
return kConfigs[value].get_bit((ArmFeatures*)features);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
|
||||||
|
if(value >= kConfigsSize)
|
||||||
|
return "unknown feature";
|
||||||
|
return kConfigs[value].proc_cpuinfo_flag;
|
||||||
|
}
|
||||||
1589
DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_x86.c
Normal file
1589
DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_x86.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "internal/filesystem.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_MOCK_FILESYSTEM)
|
||||||
|
// Implementation will be provided by test/filesystem_for_testing.cc.
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#include <io.h>
|
||||||
|
int CpuFeatures_OpenFile(const char* filename) {
|
||||||
|
int fd = -1;
|
||||||
|
_sopen_s(&fd, filename, _O_RDONLY, _SH_DENYWR, _S_IREAD);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuFeatures_CloseFile(int file_descriptor) { _close(file_descriptor); }
|
||||||
|
|
||||||
|
int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
|
||||||
|
size_t buffer_size) {
|
||||||
|
return _read(file_descriptor, buffer, (unsigned int)buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int CpuFeatures_OpenFile(const char* filename) {
|
||||||
|
int result;
|
||||||
|
do {
|
||||||
|
result = open(filename, O_RDONLY);
|
||||||
|
} while (result == -1L && errno == EINTR);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuFeatures_CloseFile(int file_descriptor) { close(file_descriptor); }
|
||||||
|
|
||||||
|
int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
|
||||||
|
size_t buffer_size) {
|
||||||
|
int result;
|
||||||
|
do {
|
||||||
|
result = read(file_descriptor, buffer, buffer_size);
|
||||||
|
} while (result == -1L && errno == EINTR);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
162
DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/hwcaps.c
Normal file
162
DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/hwcaps.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
#include "internal/filesystem.h"
|
||||||
|
#include "internal/hwcaps.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
|
#if defined(NDEBUG)
|
||||||
|
#define D(...)
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
#define D(...) \
|
||||||
|
do { \
|
||||||
|
printf(__VA_ARGS__); \
|
||||||
|
fflush(stdout); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of GetElfHwcapFromGetauxval
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
|
||||||
|
// Implementation will be provided by test/hwcaps_for_testing.cc.
|
||||||
|
#elif defined(HAVE_STRONG_GETAUXVAL)
|
||||||
|
#include <sys/auxv.h>
|
||||||
|
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
|
||||||
|
return getauxval(hwcap_type);
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_DLFCN_H)
|
||||||
|
// On Android we probe the system's C library for a 'getauxval' function and
|
||||||
|
// call it if it exits, or return 0 for failure. This function is available
|
||||||
|
// since API level 20.
|
||||||
|
//
|
||||||
|
// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge
|
||||||
|
// case where some NDK developers use headers for a platform that is newer than
|
||||||
|
// the one really targetted by their application. This is typically done to use
|
||||||
|
// newer native APIs only when running on more recent Android versions, and
|
||||||
|
// requires careful symbol management.
|
||||||
|
//
|
||||||
|
// Note that getauxval() can't really be re-implemented here, because its
|
||||||
|
// implementation does not parse /proc/self/auxv. Instead it depends on values
|
||||||
|
// that are passed by the kernel at process-init time to the C runtime
|
||||||
|
// initialization layer.
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#define AT_HWCAP 16
|
||||||
|
#define AT_HWCAP2 26
|
||||||
|
#define AT_PLATFORM 15
|
||||||
|
#define AT_BASE_PLATFORM 24
|
||||||
|
|
||||||
|
typedef unsigned long getauxval_func_t(unsigned long);
|
||||||
|
|
||||||
|
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
|
||||||
|
uint32_t ret = 0;
|
||||||
|
void* libc_handle = NULL;
|
||||||
|
getauxval_func_t* func = NULL;
|
||||||
|
|
||||||
|
dlerror(); // Cleaning error state before calling dlopen.
|
||||||
|
libc_handle = dlopen("libc.so", RTLD_NOW);
|
||||||
|
if (!libc_handle) {
|
||||||
|
D("Could not dlopen() C library: %s\n", dlerror());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
func = (getauxval_func_t*)dlsym(libc_handle, "getauxval");
|
||||||
|
if (!func) {
|
||||||
|
D("Could not find getauxval() in C library\n");
|
||||||
|
} else {
|
||||||
|
// Note: getauxval() returns 0 on failure. Doesn't touch errno.
|
||||||
|
ret = (uint32_t)(*func)(hwcap_type);
|
||||||
|
}
|
||||||
|
dlclose(libc_handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "This platform does not provide hardware capabilities."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Implementation of GetHardwareCapabilities for OS that provide
|
||||||
|
// GetElfHwcapFromGetauxval().
|
||||||
|
|
||||||
|
// Fallback when getauxval is not available, retrieves hwcaps from
|
||||||
|
// "/proc/self/auxv".
|
||||||
|
static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
|
||||||
|
struct {
|
||||||
|
uint32_t tag;
|
||||||
|
uint32_t value;
|
||||||
|
} entry;
|
||||||
|
uint32_t result = 0;
|
||||||
|
const char filepath[] = "/proc/self/auxv";
|
||||||
|
const int fd = CpuFeatures_OpenFile(filepath);
|
||||||
|
if (fd < 0) {
|
||||||
|
D("Could not open %s\n", filepath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
const int ret = CpuFeatures_ReadFile(fd, (char*)&entry, sizeof entry);
|
||||||
|
if (ret < 0) {
|
||||||
|
D("Error while reading %s\n", filepath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Detect end of list.
|
||||||
|
if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (entry.tag == hwcap_type) {
|
||||||
|
result = entry.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuFeatures_CloseFile(fd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves hardware capabilities by first trying to call getauxval, if not
|
||||||
|
// available falls back to reading "/proc/self/auxv".
|
||||||
|
static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
|
||||||
|
unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
|
||||||
|
if (!hwcaps) {
|
||||||
|
D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
|
||||||
|
hwcaps = GetElfHwcapFromProcSelfAuxv(type);
|
||||||
|
}
|
||||||
|
return hwcaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
|
||||||
|
HardwareCapabilities capabilities;
|
||||||
|
capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
|
||||||
|
capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformType kEmptyPlatformType;
|
||||||
|
|
||||||
|
PlatformType CpuFeatures_GetPlatformType(void) {
|
||||||
|
PlatformType type = kEmptyPlatformType;
|
||||||
|
char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
|
||||||
|
char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
|
||||||
|
|
||||||
|
if (platform != NULL)
|
||||||
|
CpuFeatures_StringView_CopyString(str(platform), type.platform,
|
||||||
|
sizeof(type.platform));
|
||||||
|
if (base_platform != NULL)
|
||||||
|
CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform,
|
||||||
|
sizeof(type.base_platform));
|
||||||
|
return type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "internal/stack_line_reader.h"
|
||||||
|
#include "internal/filesystem.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void StackLineReader_Initialize(StackLineReader* reader, int fd) {
|
||||||
|
reader->view.ptr = reader->buffer;
|
||||||
|
reader->view.size = 0;
|
||||||
|
reader->skip_mode = false;
|
||||||
|
reader->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replaces the content of buffer with bytes from the file.
|
||||||
|
static int LoadFullBuffer(StackLineReader* reader) {
|
||||||
|
const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer,
|
||||||
|
STACK_LINE_READER_BUFFER_SIZE);
|
||||||
|
assert(read >= 0);
|
||||||
|
reader->view.ptr = reader->buffer;
|
||||||
|
reader->view.size = read;
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Appends with bytes from the file to buffer, filling the remaining space.
|
||||||
|
static int LoadMore(StackLineReader* reader) {
|
||||||
|
char* const ptr = reader->buffer + reader->view.size;
|
||||||
|
const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size;
|
||||||
|
const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read);
|
||||||
|
assert(read >= 0);
|
||||||
|
assert(read <= (int)size_to_read);
|
||||||
|
reader->view.size += read;
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int IndexOfEol(StackLineReader* reader) {
|
||||||
|
return CpuFeatures_StringView_IndexOfChar(reader->view, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocate buffer's pending bytes at the beginning of the array and fills the
|
||||||
|
// remaining space with bytes from the file.
|
||||||
|
static int BringToFrontAndLoadMore(StackLineReader* reader) {
|
||||||
|
if (reader->view.size && reader->view.ptr != reader->buffer) {
|
||||||
|
memmove(reader->buffer, reader->view.ptr, reader->view.size);
|
||||||
|
}
|
||||||
|
reader->view.ptr = reader->buffer;
|
||||||
|
return LoadMore(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads chunks of buffer size from disks until it contains a newline character
|
||||||
|
// or end of file.
|
||||||
|
static void SkipToNextLine(StackLineReader* reader) {
|
||||||
|
for (;;) {
|
||||||
|
const int read = LoadFullBuffer(reader);
|
||||||
|
if (read == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const int eol_index = IndexOfEol(reader);
|
||||||
|
if (eol_index >= 0) {
|
||||||
|
reader->view =
|
||||||
|
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static LineResult CreateLineResult(bool eof, bool full_line, StringView view) {
|
||||||
|
LineResult result;
|
||||||
|
result.eof = eof;
|
||||||
|
result.full_line = full_line;
|
||||||
|
result.line = view;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods to provide clearer semantic in StackLineReader_NextLine.
|
||||||
|
static LineResult CreateEOFLineResult(StringView view) {
|
||||||
|
return CreateLineResult(true, true, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LineResult CreateTruncatedLineResult(StringView view) {
|
||||||
|
return CreateLineResult(false, false, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LineResult CreateValidLineResult(StringView view) {
|
||||||
|
return CreateLineResult(false, true, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
LineResult StackLineReader_NextLine(StackLineReader* reader) {
|
||||||
|
if (reader->skip_mode) {
|
||||||
|
SkipToNextLine(reader);
|
||||||
|
reader->skip_mode = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const bool can_load_more =
|
||||||
|
reader->view.size < STACK_LINE_READER_BUFFER_SIZE;
|
||||||
|
int eol_index = IndexOfEol(reader);
|
||||||
|
if (eol_index < 0 && can_load_more) {
|
||||||
|
const int read = BringToFrontAndLoadMore(reader);
|
||||||
|
if (read == 0) {
|
||||||
|
return CreateEOFLineResult(reader->view);
|
||||||
|
}
|
||||||
|
eol_index = IndexOfEol(reader);
|
||||||
|
}
|
||||||
|
if (eol_index < 0) {
|
||||||
|
reader->skip_mode = true;
|
||||||
|
return CreateTruncatedLineResult(reader->view);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StringView line =
|
||||||
|
CpuFeatures_StringView_KeepFront(reader->view, eol_index);
|
||||||
|
reader->view =
|
||||||
|
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
|
||||||
|
return CreateValidLineResult(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
|
||||||
|
if (view.ptr && view.size) {
|
||||||
|
const char* const found = (const char*)memchr(view.ptr, c, view.size);
|
||||||
|
if (found) {
|
||||||
|
return (int)(found - view.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CpuFeatures_StringView_IndexOf(const StringView view,
|
||||||
|
const StringView sub_view) {
|
||||||
|
if (sub_view.size) {
|
||||||
|
StringView remainder = view;
|
||||||
|
while (remainder.size >= sub_view.size) {
|
||||||
|
const int found_index =
|
||||||
|
CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
|
||||||
|
if (found_index < 0) break;
|
||||||
|
remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
|
||||||
|
if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
|
||||||
|
return (int)(remainder.ptr - view.ptr);
|
||||||
|
}
|
||||||
|
remainder = CpuFeatures_StringView_PopFront(remainder, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
|
||||||
|
if (a.size == b.size) {
|
||||||
|
return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
|
||||||
|
return a.ptr && b.ptr && b.size && a.size >= b.size
|
||||||
|
? memcmp(a.ptr, b.ptr, b.size) == 0
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView CpuFeatures_StringView_PopFront(const StringView str_view,
|
||||||
|
size_t count) {
|
||||||
|
if (count > str_view.size) {
|
||||||
|
return kEmptyStringView;
|
||||||
|
}
|
||||||
|
return view(str_view.ptr + count, str_view.size - count);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView CpuFeatures_StringView_PopBack(const StringView str_view,
|
||||||
|
size_t count) {
|
||||||
|
if (count > str_view.size) {
|
||||||
|
return kEmptyStringView;
|
||||||
|
}
|
||||||
|
return view(str_view.ptr, str_view.size - count);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
|
||||||
|
size_t count) {
|
||||||
|
return count <= str_view.size ? view(str_view.ptr, count) : str_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
char CpuFeatures_StringView_Front(const StringView view) {
|
||||||
|
assert(view.size);
|
||||||
|
assert(view.ptr);
|
||||||
|
return view.ptr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
char CpuFeatures_StringView_Back(const StringView view) {
|
||||||
|
assert(view.size);
|
||||||
|
return view.ptr[view.size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
|
||||||
|
while (view.size && isspace(CpuFeatures_StringView_Front(view)))
|
||||||
|
view = CpuFeatures_StringView_PopFront(view, 1);
|
||||||
|
while (view.size && isspace(CpuFeatures_StringView_Back(view)))
|
||||||
|
view = CpuFeatures_StringView_PopBack(view, 1);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int HexValue(const char c) {
|
||||||
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||||
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns -1 if view contains non digits.
|
||||||
|
static int ParsePositiveNumberWithBase(const StringView view, int base) {
|
||||||
|
int result = 0;
|
||||||
|
StringView remainder = view;
|
||||||
|
for (; remainder.size;
|
||||||
|
remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
|
||||||
|
const int value = HexValue(CpuFeatures_StringView_Front(remainder));
|
||||||
|
if (value < 0 || value >= base) return -1;
|
||||||
|
result = (result * base) + value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
|
||||||
|
if (view.size) {
|
||||||
|
const StringView hex_prefix = str("0x");
|
||||||
|
if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
|
||||||
|
const StringView span_no_prefix =
|
||||||
|
CpuFeatures_StringView_PopFront(view, hex_prefix.size);
|
||||||
|
return ParsePositiveNumberWithBase(span_no_prefix, 16);
|
||||||
|
}
|
||||||
|
return ParsePositiveNumberWithBase(view, 10);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
|
||||||
|
size_t dst_size) {
|
||||||
|
if (dst_size > 0) {
|
||||||
|
const size_t max_copy_size = dst_size - 1;
|
||||||
|
const size_t copy_size =
|
||||||
|
src.size > max_copy_size ? max_copy_size : src.size;
|
||||||
|
memcpy(dst, src.ptr, copy_size);
|
||||||
|
dst[copy_size] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuFeatures_StringView_HasWord(const StringView line,
|
||||||
|
const char* const word_str) {
|
||||||
|
const StringView word = str(word_str);
|
||||||
|
StringView remainder = line;
|
||||||
|
for (;;) {
|
||||||
|
const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
|
||||||
|
if (index_of_word < 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const StringView before =
|
||||||
|
CpuFeatures_StringView_KeepFront(line, index_of_word);
|
||||||
|
const StringView after =
|
||||||
|
CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
|
||||||
|
const bool valid_before =
|
||||||
|
before.size == 0 || CpuFeatures_StringView_Back(before) == ' ';
|
||||||
|
const bool valid_after =
|
||||||
|
after.size == 0 || CpuFeatures_StringView_Front(after) == ' ';
|
||||||
|
if (valid_before && valid_after) return true;
|
||||||
|
remainder =
|
||||||
|
CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
|
||||||
|
StringView* key,
|
||||||
|
StringView* value) {
|
||||||
|
const StringView sep = str(": ");
|
||||||
|
const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
|
||||||
|
if (index_of_separator < 0) return false;
|
||||||
|
*value = CpuFeatures_StringView_TrimWhitespace(
|
||||||
|
CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size));
|
||||||
|
*key = CpuFeatures_StringView_TrimWhitespace(
|
||||||
|
CpuFeatures_StringView_KeepFront(line, index_of_separator));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright 2017 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "internal/unix_features_aggregator.h"
|
||||||
|
#include "internal/string_view.h"
|
||||||
|
|
||||||
|
void CpuFeatures_SetFromFlags(const size_t configs_size,
|
||||||
|
const CapabilityConfig* configs,
|
||||||
|
const StringView flags_line,
|
||||||
|
void* const features) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < configs_size; ++i) {
|
||||||
|
const CapabilityConfig config = configs[i];
|
||||||
|
config.set_bit(features, CpuFeatures_StringView_HasWord(
|
||||||
|
flags_line, config.proc_cpuinfo_flag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsSet(const uint32_t mask, const uint32_t value) {
|
||||||
|
if (mask == 0) return false;
|
||||||
|
return (value & mask) == mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
|
||||||
|
const HardwareCapabilities hwcaps) {
|
||||||
|
return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
|
||||||
|
IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
|
||||||
|
const CapabilityConfig* configs,
|
||||||
|
const HardwareCapabilities hwcaps,
|
||||||
|
void* const features) {
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < configs_size; ++i) {
|
||||||
|
const CapabilityConfig* config = &configs[i];
|
||||||
|
if (IsHwCapsSet(config->hwcaps_mask, hwcaps)) {
|
||||||
|
config->set_bit(features, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,12 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#if defined(__arm__)
|
||||||
|
#include "cpuinfo_arm.h"
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: org_petero_droidfish_engine_EngineUtil
|
* Class: org_petero_droidfish_engine_EngineUtil
|
||||||
* Method: chmod
|
* Method: chmod
|
||||||
@@ -48,3 +54,21 @@ extern "C" JNIEXPORT void JNICALL Java_org_petero_droidfish_engine_EngineUtil_re
|
|||||||
setpriority(PRIO_PROCESS, pid, prio);
|
setpriority(PRIO_PROCESS, pid, prio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_petero_droidfish_engine_EngineUtil
|
||||||
|
* Method: isSimdSupported
|
||||||
|
* Signature: ()Z
|
||||||
|
*/
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL Java_org_petero_droidfish_engine_EngineUtil_isSimdSupported
|
||||||
|
(JNIEnv *env, jclass) {
|
||||||
|
#if defined(__arm__)
|
||||||
|
using namespace cpu_features;
|
||||||
|
ArmFeatures features = GetArmInfo().features;
|
||||||
|
return features.neon ? JNI_TRUE : JNI_FALSE;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
using namespace cpu_features;
|
||||||
|
X86Features features = GetX86Info().features;
|
||||||
|
return features.sse4_1 ? JNI_TRUE : JNI_FALSE;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ public class EngineUtil {
|
|||||||
!"arm64-v8a".equals(abi)) {
|
!"arm64-v8a".equals(abi)) {
|
||||||
abi = "armeabi-v7a"; // Unknown ABI, assume 32-bit arm
|
abi = "armeabi-v7a"; // Unknown ABI, assume 32-bit arm
|
||||||
}
|
}
|
||||||
return abi + "/stockfish";
|
return abi + "/stockfish" + (isSimdSupported() ? "" : "_nosimd");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true if file "engine" is a network engine. */
|
/** Return true if file "engine" is a network engine. */
|
||||||
@@ -100,6 +100,9 @@ public class EngineUtil {
|
|||||||
/** Change the priority of a process. */
|
/** Change the priority of a process. */
|
||||||
static native void reNice(int pid, int prio);
|
static native void reNice(int pid, int prio);
|
||||||
|
|
||||||
|
/** Return true if the required SIMD instructions are supported by the CPU. */
|
||||||
|
static native boolean isSimdSupported();
|
||||||
|
|
||||||
/** For synchronizing non thread safe native calls. */
|
/** For synchronizing non thread safe native calls. */
|
||||||
public static final Object nativeLock = new Object();
|
public static final Object nativeLock = new Object();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user