Add Windows support and windows-amd64/windows-i386 release binaries
The x86-64 kernels were written to the System V ABI only; on Windows's different calling convention they silently read garbage args and ran in near-constant time regardless of iteration count. Each public kernel now gets a small ABI-translating thunk (WIN64_THUNK) on Windows so the kernel bodies stay single-source. i386 also needed underscore-prefixed symbol names to match Windows's cdecl convention. Verified end-to-end under Wine, including determinism across repeated runs. Also fixes CPU-core detection (sysconf isn't available under MinGW) and adds memory/CPU-brand detection for the Windows system-info banner.
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
|
||||
.intel_syntax noprefix
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
# define SYM(name) _##name
|
||||
#else
|
||||
# define SYM(name) name
|
||||
|
||||
+74
-2
@@ -20,6 +20,14 @@
|
||||
* integer args rdi, rsi, rdx, rcx, r8, r9 (return in rax)
|
||||
* callee-saved rbx, rbp, r12, r13, r14, r15 (saved when used)
|
||||
* all of xmm0-15 are caller-saved, so no vector register need be preserved.
|
||||
*
|
||||
* Windows uses a different AMD64 ABI (integer args in rcx, rdx, r8, r9; rdi,
|
||||
* rsi and xmm6-15 callee-saved instead of caller-saved). Every kernel body
|
||||
* below is written once, unchanged, to the System V convention documented
|
||||
* above. On Windows each public name becomes a thin trampoline (WIN64_THUNK)
|
||||
* around a same-named `_sysv` implementation: it saves the registers that
|
||||
* Windows callers expect preserved, remaps args into System V registers, and
|
||||
* calls straight through - so the hot kernel bodies never need two versions.
|
||||
*/
|
||||
|
||||
.intel_syntax noprefix
|
||||
@@ -30,8 +38,14 @@
|
||||
# define SYM(name) name
|
||||
#endif
|
||||
|
||||
#define FN_BEGIN(name) FN_BEGIN_ASM SYM(name)
|
||||
#define FN_END(name) FN_END_ASM SYM(name)
|
||||
#if defined(_WIN32)
|
||||
# define ENTRY(name) SYM(name##_sysv)
|
||||
#else
|
||||
# define ENTRY(name) SYM(name)
|
||||
#endif
|
||||
|
||||
#define FN_BEGIN(name) FN_BEGIN_ASM ENTRY(name)
|
||||
#define FN_END(name) FN_END_ASM ENTRY(name)
|
||||
|
||||
.macro FN_BEGIN_ASM name
|
||||
.p2align 4
|
||||
@@ -48,6 +62,52 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* Windows x64 ABI trampoline: save the callee-saved registers System V would
|
||||
* leave to the caller (rdi, rsi, xmm6-15), remap up to 4 integer/pointer
|
||||
* args from the Windows positions (rcx, rdx, r8, r9) into System V (rdi,
|
||||
* rsi, rdx, rcx), call the `_sysv` implementation, then restore. Every
|
||||
* kernel here takes at most 4 integer/pointer args and returns a uint64_t in
|
||||
* rax (identical in both ABIs), so one thunk shape covers all nine. */
|
||||
.macro WIN64_THUNK pubname, implname
|
||||
.p2align 4
|
||||
.globl \pubname
|
||||
\pubname:
|
||||
push rdi
|
||||
push rsi
|
||||
sub rsp, 0xA8 /* 10 xmm slots + 8 pad, keeps rsp 16-aligned for the call */
|
||||
movdqu [rsp + 0x00], xmm6
|
||||
movdqu [rsp + 0x10], xmm7
|
||||
movdqu [rsp + 0x20], xmm8
|
||||
movdqu [rsp + 0x30], xmm9
|
||||
movdqu [rsp + 0x40], xmm10
|
||||
movdqu [rsp + 0x50], xmm11
|
||||
movdqu [rsp + 0x60], xmm12
|
||||
movdqu [rsp + 0x70], xmm13
|
||||
movdqu [rsp + 0x80], xmm14
|
||||
movdqu [rsp + 0x90], xmm15
|
||||
mov rdi, rcx
|
||||
mov rsi, rdx
|
||||
mov rdx, r8
|
||||
mov rcx, r9
|
||||
call \implname
|
||||
movdqu xmm6, [rsp + 0x00]
|
||||
movdqu xmm7, [rsp + 0x10]
|
||||
movdqu xmm8, [rsp + 0x20]
|
||||
movdqu xmm9, [rsp + 0x30]
|
||||
movdqu xmm10, [rsp + 0x40]
|
||||
movdqu xmm11, [rsp + 0x50]
|
||||
movdqu xmm12, [rsp + 0x60]
|
||||
movdqu xmm13, [rsp + 0x70]
|
||||
movdqu xmm14, [rsp + 0x80]
|
||||
movdqu xmm15, [rsp + 0x90]
|
||||
add rsp, 0xA8
|
||||
pop rsi
|
||||
pop rdi
|
||||
ret
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* ===================================================================
|
||||
@@ -991,6 +1051,18 @@ FN_BEGIN(fb_chase)
|
||||
ret
|
||||
FN_END(fb_chase)
|
||||
|
||||
#if defined(_WIN32)
|
||||
.text
|
||||
WIN64_THUNK SYM(fb_int_math), SYM(fb_int_math_sysv)
|
||||
WIN64_THUNK SYM(fb_fp_math), SYM(fb_fp_math_sysv)
|
||||
WIN64_THUNK SYM(fb_primes), SYM(fb_primes_sysv)
|
||||
WIN64_THUNK SYM(fb_simd), SYM(fb_simd_sysv)
|
||||
WIN64_THUNK SYM(fb_compress), SYM(fb_compress_sysv)
|
||||
WIN64_THUNK SYM(fb_chacha20), SYM(fb_chacha20_sysv)
|
||||
WIN64_THUNK SYM(fb_physics), SYM(fb_physics_sysv)
|
||||
WIN64_THUNK SYM(fb_sort), SYM(fb_sort_sysv)
|
||||
WIN64_THUNK SYM(fb_chase), SYM(fb_chase_sysv)
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__)
|
||||
.section .note.GNU-stack, "", @progbits
|
||||
|
||||
+41
-1
@@ -37,12 +37,15 @@
|
||||
# include <sys/sysctl.h>
|
||||
# include <mach/mach_time.h>
|
||||
#endif
|
||||
#if defined(_WIN32) && (defined(__i386__) || defined(__x86_64__))
|
||||
# include <cpuid.h>
|
||||
#endif
|
||||
|
||||
/* Change this at build time with -DFB_API_BASE_URL=\"https://host\". */
|
||||
#ifndef FB_API_BASE_URL
|
||||
# define FB_API_BASE_URL "https://fossbench.net"
|
||||
#endif
|
||||
#define FB_VERSION "0.1.5"
|
||||
#define FB_VERSION "0.1.5-hotfix1"
|
||||
|
||||
/* ---------- platform identification (for the banner only) ---------- */
|
||||
|
||||
@@ -429,6 +432,37 @@ static void detect_system_info(struct system_info *info)
|
||||
struct utsname u; if (uname(&u) == 0)
|
||||
snprintf(info->operating_system, sizeof(info->operating_system), "macOS %s", u.release);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
{
|
||||
MEMORYSTATUSEX ms;
|
||||
ms.dwLength = sizeof(ms);
|
||||
if (GlobalMemoryStatusEx(&ms))
|
||||
info->memory_mb = (long)(ms.ullTotalPhys / 1024 / 1024);
|
||||
}
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
{
|
||||
/* CPUID leaves 0x80000002-0x80000004 return the 48-byte brand
|
||||
* string in eax:ebx:ecx:edx, twelve bytes per leaf. */
|
||||
unsigned eax, ebx, ecx, edx, max_ext;
|
||||
char brand[49];
|
||||
int i;
|
||||
__cpuid(0x80000000, eax, ebx, ecx, edx);
|
||||
max_ext = eax;
|
||||
if (max_ext >= 0x80000004) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
__cpuid(0x80000002u + (unsigned)i, eax, ebx, ecx, edx);
|
||||
memcpy(brand + i * 16 + 0, &eax, 4);
|
||||
memcpy(brand + i * 16 + 4, &ebx, 4);
|
||||
memcpy(brand + i * 16 + 8, &ecx, 4);
|
||||
memcpy(brand + i * 16 + 12, &edx, 4);
|
||||
}
|
||||
brand[48] = '\0';
|
||||
trim(brand);
|
||||
if (brand[0])
|
||||
snprintf(info->cpu, sizeof(info->cpu), "%s", brand);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1027,7 +1061,13 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
long n = (long)si.dwNumberOfProcessors;
|
||||
#else
|
||||
long n = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#endif
|
||||
g_ncores = n > 0 ? n : 1;
|
||||
}
|
||||
detect_system_info(&system_info);
|
||||
|
||||
Reference in New Issue
Block a user