Wine lacks code to detect the CPU for FreeBSD, which causes problems with many installers. I wrote a patch some time ago which solved it for me, but I didn't submit due to not really knowing if it was right. In particular I wasn't sure if PF_XMMI_INSTRUCTIONS_AVAILABLE meant SSE or SSE2 (the commented OS check is for sse1). It also hasn't been really tested on any system but my Athlon. Anyway, if someone would like to review and possibly commit it, that would be great. I'm not subscribed to the list, so CC me on replies. I don't use wine because it hangs whenever I try to run anything I'm interested in (bug 1215, where did the description go?) -- Eric Anholt eta@lclark.edu http://people.freebsd.org/~anholt/ anholt@FreeBSD.org
--- misc/cpu.c.orig Tue Jan 7 12:36:21 2003 +++ misc/cpu.c Mon Feb 10 20:43:14 2003 @@ -37,6 +37,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg); +#ifdef __FreeBSD__ +#include <sys/sysctl.h> +#include <stdlib.h> + +#define AUTH 0x68747541 /* "Auth" */ +#define ENTI 0x69746e65 /* "enti" */ +#define CAMD 0x444d4163 /* "cAMD" */ + +/* Calls cpuid with an eax of 'ax' and returns the 16 bytes in *p + * We are compiled with -fPIC, so we can't clobber ebx. + */ +static void +do_cpuid(int ax, int *p) +{ + __asm __volatile("pushl %%ebx\n\t" + "cpuid\n\t" + "movl %%ebx, %%esi\n\t" + "popl %%ebx" + : "=a" (p[0]), "=S" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax)); +} + +/* From xf86info havecpuid.c 1.11 */ +static int +have_cpuid() +{ + unsigned int f1, f2; + __asm__ volatile("pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (0x00200000)); + return ((f1^f2) & 0x00200000) != 0; +} +#endif + static BYTE PF[64] = {0,}; static void create_registry_keys( const SYSTEM_INFO *info ) @@ -268,7 +311,61 @@ fclose (f); } memcpy(si,&cachedsi,sizeof(*si)); -#else /* linux */ +#elif defined(__FreeBSD__) + { + unsigned int regs[4], regs2[4]; + int ret, len, num; + if (!have_cpuid()) + regs[0] = 0; /* No cpuid support -- skip the rest */ + else + do_cpuid(0x00000000, regs); /* get standard cpuid level and vendor name */ + if (regs[0]>=0x00000001) { /* Check for supported cpuid version */ + do_cpuid(0x00000001, regs2); /* get cpu features */ + switch ((regs2[0] >> 8)&0xf) { /* cpu family */ + case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386; + cachedsi.wProcessorLevel = 3; + break; + case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486; + cachedsi.wProcessorLevel = 4; + break; + case 5: + case 6: /* PPro/2/3 has same info as P1 */ + cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM; + cachedsi.wProcessorLevel = 5; + break; + default: + FIXME("unknown cpu family %d, please report! (-> setting to 386)\n", \ + (regs2[0] >> 8)&0xf); + break; + } + PF[PF_FLOATING_POINT_EMULATED] = !(regs2[3] & 1); + PF[PF_RDTSC_INSTRUCTION_AVAILABLE] = (regs2[3] & (1 << 4 )) >> 4; + PF[PF_COMPARE_EXCHANGE_DOUBLE] = (regs2[3] & (1 << 8 )) >> 8; + PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = (regs2[3] & (1 << 23)) >> 23; + /* Check for OS support of SSE -- Is this used, and should it be sse1 or sse2? */ + /*len = sizeof(num); + ret = sysctlbyname("hw.instruction_sse", &num, &len, NULL, 0); + if (!ret) + PF[PF_XMMI_INSTRUCTIONS_AVAILABLE] = num;*/ + + if (regs[1] == AUTH && + regs[3] == ENTI && + regs[2] == CAMD) { + do_cpuid(0x80000000, regs); /* get vendor cpuid level */ + if (regs[0]>=0x80000001) { + do_cpuid(0x80000001, regs2); /* get vendor features */ + PF[PF_AMD3D_INSTRUCTIONS_AVAILABLE] = + (regs2[3] & (1 << 31 )) >> 31; + } + } + } + len = sizeof(num); + ret = sysctlbyname("hw.ncpu", &num, &len, NULL, 0); + if (!ret) + cachedsi.dwNumberOfProcessors = num; + } + memcpy(si,&cachedsi,sizeof(*si)); +#else /* linux || __FreeBSD__*/ FIXME("not yet supported on this system\n"); #endif /* !linux */ TRACE("<- CPU arch %d, res'd %d, pagesize %ld, minappaddr %p, maxappaddr %p,"