diff --git a/DroidFishApp/src/main/cpp/Android.mk b/DroidFishApp/src/main/cpp/Android.mk
index c9e4924..a9c581b 100644
--- a/DroidFishApp/src/main/cpp/Android.mk
+++ b/DroidFishApp/src/main/cpp/Android.mk
@@ -1,14 +1,6 @@
LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := nativeutil
-LOCAL_SRC_FILES := nativeutil.cpp
-
-include $(BUILD_SHARED_LIBRARY)
-
+include src/main/cpp/nativeutil/Android.mk
include src/main/cpp/stockfish/Android.mk
-
include src/main/cpp/gtb/Android.mk
-
include src/main/cpp/rtb/Android.mk
diff --git a/DroidFishApp/src/main/cpp/Application.mk b/DroidFishApp/src/main/cpp/Application.mk
index 9735e92..64edb0a 100644
--- a/DroidFishApp/src/main/cpp/Application.mk
+++ b/DroidFishApp/src/main/cpp/Application.mk
@@ -1,4 +1,3 @@
-APP_PLATFORM := android-14
APP_ABI := all
APP_STL := c++_static
APP_OPTIM := release
diff --git a/DroidFishApp/src/main/cpp/nativeutil/Android.mk b/DroidFishApp/src/main/cpp/nativeutil/Android.mk
new file mode 100644
index 0000000..f198f93
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/Android.mk
@@ -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)
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/LICENSE b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/LICENSE
new file mode 100644
index 0000000..a7043c6
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/LICENSE
@@ -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.
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/README.md b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/README.md
new file mode 100644
index 0000000..29d7946
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/README.md
@@ -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)
+
+
+## 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.**
+
+
+### 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
+#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
+#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
+#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.
+
+
+### 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"]}
+```
+
+
+## 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.
+
+
+## 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.
+
+
+## License
+
+The cpu_features library is licensed under the terms of the Apache license.
+See [LICENSE](LICENSE) for more information.
+
+
+## Build with CMake
+
+Please check the [CMake build instructions](cmake/README.md).
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_cache_info.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_cache_info.h
new file mode 100644
index 0000000..b7cc046
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_cache_info.h
@@ -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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_macros.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_macros.h
new file mode 100644
index 0000000..fae9f70
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpu_features_macros.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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_aarch64.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_aarch64.h
new file mode 100644
index 0000000..5a7532e
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_aarch64.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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_arm.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_arm.h
new file mode 100644
index 0000000..d15471f
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_arm.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 // 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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_x86.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_x86.h
new file mode 100644
index 0000000..1e338a9
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/cpuinfo_x86.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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/bit_utils.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/bit_utils.h
new file mode 100644
index 0000000..bc965cb
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/bit_utils.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
+#include
+#include
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/cpuid_x86.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/cpuid_x86.h
new file mode 100644
index 0000000..754ca38
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/cpuid_x86.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
+
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/filesystem.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/filesystem.h
new file mode 100644
index 0000000..3378881
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/filesystem.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
+#include
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/hwcaps.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/hwcaps.h
new file mode 100644
index 0000000..eb54f5c
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/hwcaps.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
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/stack_line_reader.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/stack_line_reader.h
new file mode 100644
index 0000000..c540f6b
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/stack_line_reader.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
+
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/string_view.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/string_view.h
new file mode 100644
index 0000000..aa3779c
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/string_view.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
+#include
+#include
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/unix_features_aggregator.h b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/unix_features_aggregator.h
new file mode 100644
index 0000000..bed668d
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/include/internal/unix_features_aggregator.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
+#include
+#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_
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_aarch64.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_aarch64.c
new file mode 100644
index 0000000..2e43a25
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_aarch64.c
@@ -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
+#include
+
+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;
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_arm.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_arm.c
new file mode 100644
index 0000000..741c99a
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_arm.c
@@ -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
+#include
+
+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;
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_x86.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_x86.c
new file mode 100644
index 0000000..1f27e14
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/cpuinfo_x86.c
@@ -0,0 +1,1589 @@
+// 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_x86.h"
+#include "internal/bit_utils.h"
+#include "internal/cpuid_x86.h"
+
+#include
+#include
+
+#if !defined(CPU_FEATURES_ARCH_X86)
+#error "Cannot compile cpuinfo_x86 on a non x86 platform."
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for CpuId and GetXCR0Eax.
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(CPU_FEATURES_MOCK_CPUID_X86)
+// Implementation will be provided by test/cpuinfo_x86_test.cc.
+#elif defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
+
+#include
+
+Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
+ Leaf leaf;
+ __cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
+ return leaf;
+}
+
+uint32_t GetXCR0Eax(void) {
+ uint32_t eax, edx;
+ /* named form of xgetbv not supported on OSX, so must use byte form, see:
+ https://github.com/asmjit/asmjit/issues/78
+ */
+ __asm(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+ return eax;
+}
+
+#elif defined(CPU_FEATURES_COMPILER_MSC)
+
+#include
+#include // For __cpuidex()
+
+Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
+ Leaf leaf;
+ int data[4];
+ __cpuidex(data, leaf_id, ecx);
+ leaf.eax = data[0];
+ leaf.ebx = data[1];
+ leaf.ecx = data[2];
+ leaf.edx = data[3];
+ return leaf;
+}
+
+uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
+
+#else
+#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC."
+#endif
+
+static Leaf CpuId(uint32_t leaf_id) { return CpuIdEx(leaf_id, 0); }
+
+static const Leaf kEmptyLeaf;
+
+static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) {
+ if (leaf_id <= max_cpuid_leaf) {
+ return CpuIdEx(leaf_id, ecx);
+ } else {
+ return kEmptyLeaf;
+ }
+}
+
+static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) {
+ return SafeCpuIdEx(max_cpuid_leaf, leaf_id, 0);
+}
+
+#define MASK_XMM 0x2
+#define MASK_YMM 0x4
+#define MASK_MASKREG 0x20
+#define MASK_ZMM0_15 0x40
+#define MASK_ZMM16_31 0x80
+
+static bool HasMask(uint32_t value, uint32_t mask) {
+ return (value & mask) == mask;
+}
+
+// Checks that operating system saves and restores xmm registers during context
+// switches.
+static bool HasXmmOsXSave(uint32_t xcr0_eax) {
+ return HasMask(xcr0_eax, MASK_XMM);
+}
+
+// Checks that operating system saves and restores ymm registers during context
+// switches.
+static bool HasYmmOsXSave(uint32_t xcr0_eax) {
+ return HasMask(xcr0_eax, MASK_XMM | MASK_YMM);
+}
+
+// Checks that operating system saves and restores zmm registers during context
+// switches.
+static bool HasZmmOsXSave(uint32_t xcr0_eax) {
+ return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
+ MASK_ZMM16_31);
+}
+
+static void SetVendor(const Leaf leaf, char* const vendor) {
+ *(uint32_t*)(vendor) = leaf.ebx;
+ *(uint32_t*)(vendor + 4) = leaf.edx;
+ *(uint32_t*)(vendor + 8) = leaf.ecx;
+ vendor[12] = '\0';
+}
+
+static int IsVendor(const Leaf leaf, const char* const name) {
+ const uint32_t ebx = *(const uint32_t*)(name);
+ const uint32_t edx = *(const uint32_t*)(name + 4);
+ const uint32_t ecx = *(const uint32_t*)(name + 8);
+ return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx;
+}
+
+static const CacheLevelInfo kEmptyCacheLevelInfo;
+
+static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
+ const int UNDEF = -1;
+ const int KiB = 1024;
+ const int MiB = 1024 * KiB;
+ switch (reg) {
+ case 0x01:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
+ case 0x02:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 2,
+ .partitioning = 0};
+ case 0x03:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0x04:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
+ case 0x05:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
+ case 0x06:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 8 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x08:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x09:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x0A:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * KiB,
+ .ways = 2,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x0B:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 4,
+ .partitioning = 0};
+ case 0x0C:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x0D:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x0E:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 24 * KiB,
+ .ways = 6,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x1D:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 2,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x21:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x22:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x23:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x24:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x25:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x29:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x2C:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x30:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x40:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = UNDEF,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x41:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x42:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x43:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x44:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x45:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x46:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x47:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x48:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 3 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x49:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case (0x49 | (1 << 8)):
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4A:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4B:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4C:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 12 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4D:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4E:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x4F:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
+ case 0x50:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0x51:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
+ case 0x52:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
+ case 0x55:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 7,
+ .partitioning = 0};
+ case 0x56:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
+ case 0x57:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
+ case 0x59:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
+ case 0x5A:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
+ case 0x5B:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0x5C:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
+ case 0x5D:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
+ case 0x60:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x61:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 48,
+ .partitioning = 0};
+ case 0x63:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 4,
+ .partitioning = 0};
+ case 0x66:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x67:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 16 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x68:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 32 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x70:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 12 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x71:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 16 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x72:
+ return (CacheLevelInfo){.level = 1,
+ .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
+ .cache_size = 32 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x76:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
+ case 0x78:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x79:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 128 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x7A:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x7B:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x7C:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 2};
+ case 0x7D:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x7F:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 2,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x80:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x82:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 256 * KiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x83:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x84:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x85:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x86:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 32,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0x87:
+ return (CacheLevelInfo){.level = 2,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xA0:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DTLB,
+ .cache_size = 4 * KiB,
+ .ways = 0xFF,
+ .line_size = UNDEF,
+ .tlb_entries = 32,
+ .partitioning = 0};
+ case 0xB0:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
+ case 0xB1:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
+ case 0xB2:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0xB3:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
+ case 0xB4:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 256,
+ .partitioning = 0};
+ case 0xB5:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0xB6:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 128,
+ .partitioning = 0};
+ case 0xBA:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 64,
+ .partitioning = 0};
+ case 0xC0:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_TLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 8,
+ .partitioning = 0};
+ case 0xC1:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 8,
+ .line_size = UNDEF,
+ .tlb_entries = 1024,
+ .partitioning = 0};
+ case 0xC2:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_DTLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 16,
+ .partitioning = 0};
+ case 0xC3:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 6,
+ .line_size = UNDEF,
+ .tlb_entries = 1536,
+ .partitioning = 0};
+ case 0xCA:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_STLB,
+ .cache_size = 4 * KiB,
+ .ways = 4,
+ .line_size = UNDEF,
+ .tlb_entries = 512,
+ .partitioning = 0};
+ case 0xD0:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 512 * KiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xD1:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xD2:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 4,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xD6:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xD7:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xD8:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 8,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xDC:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 1 * 1536 * KiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xDD:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 3 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xDE:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 6 * MiB,
+ .ways = 12,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xE2:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 2 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xE3:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 4 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xE4:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 8 * MiB,
+ .ways = 16,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xEA:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 12 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xEB:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 18 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xEC:
+ return (CacheLevelInfo){.level = 3,
+ .cache_type = CPU_FEATURE_CACHE_DATA,
+ .cache_size = 24 * MiB,
+ .ways = 24,
+ .line_size = 64,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xF0:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+ .cache_size = 64 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xF1:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_PREFETCH,
+ .cache_size = 128 * KiB,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ case 0xFF:
+ return (CacheLevelInfo){.level = UNDEF,
+ .cache_type = CPU_FEATURE_CACHE_NULL,
+ .cache_size = UNDEF,
+ .ways = UNDEF,
+ .line_size = UNDEF,
+ .tlb_entries = UNDEF,
+ .partitioning = 0};
+ default:
+ return kEmptyCacheLevelInfo;
+ }
+}
+
+static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) {
+ for (int i = 0; i < 4; ++i) {
+ result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8);
+ }
+}
+
+static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
+ Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
+ uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
+ for (int i = 0; i < 4; ++i) {
+ if (registers[i] & (1U << 31)) {
+ continue; // register does not contains valid information
+ }
+ uint32_t bytes[4];
+ GetByteArrayFromRegister(bytes, registers[i]);
+ for (int j = 0; j < 4; ++j) {
+ if (bytes[j] == 0xFF)
+ break; // leaf 4 should be used to fetch cache information
+ info->levels[info->size] = GetCacheLevelInfo(bytes[j]);
+ }
+ info->size++;
+ }
+}
+
+static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
+ info->size = 0;
+ for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) {
+ const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id);
+ CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0);
+ if (cache_type == CPU_FEATURE_CACHE_NULL) {
+ info->levels[cache_id] = kEmptyCacheLevelInfo;
+ continue;
+ }
+ int level = ExtractBitRange(leaf.eax, 7, 5);
+ int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
+ int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
+ int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
+ int tlb_entries = leaf.ecx + 1;
+ int cache_size = (ways * partitioning * line_size * (tlb_entries));
+ info->levels[cache_id] = (CacheLevelInfo){.level = level,
+ .cache_type = cache_type,
+ .cache_size = cache_size,
+ .ways = ways,
+ .line_size = line_size,
+ .tlb_entries = tlb_entries,
+ .partitioning = partitioning};
+ info->size++;
+ }
+}
+
+// Internal structure to hold the OS support for vector operations.
+// Avoid to recompute them since each call to cpuid is ~100 cycles.
+typedef struct {
+ bool have_sse;
+ bool have_avx;
+ bool have_avx512;
+} OsSupport;
+
+// Reference https://en.wikipedia.org/wiki/CPUID.
+static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport* os_support) {
+ const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
+ const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
+
+ const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
+ const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
+ const uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0;
+ os_support->have_sse = HasXmmOsXSave(xcr0_eax);
+ os_support->have_avx = HasYmmOsXSave(xcr0_eax);
+ os_support->have_avx512 = HasZmmOsXSave(xcr0_eax);
+
+ const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
+ const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
+ const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4);
+ const uint32_t extended_model = ExtractBitRange(leaf_1.eax, 19, 16);
+
+ X86Features* const features = &info->features;
+
+ info->family = extended_family + family;
+ info->model = (extended_model << 4) + model;
+ info->stepping = ExtractBitRange(leaf_1.eax, 3, 0);
+
+ features->fpu = IsBitSet(leaf_1.edx, 0);
+ features->tsc = IsBitSet(leaf_1.edx, 4);
+ features->cx8 = IsBitSet(leaf_1.edx, 8);
+ features->clfsh = IsBitSet(leaf_1.edx, 19);
+ features->mmx = IsBitSet(leaf_1.edx, 23);
+ features->ss = IsBitSet(leaf_1.edx, 27);
+ features->pclmulqdq = IsBitSet(leaf_1.ecx, 1);
+ features->smx = IsBitSet(leaf_1.ecx, 6);
+ features->cx16 = IsBitSet(leaf_1.ecx, 13);
+ features->dca = IsBitSet(leaf_1.ecx, 18);
+ features->movbe = IsBitSet(leaf_1.ecx, 22);
+ features->popcnt = IsBitSet(leaf_1.ecx, 23);
+ features->aes = IsBitSet(leaf_1.ecx, 25);
+ features->f16c = IsBitSet(leaf_1.ecx, 29);
+ features->rdrnd = IsBitSet(leaf_1.ecx, 30);
+ features->sgx = IsBitSet(leaf_7.ebx, 2);
+ features->bmi1 = IsBitSet(leaf_7.ebx, 3);
+ features->hle = IsBitSet(leaf_7.ebx, 4);
+ features->bmi2 = IsBitSet(leaf_7.ebx, 8);
+ features->erms = IsBitSet(leaf_7.ebx, 9);
+ features->rtm = IsBitSet(leaf_7.ebx, 11);
+ features->rdseed = IsBitSet(leaf_7.ebx, 18);
+ features->clflushopt = IsBitSet(leaf_7.ebx, 23);
+ features->clwb = IsBitSet(leaf_7.ebx, 24);
+ features->sha = IsBitSet(leaf_7.ebx, 29);
+ features->vaes = IsBitSet(leaf_7.ecx, 9);
+ features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
+
+ if (os_support->have_sse) {
+ features->sse = IsBitSet(leaf_1.edx, 25);
+ features->sse2 = IsBitSet(leaf_1.edx, 26);
+ features->sse3 = IsBitSet(leaf_1.ecx, 0);
+ features->ssse3 = IsBitSet(leaf_1.ecx, 9);
+ features->sse4_1 = IsBitSet(leaf_1.ecx, 19);
+ features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
+ }
+
+ if (os_support->have_avx) {
+ features->fma3 = IsBitSet(leaf_1.ecx, 12);
+ features->avx = IsBitSet(leaf_1.ecx, 28);
+ features->avx2 = IsBitSet(leaf_7.ebx, 5);
+ }
+
+ if (os_support->have_avx512) {
+ features->avx512f = IsBitSet(leaf_7.ebx, 16);
+ features->avx512cd = IsBitSet(leaf_7.ebx, 28);
+ features->avx512er = IsBitSet(leaf_7.ebx, 27);
+ features->avx512pf = IsBitSet(leaf_7.ebx, 26);
+ features->avx512bw = IsBitSet(leaf_7.ebx, 30);
+ features->avx512dq = IsBitSet(leaf_7.ebx, 17);
+ features->avx512vl = IsBitSet(leaf_7.ebx, 31);
+ features->avx512ifma = IsBitSet(leaf_7.ebx, 21);
+ features->avx512vbmi = IsBitSet(leaf_7.ecx, 1);
+ features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6);
+ features->avx512vnni = IsBitSet(leaf_7.ecx, 11);
+ features->avx512bitalg = IsBitSet(leaf_7.ecx, 12);
+ features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
+ features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
+ features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
+ }
+}
+
+// Reference https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
+static void ParseExtraAMDCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport os_support) {
+ const Leaf leaf_80000000 = CpuId(0x80000000);
+ const Leaf leaf_80000001 = SafeCpuId(leaf_80000000.eax, 0x80000001);
+
+ X86Features* const features = &info->features;
+
+ if (os_support.have_sse) {
+ features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
+ }
+
+ if (os_support.have_avx) {
+ features->fma4 = IsBitSet(leaf_80000001.ecx, 16);
+ }
+}
+
+static const X86Info kEmptyX86Info;
+static const OsSupport kEmptyOsSupport;
+static const CacheInfo kEmptyCacheInfo;
+
+X86Info GetX86Info(void) {
+ X86Info info = kEmptyX86Info;
+ OsSupport os_support = kEmptyOsSupport;
+ const Leaf leaf_0 = CpuId(0);
+ const uint32_t max_cpuid_leaf = leaf_0.eax;
+ SetVendor(leaf_0, info.vendor);
+ if (IsVendor(leaf_0, "GenuineIntel") || IsVendor(leaf_0, "AuthenticAMD")) {
+ ParseCpuId(max_cpuid_leaf, &info, &os_support);
+ }
+ if (IsVendor(leaf_0, "AuthenticAMD")) {
+ ParseExtraAMDCpuId(max_cpuid_leaf, &info, os_support);
+ }
+ return info;
+}
+
+CacheInfo GetX86CacheInfo(void) {
+ CacheInfo info = kEmptyCacheInfo;
+ const Leaf leaf_0 = CpuId(0);
+ const uint32_t max_cpuid_leaf = leaf_0.eax;
+ if (IsVendor(leaf_0, "GenuineIntel")) {
+ ParseLeaf2(max_cpuid_leaf, &info);
+ ParseLeaf4(max_cpuid_leaf, &info);
+ }
+ return info;
+}
+
+#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF))
+
+X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
+ if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) {
+ switch (CPUID(info->family, info->model)) {
+ case CPUID(0x06, 0x35):
+ case CPUID(0x06, 0x36):
+ // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture)
+ return INTEL_ATOM_BNL;
+ case CPUID(0x06, 0x37):
+ case CPUID(0x06, 0x4C):
+ // https://en.wikipedia.org/wiki/Silvermont
+ return INTEL_ATOM_SMT;
+ case CPUID(0x06, 0x5C):
+ // https://en.wikipedia.org/wiki/Goldmont
+ return INTEL_ATOM_GMT;
+ case CPUID(0x06, 0x0F):
+ case CPUID(0x06, 0x16):
+ // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture)
+ return INTEL_CORE;
+ case CPUID(0x06, 0x17):
+ case CPUID(0x06, 0x1D):
+ // https://en.wikipedia.org/wiki/Penryn_(microarchitecture)
+ return INTEL_PNR;
+ case CPUID(0x06, 0x1A):
+ case CPUID(0x06, 0x1E):
+ case CPUID(0x06, 0x1F):
+ case CPUID(0x06, 0x2E):
+ // https://en.wikipedia.org/wiki/Nehalem_(microarchitecture)
+ return INTEL_NHM;
+ case CPUID(0x06, 0x25):
+ case CPUID(0x06, 0x2C):
+ case CPUID(0x06, 0x2F):
+ // https://en.wikipedia.org/wiki/Westmere_(microarchitecture)
+ return INTEL_WSM;
+ case CPUID(0x06, 0x2A):
+ case CPUID(0x06, 0x2D):
+ // https://en.wikipedia.org/wiki/Sandy_Bridge#Models_and_steppings
+ return INTEL_SNB;
+ case CPUID(0x06, 0x3A):
+ case CPUID(0x06, 0x3E):
+ // https://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)#Models_and_steppings
+ return INTEL_IVB;
+ case CPUID(0x06, 0x3C):
+ case CPUID(0x06, 0x3F):
+ case CPUID(0x06, 0x45):
+ case CPUID(0x06, 0x46):
+ // https://en.wikipedia.org/wiki/Haswell_(microarchitecture)
+ return INTEL_HSW;
+ case CPUID(0x06, 0x3D):
+ case CPUID(0x06, 0x47):
+ case CPUID(0x06, 0x4F):
+ case CPUID(0x06, 0x56):
+ // https://en.wikipedia.org/wiki/Broadwell_(microarchitecture)
+ return INTEL_BDW;
+ case CPUID(0x06, 0x4E):
+ case CPUID(0x06, 0x55):
+ case CPUID(0x06, 0x5E):
+ // https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
+ return INTEL_SKL;
+ case CPUID(0x06, 0x66):
+ // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
+ return INTEL_CNL;
+ case CPUID(0x06, 0x7E):
+ // https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor)
+ return INTEL_ICL;
+ case CPUID(0x06, 0x8E):
+ switch (info->stepping) {
+ case 9: return INTEL_KBL; // https://en.wikipedia.org/wiki/Kaby_Lake
+ case 10: return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake
+ case 11: return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture)
+ default: return X86_UNKNOWN;
+ }
+ case CPUID(0x06, 0x9E):
+ if (info->stepping > 9) {
+ // https://en.wikipedia.org/wiki/Coffee_Lake
+ return INTEL_CFL;
+ } else {
+ // https://en.wikipedia.org/wiki/Kaby_Lake
+ return INTEL_KBL;
+ }
+ default:
+ return X86_UNKNOWN;
+ }
+ }
+ if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) {
+ switch (info->family) {
+ // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures
+ case 0x0F:
+ return AMD_HAMMER;
+ case 0x10:
+ return AMD_K10;
+ case 0x14:
+ return AMD_BOBCAT;
+ case 0x15:
+ return AMD_BULLDOZER;
+ case 0x16:
+ return AMD_JAGUAR;
+ case 0x17:
+ return AMD_ZEN;
+ default:
+ return X86_UNKNOWN;
+ }
+ }
+ return X86_UNKNOWN;
+}
+
+static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id,
+ char* buffer) {
+ const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id);
+ // We allow calling memcpy from SetString which is only called when requesting
+ // X86BrandString.
+ memcpy(buffer, &leaf, sizeof(Leaf));
+}
+
+void FillX86BrandString(char brand_string[49]) {
+ const Leaf leaf_ext_0 = CpuId(0x80000000);
+ const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax;
+ SetString(max_cpuid_leaf_ext, 0x80000002, brand_string);
+ SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16);
+ SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32);
+ brand_string[48] = '\0';
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Introspection functions
+
+int GetX86FeaturesEnumValue(const X86Features* features,
+ X86FeaturesEnum value) {
+ switch (value) {
+ case X86_FPU:
+ return features->fpu;
+ case X86_TSC:
+ return features->tsc;
+ case X86_CX8:
+ return features->cx8;
+ case X86_CLFSH:
+ return features->clfsh;
+ case X86_MMX:
+ return features->mmx;
+ case X86_AES:
+ return features->aes;
+ case X86_ERMS:
+ return features->erms;
+ case X86_F16C:
+ return features->f16c;
+ case X86_FMA4:
+ return features->fma4;
+ case X86_FMA3:
+ return features->fma3;
+ case X86_VAES:
+ return features->vaes;
+ case X86_VPCLMULQDQ:
+ return features->vpclmulqdq;
+ case X86_BMI1:
+ return features->bmi1;
+ case X86_HLE:
+ return features->hle;
+ case X86_BMI2:
+ return features->bmi2;
+ case X86_RTM:
+ return features->rtm;
+ case X86_RDSEED:
+ return features->rdseed;
+ case X86_CLFLUSHOPT:
+ return features->clflushopt;
+ case X86_CLWB:
+ return features->clwb;
+ case X86_SSE:
+ return features->sse;
+ case X86_SSE2:
+ return features->sse2;
+ case X86_SSE3:
+ return features->sse3;
+ case X86_SSSE3:
+ return features->ssse3;
+ case X86_SSE4_1:
+ return features->sse4_1;
+ case X86_SSE4_2:
+ return features->sse4_2;
+ case X86_SSE4A:
+ return features->sse4a;
+ case X86_AVX:
+ return features->avx;
+ case X86_AVX2:
+ return features->avx2;
+ case X86_AVX512F:
+ return features->avx512f;
+ case X86_AVX512CD:
+ return features->avx512cd;
+ case X86_AVX512ER:
+ return features->avx512er;
+ case X86_AVX512PF:
+ return features->avx512pf;
+ case X86_AVX512BW:
+ return features->avx512bw;
+ case X86_AVX512DQ:
+ return features->avx512dq;
+ case X86_AVX512VL:
+ return features->avx512vl;
+ case X86_AVX512IFMA:
+ return features->avx512ifma;
+ case X86_AVX512VBMI:
+ return features->avx512vbmi;
+ case X86_AVX512VBMI2:
+ return features->avx512vbmi2;
+ case X86_AVX512VNNI:
+ return features->avx512vnni;
+ case X86_AVX512BITALG:
+ return features->avx512bitalg;
+ case X86_AVX512VPOPCNTDQ:
+ return features->avx512vpopcntdq;
+ case X86_AVX512_4VNNIW:
+ return features->avx512_4vnniw;
+ case X86_AVX512_4VBMI2:
+ return features->avx512_4vbmi2;
+ case X86_PCLMULQDQ:
+ return features->pclmulqdq;
+ case X86_SMX:
+ return features->smx;
+ case X86_SGX:
+ return features->sgx;
+ case X86_CX16:
+ return features->cx16;
+ case X86_SHA:
+ return features->sha;
+ case X86_POPCNT:
+ return features->popcnt;
+ case X86_MOVBE:
+ return features->movbe;
+ case X86_RDRND:
+ return features->rdrnd;
+ case X86_DCA:
+ return features->dca;
+ case X86_SS:
+ return features->ss;
+ case X86_LAST_:
+ break;
+ }
+ return false;
+}
+
+const char* GetX86FeaturesEnumName(X86FeaturesEnum value) {
+ switch (value) {
+ case X86_FPU:
+ return "fpu";
+ case X86_TSC:
+ return "tsc";
+ case X86_CX8:
+ return "cx8";
+ case X86_CLFSH:
+ return "clfsh";
+ case X86_MMX:
+ return "mmx";
+ case X86_AES:
+ return "aes";
+ case X86_ERMS:
+ return "erms";
+ case X86_F16C:
+ return "f16c";
+ case X86_FMA4:
+ return "fma4";
+ case X86_FMA3:
+ return "fma3";
+ case X86_VAES:
+ return "vaes";
+ case X86_VPCLMULQDQ:
+ return "vpclmulqdq";
+ case X86_BMI1:
+ return "bmi1";
+ case X86_HLE:
+ return "hle";
+ case X86_BMI2:
+ return "bmi2";
+ case X86_RTM:
+ return "rtm";
+ case X86_RDSEED:
+ return "rdseed";
+ case X86_CLFLUSHOPT:
+ return "clflushopt";
+ case X86_CLWB:
+ return "clwb";
+ case X86_SSE:
+ return "sse";
+ case X86_SSE2:
+ return "sse2";
+ case X86_SSE3:
+ return "sse3";
+ case X86_SSSE3:
+ return "ssse3";
+ case X86_SSE4_1:
+ return "sse4_1";
+ case X86_SSE4_2:
+ return "sse4_2";
+ case X86_SSE4A:
+ return "sse4a";
+ case X86_AVX:
+ return "avx";
+ case X86_AVX2:
+ return "avx2";
+ case X86_AVX512F:
+ return "avx512f";
+ case X86_AVX512CD:
+ return "avx512cd";
+ case X86_AVX512ER:
+ return "avx512er";
+ case X86_AVX512PF:
+ return "avx512pf";
+ case X86_AVX512BW:
+ return "avx512bw";
+ case X86_AVX512DQ:
+ return "avx512dq";
+ case X86_AVX512VL:
+ return "avx512vl";
+ case X86_AVX512IFMA:
+ return "avx512ifma";
+ case X86_AVX512VBMI:
+ return "avx512vbmi";
+ case X86_AVX512VBMI2:
+ return "avx512vbmi2";
+ case X86_AVX512VNNI:
+ return "avx512vnni";
+ case X86_AVX512BITALG:
+ return "avx512bitalg";
+ case X86_AVX512VPOPCNTDQ:
+ return "avx512vpopcntdq";
+ case X86_AVX512_4VNNIW:
+ return "avx512_4vnniw";
+ case X86_AVX512_4VBMI2:
+ return "avx512_4vbmi2";
+ case X86_PCLMULQDQ:
+ return "pclmulqdq";
+ case X86_SMX:
+ return "smx";
+ case X86_SGX:
+ return "sgx";
+ case X86_CX16:
+ return "cx16";
+ case X86_SHA:
+ return "sha";
+ case X86_POPCNT:
+ return "popcnt";
+ case X86_MOVBE:
+ return "movbe";
+ case X86_RDRND:
+ return "rdrnd";
+ case X86_DCA:
+ return "dca";
+ case X86_SS:
+ return "ss";
+ case X86_LAST_:
+ break;
+ }
+ return "unknown_feature";
+}
+
+const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
+ switch (uarch) {
+ case X86_UNKNOWN:
+ return "X86_UNKNOWN";
+ case INTEL_CORE:
+ return "INTEL_CORE";
+ case INTEL_PNR:
+ return "INTEL_PNR";
+ case INTEL_NHM:
+ return "INTEL_NHM";
+ case INTEL_ATOM_BNL:
+ return "INTEL_ATOM_BNL";
+ case INTEL_WSM:
+ return "INTEL_WSM";
+ case INTEL_SNB:
+ return "INTEL_SNB";
+ case INTEL_IVB:
+ return "INTEL_IVB";
+ case INTEL_ATOM_SMT:
+ return "INTEL_ATOM_SMT";
+ case INTEL_HSW:
+ return "INTEL_HSW";
+ case INTEL_BDW:
+ return "INTEL_BDW";
+ case INTEL_SKL:
+ return "INTEL_SKL";
+ case INTEL_ATOM_GMT:
+ return "INTEL_ATOM_GMT";
+ case INTEL_KBL:
+ return "INTEL_KBL";
+ case INTEL_CFL:
+ return "INTEL_CFL";
+ case INTEL_WHL:
+ return "INTEL_WHL";
+ case INTEL_CNL:
+ return "INTEL_CNL";
+ case INTEL_ICL:
+ return "INTEL_ICL";
+ case AMD_HAMMER:
+ return "AMD_HAMMER";
+ case AMD_K10:
+ return "AMD_K10";
+ case AMD_BOBCAT:
+ return "AMD_BOBCAT";
+ case AMD_BULLDOZER:
+ return "AMD_BULLDOZER";
+ case AMD_JAGUAR:
+ return "AMD_JAGUAR";
+ case AMD_ZEN:
+ return "AMD_ZEN";
+ }
+ return "unknown microarchitecture";
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/filesystem.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/filesystem.c
new file mode 100644
index 0000000..2f7083b
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/filesystem.c
@@ -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
+#include
+#include
+#include
+#include
+
+#if defined(CPU_FEATURES_MOCK_FILESYSTEM)
+// Implementation will be provided by test/filesystem_for_testing.cc.
+#elif defined(_MSC_VER)
+#include
+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
+
+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
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/hwcaps.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/hwcaps.c
new file mode 100644
index 0000000..815e5c1
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/hwcaps.c
@@ -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
+#include
+
+#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
+#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
+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
+#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;
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/stack_line_reader.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/stack_line_reader.c
new file mode 100644
index 0000000..b2c48ba
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/stack_line_reader.c
@@ -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
+#include
+#include
+
+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);
+ }
+ }
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/string_view.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/string_view.c
new file mode 100644
index 0000000..856731c
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/string_view.c
@@ -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
+#include
+#include
+
+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;
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/unix_features_aggregator.c b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/unix_features_aggregator.c
new file mode 100644
index 0000000..1b43a36
--- /dev/null
+++ b/DroidFishApp/src/main/cpp/nativeutil/cpu_features/src/unix_features_aggregator.c
@@ -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);
+ }
+ }
+}
diff --git a/DroidFishApp/src/main/cpp/nativeutil.cpp b/DroidFishApp/src/main/cpp/nativeutil/nativeutil.cpp
similarity index 71%
rename from DroidFishApp/src/main/cpp/nativeutil.cpp
rename to DroidFishApp/src/main/cpp/nativeutil/nativeutil.cpp
index 4aa54e4..09c327c 100644
--- a/DroidFishApp/src/main/cpp/nativeutil.cpp
+++ b/DroidFishApp/src/main/cpp/nativeutil/nativeutil.cpp
@@ -23,6 +23,12 @@
#include
#include
+#if defined(__arm__)
+ #include "cpuinfo_arm.h"
+#elif defined(__i386__)
+ #include "cpuinfo_x86.h"
+#endif
+
/*
* Class: org_petero_droidfish_engine_EngineUtil
* Method: chmod
@@ -48,3 +54,21 @@ extern "C" JNIEXPORT void JNICALL Java_org_petero_droidfish_engine_EngineUtil_re
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;
+}
diff --git a/DroidFishApp/src/main/java/org/petero/droidfish/engine/EngineUtil.java b/DroidFishApp/src/main/java/org/petero/droidfish/engine/EngineUtil.java
index 4fd04b4..43e51af 100644
--- a/DroidFishApp/src/main/java/org/petero/droidfish/engine/EngineUtil.java
+++ b/DroidFishApp/src/main/java/org/petero/droidfish/engine/EngineUtil.java
@@ -41,7 +41,7 @@ public class EngineUtil {
!"arm64-v8a".equals(abi)) {
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. */
@@ -100,6 +100,9 @@ public class EngineUtil {
/** Change the priority of a process. */
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. */
public static final Object nativeLock = new Object();
}