diff --git a/source/lib/sysdep/ia32.asm b/source/lib/sysdep/ia32.asm index 47109e5a0d..1a14a5ed44 100644 --- a/source/lib/sysdep/ia32.asm +++ b/source/lib/sysdep/ia32.asm @@ -232,14 +232,17 @@ __SECT__ ; extern "C" bool __cdecl ia32_cpuid(u32 func, u32* regs) global _ia32_cpuid _ia32_cpuid: + ; note: must preserve before .one_time_init because it does cpuid + push ebx + push edi + +.retry: ; if unknown, detect; if not available, fail. xor eax, eax ; return val on failure cmp [cpuid_available], eax jl .one_time_init je .ret - push ebx - push edi mov ecx, [esp+8+4+0] ; func mov edi, [esp+8+4+4] ; -> regs @@ -291,7 +294,7 @@ _ia32_cpuid: cpuid mov [max_ext_func], eax - jmp _ia32_cpuid ; now try again + jmp .retry diff --git a/source/lib/sysdep/ia32.cpp b/source/lib/sysdep/ia32.cpp index 6f5ef783cf..d4d3a18b28 100755 --- a/source/lib/sysdep/ia32.cpp +++ b/source/lib/sysdep/ia32.cpp @@ -312,11 +312,13 @@ static void get_cpu_type() const uint family = bits(regs[EAX], 8, 11); // get brand string (if available) + // note: ia32_cpuid writes 4 u32s directly to cpu_type - + // be very careful with pointer arithmetic! u32* cpu_type_u32 = (u32*)cpu_type; bool have_brand_string = false; if(ia32_cpuid(0x80000002, cpu_type_u32+0 ) && - ia32_cpuid(0x80000003, cpu_type_u32+16) && - ia32_cpuid(0x80000004, cpu_type_u32+32)) + ia32_cpuid(0x80000003, cpu_type_u32+4) && + ia32_cpuid(0x80000004, cpu_type_u32+8)) have_brand_string = true;