From: Julian Seward Date: Mon, 8 Aug 2005 00:35:46 +0000 (+0000) Subject: Make Valgrind work again on x86 CPUs which don't have SSE. This is a X-Git-Tag: svn/VALGRIND_3_1_0~652 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=782965122b4463f35cfd99cdbf91e6265f799963;p=thirdparty%2Fvalgrind.git Make Valgrind work again on x86 CPUs which don't have SSE. This is a bit of an ugly hack (see comments in m_machine.c) which is suitable for merging into 3_0_BRANCH, but should be cleaned up once that's done. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4339 --- diff --git a/coregrind/m_dispatch/dispatch-x86.S b/coregrind/m_dispatch/dispatch-x86.S index 6d20d4c36c..5b751c8ebd 100644 --- a/coregrind/m_dispatch/dispatch-x86.S +++ b/coregrind/m_dispatch/dispatch-x86.S @@ -71,10 +71,12 @@ VG_(run_innerloop): /* set host SSE control word to the default mode expected by VEX-generated code. */ + cmpl $0, VG_(have_mxcsr_x86) + jz L1 pushl $0x1F80 ldmxcsr (%esp) addl $4, %esp - +L1: /* set dir flag to known value */ cld @@ -136,13 +138,15 @@ run_innerloop_exit: cmpl $0x027F, (%esp) popl %esi /* get rid of the word without trashing %eflags */ jnz invariant_violation + cmpl $0, VG_(have_mxcsr_x86) + jz L2 pushl $0 stmxcsr (%esp) andl $0xFFFFFFC0, (%esp) /* mask out status flags */ cmpl $0x1F80, (%esp) popl %esi jnz invariant_violation - /* otherwise we're OK */ +L2: /* otherwise we're OK */ jmp run_innerloop_exit_REALLY invariant_violation: diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index e3be88f8cf..43ed1e2dc8 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -196,16 +196,36 @@ ThreadId VG_(first_matching_thread_stack) return VG_INVALID_THREADID; } + ////////////////////////////////////////////////////////////////// // Architecture specifics -// PPC: what is the cache line size (for dcbz etc) ? -// This info is harvested on Linux at startup from the AT_SYSINFO -// entries. 0 means not-yet-set. +// PPC: what is the cache line size (for dcbz etc) ? This info is +// harvested on Linux at startup from the AT_SYSINFO entries. 0 means +// not-yet-set. #if defined(VGA_ppc32) Int VG_(cache_line_size_ppc32) = 0; #endif +// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store +// the SSE control/status register. For most modern CPUs this will be +// 1. It is set to 1, if possible, by m_translate.getArchAndArchInfo. +// The value is read by m_dispatch.dispatch-x86.S, which is why it +// is an Int rather than a Bool. +// +// Ugly hack: this has to start as 0 and be set to 1 in the normal +// case, rather than the other way round, because the dispatch +// loop needs it, and it runs before the first translation is +// made. Yet it is the act of making that first translation which +// causes getArchAndArchInfo to set this value to its final value. +// So it is necessary to start this value off at 0 as only that +// guarantees that the dispatch loop will not SIGILL on its first +// attempt. +#if defined(VGA_x86) +Int VG_(have_mxcsr_x86) = 0; +#endif + + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index dbebb64712..2e0e028bf7 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -35,6 +35,7 @@ #include "pub_core_cpuid.h" #include "pub_core_machine.h" // For VG_(cache_line_size_ppc32) // and VG_(get_SP) + // and VG_(have_mxcsr_x86) #include "pub_core_libcbase.h" #include "pub_core_libcassert.h" #include "pub_core_libcprint.h" @@ -53,7 +54,7 @@ /*------------------------------------------------------------*/ // Returns the architecture and auxiliary information, or indicates -// that this subarchitecture is unable to run Valgrind Returns False +// that this subarchitecture is unable to run Valgrind. Returns False // to indicate we cannot proceed further. static Bool getArchAndArchInfo( /*OUT*/VexArch* vex_arch, @@ -64,7 +65,7 @@ static Bool getArchAndArchInfo( /*OUT*/VexArch* vex_arch, LibVEX_default_VexArchInfo(vai); #if defined(VGA_x86) - Bool have_sse0, have_sse1, have_sse2; + Bool have_sse1, have_sse2; UInt eax, ebx, ecx, edx; if (!VG_(has_cpuid)()) @@ -79,31 +80,30 @@ static Bool getArchAndArchInfo( /*OUT*/VexArch* vex_arch, /* get capabilities bits into edx */ VG_(cpuid)(1, &eax, &ebx, &ecx, &edx); - have_sse0 = (edx & (1<<24)) != 0; /* True => have fxsave/fxrstor */ have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */ have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */ - if (have_sse2 && have_sse1 && have_sse0) { + VG_(have_mxcsr_x86) = 1; + + if (have_sse2 && have_sse1) { *vex_arch = VexArchX86; vai->subarch = VexSubArchX86_sse2; return True; } - if (have_sse1 && have_sse0) { + if (have_sse1) { *vex_arch = VexArchX86; vai->subarch = VexSubArchX86_sse1; return True; } - if (have_sse0) { + { *vex_arch = VexArchX86; vai->subarch = VexSubArchX86_sse0; + VG_(have_mxcsr_x86) = 0; return True; } - /* we need at least SSE state to operate. */ - return False; - #elif defined(VGA_amd64) vg_assert(VG_(has_cpuid)()); *vex_arch = VexArchAMD64; @@ -459,7 +459,7 @@ Bool VG_(translate) ( ThreadId tid, VG_(printf)("\n"); VG_(printf)("valgrind: fatal error: unsupported CPU.\n"); VG_(printf)(" Supported CPUs are:\n"); - VG_(printf)(" * x86 with SSE (Pentium III or above, " + VG_(printf)(" * x86 (practically any; Pentium-I or above), " "AMD Athlon or above)\n"); VG_(printf)(" * AMD Athlon64/Opteron\n"); VG_(printf)(" * PowerPC with Altivec\n"); diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h index 8b9cdba27f..ed448814da 100644 --- a/coregrind/pub_core_machine.h +++ b/coregrind/pub_core_machine.h @@ -71,9 +71,11 @@ # error Unknown arch #endif + // Offsets for the Vex state #define VG_O_STACK_PTR (offsetof(VexGuestArchState, VG_STACK_PTR)) + // Architecture specifics // PPC: what is the cache line size (for dcbz etc) ? @@ -83,6 +85,13 @@ extern Int VG_(cache_line_size_ppc32); #endif +// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store +// the SSE control/status register. +#if defined(VGA_x86) +extern Int VG_(have_mxcsr_x86); +#endif + + #endif // __PUB_CORE_MACHINE_H /*--------------------------------------------------------------------*/