* 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,
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 */
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,
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 */
/* 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 */
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 \
--- /dev/null
+
+##--------------------------------------------------------------------##
+##--- 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
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];
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++)
}
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:
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) {
/* 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 ===*/
/*====================================================================*/