/* 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
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:
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 ---*/
/*--------------------------------------------------------------------*/
#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"
/*------------------------------------------------------------*/
// 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,
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)())
/* 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;
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");
# 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) ?
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
/*--------------------------------------------------------------------*/