├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── build-logic ├── build.gradle.kts ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ ├── Extensions.kt │ ├── NativesExtension.kt │ ├── base-conventions.gradle.kts │ ├── java-conventions.gradle.kts │ ├── natives-conventions.gradle.kts │ ├── natives-linux-conventions.gradle.kts │ ├── natives-macos-conventions.gradle.kts │ ├── natives-windows-conventions.gradle.kts │ ├── parent-conventions.gradle.kts │ └── publishing-conventions.gradle.kts ├── build.gradle.kts ├── cpu-features-java-headers ├── build.gradle.kts └── src │ └── main │ └── java │ └── cpufeatures │ └── headers │ └── x86 │ ├── CacheInfo.java │ ├── CacheLevelInfo.java │ ├── Constants$root.java │ ├── CpuInfoX86.java │ ├── RuntimeHelper.java │ ├── X86Features.java │ ├── X86Info.java │ ├── constants$0.java │ └── constants$1.java ├── cpu-features-java-natives-linux-x86 └── build.gradle.kts ├── cpu-features-java-natives-macos-x86 └── build.gradle.kts ├── cpu-features-java-natives-windows-x86 └── build.gradle.kts ├── gradle ├── libs.versions.yml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── src ├── main └── java │ └── cpufeatures │ ├── CpuArchitecture.java │ ├── CpuFeatures.java │ ├── CpuPlatform.java │ ├── arm │ ├── ArmFeature.java │ ├── ArmFeatures.java │ └── ArmInfo.java │ └── x86 │ ├── X86Feature.java │ ├── X86Features.java │ ├── X86Info.java │ └── X86Uarch.java └── test └── java └── cpufeatures └── HelloCpuFeatures.java /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | 3 | on: 4 | push: 5 | branches: [ "**" ] 6 | tags-ignore: [ "**" ] 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | # Only run on PRs if the source branch is on someone else's repo 12 | if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} 13 | strategy: 14 | matrix: 15 | os: [ ubuntu-latest, windows-latest, macos-latest ] 16 | include: 17 | - os: ubuntu-latest 18 | publish-core: true 19 | runs-on: ${{ matrix.os }} 20 | steps: 21 | - name: "Checkout source" 22 | uses: actions/checkout@v3 23 | with: 24 | submodules: true 25 | - name: "Setup Java" 26 | uses: actions/setup-java@v3 27 | with: 28 | distribution: temurin 29 | java-version: 19 30 | - name: "Setup Gradle" 31 | uses: gradle/gradle-build-action@v2 32 | - name: "Run Gradle build" 33 | run: ./gradlew --stacktrace build 34 | - name: "sh: Get version type " 35 | if: ${{ matrix.os != 'windows-latest' }} 36 | run: | 37 | VERSION_TYPE=$(./gradlew -q --console=plain --no-daemon printVersionType) 38 | echo VERSION_TYPE=$VERSION_TYPE 39 | echo VERSION_TYPE=$VERSION_TYPE >> $GITHUB_ENV 40 | - name: "ps: Get version type" 41 | if: ${{ matrix.os == 'windows-latest' }} 42 | run: | 43 | $VERSION_TYPE = ./gradlew -q --console=plain --no-daemon printVersionType 44 | echo VERSION_TYPE=$VERSION_TYPE 45 | echo VERSION_TYPE=$VERSION_TYPE >> $env:GITHUB_ENV 46 | - name: "Publish snapshot" 47 | if: ${{ env.VERSION_TYPE == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/main' }} 48 | run: ./gradlew publish 49 | env: 50 | CI_PUBLISH_CORE: ${{ matrix.publish-core }} 51 | ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} 52 | ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} 53 | - name: "Publish release" 54 | if: ${{ env.VERSION_TYPE == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }} 55 | run: ./gradlew -PforceSign=true publishToSonatype closeSonatypeStagingRepository 56 | env: 57 | CI_PUBLISH_CORE: ${{ matrix.publish-core }} 58 | ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} 59 | ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} 60 | ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} 61 | ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} 62 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | 11 | # Eclipse 12 | .classpath 13 | .project 14 | .settings/ 15 | plugin/bin/ 16 | api/bin/ 17 | 18 | # VS Code 19 | *bin/ 20 | 21 | # Fleet 22 | .fleet/ 23 | 24 | # Compiled class file 25 | *.class 26 | 27 | # Log file 28 | *.log 29 | 30 | # BlueJ files 31 | *.ctxt 32 | 33 | # Package Files # 34 | *.war 35 | *.nar 36 | *.ear 37 | *.zip 38 | *.tar.gz 39 | *.rar 40 | 41 | # debugger attaches 42 | .attach_pid* 43 | 44 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 45 | hs_err_pid* 46 | 47 | *~ 48 | 49 | # temporary files which can be created if a process still has a handle open of a deleted file 50 | .fuse_hidden* 51 | 52 | # KDE directory preferences 53 | .directory 54 | 55 | # Linux trash folder which might appear on any partition or disk 56 | .Trash-* 57 | 58 | # .nfs files are created when an open file is removed but is still being accessed 59 | .nfs* 60 | 61 | # General 62 | .DS_Store 63 | .AppleDouble 64 | .LSOverride 65 | 66 | # Icon must end with two \r 67 | Icon 68 | 69 | # Thumbnails 70 | ._* 71 | 72 | # Files that might appear in the root of a volume 73 | .DocumentRevisions-V100 74 | .fseventsd 75 | .Spotlight-V100 76 | .TemporaryItems 77 | .Trashes 78 | .VolumeIcon.icns 79 | .com.apple.timemachine.donotpresent 80 | 81 | # Directories potentially created on remote AFP share 82 | .AppleDB 83 | .AppleDesktop 84 | Network Trash Folder 85 | Temporary Items 86 | .apdisk 87 | 88 | # Windows thumbnail cache files 89 | Thumbs.db 90 | Thumbs.db:encryptable 91 | ehthumbs.db 92 | ehthumbs_vista.db 93 | 94 | # Dump file 95 | *.stackdump 96 | 97 | # Folder config file 98 | [Dd]esktop.ini 99 | 100 | # Recycle Bin used on file shares 101 | $RECYCLE.BIN/ 102 | 103 | # Windows Installer files 104 | *.cab 105 | *.msi 106 | *.msix 107 | *.msm 108 | *.msp 109 | 110 | # Windows shortcuts 111 | *.lnk 112 | 113 | target/ 114 | 115 | pom.xml.tag 116 | pom.xml.releaseBackup 117 | pom.xml.versionsBackup 118 | pom.xml.next 119 | 120 | release.properties 121 | dependency-reduced-pom.xml 122 | buildNumber.properties 123 | .mvn/timing.properties 124 | .mvn/wrapper/maven-wrapper.jar 125 | .flattened-pom.xml 126 | 127 | # Common working directory 128 | run/ 129 | build 130 | .gradle 131 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cpu_features"] 2 | path = cpu_features 3 | url = https://github.com/google/cpu_features.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 aecsocket 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # CpuFeaturesJava 4 | [![License](https://img.shields.io/github/license/aecsocket/cpu-features-java)](LICENSE) 5 | [![CI](https://img.shields.io/github/actions/workflow/status/aecsocket/cpu-features-java/build.yml)](https://github.com/aecsocket/cpu-features-java/actions/workflows/build.yml) 6 | ![Release](https://img.shields.io/maven-central/v/io.github.aecsocket/cpu-features-java?label=release) 7 | ![Snapshot](https://img.shields.io/nexus/s/io.github.aecsocket/cpu-features-java?label=snapshot&server=https%3A%2F%2Fs01.oss.sonatype.org) 8 | 9 | Java bindings for [Google cpu_features](https://github.com/google/cpu_features) 10 | 11 | --- 12 | 13 |
14 | 15 | Even though Java is a "write once, run anywhere" language, often a library will still want to use a native library, 16 | which is not only OS-specific but also host-specific. These libraries may be compiled with different CPU flags enabled, 17 | such as AVX2 or F16C, to utilise different CPU features. When loading a library from Java, the program has no clue 18 | which features may be supported, so must rely on the most accessible version - which is often the slowest. Using 19 | cpu_features, Java programs can detect which features the host CPU supports and load different native libraries based 20 | on this info. 21 | 22 | **Note**: Version 2.0 of this library uses the (currently unstable) Java foreign function interface, and will require 23 | Java 19 as well as the command line arguments `--enable-preview --enable-native-access=ALL-UNNAMED`. The previous 24 | version, using JNI and Java 15, is still available under `io.github.aecsocket:cpu-features-jni:1.0.1`. 25 | 26 | ## Coverage 27 | 28 | Platforms: 29 | - [x] Linux (x86) 30 | - [x] Windows (x86) 31 | - [x] MacOS (x86) 32 | 33 | Architectures: 34 | - [ ] AArch64 35 | - [ ] ARM 36 | - [x] X86 37 | 38 | ## Usage 39 | 40 | ```kotlin 41 | repositories { 42 | mavenCentral() 43 | } 44 | 45 | dependencies { 46 | implementation("io.github.aecsocket", "cpu-features-java", "VERSION") 47 | // native libraries 48 | runtimeOnly("io.github.aecsocket", "cpu-features-java-natives-linux-x86", "VERSION") 49 | runtimeOnly("io.github.aecsocket", "cpu-features-java-natives-windows-x86", "VERSION") 50 | runtimeOnly("io.github.aecsocket", "cpu-features-java-natives-macos-x86", "VERSION") 51 | } 52 | ``` 53 | 54 | Usage is very similar to cpu_features. See [HelloCpuFeatures.java](src/test/java/cpufeatures/HelloCpuFeatures.java) 55 | to get a minimal implementation. 56 | 57 | ### Getting CPU info 58 | 59 | ```java 60 | // If using the native library dependencies: 61 | CpuFeatures.load(); 62 | // Otherwise load the libraries yourself: 63 | // System.loadLibrary("cpu_features"); 64 | 65 | // CpuFeatures is the entry point to the application 66 | CpuArchitecture arch = CpuFeatures.getArchitecture(); 67 | switch (arch) { 68 | case ARM -> { 69 | // The various -Info classes hold all CPU info 70 | ArmInfo info = ArmInfo.get(); 71 | System.out.println(info.implementer); 72 | } 73 | case X86 -> { 74 | X86Info info = X86Info.get() 75 | System.out.println(info.vendor); 76 | } 77 | // ... 78 | } 79 | ``` 80 | 81 | ### Querying CPU features 82 | 83 | ```java 84 | public static boolean useAVX2 = false; 85 | 86 | public static void init() { 87 | X86Info info = X86Info.get(); 88 | // Prefer accessing `features` directly over using an enum 89 | useAVX2 = info.features().avx2(); 90 | // useAVX2 = X86Feature.AVX2.in(info.features()); 91 | 92 | Set features = info.featureSet(); 93 | System.out.println("features: " + features); 94 | } 95 | ``` 96 | 97 | ## Building from source 98 | 99 | On Windows, you need [Ninja](https://ninja-build.org/manual.html) installed. 100 | 101 | ```sh 102 | git clone https://github.com/aecsocket/cpu-features-java 103 | cd cpu-features-java 104 | git submodule update --init 105 | ./gradlew build 106 | ``` 107 | -------------------------------------------------------------------------------- /build-logic/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | gradlePluginPortal() 7 | } 8 | 9 | dependencies { 10 | implementation(libs.indraCommon) 11 | implementation(libs.indraPublishingSonatype) 12 | implementation(libs.jextract) 13 | } 14 | -------------------------------------------------------------------------------- /build-logic/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | import ca.stellardrift.build.configurate.ConfigFormats 2 | import ca.stellardrift.build.configurate.catalog.PolyglotVersionCatalogExtension 3 | 4 | plugins { 5 | id("ca.stellardrift.polyglot-version-catalogs") version "6.0.1" 6 | } 7 | 8 | extensions.configure { 9 | from(ConfigFormats.YAML, file("../gradle/libs.versions.yml")) 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/Extensions.kt: -------------------------------------------------------------------------------- 1 | import org.gradle.api.Project 2 | import org.gradle.api.provider.Provider 3 | import org.gradle.kotlin.dsl.findByType 4 | import org.gradle.plugins.signing.SigningExtension 5 | import java.io.File 6 | 7 | val Project.cpuFeaturesDir: File 8 | get() = rootDir.resolve("cpu_features") 9 | 10 | val Project.ci: Provider 11 | get() = providers.environmentVariable("CI").map { it.toBoolean() }.orElse(false) 12 | 13 | val Project.ciPublishCore: Provider 14 | get() = providers.environmentVariable("CI_PUBLISH_CORE").map { it.toBoolean() }.orElse(false) 15 | 16 | fun Project.publishCore(): Boolean { 17 | if (ci.get() && !ciPublishCore.get()) 18 | return false 19 | 20 | plugins.apply("publishing-conventions") 21 | return true 22 | } 23 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/NativesExtension.kt: -------------------------------------------------------------------------------- 1 | import org.gradle.api.provider.Property 2 | import org.gradle.internal.os.OperatingSystem 3 | import java.util.function.Predicate 4 | 5 | abstract class NativesExtension { 6 | abstract val platformPredicate: Property> 7 | abstract val generator: Property 8 | abstract val generatorBinary: Property 9 | abstract val sourceLibraryName: Property 10 | abstract val destDir: Property 11 | } 12 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/base-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("net.kyori.indra.git") 3 | } 4 | 5 | group = rootProject.group 6 | version = rootProject.version 7 | description = rootProject.description 8 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/java-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("base-conventions") 3 | id("java-library") 4 | id("net.kyori.indra") 5 | } 6 | 7 | indra { 8 | javaVersions { 9 | target(19) 10 | } 11 | } 12 | 13 | repositories { 14 | mavenCentral() 15 | } 16 | 17 | tasks { 18 | withType { 19 | options.compilerArgs.addAll(listOf("--enable-preview")) 20 | } 21 | 22 | javadoc { 23 | (options as CoreJavadocOptions).apply { 24 | addBooleanOption("-enable-preview", true) 25 | } 26 | } 27 | 28 | withType { 29 | jvmArgs("--enable-preview", "--enable-native-access=ALL-UNNAMED") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/natives-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradle.internal.os.OperatingSystem 2 | 3 | plugins { 4 | id("java-conventions") 5 | } 6 | 7 | val nativesExt = extensions.create("natives", NativesExtension::class) 8 | val workers = kotlin.math.min(32, Runtime.getRuntime().availableProcessors()) 9 | val nativesBuildDir = "$buildDir/natives" 10 | 11 | afterEvaluate { 12 | val os = OperatingSystem.current() 13 | if (!nativesExt.platformPredicate.get().test(os)) return@afterEvaluate 14 | 15 | // only publish if we can actually build the artifact 16 | apply(plugin = "publishing-conventions") 17 | 18 | tasks { 19 | val assembleNatives = register("assembleNatives") { 20 | group = "build natives" 21 | 22 | workingDir = file(cpuFeaturesDir) 23 | commandLine = listOf( 24 | "cmake", 25 | "-S", ".", // source at `cpu_features/` 26 | "-B", file(nativesBuildDir).absolutePath, // put makefiles into this project's `build/natives/` 27 | "-G", nativesExt.generator.get(), // use the platform-specific generator 28 | "-DBUILD_TESTING=OFF", // no testing 29 | "-DCMAKE_BUILD_TYPE=Release", // release build type 30 | "-DBUILD_SHARED_LIBS=ON", // make a platform-specific library (`.so` etc.), not a `.a` 31 | ) 32 | 33 | doLast { 34 | exec { 35 | workingDir = file(nativesBuildDir) 36 | commandLine = listOf( 37 | nativesExt.generatorBinary.get(), 38 | "-j$workers" 39 | ) 40 | } 41 | } 42 | } 43 | 44 | jar { 45 | dependsOn(assembleNatives.get()) 46 | from("$nativesBuildDir/${nativesExt.sourceLibraryName.get()}") 47 | into("cpufeatures/${nativesExt.destDir.get()}") 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/natives-linux-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-conventions") 3 | } 4 | 5 | extensions.getByType().apply { 6 | platformPredicate.set { it.isLinux } 7 | generator.set("Unix Makefiles") 8 | generatorBinary.set("make") 9 | sourceLibraryName.set("libcpu_features.so") 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/natives-macos-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-conventions") 3 | } 4 | 5 | extensions.getByType().apply { 6 | platformPredicate.set { it.isMacOsX } 7 | generator.set("Unix Makefiles") 8 | generatorBinary.set("make") 9 | sourceLibraryName.set("libcpu_features.dylib") 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/natives-windows-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-conventions") 3 | } 4 | 5 | extensions.getByType().apply { 6 | platformPredicate.set { it.isWindows } 7 | generator.set("Ninja") 8 | generatorBinary.set("ninja") 9 | sourceLibraryName.set("libcpu_features.dll") 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/parent-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("net.kyori.indra.publishing.sonatype") 3 | id("publishing-conventions") 4 | } 5 | 6 | indraSonatype { 7 | useAlternateSonatypeOSSHost("s01") 8 | } 9 | 10 | tasks.register("printVersionType") { 11 | doFirst { 12 | println(if (net.kyori.indra.util.Versioning.isSnapshot(project)) "snapshot" else "release") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /build-logic/src/main/kotlin/publishing-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("net.kyori.indra.publishing") 3 | } 4 | 5 | signing { 6 | val signingKey = findProperty("signingKey") as? String 7 | val signingPassword = findProperty("signingPassword") as? String 8 | if (signingKey != null) { 9 | useInMemoryPgpKeys(signingKey, signingPassword) 10 | } 11 | } 12 | 13 | indra { 14 | github("aecsocket", "cpu-features-java") 15 | mitLicense() 16 | 17 | configurePublications { 18 | pom { 19 | developers { 20 | developer { 21 | name.set("aecsocket") 22 | email.set("aecsocket@tutanota.com") 23 | url.set("https://github.com/aecsocket") 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("parent-conventions") 3 | id("java-conventions") 4 | } 5 | 6 | group = "io.github.aecsocket" 7 | version = "2.0.1" 8 | description = "Java bindings for Google cpu_features" 9 | 10 | dependencies { 11 | implementation(projects.cpuFeaturesJavaHeaders) 12 | compileOnlyApi(libs.findBugs) 13 | 14 | testImplementation(libs.jUnitJupiterApi) 15 | testImplementation(libs.jUnitJupiterEngine) 16 | testImplementation(libs.findBugs) 17 | testRuntimeOnly(projects.cpuFeaturesJavaNativesLinuxX86) 18 | testRuntimeOnly(projects.cpuFeaturesJavaNativesWindowsX86) 19 | testRuntimeOnly(projects.cpuFeaturesJavaNativesMacosX86) 20 | } 21 | 22 | if (!publishCore()) { 23 | tasks { 24 | withType { 25 | enabled = false 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cpu-features-java-headers/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import io.github.krakowski.jextract.JextractTask 2 | 3 | plugins { 4 | id("java-conventions") 5 | } 6 | 7 | publishCore() 8 | 9 | tasks { 10 | fun registerGenerateHeaders(platformKey: String, platformName: String) { 11 | register("generateHeaders$platformName") { 12 | toolchain.convention(org.gradle.internal.jvm.Jvm.current().javaHome.absolutePath) 13 | 14 | header("$cpuFeaturesDir/include/cpuinfo_$platformKey.h") { 15 | this.targetPackage.set("cpufeatures.headers.$platformKey") 16 | this.className.set("CpuInfo$platformName") 17 | } 18 | 19 | doLast { 20 | copy { 21 | from("${outputDir.get()}") 22 | into("$projectDir/src/main/java") 23 | } 24 | } 25 | } 26 | } 27 | 28 | // uncomment the headers for your machine's architecture 29 | 30 | registerGenerateHeaders("x86", "X86") 31 | //registerGenerateHeaders("aarch64", "Aarch64") 32 | } 33 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/CacheInfo.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.*; 6 | import java.lang.invoke.VarHandle; 7 | 8 | import static java.lang.foreign.ValueLayout.PathElement; 9 | public class CacheInfo { 10 | 11 | static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout( 12 | Constants$root.C_INT$LAYOUT.withName("size"), 13 | MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout( 14 | Constants$root.C_INT$LAYOUT.withName("level"), 15 | Constants$root.C_INT$LAYOUT.withName("cache_type"), 16 | Constants$root.C_INT$LAYOUT.withName("cache_size"), 17 | Constants$root.C_INT$LAYOUT.withName("ways"), 18 | Constants$root.C_INT$LAYOUT.withName("line_size"), 19 | Constants$root.C_INT$LAYOUT.withName("tlb_entries"), 20 | Constants$root.C_INT$LAYOUT.withName("partitioning") 21 | )).withName("levels") 22 | ); 23 | public static MemoryLayout $LAYOUT() { 24 | return CacheInfo.$struct$LAYOUT; 25 | } 26 | static final VarHandle size$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("size")); 27 | public static VarHandle size$VH() { 28 | return CacheInfo.size$VH; 29 | } 30 | public static int size$get(MemorySegment seg) { 31 | return (int)CacheInfo.size$VH.get(seg); 32 | } 33 | public static void size$set( MemorySegment seg, int x) { 34 | CacheInfo.size$VH.set(seg, x); 35 | } 36 | public static int size$get(MemorySegment seg, long index) { 37 | return (int)CacheInfo.size$VH.get(seg.asSlice(index*sizeof())); 38 | } 39 | public static void size$set(MemorySegment seg, long index, int x) { 40 | CacheInfo.size$VH.set(seg.asSlice(index*sizeof()), x); 41 | } 42 | public static MemorySegment levels$slice(MemorySegment seg) { 43 | return seg.asSlice(4, 280); 44 | } 45 | public static long sizeof() { return $LAYOUT().byteSize(); } 46 | public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } 47 | public static MemorySegment allocateArray(int len, SegmentAllocator allocator) { 48 | return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); 49 | } 50 | public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); } 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/CacheLevelInfo.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.*; 6 | import java.lang.invoke.VarHandle; 7 | 8 | import static java.lang.foreign.ValueLayout.PathElement; 9 | public class CacheLevelInfo { 10 | 11 | static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout( 12 | Constants$root.C_INT$LAYOUT.withName("level"), 13 | Constants$root.C_INT$LAYOUT.withName("cache_type"), 14 | Constants$root.C_INT$LAYOUT.withName("cache_size"), 15 | Constants$root.C_INT$LAYOUT.withName("ways"), 16 | Constants$root.C_INT$LAYOUT.withName("line_size"), 17 | Constants$root.C_INT$LAYOUT.withName("tlb_entries"), 18 | Constants$root.C_INT$LAYOUT.withName("partitioning") 19 | ); 20 | public static MemoryLayout $LAYOUT() { 21 | return CacheLevelInfo.$struct$LAYOUT; 22 | } 23 | static final VarHandle level$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("level")); 24 | public static VarHandle level$VH() { 25 | return CacheLevelInfo.level$VH; 26 | } 27 | public static int level$get(MemorySegment seg) { 28 | return (int)CacheLevelInfo.level$VH.get(seg); 29 | } 30 | public static void level$set( MemorySegment seg, int x) { 31 | CacheLevelInfo.level$VH.set(seg, x); 32 | } 33 | public static int level$get(MemorySegment seg, long index) { 34 | return (int)CacheLevelInfo.level$VH.get(seg.asSlice(index*sizeof())); 35 | } 36 | public static void level$set(MemorySegment seg, long index, int x) { 37 | CacheLevelInfo.level$VH.set(seg.asSlice(index*sizeof()), x); 38 | } 39 | static final VarHandle cache_type$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("cache_type")); 40 | public static VarHandle cache_type$VH() { 41 | return CacheLevelInfo.cache_type$VH; 42 | } 43 | public static int cache_type$get(MemorySegment seg) { 44 | return (int)CacheLevelInfo.cache_type$VH.get(seg); 45 | } 46 | public static void cache_type$set( MemorySegment seg, int x) { 47 | CacheLevelInfo.cache_type$VH.set(seg, x); 48 | } 49 | public static int cache_type$get(MemorySegment seg, long index) { 50 | return (int)CacheLevelInfo.cache_type$VH.get(seg.asSlice(index*sizeof())); 51 | } 52 | public static void cache_type$set(MemorySegment seg, long index, int x) { 53 | CacheLevelInfo.cache_type$VH.set(seg.asSlice(index*sizeof()), x); 54 | } 55 | static final VarHandle cache_size$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("cache_size")); 56 | public static VarHandle cache_size$VH() { 57 | return CacheLevelInfo.cache_size$VH; 58 | } 59 | public static int cache_size$get(MemorySegment seg) { 60 | return (int)CacheLevelInfo.cache_size$VH.get(seg); 61 | } 62 | public static void cache_size$set( MemorySegment seg, int x) { 63 | CacheLevelInfo.cache_size$VH.set(seg, x); 64 | } 65 | public static int cache_size$get(MemorySegment seg, long index) { 66 | return (int)CacheLevelInfo.cache_size$VH.get(seg.asSlice(index*sizeof())); 67 | } 68 | public static void cache_size$set(MemorySegment seg, long index, int x) { 69 | CacheLevelInfo.cache_size$VH.set(seg.asSlice(index*sizeof()), x); 70 | } 71 | static final VarHandle ways$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("ways")); 72 | public static VarHandle ways$VH() { 73 | return CacheLevelInfo.ways$VH; 74 | } 75 | public static int ways$get(MemorySegment seg) { 76 | return (int)CacheLevelInfo.ways$VH.get(seg); 77 | } 78 | public static void ways$set( MemorySegment seg, int x) { 79 | CacheLevelInfo.ways$VH.set(seg, x); 80 | } 81 | public static int ways$get(MemorySegment seg, long index) { 82 | return (int)CacheLevelInfo.ways$VH.get(seg.asSlice(index*sizeof())); 83 | } 84 | public static void ways$set(MemorySegment seg, long index, int x) { 85 | CacheLevelInfo.ways$VH.set(seg.asSlice(index*sizeof()), x); 86 | } 87 | static final VarHandle line_size$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("line_size")); 88 | public static VarHandle line_size$VH() { 89 | return CacheLevelInfo.line_size$VH; 90 | } 91 | public static int line_size$get(MemorySegment seg) { 92 | return (int)CacheLevelInfo.line_size$VH.get(seg); 93 | } 94 | public static void line_size$set( MemorySegment seg, int x) { 95 | CacheLevelInfo.line_size$VH.set(seg, x); 96 | } 97 | public static int line_size$get(MemorySegment seg, long index) { 98 | return (int)CacheLevelInfo.line_size$VH.get(seg.asSlice(index*sizeof())); 99 | } 100 | public static void line_size$set(MemorySegment seg, long index, int x) { 101 | CacheLevelInfo.line_size$VH.set(seg.asSlice(index*sizeof()), x); 102 | } 103 | static final VarHandle tlb_entries$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("tlb_entries")); 104 | public static VarHandle tlb_entries$VH() { 105 | return CacheLevelInfo.tlb_entries$VH; 106 | } 107 | public static int tlb_entries$get(MemorySegment seg) { 108 | return (int)CacheLevelInfo.tlb_entries$VH.get(seg); 109 | } 110 | public static void tlb_entries$set( MemorySegment seg, int x) { 111 | CacheLevelInfo.tlb_entries$VH.set(seg, x); 112 | } 113 | public static int tlb_entries$get(MemorySegment seg, long index) { 114 | return (int)CacheLevelInfo.tlb_entries$VH.get(seg.asSlice(index*sizeof())); 115 | } 116 | public static void tlb_entries$set(MemorySegment seg, long index, int x) { 117 | CacheLevelInfo.tlb_entries$VH.set(seg.asSlice(index*sizeof()), x); 118 | } 119 | static final VarHandle partitioning$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("partitioning")); 120 | public static VarHandle partitioning$VH() { 121 | return CacheLevelInfo.partitioning$VH; 122 | } 123 | public static int partitioning$get(MemorySegment seg) { 124 | return (int)CacheLevelInfo.partitioning$VH.get(seg); 125 | } 126 | public static void partitioning$set( MemorySegment seg, int x) { 127 | CacheLevelInfo.partitioning$VH.set(seg, x); 128 | } 129 | public static int partitioning$get(MemorySegment seg, long index) { 130 | return (int)CacheLevelInfo.partitioning$VH.get(seg.asSlice(index*sizeof())); 131 | } 132 | public static void partitioning$set(MemorySegment seg, long index, int x) { 133 | CacheLevelInfo.partitioning$VH.set(seg.asSlice(index*sizeof()), x); 134 | } 135 | public static long sizeof() { return $LAYOUT().byteSize(); } 136 | public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } 137 | public static MemorySegment allocateArray(int len, SegmentAllocator allocator) { 138 | return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); 139 | } 140 | public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); } 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/Constants$root.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.ValueLayout; 6 | 7 | import static java.lang.foreign.ValueLayout.*; 8 | public class Constants$root { 9 | 10 | static final OfBoolean C_BOOL$LAYOUT = ValueLayout.JAVA_BOOLEAN; 11 | static final OfByte C_CHAR$LAYOUT = ValueLayout.JAVA_BYTE; 12 | static final OfShort C_SHORT$LAYOUT = ValueLayout.JAVA_SHORT.withBitAlignment(16); 13 | static final OfInt C_INT$LAYOUT = ValueLayout.JAVA_INT.withBitAlignment(32); 14 | static final OfLong C_LONG$LAYOUT = ValueLayout.JAVA_LONG.withBitAlignment(64); 15 | static final OfLong C_LONG_LONG$LAYOUT = ValueLayout.JAVA_LONG.withBitAlignment(64); 16 | static final OfFloat C_FLOAT$LAYOUT = ValueLayout.JAVA_FLOAT.withBitAlignment(32); 17 | static final OfDouble C_DOUBLE$LAYOUT = ValueLayout.JAVA_DOUBLE.withBitAlignment(64); 18 | static final OfAddress C_POINTER$LAYOUT = ValueLayout.ADDRESS.withBitAlignment(64); 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/CpuInfoX86.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.Addressable; 6 | import java.lang.foreign.MemoryAddress; 7 | import java.lang.foreign.MemorySegment; 8 | import java.lang.foreign.SegmentAllocator; 9 | import java.lang.invoke.MethodHandle; 10 | 11 | import static java.lang.foreign.ValueLayout.*; 12 | public class CpuInfoX86 { 13 | 14 | /* package-private */ CpuInfoX86() {} 15 | public static OfByte C_CHAR = Constants$root.C_CHAR$LAYOUT; 16 | public static OfShort C_SHORT = Constants$root.C_SHORT$LAYOUT; 17 | public static OfInt C_INT = Constants$root.C_INT$LAYOUT; 18 | public static OfLong C_LONG = Constants$root.C_LONG_LONG$LAYOUT; 19 | public static OfLong C_LONG_LONG = Constants$root.C_LONG_LONG$LAYOUT; 20 | public static OfFloat C_FLOAT = Constants$root.C_FLOAT$LAYOUT; 21 | public static OfDouble C_DOUBLE = Constants$root.C_DOUBLE$LAYOUT; 22 | public static OfAddress C_POINTER = Constants$root.C_POINTER$LAYOUT; 23 | public static int CPU_FEATURES_COMPILED_X86_AES() { 24 | return (int)0L; 25 | } 26 | public static int CPU_FEATURES_COMPILED_X86_F16C() { 27 | return (int)0L; 28 | } 29 | public static int CPU_FEATURES_COMPILED_X86_BMI() { 30 | return (int)0L; 31 | } 32 | public static int CPU_FEATURES_COMPILED_X86_BMI2() { 33 | return (int)0L; 34 | } 35 | public static int CPU_FEATURES_COMPILED_X86_SSE() { 36 | return (int)1L; 37 | } 38 | public static int CPU_FEATURES_COMPILED_X86_SSE2() { 39 | return (int)1L; 40 | } 41 | public static int CPU_FEATURES_COMPILED_X86_SSE3() { 42 | return (int)0L; 43 | } 44 | public static int CPU_FEATURES_COMPILED_X86_SSSE3() { 45 | return (int)0L; 46 | } 47 | public static int CPU_FEATURES_COMPILED_X86_SSE4_1() { 48 | return (int)0L; 49 | } 50 | public static int CPU_FEATURES_COMPILED_X86_SSE4_2() { 51 | return (int)0L; 52 | } 53 | public static int CPU_FEATURES_COMPILED_X86_AVX() { 54 | return (int)0L; 55 | } 56 | public static int CPU_FEATURES_COMPILED_X86_AVX2() { 57 | return (int)0L; 58 | } 59 | public static int CPU_FEATURES_MAX_CACHE_LEVEL() { 60 | return (int)10L; 61 | } 62 | public static int CPU_FEATURE_CACHE_NULL() { 63 | return (int)0L; 64 | } 65 | public static int CPU_FEATURE_CACHE_DATA() { 66 | return (int)1L; 67 | } 68 | public static int CPU_FEATURE_CACHE_INSTRUCTION() { 69 | return (int)2L; 70 | } 71 | public static int CPU_FEATURE_CACHE_UNIFIED() { 72 | return (int)3L; 73 | } 74 | public static int CPU_FEATURE_CACHE_TLB() { 75 | return (int)4L; 76 | } 77 | public static int CPU_FEATURE_CACHE_DTLB() { 78 | return (int)5L; 79 | } 80 | public static int CPU_FEATURE_CACHE_STLB() { 81 | return (int)6L; 82 | } 83 | public static int CPU_FEATURE_CACHE_PREFETCH() { 84 | return (int)7L; 85 | } 86 | public static MethodHandle GetX86Info$MH() { 87 | return RuntimeHelper.requireNonNull(constants$0.GetX86Info$MH,"GetX86Info"); 88 | } 89 | public static MemorySegment GetX86Info ( SegmentAllocator allocator) { 90 | var mh$ = GetX86Info$MH(); 91 | try { 92 | return (MemorySegment)mh$.invokeExact(allocator); 93 | } catch (Throwable ex$) { 94 | throw new AssertionError("should not reach here", ex$); 95 | } 96 | } 97 | public static MethodHandle GetX86CacheInfo$MH() { 98 | return RuntimeHelper.requireNonNull(constants$0.GetX86CacheInfo$MH,"GetX86CacheInfo"); 99 | } 100 | public static MemorySegment GetX86CacheInfo ( SegmentAllocator allocator) { 101 | var mh$ = GetX86CacheInfo$MH(); 102 | try { 103 | return (MemorySegment)mh$.invokeExact(allocator); 104 | } catch (Throwable ex$) { 105 | throw new AssertionError("should not reach here", ex$); 106 | } 107 | } 108 | public static int X86_UNKNOWN() { 109 | return (int)0L; 110 | } 111 | public static int ZHAOXIN_ZHANGJIANG() { 112 | return (int)1L; 113 | } 114 | public static int ZHAOXIN_WUDAOKOU() { 115 | return (int)2L; 116 | } 117 | public static int ZHAOXIN_LUJIAZUI() { 118 | return (int)3L; 119 | } 120 | public static int ZHAOXIN_YONGFENG() { 121 | return (int)4L; 122 | } 123 | public static int INTEL_80486() { 124 | return (int)5L; 125 | } 126 | public static int INTEL_P5() { 127 | return (int)6L; 128 | } 129 | public static int INTEL_LAKEMONT() { 130 | return (int)7L; 131 | } 132 | public static int INTEL_CORE() { 133 | return (int)8L; 134 | } 135 | public static int INTEL_PNR() { 136 | return (int)9L; 137 | } 138 | public static int INTEL_NHM() { 139 | return (int)10L; 140 | } 141 | public static int INTEL_ATOM_BNL() { 142 | return (int)11L; 143 | } 144 | public static int INTEL_WSM() { 145 | return (int)12L; 146 | } 147 | public static int INTEL_SNB() { 148 | return (int)13L; 149 | } 150 | public static int INTEL_IVB() { 151 | return (int)14L; 152 | } 153 | public static int INTEL_ATOM_SMT() { 154 | return (int)15L; 155 | } 156 | public static int INTEL_HSW() { 157 | return (int)16L; 158 | } 159 | public static int INTEL_BDW() { 160 | return (int)17L; 161 | } 162 | public static int INTEL_SKL() { 163 | return (int)18L; 164 | } 165 | public static int INTEL_CCL() { 166 | return (int)19L; 167 | } 168 | public static int INTEL_ATOM_GMT() { 169 | return (int)20L; 170 | } 171 | public static int INTEL_ATOM_GMT_PLUS() { 172 | return (int)21L; 173 | } 174 | public static int INTEL_ATOM_TMT() { 175 | return (int)22L; 176 | } 177 | public static int INTEL_KBL() { 178 | return (int)23L; 179 | } 180 | public static int INTEL_CFL() { 181 | return (int)24L; 182 | } 183 | public static int INTEL_WHL() { 184 | return (int)25L; 185 | } 186 | public static int INTEL_CML() { 187 | return (int)26L; 188 | } 189 | public static int INTEL_CNL() { 190 | return (int)27L; 191 | } 192 | public static int INTEL_ICL() { 193 | return (int)28L; 194 | } 195 | public static int INTEL_TGL() { 196 | return (int)29L; 197 | } 198 | public static int INTEL_SPR() { 199 | return (int)30L; 200 | } 201 | public static int INTEL_ADL() { 202 | return (int)31L; 203 | } 204 | public static int INTEL_RCL() { 205 | return (int)32L; 206 | } 207 | public static int INTEL_RPL() { 208 | return (int)33L; 209 | } 210 | public static int INTEL_KNIGHTS_M() { 211 | return (int)34L; 212 | } 213 | public static int INTEL_KNIGHTS_L() { 214 | return (int)35L; 215 | } 216 | public static int INTEL_KNIGHTS_F() { 217 | return (int)36L; 218 | } 219 | public static int INTEL_KNIGHTS_C() { 220 | return (int)37L; 221 | } 222 | public static int INTEL_NETBURST() { 223 | return (int)38L; 224 | } 225 | public static int AMD_HAMMER() { 226 | return (int)39L; 227 | } 228 | public static int AMD_K10() { 229 | return (int)40L; 230 | } 231 | public static int AMD_K11() { 232 | return (int)41L; 233 | } 234 | public static int AMD_K12() { 235 | return (int)42L; 236 | } 237 | public static int AMD_BOBCAT() { 238 | return (int)43L; 239 | } 240 | public static int AMD_PILEDRIVER() { 241 | return (int)44L; 242 | } 243 | public static int AMD_STREAMROLLER() { 244 | return (int)45L; 245 | } 246 | public static int AMD_EXCAVATOR() { 247 | return (int)46L; 248 | } 249 | public static int AMD_BULLDOZER() { 250 | return (int)47L; 251 | } 252 | public static int AMD_JAGUAR() { 253 | return (int)48L; 254 | } 255 | public static int AMD_PUMA() { 256 | return (int)49L; 257 | } 258 | public static int AMD_ZEN() { 259 | return (int)50L; 260 | } 261 | public static int AMD_ZEN_PLUS() { 262 | return (int)51L; 263 | } 264 | public static int AMD_ZEN2() { 265 | return (int)52L; 266 | } 267 | public static int AMD_ZEN3() { 268 | return (int)53L; 269 | } 270 | public static int AMD_ZEN4() { 271 | return (int)54L; 272 | } 273 | public static int X86_MICROARCHITECTURE_LAST_() { 274 | return (int)55L; 275 | } 276 | public static MethodHandle GetX86Microarchitecture$MH() { 277 | return RuntimeHelper.requireNonNull(constants$0.GetX86Microarchitecture$MH,"GetX86Microarchitecture"); 278 | } 279 | public static int GetX86Microarchitecture ( Addressable info) { 280 | var mh$ = GetX86Microarchitecture$MH(); 281 | try { 282 | return (int)mh$.invokeExact(info); 283 | } catch (Throwable ex$) { 284 | throw new AssertionError("should not reach here", ex$); 285 | } 286 | } 287 | public static MethodHandle FillX86BrandString$MH() { 288 | return RuntimeHelper.requireNonNull(constants$0.FillX86BrandString$MH,"FillX86BrandString"); 289 | } 290 | public static void FillX86BrandString ( Addressable brand_string) { 291 | var mh$ = FillX86BrandString$MH(); 292 | try { 293 | mh$.invokeExact(brand_string); 294 | } catch (Throwable ex$) { 295 | throw new AssertionError("should not reach here", ex$); 296 | } 297 | } 298 | public static int X86_FPU() { 299 | return (int)0L; 300 | } 301 | public static int X86_TSC() { 302 | return (int)1L; 303 | } 304 | public static int X86_CX8() { 305 | return (int)2L; 306 | } 307 | public static int X86_CLFSH() { 308 | return (int)3L; 309 | } 310 | public static int X86_MMX() { 311 | return (int)4L; 312 | } 313 | public static int X86_AES() { 314 | return (int)5L; 315 | } 316 | public static int X86_ERMS() { 317 | return (int)6L; 318 | } 319 | public static int X86_F16C() { 320 | return (int)7L; 321 | } 322 | public static int X86_FMA4() { 323 | return (int)8L; 324 | } 325 | public static int X86_FMA3() { 326 | return (int)9L; 327 | } 328 | public static int X86_VAES() { 329 | return (int)10L; 330 | } 331 | public static int X86_VPCLMULQDQ() { 332 | return (int)11L; 333 | } 334 | public static int X86_BMI1() { 335 | return (int)12L; 336 | } 337 | public static int X86_HLE() { 338 | return (int)13L; 339 | } 340 | public static int X86_BMI2() { 341 | return (int)14L; 342 | } 343 | public static int X86_RTM() { 344 | return (int)15L; 345 | } 346 | public static int X86_RDSEED() { 347 | return (int)16L; 348 | } 349 | public static int X86_CLFLUSHOPT() { 350 | return (int)17L; 351 | } 352 | public static int X86_CLWB() { 353 | return (int)18L; 354 | } 355 | public static int X86_SSE() { 356 | return (int)19L; 357 | } 358 | public static int X86_SSE2() { 359 | return (int)20L; 360 | } 361 | public static int X86_SSE3() { 362 | return (int)21L; 363 | } 364 | public static int X86_SSSE3() { 365 | return (int)22L; 366 | } 367 | public static int X86_SSE4_1() { 368 | return (int)23L; 369 | } 370 | public static int X86_SSE4_2() { 371 | return (int)24L; 372 | } 373 | public static int X86_SSE4A() { 374 | return (int)25L; 375 | } 376 | public static int X86_AVX() { 377 | return (int)26L; 378 | } 379 | public static int X86_AVX_VNNI() { 380 | return (int)27L; 381 | } 382 | public static int X86_AVX2() { 383 | return (int)28L; 384 | } 385 | public static int X86_AVX512F() { 386 | return (int)29L; 387 | } 388 | public static int X86_AVX512CD() { 389 | return (int)30L; 390 | } 391 | public static int X86_AVX512ER() { 392 | return (int)31L; 393 | } 394 | public static int X86_AVX512PF() { 395 | return (int)32L; 396 | } 397 | public static int X86_AVX512BW() { 398 | return (int)33L; 399 | } 400 | public static int X86_AVX512DQ() { 401 | return (int)34L; 402 | } 403 | public static int X86_AVX512VL() { 404 | return (int)35L; 405 | } 406 | public static int X86_AVX512IFMA() { 407 | return (int)36L; 408 | } 409 | public static int X86_AVX512VBMI() { 410 | return (int)37L; 411 | } 412 | public static int X86_AVX512VBMI2() { 413 | return (int)38L; 414 | } 415 | public static int X86_AVX512VNNI() { 416 | return (int)39L; 417 | } 418 | public static int X86_AVX512BITALG() { 419 | return (int)40L; 420 | } 421 | public static int X86_AVX512VPOPCNTDQ() { 422 | return (int)41L; 423 | } 424 | public static int X86_AVX512_4VNNIW() { 425 | return (int)42L; 426 | } 427 | public static int X86_AVX512_4VBMI2() { 428 | return (int)43L; 429 | } 430 | public static int X86_AVX512_SECOND_FMA() { 431 | return (int)44L; 432 | } 433 | public static int X86_AVX512_4FMAPS() { 434 | return (int)45L; 435 | } 436 | public static int X86_AVX512_BF16() { 437 | return (int)46L; 438 | } 439 | public static int X86_AVX512_VP2INTERSECT() { 440 | return (int)47L; 441 | } 442 | public static int X86_AVX512_FP16() { 443 | return (int)48L; 444 | } 445 | public static int X86_AMX_BF16() { 446 | return (int)49L; 447 | } 448 | public static int X86_AMX_TILE() { 449 | return (int)50L; 450 | } 451 | public static int X86_AMX_INT8() { 452 | return (int)51L; 453 | } 454 | public static int X86_PCLMULQDQ() { 455 | return (int)52L; 456 | } 457 | public static int X86_SMX() { 458 | return (int)53L; 459 | } 460 | public static int X86_SGX() { 461 | return (int)54L; 462 | } 463 | public static int X86_CX16() { 464 | return (int)55L; 465 | } 466 | public static int X86_SHA() { 467 | return (int)56L; 468 | } 469 | public static int X86_POPCNT() { 470 | return (int)57L; 471 | } 472 | public static int X86_MOVBE() { 473 | return (int)58L; 474 | } 475 | public static int X86_RDRND() { 476 | return (int)59L; 477 | } 478 | public static int X86_DCA() { 479 | return (int)60L; 480 | } 481 | public static int X86_SS() { 482 | return (int)61L; 483 | } 484 | public static int X86_ADX() { 485 | return (int)62L; 486 | } 487 | public static int X86_LZCNT() { 488 | return (int)63L; 489 | } 490 | public static int X86_GFNI() { 491 | return (int)64L; 492 | } 493 | public static int X86_MOVDIRI() { 494 | return (int)65L; 495 | } 496 | public static int X86_MOVDIR64B() { 497 | return (int)66L; 498 | } 499 | public static int X86_FS_REP_MOV() { 500 | return (int)67L; 501 | } 502 | public static int X86_FZ_REP_MOVSB() { 503 | return (int)68L; 504 | } 505 | public static int X86_FS_REP_STOSB() { 506 | return (int)69L; 507 | } 508 | public static int X86_FS_REP_CMPSB_SCASB() { 509 | return (int)70L; 510 | } 511 | public static int X86_LAST_() { 512 | return (int)71L; 513 | } 514 | public static MethodHandle GetX86FeaturesEnumValue$MH() { 515 | return RuntimeHelper.requireNonNull(constants$0.GetX86FeaturesEnumValue$MH,"GetX86FeaturesEnumValue"); 516 | } 517 | public static int GetX86FeaturesEnumValue ( Addressable features, int value) { 518 | var mh$ = GetX86FeaturesEnumValue$MH(); 519 | try { 520 | return (int)mh$.invokeExact(features, value); 521 | } catch (Throwable ex$) { 522 | throw new AssertionError("should not reach here", ex$); 523 | } 524 | } 525 | public static MethodHandle GetX86FeaturesEnumName$MH() { 526 | return RuntimeHelper.requireNonNull(constants$0.GetX86FeaturesEnumName$MH,"GetX86FeaturesEnumName"); 527 | } 528 | public static MemoryAddress GetX86FeaturesEnumName ( int x0) { 529 | var mh$ = GetX86FeaturesEnumName$MH(); 530 | try { 531 | return (MemoryAddress)mh$.invokeExact(x0); 532 | } catch (Throwable ex$) { 533 | throw new AssertionError("should not reach here", ex$); 534 | } 535 | } 536 | public static MethodHandle GetX86MicroarchitectureName$MH() { 537 | return RuntimeHelper.requireNonNull(constants$1.GetX86MicroarchitectureName$MH,"GetX86MicroarchitectureName"); 538 | } 539 | public static MemoryAddress GetX86MicroarchitectureName ( int x0) { 540 | var mh$ = GetX86MicroarchitectureName$MH(); 541 | try { 542 | return (MemoryAddress)mh$.invokeExact(x0); 543 | } catch (Throwable ex$) { 544 | throw new AssertionError("should not reach here", ex$); 545 | } 546 | } 547 | public static MemorySegment CPU_FEATURES_VENDOR_GENUINE_INTEL() { 548 | return constants$1.CPU_FEATURES_VENDOR_GENUINE_INTEL$SEGMENT; 549 | } 550 | public static MemorySegment CPU_FEATURES_VENDOR_AUTHENTIC_AMD() { 551 | return constants$1.CPU_FEATURES_VENDOR_AUTHENTIC_AMD$SEGMENT; 552 | } 553 | public static MemorySegment CPU_FEATURES_VENDOR_HYGON_GENUINE() { 554 | return constants$1.CPU_FEATURES_VENDOR_HYGON_GENUINE$SEGMENT; 555 | } 556 | public static MemorySegment CPU_FEATURES_VENDOR_CENTAUR_HAULS() { 557 | return constants$1.CPU_FEATURES_VENDOR_CENTAUR_HAULS$SEGMENT; 558 | } 559 | public static MemorySegment CPU_FEATURES_VENDOR_SHANGHAI() { 560 | return constants$1.CPU_FEATURES_VENDOR_SHANGHAI$SEGMENT; 561 | } 562 | } 563 | 564 | 565 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/RuntimeHelper.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.headers.x86; 2 | // Generated by jextract 3 | 4 | import java.lang.foreign.*; 5 | import java.lang.invoke.MethodHandle; 6 | import java.lang.invoke.MethodHandles; 7 | import java.lang.invoke.MethodType; 8 | 9 | import static java.lang.foreign.ValueLayout.*; 10 | 11 | final class RuntimeHelper { 12 | 13 | private RuntimeHelper() {} 14 | private final static Linker LINKER = Linker.nativeLinker(); 15 | private final static ClassLoader LOADER = RuntimeHelper.class.getClassLoader(); 16 | private final static MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup(); 17 | private final static SymbolLookup SYMBOL_LOOKUP; 18 | 19 | final static SegmentAllocator CONSTANT_ALLOCATOR = 20 | (size, align) -> MemorySegment.allocateNative(size, align, MemorySession.openImplicit()); 21 | 22 | static { 23 | 24 | SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); 25 | SYMBOL_LOOKUP = name -> loaderLookup.lookup(name).or(() -> LINKER.defaultLookup().lookup(name)); 26 | } 27 | 28 | static T requireNonNull(T obj, String symbolName) { 29 | if (obj == null) { 30 | throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName); 31 | } 32 | return obj; 33 | } 34 | 35 | private final static SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); }; 36 | 37 | static final MemorySegment lookupGlobalVariable(String name, MemoryLayout layout) { 38 | return SYMBOL_LOOKUP.lookup(name).map(symbol -> MemorySegment.ofAddress(symbol.address(), layout.byteSize(), MemorySession.openShared())).orElse(null); 39 | } 40 | 41 | static final MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) { 42 | return SYMBOL_LOOKUP.lookup(name). 43 | map(addr -> LINKER.downcallHandle(addr, fdesc)). 44 | orElse(null); 45 | } 46 | 47 | static final MethodHandle downcallHandle(FunctionDescriptor fdesc) { 48 | return LINKER.downcallHandle(fdesc); 49 | } 50 | 51 | static final MethodHandle downcallHandleVariadic(String name, FunctionDescriptor fdesc) { 52 | return SYMBOL_LOOKUP.lookup(name). 53 | map(addr -> VarargsInvoker.make(addr, fdesc)). 54 | orElse(null); 55 | } 56 | 57 | static final MemorySegment upcallStub(Class fi, Z z, FunctionDescriptor fdesc, MemorySession session) { 58 | try { 59 | MethodHandle handle = MH_LOOKUP.findVirtual(fi, "apply", Linker.upcallType(fdesc)); 60 | handle = handle.bindTo(z); 61 | return LINKER.upcallStub(handle, fdesc, session); 62 | } catch (Throwable ex) { 63 | throw new AssertionError(ex); 64 | } 65 | } 66 | 67 | static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements, MemorySession session) { 68 | return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), session); 69 | } 70 | 71 | // Internals only below this point 72 | 73 | private static class VarargsInvoker { 74 | private static final MethodHandle INVOKE_MH; 75 | private final MemorySegment symbol; 76 | private final FunctionDescriptor function; 77 | 78 | private VarargsInvoker(MemorySegment symbol, FunctionDescriptor function) { 79 | this.symbol = symbol; 80 | this.function = function; 81 | } 82 | 83 | static { 84 | try { 85 | INVOKE_MH = MethodHandles.lookup().findVirtual(VarargsInvoker.class, "invoke", MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class)); 86 | } catch (ReflectiveOperationException e) { 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | 91 | static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) { 92 | VarargsInvoker invoker = new VarargsInvoker(symbol, function); 93 | MethodHandle handle = INVOKE_MH.bindTo(invoker).asCollector(Object[].class, function.argumentLayouts().size() + 1); 94 | MethodType mtype = MethodType.methodType(function.returnLayout().isPresent() ? carrier(function.returnLayout().get(), true) : void.class); 95 | for (MemoryLayout layout : function.argumentLayouts()) { 96 | mtype = mtype.appendParameterTypes(carrier(layout, false)); 97 | } 98 | mtype = mtype.appendParameterTypes(Object[].class); 99 | if (mtype.returnType().equals(MemorySegment.class)) { 100 | mtype = mtype.insertParameterTypes(0, SegmentAllocator.class); 101 | } else { 102 | handle = MethodHandles.insertArguments(handle, 0, THROWING_ALLOCATOR); 103 | } 104 | return handle.asType(mtype); 105 | } 106 | 107 | static Class carrier(MemoryLayout layout, boolean ret) { 108 | if (layout instanceof ValueLayout valueLayout) { 109 | return (ret || valueLayout.carrier() != MemoryAddress.class) ? 110 | valueLayout.carrier() : Addressable.class; 111 | } else if (layout instanceof GroupLayout) { 112 | return MemorySegment.class; 113 | } else { 114 | throw new AssertionError("Cannot get here!"); 115 | } 116 | } 117 | 118 | private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable { 119 | // one trailing Object[] 120 | int nNamedArgs = function.argumentLayouts().size(); 121 | assert(args.length == nNamedArgs + 1); 122 | // The last argument is the array of vararg collector 123 | Object[] unnamedArgs = (Object[]) args[args.length - 1]; 124 | 125 | int argsCount = nNamedArgs + unnamedArgs.length; 126 | Class[] argTypes = new Class[argsCount]; 127 | MemoryLayout[] argLayouts = new MemoryLayout[nNamedArgs + unnamedArgs.length]; 128 | 129 | int pos = 0; 130 | for (pos = 0; pos < nNamedArgs; pos++) { 131 | argLayouts[pos] = function.argumentLayouts().get(pos); 132 | } 133 | 134 | assert pos == nNamedArgs; 135 | for (Object o: unnamedArgs) { 136 | argLayouts[pos] = variadicLayout(normalize(o.getClass())); 137 | pos++; 138 | } 139 | assert pos == argsCount; 140 | 141 | FunctionDescriptor f = (function.returnLayout().isEmpty()) ? 142 | FunctionDescriptor.ofVoid(argLayouts) : 143 | FunctionDescriptor.of(function.returnLayout().get(), argLayouts); 144 | MethodHandle mh = LINKER.downcallHandle(symbol, f); 145 | if (mh.type().returnType() == MemorySegment.class) { 146 | mh = mh.bindTo(allocator); 147 | } 148 | // flatten argument list so that it can be passed to an asSpreader MH 149 | Object[] allArgs = new Object[nNamedArgs + unnamedArgs.length]; 150 | System.arraycopy(args, 0, allArgs, 0, nNamedArgs); 151 | System.arraycopy(unnamedArgs, 0, allArgs, nNamedArgs, unnamedArgs.length); 152 | 153 | return mh.asSpreader(Object[].class, argsCount).invoke(allArgs); 154 | } 155 | 156 | private static Class unboxIfNeeded(Class clazz) { 157 | if (clazz == Boolean.class) { 158 | return boolean.class; 159 | } else if (clazz == Void.class) { 160 | return void.class; 161 | } else if (clazz == Byte.class) { 162 | return byte.class; 163 | } else if (clazz == Character.class) { 164 | return char.class; 165 | } else if (clazz == Short.class) { 166 | return short.class; 167 | } else if (clazz == Integer.class) { 168 | return int.class; 169 | } else if (clazz == Long.class) { 170 | return long.class; 171 | } else if (clazz == Float.class) { 172 | return float.class; 173 | } else if (clazz == Double.class) { 174 | return double.class; 175 | } else { 176 | return clazz; 177 | } 178 | } 179 | 180 | private Class promote(Class c) { 181 | if (c == byte.class || c == char.class || c == short.class || c == int.class) { 182 | return long.class; 183 | } else if (c == float.class) { 184 | return double.class; 185 | } else { 186 | return c; 187 | } 188 | } 189 | 190 | private Class normalize(Class c) { 191 | c = unboxIfNeeded(c); 192 | if (c.isPrimitive()) { 193 | return promote(c); 194 | } 195 | if (MemoryAddress.class.isAssignableFrom(c)) { 196 | return MemoryAddress.class; 197 | } 198 | if (MemorySegment.class.isAssignableFrom(c)) { 199 | return MemorySegment.class; 200 | } 201 | throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); 202 | } 203 | 204 | private MemoryLayout variadicLayout(Class c) { 205 | if (c == long.class) { 206 | return JAVA_LONG; 207 | } else if (c == double.class) { 208 | return JAVA_DOUBLE; 209 | } else if (MemoryAddress.class.isAssignableFrom(c)) { 210 | return ADDRESS; 211 | } else { 212 | throw new IllegalArgumentException("Unhandled variadic argument class: " + c); 213 | } 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/X86Features.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.*; 6 | 7 | public class X86Features { 8 | 9 | static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout( 10 | // cpu-features-java 11 | Constants$root.C_INT$LAYOUT.withName("a"), 12 | Constants$root.C_INT$LAYOUT.withName("b"), 13 | Constants$root.C_INT$LAYOUT.withName("c") 14 | ); 15 | public static MemoryLayout $LAYOUT() { 16 | return X86Features.$struct$LAYOUT; 17 | } 18 | public static long sizeof() { return $LAYOUT().byteSize(); } 19 | public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } 20 | public static MemorySegment allocateArray(int len, SegmentAllocator allocator) { 21 | return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); 22 | } 23 | public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/X86Info.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.*; 6 | import java.lang.invoke.VarHandle; 7 | 8 | import static java.lang.foreign.ValueLayout.PathElement; 9 | public class X86Info { 10 | 11 | static final GroupLayout $struct$LAYOUT = MemoryLayout.structLayout( 12 | // cpu-features-java 13 | MemoryLayout.structLayout( 14 | Constants$root.C_INT$LAYOUT.withName("a"), 15 | Constants$root.C_INT$LAYOUT.withName("b"), 16 | Constants$root.C_INT$LAYOUT.withName("c") 17 | ).withName("features"), 18 | Constants$root.C_INT$LAYOUT.withName("family"), 19 | Constants$root.C_INT$LAYOUT.withName("model"), 20 | Constants$root.C_INT$LAYOUT.withName("stepping"), 21 | MemoryLayout.sequenceLayout(13, Constants$root.C_CHAR$LAYOUT).withName("vendor"), 22 | MemoryLayout.sequenceLayout(49, Constants$root.C_CHAR$LAYOUT).withName("brand_string"), 23 | MemoryLayout.paddingLayout(16) 24 | ); 25 | public static MemoryLayout $LAYOUT() { 26 | return X86Info.$struct$LAYOUT; 27 | } 28 | public static MemorySegment features$slice(MemorySegment seg) { 29 | return seg.asSlice(0, 12); 30 | } 31 | static final VarHandle family$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("family")); 32 | public static VarHandle family$VH() { 33 | return X86Info.family$VH; 34 | } 35 | public static int family$get(MemorySegment seg) { 36 | return (int)X86Info.family$VH.get(seg); 37 | } 38 | public static void family$set( MemorySegment seg, int x) { 39 | X86Info.family$VH.set(seg, x); 40 | } 41 | public static int family$get(MemorySegment seg, long index) { 42 | return (int)X86Info.family$VH.get(seg.asSlice(index*sizeof())); 43 | } 44 | public static void family$set(MemorySegment seg, long index, int x) { 45 | X86Info.family$VH.set(seg.asSlice(index*sizeof()), x); 46 | } 47 | static final VarHandle model$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("model")); 48 | public static VarHandle model$VH() { 49 | return X86Info.model$VH; 50 | } 51 | public static int model$get(MemorySegment seg) { 52 | return (int)X86Info.model$VH.get(seg); 53 | } 54 | public static void model$set( MemorySegment seg, int x) { 55 | X86Info.model$VH.set(seg, x); 56 | } 57 | public static int model$get(MemorySegment seg, long index) { 58 | return (int)X86Info.model$VH.get(seg.asSlice(index*sizeof())); 59 | } 60 | public static void model$set(MemorySegment seg, long index, int x) { 61 | X86Info.model$VH.set(seg.asSlice(index*sizeof()), x); 62 | } 63 | static final VarHandle stepping$VH = $struct$LAYOUT.varHandle(PathElement.groupElement("stepping")); 64 | public static VarHandle stepping$VH() { 65 | return X86Info.stepping$VH; 66 | } 67 | public static int stepping$get(MemorySegment seg) { 68 | return (int)X86Info.stepping$VH.get(seg); 69 | } 70 | public static void stepping$set( MemorySegment seg, int x) { 71 | X86Info.stepping$VH.set(seg, x); 72 | } 73 | public static int stepping$get(MemorySegment seg, long index) { 74 | return (int)X86Info.stepping$VH.get(seg.asSlice(index*sizeof())); 75 | } 76 | public static void stepping$set(MemorySegment seg, long index, int x) { 77 | X86Info.stepping$VH.set(seg.asSlice(index*sizeof()), x); 78 | } 79 | public static MemorySegment vendor$slice(MemorySegment seg) { 80 | return seg.asSlice(24, 13); 81 | } 82 | public static MemorySegment brand_string$slice(MemorySegment seg) { 83 | return seg.asSlice(37, 49); 84 | } 85 | public static long sizeof() { return $LAYOUT().byteSize(); } 86 | public static MemorySegment allocate(SegmentAllocator allocator) { return allocator.allocate($LAYOUT()); } 87 | public static MemorySegment allocateArray(int len, SegmentAllocator allocator) { 88 | return allocator.allocate(MemoryLayout.sequenceLayout(len, $LAYOUT())); 89 | } 90 | public static MemorySegment ofAddress(MemoryAddress addr, MemorySession session) { return RuntimeHelper.asArray(addr, $LAYOUT(), 1, session); } 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/constants$0.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.FunctionDescriptor; 6 | import java.lang.foreign.MemoryLayout; 7 | import java.lang.invoke.MethodHandle; 8 | 9 | class constants$0 { 10 | 11 | static final FunctionDescriptor GetX86Info$FUNC = FunctionDescriptor.of(MemoryLayout.structLayout( 12 | // cpu-features-java 13 | MemoryLayout.structLayout( 14 | Constants$root.C_INT$LAYOUT.withName("a"), 15 | Constants$root.C_INT$LAYOUT.withName("b"), 16 | Constants$root.C_INT$LAYOUT.withName("c") 17 | ).withName("features"), 18 | Constants$root.C_INT$LAYOUT.withName("family"), 19 | Constants$root.C_INT$LAYOUT.withName("model"), 20 | Constants$root.C_INT$LAYOUT.withName("stepping"), 21 | MemoryLayout.sequenceLayout(13, Constants$root.C_CHAR$LAYOUT).withName("vendor"), 22 | MemoryLayout.sequenceLayout(49, Constants$root.C_CHAR$LAYOUT).withName("brand_string"), 23 | MemoryLayout.paddingLayout(16) 24 | )); 25 | static final MethodHandle GetX86Info$MH = RuntimeHelper.downcallHandle( 26 | "GetX86Info", 27 | constants$0.GetX86Info$FUNC 28 | ); 29 | static final FunctionDescriptor GetX86CacheInfo$FUNC = FunctionDescriptor.of(MemoryLayout.structLayout( 30 | Constants$root.C_INT$LAYOUT.withName("size"), 31 | MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout( 32 | Constants$root.C_INT$LAYOUT.withName("level"), 33 | Constants$root.C_INT$LAYOUT.withName("cache_type"), 34 | Constants$root.C_INT$LAYOUT.withName("cache_size"), 35 | Constants$root.C_INT$LAYOUT.withName("ways"), 36 | Constants$root.C_INT$LAYOUT.withName("line_size"), 37 | Constants$root.C_INT$LAYOUT.withName("tlb_entries"), 38 | Constants$root.C_INT$LAYOUT.withName("partitioning") 39 | )).withName("levels") 40 | )); 41 | static final MethodHandle GetX86CacheInfo$MH = RuntimeHelper.downcallHandle( 42 | "GetX86CacheInfo", 43 | constants$0.GetX86CacheInfo$FUNC 44 | ); 45 | static final FunctionDescriptor GetX86Microarchitecture$FUNC = FunctionDescriptor.of(Constants$root.C_INT$LAYOUT, 46 | Constants$root.C_POINTER$LAYOUT 47 | ); 48 | static final MethodHandle GetX86Microarchitecture$MH = RuntimeHelper.downcallHandle( 49 | "GetX86Microarchitecture", 50 | constants$0.GetX86Microarchitecture$FUNC 51 | ); 52 | static final FunctionDescriptor FillX86BrandString$FUNC = FunctionDescriptor.ofVoid( 53 | Constants$root.C_POINTER$LAYOUT 54 | ); 55 | static final MethodHandle FillX86BrandString$MH = RuntimeHelper.downcallHandle( 56 | "FillX86BrandString", 57 | constants$0.FillX86BrandString$FUNC 58 | ); 59 | static final FunctionDescriptor GetX86FeaturesEnumValue$FUNC = FunctionDescriptor.of(Constants$root.C_INT$LAYOUT, 60 | Constants$root.C_POINTER$LAYOUT, 61 | Constants$root.C_INT$LAYOUT 62 | ); 63 | static final MethodHandle GetX86FeaturesEnumValue$MH = RuntimeHelper.downcallHandle( 64 | "GetX86FeaturesEnumValue", 65 | constants$0.GetX86FeaturesEnumValue$FUNC 66 | ); 67 | static final FunctionDescriptor GetX86FeaturesEnumName$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT, 68 | Constants$root.C_INT$LAYOUT 69 | ); 70 | static final MethodHandle GetX86FeaturesEnumName$MH = RuntimeHelper.downcallHandle( 71 | "GetX86FeaturesEnumName", 72 | constants$0.GetX86FeaturesEnumName$FUNC 73 | ); 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /cpu-features-java-headers/src/main/java/cpufeatures/headers/x86/constants$1.java: -------------------------------------------------------------------------------- 1 | // Generated by jextract 2 | 3 | package cpufeatures.headers.x86; 4 | 5 | import java.lang.foreign.FunctionDescriptor; 6 | import java.lang.foreign.MemorySegment; 7 | import java.lang.invoke.MethodHandle; 8 | 9 | class constants$1 { 10 | 11 | static final FunctionDescriptor GetX86MicroarchitectureName$FUNC = FunctionDescriptor.of(Constants$root.C_POINTER$LAYOUT, 12 | Constants$root.C_INT$LAYOUT 13 | ); 14 | static final MethodHandle GetX86MicroarchitectureName$MH = RuntimeHelper.downcallHandle( 15 | "GetX86MicroarchitectureName", 16 | constants$1.GetX86MicroarchitectureName$FUNC 17 | ); 18 | static final MemorySegment CPU_FEATURES_VENDOR_GENUINE_INTEL$SEGMENT = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("GenuineIntel"); 19 | static final MemorySegment CPU_FEATURES_VENDOR_AUTHENTIC_AMD$SEGMENT = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("AuthenticAMD"); 20 | static final MemorySegment CPU_FEATURES_VENDOR_HYGON_GENUINE$SEGMENT = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("HygonGenuine"); 21 | static final MemorySegment CPU_FEATURES_VENDOR_CENTAUR_HAULS$SEGMENT = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String("CentaurHauls"); 22 | static final MemorySegment CPU_FEATURES_VENDOR_SHANGHAI$SEGMENT = RuntimeHelper.CONSTANT_ALLOCATOR.allocateUtf8String(" Shanghai "); 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /cpu-features-java-natives-linux-x86/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-linux-conventions") 3 | } 4 | 5 | natives { 6 | destDir.set("linux_x86") 7 | } 8 | -------------------------------------------------------------------------------- /cpu-features-java-natives-macos-x86/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-macos-conventions") 3 | } 4 | 5 | natives { 6 | destDir.set("macos_x86") 7 | } 8 | -------------------------------------------------------------------------------- /cpu-features-java-natives-windows-x86/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("natives-windows-conventions") 3 | } 4 | 5 | natives { 6 | destDir.set("windows_x86") 7 | } 8 | -------------------------------------------------------------------------------- /gradle/libs.versions.yml: -------------------------------------------------------------------------------- 1 | metadata: 2 | format: { version: 1.0 } 3 | polyglot-extensions: [ plugins ] 4 | 5 | versions: 6 | indra: 3.0.1 7 | jextract: 0.3.1 8 | findBugs: 3.0.2 9 | jUnit: 5.9.2 10 | 11 | dependencies: 12 | indraCommon: { group: net.kyori, name: indra-common, version: { ref: indra } } 13 | indraPublishingSonatype: { group: net.kyori, name: indra-publishing-sonatype, version: { ref: indra } } 14 | jextract: { group: gradle.plugin.io.github.krakowski, name: gradle-jextract, version: { ref: jextract } } 15 | findBugs: { group: com.google.code.findbugs, name: jsr305, version: { ref: findBugs } } 16 | jUnitJupiterApi: { group: org.junit.jupiter, name: junit-jupiter-api, version: { ref: jUnit } } 17 | jUnitJupiterEngine: { group: org.junit.jupiter, name: junit-jupiter-engine, version: { ref: jUnit } } 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aecsocket/cpu-features-java/bd490ab7042ece2627827da13bd9d9ef06765037/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 147 | # shellcheck disable=SC3045 148 | MAX_FD=$( ulimit -H -n ) || 149 | warn "Could not query maximum file descriptor limit" 150 | esac 151 | case $MAX_FD in #( 152 | '' | soft) :;; #( 153 | *) 154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 155 | # shellcheck disable=SC3045 156 | ulimit -n "$MAX_FD" || 157 | warn "Could not set maximum file descriptor limit to $MAX_FD" 158 | esac 159 | fi 160 | 161 | # Collect all arguments for the java command, stacking in reverse order: 162 | # * args from the command line 163 | # * the main class name 164 | # * -classpath 165 | # * -D...appname settings 166 | # * --module-path (only if needed) 167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 168 | 169 | # For Cygwin or MSYS, switch paths to Windows format before running java 170 | if "$cygwin" || "$msys" ; then 171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 173 | 174 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 175 | 176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 177 | for arg do 178 | if 179 | case $arg in #( 180 | -*) false ;; # don't mess with options #( 181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 182 | [ -e "$t" ] ;; #( 183 | *) false ;; 184 | esac 185 | then 186 | arg=$( cygpath --path --ignore --mixed "$arg" ) 187 | fi 188 | # Roll the args list around exactly as many times as the number of 189 | # args, so each arg winds up back in the position where it started, but 190 | # possibly modified. 191 | # 192 | # NB: a `for` loop captures its iteration list before it begins, so 193 | # changing the positional parameters here affects neither the number of 194 | # iterations, nor the values presented in `arg`. 195 | shift # remove old arg 196 | set -- "$@" "$arg" # push replacement arg 197 | done 198 | fi 199 | 200 | # Collect all arguments for the java command; 201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 202 | # shell script including quotes and variable substitutions, so put them in 203 | # double quotes to make sure that they get re-expanded; and 204 | # * put everything else in single quotes, so that it's not re-expanded. 205 | 206 | set -- \ 207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 208 | -classpath "$CLASSPATH" \ 209 | org.gradle.wrapper.GradleWrapperMain \ 210 | "$@" 211 | 212 | # Stop when "xargs" is not available. 213 | if ! command -v xargs >/dev/null 2>&1 214 | then 215 | die "xargs is not available" 216 | fi 217 | 218 | # Use "xargs" to parse quoted args. 219 | # 220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 221 | # 222 | # In Bash we could simply go: 223 | # 224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 225 | # set -- "${ARGS[@]}" "$@" 226 | # 227 | # but POSIX shell has neither arrays nor command substitution, so instead we 228 | # post-process each arg (as a line of input to sed) to backslash-escape any 229 | # character that might be a shell metacharacter, then use eval to reverse 230 | # that process (while maintaining the separation between arguments), and wrap 231 | # the whole thing up as a single "set" statement. 232 | # 233 | # This will of course break if any of these variables contains a newline or 234 | # an unmatched quote. 235 | # 236 | 237 | eval "set -- $( 238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 239 | xargs -n1 | 240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 241 | tr '\n' ' ' 242 | )" '"$@"' 243 | 244 | exec "$JAVACMD" "$@" 245 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 2 | 3 | pluginManagement { 4 | repositories { 5 | gradlePluginPortal() 6 | } 7 | includeBuild("build-logic") 8 | } 9 | 10 | plugins { 11 | id("ca.stellardrift.polyglot-version-catalogs") version "6.0.1" 12 | } 13 | 14 | rootProject.name = "cpu-features-java" 15 | 16 | include("cpu-features-java-headers") 17 | include("cpu-features-java-natives-linux-x86") 18 | include("cpu-features-java-natives-windows-x86") 19 | include("cpu-features-java-natives-macos-x86") 20 | include("cpu-features-java-natives-macos-aarch64") 21 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/CpuArchitecture.java: -------------------------------------------------------------------------------- 1 | package cpufeatures; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * Processor architecture. 7 | */ 8 | public enum CpuArchitecture { 9 | /** Unknown architecture */ 10 | UNKNOWN, 11 | /** AArch64 */ 12 | AARCH64, 13 | /** ARM */ 14 | ARM, 15 | /** X86 */ 16 | X86; 17 | 18 | /** 19 | * Gets the processor architecture that the machine running this JVM is on. 20 | * @return Architecture. 21 | */ 22 | public static CpuArchitecture get() { 23 | String arch = System.getProperty("os.arch") 24 | .toLowerCase(Locale.ROOT) 25 | .replaceAll("[^a-z0-9]+", ""); 26 | return switch (arch) { 27 | case "aarch64" -> CpuArchitecture.AARCH64; 28 | case "arm", "arm32" -> CpuArchitecture.ARM; 29 | case "x8664", "amd64", "ia32e", "em64t", "x64" -> CpuArchitecture.X86; 30 | default -> CpuArchitecture.UNKNOWN; 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/CpuFeatures.java: -------------------------------------------------------------------------------- 1 | package cpufeatures; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.StandardCopyOption; 6 | import java.util.Locale; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | 9 | /** 10 | * Entry point of the cpu_features bindings library. 11 | */ 12 | public final class CpuFeatures { 13 | private CpuFeatures() {} 14 | 15 | private static final AtomicBoolean loaded = new AtomicBoolean(false); 16 | 17 | /** 18 | * Loads the native libraries from the JAR. 19 | */ 20 | public static void load() { 21 | if (loaded.getAndSet(true)) return; 22 | 23 | CpuPlatform platform = CpuPlatform.get(); 24 | CpuArchitecture arch = CpuArchitecture.get(); 25 | String resourcePath = "cpufeatures/" + switch (platform) { 26 | case LINUX -> switch (arch) { 27 | case X86 -> "linux_x86/libcpu_features.so"; 28 | default -> throw new RuntimeException("Invalid architecture " + arch + " for Linux"); 29 | }; 30 | case WINDOWS -> switch (arch) { 31 | case X86 -> "windows_x86/libcpu_features.dll"; 32 | default -> throw new RuntimeException("Invalid architecture " + arch + " for Windows"); 33 | }; 34 | case MACOS -> switch (arch) { 35 | case X86 -> "macos_x86/libcpu_features.dylib"; 36 | default -> throw new RuntimeException("Invalid architecture " + arch + " for MacOS"); 37 | }; 38 | }; 39 | 40 | try (var resourceIn = CpuFeatures.class.getClassLoader().getResourceAsStream(resourcePath)) { 41 | if (resourceIn == null) 42 | throw new RuntimeException("No native library in JAR at " + resourcePath); 43 | var libFile = Files.createTempFile("cpu_features", null); 44 | Files.copy(resourceIn, libFile, StandardCopyOption.REPLACE_EXISTING); 45 | System.load(libFile.toAbsolutePath().toString()); 46 | } catch (IOException ex) { 47 | throw new RuntimeException("Could not load native library", ex); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/CpuPlatform.java: -------------------------------------------------------------------------------- 1 | package cpufeatures; 2 | 3 | import java.util.Locale; 4 | 5 | public enum CpuPlatform { 6 | LINUX, 7 | WINDOWS, 8 | MACOS; 9 | 10 | public static CpuPlatform get() { 11 | String os = System.getProperty("os.name").toLowerCase(Locale.ROOT); 12 | 13 | if (os.contains("linux")) return LINUX; 14 | if (os.contains("windows")) return WINDOWS; 15 | if (os.contains("mac os x") || os.contains("darwin")) return MACOS; 16 | throw new RuntimeException("Unsupported OS " + System.getProperty("os.name")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/arm/ArmFeature.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.arm; 2 | 3 | import java.util.function.Predicate; 4 | 5 | /** 6 | * Feature that can be present on an ARM processor. 7 | */ 8 | public enum ArmFeature { 9 | /** SWP instruction (atomic read-modify-write) */ 10 | SWP (ArmFeatures::swp), 11 | /** Half-word loads and stores */ 12 | HALF (ArmFeatures::half), 13 | /** Thumb (16-bit instruction set) */ 14 | THUMB (ArmFeatures::thumb), 15 | /** "26 Bit" Model (Processor status register folded into program counter) */ 16 | _26BIT (ArmFeatures::_26bit), 17 | /** 32x32->64-bit multiplication */ 18 | FASTMULT (ArmFeatures::fastmult), 19 | /** Floating point accelerator */ 20 | FPA (ArmFeatures::fpa), 21 | /** Vector Floating Point */ 22 | VFP (ArmFeatures::vfp), 23 | /** DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above) */ 24 | EDSP (ArmFeatures::edsp), 25 | /** Jazelle (Java bytecode accelerator) */ 26 | JAVA (ArmFeatures::java), 27 | /** Intel Wireless MMX Technology */ 28 | IWMMXT (ArmFeatures::iwmmxt), 29 | /** MaverickCrunch coprocessor */ 30 | CRUNCH (ArmFeatures::crunch), 31 | /** ThumbEE */ 32 | THUMBEE (ArmFeatures::thumbee), 33 | /** Advanced SIMD */ 34 | NEON (ArmFeatures::neon), 35 | /** VFP version 3 */ 36 | VFPV3 (ArmFeatures::vfpv3), 37 | /** VFP version 3 with 16 D-registers */ 38 | VFPV3D16 (ArmFeatures::vfpv3d16), 39 | /** TLS register */ 40 | TLS (ArmFeatures::tls), 41 | /** VFP version 4 with fast context switching */ 42 | VFPV4 (ArmFeatures::vfpv4), 43 | /** SDIV and UDIV hardware division in ARM mode */ 44 | IDIVA (ArmFeatures::idiva), 45 | /** SDIV and UDIV hardware division in Thumb mode */ 46 | IDIVT (ArmFeatures::idivt), 47 | /** VFP with 32 D-registers */ 48 | VFPD32 (ArmFeatures::vfpd32), 49 | /** VFP with 32 D-registersLarge Physical Address Extension (>4GB physical memory on 32-bit architecture) */ 50 | LPAE (ArmFeatures::lpae), 51 | /** Kernel event stream using generic architected timer */ 52 | EVTSTRM (ArmFeatures::evtstrm), 53 | /** Hardware-accelerated Advanced Encryption Standard */ 54 | AES (ArmFeatures::aes), 55 | /** Polynomial multiply long */ 56 | PMULL (ArmFeatures::pmull), 57 | /** Hardware-accelerated SHA1 */ 58 | SHA1 (ArmFeatures::sha1), 59 | /** Hardware-accelerated SHA2-256 */ 60 | SHA2 (ArmFeatures::sha2), 61 | /** Hardware-accelerated CRC-32 */ 62 | CRC32 (ArmFeatures::crc32); 63 | 64 | private final Predicate predicate; 65 | 66 | ArmFeature(Predicate predicate) { 67 | this.predicate = predicate; 68 | } 69 | 70 | /** 71 | * Gets if this feature is present in a features object. 72 | * @param features Features object. 73 | * @return Present state. 74 | */ 75 | public boolean in(ArmFeatures features) { return predicate.test(features); } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/arm/ArmFeatures.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.arm; 2 | 3 | /** 4 | * Feature set of a processor running the ARM architecture. 5 | * @param swp SWP instruction (atomic read-modify-write) 6 | * @param half Half-word loads and stores 7 | * @param thumb Thumb (16-bit instruction set) 8 | * @param _26bit "26 Bit" Model (Processor status register folded into program counter) 9 | * @param fastmult 32x32->64-bit multiplication 10 | * @param fpa Floating point accelerator 11 | * @param vfp Vector Floating Point. 12 | * @param edsp DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above) 13 | * @param java Jazelle (Java bytecode accelerator) 14 | * @param iwmmxt Intel Wireless MMX Technology. 15 | * @param crunch MaverickCrunch coprocessor 16 | * @param thumbee ThumbEE 17 | * @param neon Advanced SIMD. 18 | * @param vfpv3 VFP version 3 19 | * @param vfpv3d16 VFP version 3 with 16 D-registers 20 | * @param tls TLS register 21 | * @param vfpv4 VFP version 4 with fast context switching 22 | * @param idiva SDIV and UDIV hardware division in ARM mode. 23 | * @param idivt SDIV and UDIV hardware division in Thumb mode. 24 | * @param vfpd32 VFP with 32 D-registers 25 | * @param lpae Large Physical Address Extension (>4GB physical memory on 32-bit architecture) 26 | * @param evtstrm kernel event stream using generic architected timer 27 | * @param aes Hardware-accelerated Advanced Encryption Standard. 28 | * @param pmull Polynomial multiply long. 29 | * @param sha1 Hardware-accelerated SHA1. 30 | * @param sha2 Hardware-accelerated SHA2-256. 31 | * @param crc32 Hardware-accelerated CRC-32. 32 | */ 33 | public record ArmFeatures( 34 | boolean swp, 35 | boolean half, 36 | boolean thumb, 37 | boolean _26bit, 38 | boolean fastmult, 39 | boolean fpa, 40 | boolean vfp, 41 | boolean edsp, 42 | boolean java, 43 | boolean iwmmxt, 44 | boolean crunch, 45 | boolean thumbee, 46 | boolean neon, 47 | boolean vfpv3, 48 | boolean vfpv3d16, 49 | boolean tls, 50 | boolean vfpv4, 51 | boolean idiva, 52 | boolean idivt, 53 | boolean vfpd32, 54 | boolean lpae, 55 | boolean evtstrm, 56 | boolean aes, 57 | boolean pmull, 58 | boolean sha1, 59 | boolean sha2, 60 | boolean crc32 61 | ) {} 62 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/arm/ArmInfo.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.arm; 2 | 3 | import java.util.LinkedHashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * Info on a processor running the ARM architecture. 8 | * @param features Which features this processor supports. 9 | * @param implementer Implementer. 10 | * @param architecture Architecture. 11 | * @param variant Variant. 12 | * @param part Part. 13 | * @param revision Revision. 14 | */ 15 | public record ArmInfo( 16 | ArmFeatures features, 17 | int implementer, 18 | int architecture, 19 | int variant, 20 | int part, 21 | int revision 22 | ) { 23 | // private static final VarHandle a$VH = cpufeatures.natives.x86.X86Features.$LAYOUT().varHandle(groupElement("a")); 24 | // private static final VarHandle b$VH = cpufeatures.natives.x86.X86Features.$LAYOUT().varHandle(groupElement("b")); 25 | // private static final VarHandle c$VH = cpufeatures.natives.x86.X86Features.$LAYOUT().varHandle(groupElement("c")); 26 | // 27 | // private static boolean get(int bits, int position) { 28 | // return ((bits >> position) & 1) == 1; 29 | // } 30 | 31 | /** 32 | * Gets info on the ARM processor running on this JVM. 33 | *

34 | * If the host is not on an ARM processor, this operation will fail. 35 | * @return Processor info. 36 | */ 37 | public static ArmInfo get() { 38 | throw new UnsupportedOperationException(); 39 | } 40 | 41 | /** 42 | * Gets a set of all features that this info holds. If you are testing for a specific feature, prefer using 43 | * {@link #features()} instead. 44 | * @return Set of features. 45 | */ 46 | public Set featureSet() { 47 | var result = new LinkedHashSet(); 48 | for (var feature : ArmFeature.values()) { 49 | if (feature.in(features)) { 50 | result.add(feature); 51 | } 52 | } 53 | return result; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/x86/X86Feature.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.x86; 2 | 3 | import java.util.function.Predicate; 4 | 5 | /** 6 | * Feature that can be present on an X86 processor. 7 | */ 8 | public enum X86Feature { 9 | FPU (X86Features::fpu), 10 | TSC (X86Features::tsc), 11 | CX8 (X86Features::cx8), 12 | CLFSH (X86Features::clfsh), 13 | MMX (X86Features::mmx), 14 | AES (X86Features::aes), 15 | ERMS (X86Features::erms), 16 | F16C (X86Features::f16c), 17 | FMA4 (X86Features::fma4), 18 | FMA3 (X86Features::fma3), 19 | VAES (X86Features::vaes), 20 | VPCLMULQDQ (X86Features::vpclmulqdq), 21 | BMI1 (X86Features::bmi1), 22 | HLE (X86Features::hle), 23 | BMI2 (X86Features::bmi2), 24 | RTM (X86Features::rtm), 25 | RDSEED (X86Features::rdseed), 26 | CLFLUSHOPT (X86Features::clflushopt), 27 | CLWB (X86Features::clwb), 28 | SSE (X86Features::sse), 29 | SSE2 (X86Features::sse2), 30 | SSE3 (X86Features::sse3), 31 | SSSE3 (X86Features::ssse3), 32 | SSE4_1 (X86Features::sse4_1), 33 | SSE4_2 (X86Features::sse4_2), 34 | SSE4A (X86Features::sse4a), 35 | AVX (X86Features::avx), 36 | AVX_VNNI (X86Features::avx_vnni), 37 | AVX2 (X86Features::avx2), 38 | AVX512F (X86Features::avx512f), 39 | AVX512CD (X86Features::avx512cd), 40 | AVX512ER (X86Features::avx512er), 41 | AVX512PF (X86Features::avx512pf), 42 | AVX512BW (X86Features::avx512bw), 43 | AVX512DQ (X86Features::avx512dq), 44 | AVX512VL (X86Features::avx512vl), 45 | AVX512IFMA (X86Features::avx512ifma), 46 | AVX512VBMI (X86Features::avx512vbmi), 47 | AVX512VBMI2 (X86Features::avx512vbmi2), 48 | AVX512VNNI (X86Features::avx512vnni), 49 | AVX512BITALG (X86Features::avx512bitalg), 50 | AVX512VPOPCNTDQ (X86Features::avx512vpopcntdq), 51 | AVX512_4VNNIW (X86Features::avx512_4vnniw), 52 | AVX512_4VBMI2 (X86Features::avx512_4vbmi2), 53 | AVX512_SECOND_FMA (X86Features::avx512_second_fma), 54 | AVX512_4FMAPS (X86Features::avx512_4fmaps), 55 | AVX512_BF16 (X86Features::avx512_bf16), 56 | AVX512_VP2INTERSECT (X86Features::avx512_vp2intersect), 57 | AVX512_FP16 (X86Features::avx512_fp16), 58 | AMX_BF16 (X86Features::amx_bf16), 59 | AMX_TILE (X86Features::amx_tile), 60 | AMX_INT8 (X86Features::amx_int8), 61 | PCLMULQDQ (X86Features::pclmulqdq), 62 | SMX (X86Features::smx), 63 | SGX (X86Features::sgx), 64 | CX16 (X86Features::cx16), 65 | SHA (X86Features::sha), 66 | POPCNT (X86Features::popcnt), 67 | MOVBE (X86Features::movbe), 68 | RDRND (X86Features::rdrnd), 69 | DCA (X86Features::dca), 70 | SS (X86Features::ss), 71 | ADX (X86Features::adx), 72 | LZCNT (X86Features::lzcnt), 73 | GFNI (X86Features::gfni), 74 | MOVDIRI (X86Features::movdiri), 75 | MOVDIR64B (X86Features::movdir64b), 76 | FS_REP_MOV (X86Features::fs_rep_mov), 77 | FZ_REP_MOVSB (X86Features::fz_rep_movsb), 78 | FS_REP_STOSB (X86Features::fs_rep_stosb), 79 | FS_REP_CMPSB_SCASB (X86Features::fs_rep_cmpsb_scasb); 80 | 81 | private final Predicate predicate; 82 | 83 | X86Feature(Predicate predicate) { 84 | this.predicate = predicate; 85 | } 86 | 87 | /** 88 | * Gets if this feature is present in a features object. 89 | * @param features Features object. 90 | * @return Present state. 91 | */ 92 | public boolean in(X86Features features) { return predicate.test(features); } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/x86/X86Features.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.x86; 2 | 3 | /** 4 | * Feature set of a processor running the ARM architecture. 5 | * @param fpu 6 | * @param tsc 7 | * @param cx8 8 | * @param clfsh 9 | * @param mmx 10 | * @param aes 11 | * @param erms 12 | * @param f16c 13 | * @param fma4 14 | * @param fma3 15 | * @param vaes 16 | * @param vpclmulqdq 17 | * @param bmi1 18 | * @param hle 19 | * @param bmi2 20 | * @param rtm 21 | * @param rdseed 22 | * @param clflushopt 23 | * @param clwb 24 | * @param sse 25 | * @param sse2 26 | * @param sse3 27 | * @param ssse3 28 | * @param sse4_1 29 | * @param sse4_2 30 | * @param sse4a 31 | * @param avx 32 | * @param avx_vnni 33 | * @param avx2 34 | * @param avx512f 35 | * @param avx512cd 36 | * @param avx512er 37 | * @param avx512pf 38 | * @param avx512bw 39 | * @param avx512dq 40 | * @param avx512vl 41 | * @param avx512ifma 42 | * @param avx512vbmi 43 | * @param avx512vbmi2 44 | * @param avx512vnni 45 | * @param avx512bitalg 46 | * @param avx512vpopcntdq 47 | * @param avx512_4vnniw 48 | * @param avx512_4vbmi2 49 | * @param avx512_second_fma 50 | * @param avx512_4fmaps 51 | * @param avx512_bf16 52 | * @param avx512_vp2intersect 53 | * @param avx512_fp16 54 | * @param amx_bf16 55 | * @param amx_tile 56 | * @param amx_int8 57 | * @param pclmulqdq 58 | * @param smx 59 | * @param sgx 60 | * @param cx16 61 | * @param sha 62 | * @param popcnt 63 | * @param movbe 64 | * @param rdrnd 65 | * @param dca 66 | * @param ss 67 | * @param adx 68 | * @param lzcnt 69 | * @param gfni 70 | * @param movdiri 71 | * @param movdir64b 72 | * @param fs_rep_mov 73 | * @param fz_rep_movsb 74 | * @param fs_rep_stosb 75 | * @param fs_rep_cmpsb_scasb 76 | */ 77 | public record X86Features( 78 | boolean fpu, 79 | boolean tsc, 80 | boolean cx8, 81 | boolean clfsh, 82 | boolean mmx, 83 | boolean aes, 84 | boolean erms, 85 | boolean f16c, 86 | boolean fma4, 87 | boolean fma3, 88 | boolean vaes, 89 | boolean vpclmulqdq, 90 | boolean bmi1, 91 | boolean hle, 92 | boolean bmi2, 93 | boolean rtm, 94 | boolean rdseed, 95 | boolean clflushopt, 96 | boolean clwb, 97 | boolean sse, 98 | boolean sse2, 99 | boolean sse3, 100 | boolean ssse3, 101 | boolean sse4_1, 102 | boolean sse4_2, 103 | boolean sse4a, 104 | boolean avx, 105 | boolean avx_vnni, 106 | boolean avx2, 107 | boolean avx512f, 108 | boolean avx512cd, 109 | boolean avx512er, 110 | boolean avx512pf, 111 | boolean avx512bw, 112 | boolean avx512dq, 113 | boolean avx512vl, 114 | boolean avx512ifma, 115 | boolean avx512vbmi, 116 | boolean avx512vbmi2, 117 | boolean avx512vnni, 118 | boolean avx512bitalg, 119 | boolean avx512vpopcntdq, 120 | boolean avx512_4vnniw, 121 | boolean avx512_4vbmi2, 122 | boolean avx512_second_fma, 123 | boolean avx512_4fmaps, 124 | boolean avx512_bf16, 125 | boolean avx512_vp2intersect, 126 | boolean avx512_fp16, 127 | boolean amx_bf16, 128 | boolean amx_tile, 129 | boolean amx_int8, 130 | boolean pclmulqdq, 131 | boolean smx, 132 | boolean sgx, 133 | boolean cx16, 134 | boolean sha, 135 | boolean popcnt, 136 | boolean movbe, 137 | boolean rdrnd, 138 | boolean dca, 139 | boolean ss, 140 | boolean adx, 141 | boolean lzcnt, 142 | boolean gfni, 143 | boolean movdiri, 144 | boolean movdir64b, 145 | boolean fs_rep_mov, 146 | boolean fz_rep_movsb, 147 | boolean fs_rep_stosb, 148 | boolean fs_rep_cmpsb_scasb 149 | ) {} 150 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/x86/X86Info.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.x86; 2 | 3 | import java.lang.foreign.MemorySession; 4 | import java.lang.invoke.VarHandle; 5 | import java.util.LinkedHashSet; 6 | import java.util.Set; 7 | 8 | import static cpufeatures.headers.x86.CpuInfoX86.*; 9 | import static cpufeatures.headers.x86.X86Info.*; 10 | import static java.lang.foreign.MemoryLayout.PathElement.groupElement; 11 | 12 | /** 13 | * Info on a processor running the X86 architecture. 14 | * @param features Which features this processor supports. 15 | * @param family Family. 16 | * @param model Model. 17 | * @param stepping Stepping. 18 | * @param vendor Manufacturer. 19 | * @param brandString Brand name. 20 | * @param uarch Microarchitecture. 21 | */ 22 | public record X86Info( 23 | X86Features features, 24 | int family, 25 | int model, 26 | int stepping, 27 | String vendor, 28 | String brandString, 29 | X86Uarch uarch 30 | ) { 31 | private static final VarHandle a$VH = cpufeatures.headers.x86.X86Features.$LAYOUT().varHandle(groupElement("a")); 32 | private static final VarHandle b$VH = cpufeatures.headers.x86.X86Features.$LAYOUT().varHandle(groupElement("b")); 33 | private static final VarHandle c$VH = cpufeatures.headers.x86.X86Features.$LAYOUT().varHandle(groupElement("c")); 34 | 35 | private static boolean get(int bits, int position) { 36 | return ((bits >> position) & 1) == 1; 37 | } 38 | 39 | /** 40 | * Gets info on the X86 processor running on this JVM. 41 | *

42 | * If the host is not on an X86 processor, this operation will fail. 43 | * @return Processor info. 44 | */ 45 | public static X86Info get() { 46 | try (var session = MemorySession.openConfined()) { 47 | var info = GetX86Info(session); 48 | 49 | var features = features$slice(info); 50 | int a = (int) a$VH.get(features); 51 | int b = (int) b$VH.get(features); 52 | int c = (int) c$VH.get(features); 53 | /* 54 | for i in range(len(flags)): 55 | curfield = ["a","b","c"][int(i / 32)] 56 | print(f"boolean {flags[i]} = get({curfield}, {i % 32});") 57 | */ 58 | boolean fpu = get(a, 0); 59 | boolean tsc = get(a, 1); 60 | boolean cx8 = get(a, 2); 61 | boolean clfsh = get(a, 3); 62 | boolean mmx = get(a, 4); 63 | boolean aes = get(a, 5); 64 | boolean erms = get(a, 6); 65 | boolean f16c = get(a, 7); 66 | boolean fma4 = get(a, 8); 67 | boolean fma3 = get(a, 9); 68 | boolean vaes = get(a, 10); 69 | boolean vpclmulqdq = get(a, 11); 70 | boolean bmi1 = get(a, 12); 71 | boolean hle = get(a, 13); 72 | boolean bmi2 = get(a, 14); 73 | boolean rtm = get(a, 15); 74 | boolean rdseed = get(a, 16); 75 | boolean clflushopt = get(a, 17); 76 | boolean clwb = get(a, 18); 77 | boolean sse = get(a, 19); 78 | boolean sse2 = get(a, 20); 79 | boolean sse3 = get(a, 21); 80 | boolean ssse3 = get(a, 22); 81 | boolean sse4_1 = get(a, 23); 82 | boolean sse4_2 = get(a, 24); 83 | boolean sse4a = get(a, 25); 84 | boolean avx = get(a, 26); 85 | boolean avx_vnni = get(a, 27); 86 | boolean avx2 = get(a, 28); 87 | boolean avx512f = get(a, 29); 88 | boolean avx512cd = get(a, 30); 89 | boolean avx512er = get(a, 31); 90 | boolean avx512pf = get(b, 0); 91 | boolean avx512bw = get(b, 1); 92 | boolean avx512dq = get(b, 2); 93 | boolean avx512vl = get(b, 3); 94 | boolean avx512ifma = get(b, 4); 95 | boolean avx512vbmi = get(b, 5); 96 | boolean avx512vbmi2 = get(b, 6); 97 | boolean avx512vnni = get(b, 7); 98 | boolean avx512bitalg = get(b, 8); 99 | boolean avx512vpopcntdq = get(b, 9); 100 | boolean avx512_4vnniw = get(b, 10); 101 | boolean avx512_4vbmi2 = get(b, 11); 102 | boolean avx512_second_fma = get(b, 12); 103 | boolean avx512_4fmaps = get(b, 13); 104 | boolean avx512_bf16 = get(b, 14); 105 | boolean avx512_vp2intersect = get(b, 15); 106 | boolean avx512_fp16 = get(b, 16); 107 | boolean amx_bf16 = get(b, 17); 108 | boolean amx_tile = get(b, 18); 109 | boolean amx_int8 = get(b, 19); 110 | boolean pclmulqdq = get(b, 20); 111 | boolean smx = get(b, 21); 112 | boolean sgx = get(b, 22); 113 | boolean cx16 = get(b, 23); 114 | boolean sha = get(b, 24); 115 | boolean popcnt = get(b, 25); 116 | boolean movbe = get(b, 26); 117 | boolean rdrnd = get(b, 27); 118 | boolean dca = get(b, 28); 119 | boolean ss = get(b, 29); 120 | boolean adx = get(b, 30); 121 | boolean lzcnt = get(b, 31); 122 | boolean gfni = get(c, 0); 123 | boolean movdiri = get(c, 1); 124 | boolean movdir64b = get(c, 2); 125 | boolean fs_rep_mov = get(c, 3); 126 | boolean fz_rep_movsb = get(c, 4); 127 | boolean fs_rep_stosb = get(c, 5); 128 | boolean fs_rep_cmpsb_scasb = get(c, 6); 129 | 130 | int family = family$get(info); 131 | int model = model$get(info); 132 | int stepping = stepping$get(info); 133 | String vendor = vendor$slice(info).getUtf8String(0); 134 | String brandString = brand_string$slice(info).getUtf8String(0); 135 | 136 | X86Uarch uarch = X86Uarch.values()[GetX86Microarchitecture(info)]; 137 | 138 | return new X86Info( 139 | new X86Features(fpu, tsc, cx8, clfsh, mmx, aes, erms, f16c, fma4, fma3, vaes, vpclmulqdq, bmi1, hle, bmi2, rtm, rdseed, clflushopt, clwb, sse, sse2, sse3, ssse3, sse4_1, sse4_2, sse4a, avx, avx_vnni, avx2, avx512f, avx512cd, avx512er, avx512pf, avx512bw, avx512dq, avx512vl, avx512ifma, avx512vbmi, avx512vbmi2, avx512vnni, avx512bitalg, avx512vpopcntdq, avx512_4vnniw, avx512_4vbmi2, avx512_second_fma, avx512_4fmaps, avx512_bf16, avx512_vp2intersect, avx512_fp16, amx_bf16, amx_tile, amx_int8, pclmulqdq, smx, sgx, cx16, sha, popcnt, movbe, rdrnd, dca, ss, adx, lzcnt, gfni, movdiri, movdir64b, fs_rep_mov, fz_rep_movsb, fs_rep_stosb, fs_rep_cmpsb_scasb), 140 | family, 141 | model, 142 | stepping, 143 | vendor, 144 | brandString, 145 | uarch 146 | ); 147 | } 148 | } 149 | 150 | /** 151 | * Gets a set of all features that this info holds. If you are testing for a specific feature, prefer using 152 | * {@link #features()} instead. 153 | * @return Set of features. 154 | */ 155 | public Set featureSet() { 156 | var result = new LinkedHashSet(); 157 | for (var feature : X86Feature.values()) { 158 | if (feature.in(features)) { 159 | result.add(feature); 160 | } 161 | } 162 | return result; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/cpufeatures/x86/X86Uarch.java: -------------------------------------------------------------------------------- 1 | package cpufeatures.x86; 2 | 3 | /** 4 | * Microarchitecture of an X86 processor. 5 | */ 6 | public enum X86Uarch { 7 | /** Unknown architecture */ 8 | X86_UNKNOWN, 9 | /** ZhangJiang */ 10 | ZHAOXIN_ZHANGJIANG, 11 | /** WuDaoKou */ 12 | ZHAOXIN_WUDAOKOU, 13 | /** LuJiaZui */ 14 | ZHAOXIN_LUJIAZUI, 15 | /** YongFeng */ 16 | ZHAOXIN_YONGFENG, 17 | /** 80486 */ 18 | INTEL_80486, 19 | /** P5 */ 20 | INTEL_P5, 21 | /** Lakemont */ 22 | INTEL_LAKEMONT, 23 | /** Core */ 24 | INTEL_CORE, 25 | /** Penryn */ 26 | INTEL_PNR, 27 | /** Nehalem */ 28 | INTEL_NHM, 29 | /** Bonnell */ 30 | INTEL_ATOM_BNL, 31 | /** Westmere */ 32 | INTEL_WSM, 33 | /** Sandy Bridge */ 34 | INTEL_SNB, 35 | /** Ivy Bridge */ 36 | INTEL_IVB, 37 | /** Silvermont */ 38 | INTEL_ATOM_SMT, 39 | /** Haswell */ 40 | INTEL_HSW, 41 | /** Broadwell */ 42 | INTEL_BDW, 43 | /** Skylake */ 44 | INTEL_SKL, 45 | /** Cascade Lake */ 46 | INTEL_CCL, 47 | /** Goldmont */ 48 | INTEL_ATOM_GMT, 49 | /** Goldmont+ */ 50 | INTEL_ATOM_GMT_PLUS, 51 | /** Tremont */ 52 | INTEL_ATOM_TMT, 53 | /** Kaby Lake */ 54 | INTEL_KBL, 55 | /** Coffee Lake */ 56 | INTEL_CFL, 57 | /** Whiskey Lake */ 58 | INTEL_WHL, 59 | /** Comet Lake */ 60 | INTEL_CML, 61 | /** Cannon Lake */ 62 | INTEL_CNL, 63 | /** Ice Lake */ 64 | INTEL_ICL, 65 | /** Tiger Lake */ 66 | INTEL_TGL, 67 | /** Sapphire Rapids */ 68 | INTEL_SPR, 69 | /** Alder Lake */ 70 | INTEL_ADL, 71 | /** Rocket Lake */ 72 | INTEL_RCL, 73 | /** Raptor Lake */ 74 | INTEL_RPL, 75 | /** Knights Mill */ 76 | INTEL_KNIGHTS_M, 77 | /** Knights Landing */ 78 | INTEL_KNIGHTS_L, 79 | /** Knights Ferry */ 80 | INTEL_KNIGHTS_F, 81 | /** Knights Corner */ 82 | INTEL_KNIGHTS_C, 83 | /** Netburst */ 84 | INTEL_NETBURST, 85 | /** K8 Hammer */ 86 | AMD_HAMMER, 87 | /** K10 */ 88 | AMD_K10, 89 | /** K11 */ 90 | AMD_K11, 91 | /** K12 Llano */ 92 | AMD_K12, 93 | /** K14 Bobcat */ 94 | AMD_BOBCAT, 95 | /** K15 Piledriver */ 96 | AMD_PILEDRIVER, 97 | /** K15 Steamroller */ 98 | AMD_STREAMROLLER, 99 | /** K15 Excavator */ 100 | AMD_EXCAVATOR, 101 | /** K15 Bulldozer */ 102 | AMD_BULLDOZER, 103 | /** K16 Jaguar */ 104 | AMD_JAGUAR, 105 | /** K16 Puma */ 106 | AMD_PUMA, 107 | /** K17 Zen */ 108 | AMD_ZEN, 109 | /** K17 Zen+ */ 110 | AMD_ZEN_PLUS, 111 | /** K17 Zen 2 */ 112 | AMD_ZEN2, 113 | /** K19 Zen 3 */ 114 | AMD_ZEN3, 115 | /** K19 Zen 4 */ 116 | AMD_ZEN4 117 | } 118 | -------------------------------------------------------------------------------- /src/test/java/cpufeatures/HelloCpuFeatures.java: -------------------------------------------------------------------------------- 1 | package cpufeatures; 2 | 3 | import cpufeatures.x86.X86Info; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Collection; 7 | import java.util.LinkedHashMap; 8 | import java.util.List; 9 | 10 | public final class HelloCpuFeatures { 11 | private static String format(int value) { 12 | return String.format("%3d (0x%02x)", value, value); 13 | } 14 | 15 | private static List format(Collection> enums) { 16 | return enums.stream() 17 | .map(Enum::name) 18 | .sorted().toList(); 19 | } 20 | 21 | @Test 22 | public void helloWorld() { 23 | CpuFeatures.load(); 24 | 25 | var keys = new LinkedHashMap(); 26 | 27 | CpuArchitecture arch = CpuArchitecture.get(); 28 | switch (arch) { 29 | case AARCH64 -> throw new UnsupportedOperationException(); 30 | case ARM -> throw new UnsupportedOperationException(); 31 | case X86 -> { 32 | X86Info info = X86Info.get(); 33 | keys.put("arch", "x86"); 34 | keys.put("family", format(info.family())); 35 | keys.put("model", format(info.model())); 36 | keys.put("stepping", format(info.stepping())); 37 | keys.put("vendor", info.vendor()); 38 | keys.put("brand", info.brandString()); 39 | keys.put("uarch", info.uarch().name()); 40 | var featureSet = format(info.featureSet()); 41 | keys.put("flags", "(" + featureSet.size() + ") " + featureSet); 42 | } 43 | default -> throw new RuntimeException("Invalid architecture " + arch); 44 | } 45 | 46 | for (var entry : keys.entrySet()) { 47 | System.out.printf("%10s: %s%n", entry.getKey(), entry.getValue()); 48 | } 49 | } 50 | } 51 | --------------------------------------------------------------------------------