Skip to content

Instantly share code, notes, and snippets.

@KalleZ
Created December 30, 2018 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KalleZ/32eb26c5d0b153d9776e7cfc35e49417 to your computer and use it in GitHub Desktop.
Save KalleZ/32eb26c5d0b153d9776e7cfc35e49417 to your computer and use it in GitHub Desktop.
diff --git a/.gitignore b/.gitignore
index c0e059714d..e0b5b7211e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -225,6 +225,8 @@ php
/main/config.w32.h
/win32/build/deplister.exe
/win32/build/deplister.obj
+/win32/build/cpuinfo.exe
+/win32/build/cpuinfo.obj
/win32/*.aps
/win32/*.positions
/win32/*.suo
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 3d1fa21b56..dd2d390244 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -3291,6 +3291,24 @@ function toolset_setup_intrinsic_cflags()
PHP_NATIVE_INTRINSICS = default_enabled;
}
+ if ("native" == PHP_NATIVE_INTRINSICS) {
+ var native_intrin = new Array();
+ var exe = compile_build_tool('win32\\build\\cpuinfo.cpp', '/EHsc');
+
+ for (var x = 0; x < scale.length; ++x) {
+ var test = trim(execute('cpuinfo ' + scale[x].replace('.', '')).substring(scale[x].length));
+
+ if (test == 'yes') {
+ native_intrin[native_intrin.length] = scale[x];
+ }
+ }
+
+ //FSO.DeleteFile(exe);
+ //FSO.DeleteFile(exe.replace('exe', 'obj'));
+
+ PHP_NATIVE_INTRINSICS = (native_intrin.length ? native_intrin.join(',') : default_enabled);
+ }
+
if ("all" == PHP_NATIVE_INTRINSICS) {
var list = (new VBArray(avail.Keys())).toArray();
@@ -3705,3 +3723,24 @@ function setup_verbosity()
CMD_MOD2 = "@";
}
}
+
+function compile_build_tool(tool, flags)
+{
+ var exe, log;
+
+ exe = tool.split('.');
+ exe[exe.length - 1] = '';
+ exe = exe.join('.') + 'exe';
+ exe = exe.split('\\');
+ exe = exe[exe.length - 1];
+
+ MESSAGE('Compiling build tool: ' + tool);
+
+ log = execute(PATH_PROG('cl', null) + ' "' + tool + '"' + (flags ? ' ' + flags : ''));
+
+ if (!FSO.FileExists(exe)) {
+ ERROR(log);
+ }
+
+ return exe;
+}
\ No newline at end of file
diff --git a/win32/build/cpuinfo.cpp b/win32/build/cpuinfo.cpp
new file mode 100644
index 0000000000..b8e16515d4
--- /dev/null
+++ b/win32/build/cpuinfo.cpp
@@ -0,0 +1,549 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2018 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Kalle Sommer Nielsen <kalle@php.net> |
+ | Microsoft (MSDN Documentation) |
+ +----------------------------------------------------------------------+
+ */
+
+#include <iostream>
+#include <vector>
+#include <bitset>
+#include <array>
+#include <string>
+#include <intrin.h>
+
+using namespace std;
+
+class PHP_Intrin
+{
+ class PHP_Intrin_Intern;
+
+public:
+ static string getVendor(void)
+ {
+ return PHP_Intrin::CPU.cpuVendor;
+ }
+
+ static string getBrand(void)
+ {
+ return PHP_Intrin::CPU.cpuBrand;
+ }
+
+ static bool isSSE3(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[0];
+ }
+
+ static bool isPCLMULQDQ(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[1];
+ }
+
+ static bool isMONITOR(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[3];
+ }
+
+ static bool isSSSE3(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[9];
+ }
+
+ static bool isFMA(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[12];
+ }
+
+ static bool isCMPXCHG16B(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[13];
+ }
+
+ static bool isSSE41(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[19];
+ }
+
+ static bool isSSE42(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[20];
+ }
+
+ static bool isMOVBE(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[22];
+ }
+
+ static bool isPOPCNT(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[23];
+ }
+
+ static bool isAES(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[25];
+ }
+
+ static bool isXSAVE(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[26];
+ }
+
+ static bool isOSXSAVE(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[27];
+ }
+
+ static bool isAVX(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[28];
+ }
+
+ static bool isF16C(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[29];
+ }
+
+ static bool isRDRAND(void)
+ {
+ return PHP_Intrin::CPU.F_1_ECX[30];
+ }
+
+ static bool isMSR(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[5];
+ }
+
+ static bool isCX8(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[8];
+ }
+
+ static bool isSEP(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[11];
+ }
+
+ static bool isCMOV(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[15];
+ }
+
+ static bool isCLFSH(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[19];
+ }
+
+ static bool isMMX(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[23];
+ }
+
+ static bool isFXSR(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[24];
+ }
+
+ static bool isSSE(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[25];
+ }
+
+ static bool isSSE2(void)
+ {
+ return PHP_Intrin::CPU.F_1_EDX[26];
+ }
+
+ static bool isFSGSBASE(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[0];
+ }
+
+ static bool isBMI1(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[3];
+ }
+
+ static bool isHLE(void)
+ {
+ return PHP_Intrin::CPU.isIntel && PHP_Intrin::CPU.F_7_EBX[4];
+ }
+
+ static bool isAVX2(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[5];
+ }
+
+ static bool isBMI2(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[8];
+ }
+
+ static bool isERMS(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[9];
+ }
+
+ static bool isINVPCID(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[10];
+ }
+
+ static bool isRTM(void)
+ {
+ return PHP_Intrin::CPU.isIntel && PHP_Intrin::CPU.F_7_EBX[11];
+ }
+
+ static bool isAVX512F(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[16];
+ }
+
+ static bool isRDSEED(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[18];
+ }
+
+ static bool isADX(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[19];
+ }
+
+ static bool isAVX512PF(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[26];
+ }
+
+ static bool isAVX512ER(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[27];
+ }
+
+ static bool isAVX512CD(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[28];
+ }
+
+ static bool isSHA(void)
+ {
+ return PHP_Intrin::CPU.F_7_EBX[29];
+ }
+
+ static bool isPREFETCHWT1(void)
+ {
+ return PHP_Intrin::CPU.F_7_ECX[0];
+ }
+
+ static bool isLAHF(void)
+ {
+ return PHP_Intrin::CPU.F_81_ECX[0];
+ }
+
+ static bool isLZCNT(void)
+ {
+ return PHP_Intrin::CPU.isIntel && PHP_Intrin::CPU.F_81_ECX[5];
+ }
+
+ static bool isABM(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_ECX[5];
+ }
+
+ static bool isSSE4A(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_ECX[6];
+ }
+
+ static bool isXOP(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_ECX[11];
+ }
+
+ static bool isTBM(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_ECX[21];
+ }
+
+ static bool isSYSCALL(void)
+ {
+ return PHP_Intrin::CPU.isIntel && PHP_Intrin::CPU.F_81_EDX[11];
+ }
+
+ static bool isMMXEXT(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_EDX[22];
+ }
+
+ static bool isRDTSCP(void)
+ {
+ return PHP_Intrin::CPU.isIntel && PHP_Intrin::CPU.F_81_EDX[27];
+ }
+
+ static bool is3DNOWEXT(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_EDX[30];
+ }
+
+ static bool is3DNOW(void)
+ {
+ return PHP_Intrin::CPU.isAMD && PHP_Intrin::CPU.F_81_EDX[31];
+ }
+
+private:
+ static const PHP_Intrin_Intern CPU;
+
+ class PHP_Intrin_Intern
+ {
+ public:
+ int numIds;
+ int numExIds;
+
+ string cpuVendor;
+ string cpuBrand;
+
+ bool isIntel;
+ bool isAMD;
+
+ bitset<32> F_1_ECX;
+ bitset<32> F_1_EDX;
+ bitset<32> F_7_EBX;
+ bitset<32> F_7_ECX;
+ bitset<32> F_81_ECX;
+ bitset<32> F_81_EDX;
+
+ vector<array<int, 4>> data;
+ vector<array<int, 4>> exData;
+
+ PHP_Intrin_Intern()
+ {
+ this->numIds = 0;
+ this->numExIds = 0;
+
+ this->isIntel = false;
+ this->isAMD = false;
+
+ this->F_1_ECX = 0;
+ this->F_1_EDX = 0;
+ this->F_7_EBX = 0;
+ this->F_7_ECX = 0;
+ this->F_81_ECX = 0;
+ this->F_81_EDX = 0;
+
+ array<int, 4> cpuInfo;
+
+ __cpuid(cpuInfo.data(), 0);
+ this->numIds = cpuInfo[0];
+
+ for (int i = 0; i <= this->numIds; ++i)
+ {
+ __cpuidex(cpuInfo.data(), i, 0);
+ this->data.push_back(cpuInfo);
+ }
+
+ char vendor[0x20];
+ memset(vendor, 0, sizeof(vendor));
+
+ *reinterpret_cast<int *>(vendor) = this->data[0][1];
+ *reinterpret_cast<int *>(vendor + 4) = this->data[0][3];
+ *reinterpret_cast<int *>(vendor + 8) = this->data[0][2];
+
+ this->cpuVendor = vendor;
+
+ if (this->cpuVendor == "GenuineIntel")
+ {
+ this->isIntel = true;
+ }
+ else if (this->cpuVendor == "AuthenticAMD")
+ {
+ this->isAMD = true;
+ }
+
+ if (this->numIds >= 1)
+ {
+ this->F_1_ECX = this->data[1][2];
+ this->F_1_EDX = this->data[1][3];
+ }
+
+ if (this->numIds >= 7)
+ {
+ this->F_7_EBX = this->data[7][1];
+ this->F_7_ECX = this->data[7][2];
+ }
+
+ __cpuid(cpuInfo.data(), 0x80000000);
+ this->numExIds = cpuInfo[0];
+
+ char brand[0x40];
+ memset(brand, 0, sizeof(brand));
+
+ for (int i = 0x80000000; i <= this->numExIds; ++i)
+ {
+ __cpuidex(cpuInfo.data(), i, 0);
+ this->exData.push_back(cpuInfo);
+ }
+
+ if (this->numExIds >= 0x80000001)
+ {
+ this->F_81_ECX = this->exData[1][2];
+ this->F_81_EDX = this->exData[1][3];
+ }
+
+ if (this->numExIds >= 0x80000004)
+ {
+ memcpy(brand, this->exData[2].data(), sizeof(cpuInfo));
+ memcpy(brand + 16, this->exData[3].data(), sizeof(cpuInfo));
+ memcpy(brand + 32, this->exData[4].data(), sizeof(cpuInfo));
+
+ this->cpuBrand = brand;
+ }
+ }
+ };
+};
+
+#define SIMPLE_SUPPORT(feature, call) \
+ if (strcmp(feature, argv[1]) == 0) { \
+ simple_support(call); \
+ return 0; \
+ }
+
+const PHP_Intrin::PHP_Intrin_Intern PHP_Intrin::CPU;
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1) {
+ cout << argv[1] << endl;
+
+ auto simple_support = [](bool supported)
+ {
+ cout << (supported ? "yes" : "no") << endl;
+ };
+
+ SIMPLE_SUPPORT("3dnow", PHP_Intrin::is3DNOW())
+ SIMPLE_SUPPORT("3dnowext", PHP_Intrin::is3DNOWEXT())
+ SIMPLE_SUPPORT("abm", PHP_Intrin::isABM())
+ SIMPLE_SUPPORT("adx", PHP_Intrin::isADX())
+ SIMPLE_SUPPORT("aes", PHP_Intrin::isAES())
+ SIMPLE_SUPPORT("avx", PHP_Intrin::isAVX())
+ SIMPLE_SUPPORT("avx2", PHP_Intrin::isAVX2())
+ SIMPLE_SUPPORT("avx512cd", PHP_Intrin::isAVX512CD())
+ SIMPLE_SUPPORT("avx512er", PHP_Intrin::isAVX512ER())
+ SIMPLE_SUPPORT("avx512f", PHP_Intrin::isAVX512F())
+ SIMPLE_SUPPORT("avx512pf", PHP_Intrin::isAVX512PF())
+ SIMPLE_SUPPORT("bmi1", PHP_Intrin::isBMI1())
+ SIMPLE_SUPPORT("bmi2", PHP_Intrin::isBMI2())
+ SIMPLE_SUPPORT("clfsh", PHP_Intrin::isCLFSH())
+ SIMPLE_SUPPORT("cmpxchg16b", PHP_Intrin::isCMPXCHG16B())
+ SIMPLE_SUPPORT("cx8", PHP_Intrin::isCX8())
+ SIMPLE_SUPPORT("erms", PHP_Intrin::isERMS())
+ SIMPLE_SUPPORT("f16c", PHP_Intrin::isF16C())
+ SIMPLE_SUPPORT("fma", PHP_Intrin::isFMA())
+ SIMPLE_SUPPORT("fsgsbase", PHP_Intrin::isFSGSBASE())
+ SIMPLE_SUPPORT("fxsr", PHP_Intrin::isFXSR())
+ SIMPLE_SUPPORT("hle", PHP_Intrin::isHLE())
+ SIMPLE_SUPPORT("invpcid", PHP_Intrin::isINVPCID())
+ SIMPLE_SUPPORT("lahf", PHP_Intrin::isLAHF())
+ SIMPLE_SUPPORT("lzcnt", PHP_Intrin::isLZCNT())
+ SIMPLE_SUPPORT("mmx", PHP_Intrin::isMMX())
+ SIMPLE_SUPPORT("mmxext", PHP_Intrin::isMMXEXT())
+ SIMPLE_SUPPORT("monitor", PHP_Intrin::isMONITOR())
+ SIMPLE_SUPPORT("movbe", PHP_Intrin::isMOVBE())
+ SIMPLE_SUPPORT("msr", PHP_Intrin::isMSR())
+ SIMPLE_SUPPORT("osxsave", PHP_Intrin::isOSXSAVE())
+ SIMPLE_SUPPORT("pclmulqdq", PHP_Intrin::isPCLMULQDQ())
+ SIMPLE_SUPPORT("popcnt", PHP_Intrin::isPOPCNT())
+ SIMPLE_SUPPORT("prefetchwt1", PHP_Intrin::isPREFETCHWT1())
+ SIMPLE_SUPPORT("rdrand", PHP_Intrin::isRDRAND())
+ SIMPLE_SUPPORT("rdseed", PHP_Intrin::isRDSEED())
+ SIMPLE_SUPPORT("rdtscp", PHP_Intrin::isRDTSCP())
+ SIMPLE_SUPPORT("rtm", PHP_Intrin::isRTM())
+ SIMPLE_SUPPORT("sep", PHP_Intrin::isSEP())
+ SIMPLE_SUPPORT("sha", PHP_Intrin::isSHA())
+ SIMPLE_SUPPORT("sse", PHP_Intrin::isSSE())
+ SIMPLE_SUPPORT("sse2", PHP_Intrin::isSSE2())
+ SIMPLE_SUPPORT("sse3", PHP_Intrin::isSSE3())
+ SIMPLE_SUPPORT("sse41", PHP_Intrin::isSSE41())
+ SIMPLE_SUPPORT("sse42", PHP_Intrin::isSSE42())
+ SIMPLE_SUPPORT("sse4a", PHP_Intrin::isSSE4A())
+ SIMPLE_SUPPORT("ssse3", PHP_Intrin::isSSSE3())
+ SIMPLE_SUPPORT("syscall", PHP_Intrin::isSYSCALL())
+ SIMPLE_SUPPORT("tbm", PHP_Intrin::isTBM())
+ SIMPLE_SUPPORT("xop", PHP_Intrin::isXOP())
+ SIMPLE_SUPPORT("xsave", PHP_Intrin::isXSAVE())
+
+ return 0;
+ }
+
+ auto support_message = [](string feature, bool supported)
+ {
+ cout << feature << (supported ? " supported" : " NOT supported") << endl;
+ };
+
+ cout << PHP_Intrin::getVendor() << endl;
+ cout << PHP_Intrin::getBrand() << endl;
+
+ support_message("3DNOW", PHP_Intrin::is3DNOW());
+ support_message("3DNOWEXT", PHP_Intrin::is3DNOWEXT());
+ support_message("ABM", PHP_Intrin::isABM());
+ support_message("ADX", PHP_Intrin::isADX());
+ support_message("AES", PHP_Intrin::isAES());
+ support_message("AVX", PHP_Intrin::isAVX());
+ support_message("AVX2", PHP_Intrin::isAVX2());
+ support_message("AVX512CD", PHP_Intrin::isAVX512CD());
+ support_message("AVX512ER", PHP_Intrin::isAVX512ER());
+ support_message("AVX512F", PHP_Intrin::isAVX512F());
+ support_message("AVX512PF", PHP_Intrin::isAVX512PF());
+ support_message("BMI1", PHP_Intrin::isBMI1());
+ support_message("BMI2", PHP_Intrin::isBMI2());
+ support_message("CLFSH", PHP_Intrin::isCLFSH());
+ support_message("CMPXCHG16B", PHP_Intrin::isCMPXCHG16B());
+ support_message("CX8", PHP_Intrin::isCX8());
+ support_message("ERMS", PHP_Intrin::isERMS());
+ support_message("F16C", PHP_Intrin::isF16C());
+ support_message("FMA", PHP_Intrin::isFMA());
+ support_message("FSGSBASE", PHP_Intrin::isFSGSBASE());
+ support_message("FXSR", PHP_Intrin::isFXSR());
+ support_message("HLE", PHP_Intrin::isHLE());
+ support_message("INVPCID", PHP_Intrin::isINVPCID());
+ support_message("LAHF", PHP_Intrin::isLAHF());
+ support_message("LZCNT", PHP_Intrin::isLZCNT());
+ support_message("MMX", PHP_Intrin::isMMX());
+ support_message("MMXEXT", PHP_Intrin::isMMXEXT());
+ support_message("MONITOR", PHP_Intrin::isMONITOR());
+ support_message("MOVBE", PHP_Intrin::isMOVBE());
+ support_message("MSR", PHP_Intrin::isMSR());
+ support_message("OSXSAVE", PHP_Intrin::isOSXSAVE());
+ support_message("PCLMULQDQ", PHP_Intrin::isPCLMULQDQ());
+ support_message("POPCNT", PHP_Intrin::isPOPCNT());
+ support_message("PREFETCHWT1", PHP_Intrin::isPREFETCHWT1());
+ support_message("RDRAND", PHP_Intrin::isRDRAND());
+ support_message("RDSEED", PHP_Intrin::isRDSEED());
+ support_message("RDTSCP", PHP_Intrin::isRDTSCP());
+ support_message("RTM", PHP_Intrin::isRTM());
+ support_message("SEP", PHP_Intrin::isSEP());
+ support_message("SHA", PHP_Intrin::isSHA());
+ support_message("SSE", PHP_Intrin::isSSE());
+ support_message("SSE2", PHP_Intrin::isSSE2());
+ support_message("SSE3", PHP_Intrin::isSSE3());
+ support_message("SSE4.1", PHP_Intrin::isSSE41());
+ support_message("SSE4.2", PHP_Intrin::isSSE42());
+ support_message("SSE4a", PHP_Intrin::isSSE4A());
+ support_message("SSSE3", PHP_Intrin::isSSSE3());
+ support_message("SYSCALL", PHP_Intrin::isSYSCALL());
+ support_message("TBM", PHP_Intrin::isTBM());
+ support_message("XOP", PHP_Intrin::isXOP());
+ support_message("XSAVE", PHP_Intrin::isXSAVE());
+
+ return 0;
+}
\ No newline at end of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment