From: Tom Hughes Date: Wed, 16 Jun 2004 20:51:45 +0000 (+0000) Subject: Added VG_(cpuid) to replace the various bits of inline assembler used X-Git-Tag: svn/VALGRIND_2_1_2~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3561ea08ca8f538df4024ff9ceab8e1e96854128;p=thirdparty%2Fvalgrind.git Added VG_(cpuid) to replace the various bits of inline assembler used to query the CPU characteristics as the use of four implicit registers causes havoc when GCC tries to inline and optimise the assembler. Fix to bug #79696. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2421 --- diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index a0641dd4cc..8d72ff42f4 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -1177,15 +1177,6 @@ static cache_t clo_L2_cache = UNDEFINED_CACHE; * them. */ -static __inline__ void cpuid(Int n, UInt *a, UInt *b, UInt *c, UInt *d) -{ - __asm__ __volatile__ ( - "cpuid" - : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) /* output */ - : "0" (n) /* input */ - ); -} - static void micro_ops_warn(Int actual_size, Int used_size, Int line_size) { VG_(message)(Vg_DebugMsg, @@ -1214,8 +1205,8 @@ Int Intel_cache_info(Int level, cache_t* I1c, cache_t* D1c, cache_t* L2c) return -1; } - cpuid(2, (Int*)&info[0], (Int*)&info[4], - (Int*)&info[8], (Int*)&info[12]); + VG_(cpuid)(2, (Int*)&info[0], (Int*)&info[4], + (Int*)&info[8], (Int*)&info[12]); trials = info[0] - 1; /* AL register - bits 0..7 of %eax */ info[0] = 0x0; /* reset AL */ @@ -1358,10 +1349,10 @@ static Int AMD_cache_info(cache_t* I1c, cache_t* D1c, cache_t* L2c) { UInt ext_level; - Int dummy, model; - Int I1i, D1i, L2i; + UInt dummy, model; + UInt I1i, D1i, L2i; - cpuid(0x80000000, &ext_level, &dummy, &dummy, &dummy); + VG_(cpuid)(0x80000000, &ext_level, &dummy, &dummy, &dummy); if (0 == (ext_level & 0x80000000) || ext_level < 0x80000006) { VG_(message)(Vg_UserMsg, @@ -1370,10 +1361,10 @@ Int AMD_cache_info(cache_t* I1c, cache_t* D1c, cache_t* L2c) return -1; } - cpuid(0x80000005, &dummy, &dummy, &D1i, &I1i); - cpuid(0x80000006, &dummy, &dummy, &L2i, &dummy); + VG_(cpuid)(0x80000005, &dummy, &dummy, &D1i, &I1i); + VG_(cpuid)(0x80000006, &dummy, &dummy, &L2i, &dummy); - cpuid(0x1, &model, &dummy, &dummy, &dummy); + VG_(cpuid)(0x1, &model, &dummy, &dummy, &dummy); /*VG_(message)(Vg_UserMsg,"CPU model %04x",model);*/ /* Check for Duron bug */ @@ -1426,8 +1417,8 @@ Int get_caches_from_CPUID(cache_t* I1c, cache_t* D1c, cache_t* L2c) /* Trap for illegal instruction, in case it's a really old processor that * doesn't support CPUID. */ if (__builtin_setjmp(cpuid_jmpbuf) == 0) { - cpuid(0, &level, (int*)&vendor_id[0], - (int*)&vendor_id[8], (int*)&vendor_id[4]); + VG_(cpuid)(0, &level, (int*)&vendor_id[0], + (int*)&vendor_id[8], (int*)&vendor_id[4]); vendor_id[12] = '\0'; /* Restore old SIGILL handler */ diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 720cc4a5dc..fcd1f8803b 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -75,7 +75,8 @@ stage2_SOURCES = \ vg_toolint.c \ vg_translate.c \ vg_transtab.c \ - vg_ldt.c + vg_ldt.c \ + vg_cpuid.S stage2_DEPENDENCIES = $(srcdir)/valgrind.vs x86/stage2.lds stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry -g \ -Wl,-defsym,kickstart_base=0xb8000000 \ diff --git a/coregrind/vg_cpuid.S b/coregrind/vg_cpuid.S new file mode 100644 index 0000000000..a5386f9a03 --- /dev/null +++ b/coregrind/vg_cpuid.S @@ -0,0 +1,77 @@ + +##--------------------------------------------------------------------## +##--- Support for determining CPU characteristics. ---## +##--- vg_cpuid.S ---## +##--------------------------------------------------------------------## + +/* + This file is part of Valgrind, an extensible x86 protected-mode + emulator for monitoring program execution on x86-Unixes. + + Copyright (C) 2000-2004 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "vg_constants.h" +#include "vg_unistd.h" + +/* + int VG_(cpuid)(UInt eax, + UInt *eax_ret, UInt *ebx_ret, UInt *ecx_ret, UInt *edx_ret) + */ +.globl VG_(cpuid) +VG_(cpuid): + pushl %ebp + movl %esp, %ebp + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + movl 8(%ebp), %eax + cpuid + movl 12(%ebp), %esi + testl %esi, %esi + jz 1f + movl %eax, (%esi) +1: + movl 16(%ebp), %esi + testl %esi, %esi + jz 2f + movl %ebx, (%esi) +2: + movl 20(%ebp), %esi + testl %esi, %esi + jz 3f + movl %ecx, (%esi) +3: + movl 24(%ebp), %esi + testl %esi, %esi + jz 4f + movl %edx, (%esi) +4: + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %eax + movl %ebp, %esp + popl %ebp + ret diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index c55282c989..4a0e3cff48 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -95,29 +95,6 @@ static Bool has_cpuid(void) return flag_is_changeable(EFlagID); } -static inline UInt cpuid_eax(UInt eax) -{ - asm("cpuid" : "=a" (eax) : "0" (eax) : "bx", "cx", "dx"); - return eax; -} - -static inline void cpuid(UInt eax, - UInt *eax_ret, UInt *ebx_ret, UInt *ecx_ret, UInt *edx_ret) -{ - UInt ebx, ecx, edx; - - asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "0" (eax)); - - if (eax_ret) - *eax_ret = eax; - if (ebx_ret) - *ebx_ret = ebx; - if (ecx_ret) - *ecx_ret = ecx; - if (edx_ret) - *edx_ret = edx; -} - static void get_cpu_features(void) { Char vendorstr[13]; @@ -130,7 +107,7 @@ static void get_cpu_features(void) cpu_features[VG_INT_FEAT] |= (1 << (VG_X86_FEAT_CPUID%32)); - cpuid(0, &cpuid_level, (UInt *)&vendorstr[0], (UInt *)&vendorstr[8], (UInt *)&vendorstr[4]); + VG_(cpuid)(0, &cpuid_level, (UInt *)&vendorstr[0], (UInt *)&vendorstr[8], (UInt *)&vendorstr[4]); vendorstr[12] = '\0'; for(i = 0; i < sizeof(cpu_vendors)/sizeof(*cpu_vendors); i++) @@ -140,12 +117,12 @@ static void get_cpu_features(void) } if (cpuid_level >= 1) - cpuid(1, NULL, NULL, &cpu_features[VG_EXT_FEAT], &cpu_features[VG_X86_FEAT]); + VG_(cpuid)(1, NULL, NULL, &cpu_features[VG_EXT_FEAT], &cpu_features[VG_X86_FEAT]); switch(cpu_vendor) { case VG_CPU_VENDOR_AMD: /* get AMD-specific flags */ - cpuid(0x80000001, NULL, NULL, NULL, &cpu_features[VG_AMD_FEAT]); + VG_(cpuid)(0x80000001, NULL, NULL, NULL, &cpu_features[VG_AMD_FEAT]); break; default: @@ -259,7 +236,7 @@ void VG_(helperc_CPUID)(UInt op, UInt *eax_ret, UInt *ebx_ret, UInt *ecx_ret, UI if (cpuid_level == -2) get_cpu_features(); /* for cpu_vendor */ - cpuid(op, &eax, &ebx, &ecx, &edx); + VG_(cpuid)(op, &eax, &ebx, &ecx, &edx); /* Common mangling */ switch(op) { diff --git a/include/vg_skin.h.base b/include/vg_skin.h.base index 2a682996f4..71bca4a47c 100644 --- a/include/vg_skin.h.base +++ b/include/vg_skin.h.base @@ -585,6 +585,10 @@ extern Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, /* other, randomly useful functions */ extern UInt VG_(read_millisecond_timer) ( void ); +extern void VG_(cpuid) ( UInt eax, + UInt *eax_ret, UInt *ebx_ret, + UInt *ecx_ret, UInt *edx_ret ); + /*====================================================================*/ /*=== UCode definition ===*/ /*====================================================================*/