From 94ab2ea0f75a5db267c21a1217e5b43cad141e8c Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Tue, 27 Jan 2009 01:42:23 +0000 Subject: [PATCH] Ported to win64. Assembly bits are taken out to external .asm file. Passes tests on Windows 2003 Server x64 git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@53 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- libcpuid/Makefile.x64 | 36 ++++++++++++++++++++++++++++++++++ libcpuid/asm-bits.c | 39 ++++++++++++++++++++++--------------- libcpuid/asm-bits.h | 19 ++++++++++++++++++ libcpuid/libcpuid_util.c | 3 +++ libcpuid/masm-x64.asm | 42 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 libcpuid/Makefile.x64 create mode 100644 libcpuid/masm-x64.asm diff --git a/libcpuid/Makefile.x64 b/libcpuid/Makefile.x64 new file mode 100644 index 0000000..9ee53ba --- /dev/null +++ b/libcpuid/Makefile.x64 @@ -0,0 +1,36 @@ +## Makefile for libcpuid, MSVC compiler, X64 + +all: libcpuid.lib + +ASM = ml64 /nologo +CC = cl.exe /nologo /TC +OPTFLAGS = +DEFINES = /D "VERSION=\"0.1.0\"" +OBJECTS = masm-x64.obj asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj + +libcpuid.lib: $(OBJECTS) + lib /nologo /MACHINE:AMD64 /out:libcpuid.lib $(OBJECTS) bufferoverflowU.lib + +masm-x64.obj: masm-x64.asm + $(ASM) /c masm-x64.asm + +asm-bits.obj: asm-bits.c + $(CC) $(OPTFLAGS) $(DEFINES) /c asm-bits.c + +cpuid_main.obj: cpuid_main.c + $(CC) $(OPTFLAGS) $(DEFINES) /c cpuid_main.c + +libcpuid_util.obj: libcpuid_util.c + $(CC) $(OPTFLAGS) $(DEFINES) /c libcpuid_util.c + +recog_amd.obj: recog_amd.c + $(CC) $(OPTFLAGS) $(DEFINES) /c recog_amd.c + +recog_intel.obj: recog_intel.c + $(CC) $(OPTFLAGS) $(DEFINES) /c recog_intel.c + +rdtsc.obj: rdtsc.c + $(CC) $(OPTFLASG) $(DEFINES) /c rdtsc.c + +clean: + del *.obj libcpuid.lib diff --git a/libcpuid/asm-bits.c b/libcpuid/asm-bits.c index 09a84d7..8bb32c1 100644 --- a/libcpuid/asm-bits.c +++ b/libcpuid/asm-bits.c @@ -29,10 +29,10 @@ int cpuid_exists_by_eflags(void) { -#ifdef __x86_64__ +#ifdef PLATFORM_X64 return 1; /* CPUID is always present on the x86_64 */ #else -# ifdef __GNUC__ +# ifdef COMPILER_GCC int result; __asm __volatile( " pushfl\n" @@ -51,7 +51,7 @@ int cpuid_exists_by_eflags(void) : :"eax", "ecx", "memory"); return (result != 0); # else -# ifdef _MSC_VER +# ifdef COMPILER_MICROSOFT int result; __asm { pushfd @@ -70,15 +70,20 @@ int cpuid_exists_by_eflags(void) return (result != 0); # else # error "Unsupported compiler" -# endif /* _MSC_VER */ -# endif /* __GNUC__ */ -#endif /* __x86_64__ */ +# endif /* COMPILER_MICROSOFT */ +# endif /* COMPILER_GCC */ +#endif /* PLATFORM_X64 */ } +/* + * with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions + * are implemented in separate .asm files. Otherwise, use inline assembly + */ +#ifdef INLINE_ASM_SUPPORTED void exec_cpiud(uint32_t *regs) { -#ifdef __GNUC__ -# ifdef __x86_64__ +#ifdef COMPILER_GCC +# ifdef PLATFORM_X64 __asm __volatile( " push %%rbx\n" " push %%rcx\n" @@ -133,9 +138,9 @@ void exec_cpiud(uint32_t *regs) :"m"(regs) :"memory", "eax" ); -# endif /* __x86_64__ */ +# endif /* COMPILER_GCC */ #else -# ifdef _MSC_VER +# ifdef COMPILER_MICROSOFT __asm { push ebx push ecx @@ -162,15 +167,16 @@ void exec_cpiud(uint32_t *regs) } # else # error "Unsupported compiler" -# endif /* _MSC_VER */ +# endif /* COMPILER_MICROSOFT */ #endif - } +#endif /* INLINE_ASSEMBLY_SUPPORTED */ +#ifdef INLINE_ASM_SUPPORTED void cpu_rdtsc(uint64_t* result) { uint32_t low_part, hi_part; -#ifdef __GNUC__ +#ifdef COMPILER_GCC __asm __volatile ( " rdtsc\n" " mov %%eax, %0\n" @@ -178,7 +184,7 @@ void cpu_rdtsc(uint64_t* result) :"=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx" ); #else -# ifdef _MSC_VER +# ifdef COMPILER_MICROSOFT __asm { rdtsc mov low_part, eax @@ -186,7 +192,8 @@ void cpu_rdtsc(uint64_t* result) }; # else # error "Unsupported compiler" -# endif /* _MSC_VER */ -#endif /* __GNUC__ */ +# endif /* COMPILER_MICROSOFT */ +#endif /* COMPILER_GCC */ *result = (uint64_t)low_part + (((uint64_t) hi_part) << 32); } +#endif /* INLINE_ASM_SUPPORTED */ diff --git a/libcpuid/asm-bits.h b/libcpuid/asm-bits.h index e486f56..d72fab4 100644 --- a/libcpuid/asm-bits.h +++ b/libcpuid/asm-bits.h @@ -27,6 +27,25 @@ #define __ASM_BITS_H__ #include "libcpuid.h" +/* Determine Compiler: */ +#ifdef _MSC_VER +# define COMPILER_MICROSOFT +#else +# define COMPILER_GCC +#endif + +/* Determine Platform */ +#if defined(__x86_64__) || defined(_M_AMD64) +# define PLATFORM_X64 +#else +# define PLATFORM_X86 +#endif + +/* Under Windows/AMD64 with MSVC, inline assembly isn't supported */ +#if defined(COMPILER_GCC) || defined(PLATFORM_X86) +# define INLINE_ASM_SUPPORTED +#endif + int cpuid_exists_by_eflags(void); void exec_cpiud(uint32_t *regs); diff --git a/libcpuid/libcpuid_util.c b/libcpuid/libcpuid_util.c index 7465233..979383f 100644 --- a/libcpuid/libcpuid_util.c +++ b/libcpuid/libcpuid_util.c @@ -48,6 +48,9 @@ static void default_warn(const char *msg) libcpuid_warn_fn_t _warn_fun = default_warn; +#if defined(_MSC_VER) && defined(_M_AMD64) +# define vsnprintf _vsnprintf +#endif void warnf(const char* format, ...) { char buff[1024]; diff --git a/libcpuid/masm-x64.asm b/libcpuid/masm-x64.asm new file mode 100644 index 0000000..69bc933 --- /dev/null +++ b/libcpuid/masm-x64.asm @@ -0,0 +1,42 @@ + +.code +; procedure exec_cpuid +; Signature: void exec_cpiud(uint32_t *regs) +exec_cpuid Proc + push rbx + push rcx + push rdx + push rdi + + mov rdi, rcx + + mov eax, [rdi] + mov ebx, [rdi+4] + mov ecx, [rdi+8] + mov edx, [rdi+12] + + cpuid + + mov [rdi], eax + mov [rdi+4], ebx + mov [rdi+8], ecx + mov [rdi+12], edx + pop rdi + pop rdx + pop rcx + pop rbx + ret +exec_cpuid endp + +; procedure cpu_rdtsc +; Signature: void cpu_rdtsc(uint64_t *result) +cpu_rdtsc Proc + push rdx + rdtsc + mov [rcx], eax + mov [rcx+4], edx + pop rdx + ret +cpu_rdtsc endp + +END