From 07a8a2e8f3f11e310600122ca665a09f84b9d46e Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 7 Jun 2004 22:53:50 +0000 Subject: [PATCH] Add an API for querying the x86 "cpuid" information. --- ChangeLog | 5 ++ jit/Makefile.am | 2 + jit/jit-cpuid-x86.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ jit/jit-cpuid-x86.h | 103 +++++++++++++++++++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 jit/jit-cpuid-x86.c create mode 100644 jit/jit-cpuid-x86.h diff --git a/ChangeLog b/ChangeLog index 9aa0daa..9aa0a5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ +2004-06-08 Rhys Weatherley + + * jit/Makefile.am, jit/jit-cpuid-x86.c, jit/jit-cpuid-x86.h: + add an API for querying the x86 "cpuid" information. + 2004-06-08 Miroslaw Dobrzanski-Neumann * jit/jit-alloc.c: fix ROUND_END_PTR so that it adds the size diff --git a/jit/Makefile.am b/jit/Makefile.am index 1f6fd7a..4bc7469 100644 --- a/jit/Makefile.am +++ b/jit/Makefile.am @@ -12,6 +12,8 @@ libjit_la_SOURCES = \ jit-block.c \ jit-cache.c \ jit-context.c \ + jit-cpuid-x86.h \ + jit-cpuid-x86.c \ jit-dump.c \ jit-elf-defs.h \ jit-elf-read.c \ diff --git a/jit/jit-cpuid-x86.c b/jit/jit-cpuid-x86.c new file mode 100644 index 0000000..03b0e62 --- /dev/null +++ b/jit/jit-cpuid-x86.c @@ -0,0 +1,127 @@ +/* + * jit-cpuid-x86.c - Wrapper for the CPUID instruction. + * + * Copyright (C) 2004 Southern Storm Software, Pty Ltd. + * + * 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 + */ + +#include "jit-cpuid-x86.h" + +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) + +/* + * Determine if the "cpuid" instruction is present by twiddling + * bit 21 of the EFLAGS register. + */ +static int cpuid_present(void) +{ +#if defined(__GNUC__) + int result; + __asm__ __volatile__ ( + "\tpushfl\n" + "\tpopl %%eax\n" + "\tmovl %%eax, %%ecx\n" + "\tandl $0x200000, %%ecx\n" + "\txorl $0x200000, %%eax\n" + "\tpushl %%eax\n" + "\tpopfl\n" + "\tpushfl\n" + "\tandl $0x200000, %%eax\n" + "\txorl %%ecx, %%eax\n" + "\tmovl %%eax, %0\n" + : "=m" (result) : : "eax", "ecx" + ); + return (result != 0); +#else + return 0; +#endif +} + +/* + * Issue a "cpuid" query and get the result. + */ +static void cpuid_query(unsigned int index, jit_cpuid_x86_t *info) +{ +#if defined(__GNUC__) + __asm__ __volatile__ ( + "\tmovl %0, %%eax\n" + "\txorl %%ebx, %%ebx\n" + "\txorl %%ecx, %%ecx\n" + "\txorl %%edx, %%edx\n" + "\t.byte 0x0F\n" /* cpuid, safe against old assemblers */ + "\t.byte 0xA2\n" + "\tmovl %1, %%esi\n" + "\tmovl %%eax, (%%esi)\n" + "\tmovl %%ebx, 4(%%esi)\n" + "\tmovl %%ecx, 8(%%esi)\n" + "\tmovl %%edx, 12(%%esi)\n" + : : "m"(index), "m"(info) : "eax", "ebx", "ecx", "edx", "esi" + ); +#endif +} + +int _jit_cpuid_x86_get(unsigned int index, jit_cpuid_x86_t *info) +{ + /* Determine if this cpu has the "cpuid" instruction */ + if(!cpuid_present()) + { + return 0; + } + + /* Validate the index */ + if((index & 0x80000000) == 0) + { + cpuid_query(0, info); + } + else + { + cpuid_query(0x80000000, info); + } + if(index > info->eax) + { + return 0; + } + + /* Execute the actual requested query */ + cpuid_query(index, info); + return 1; +} + +int _jit_cpuid_x86_has_feature(unsigned int feature) +{ + jit_cpuid_x86_t info; + if(!_jit_cpuid_x86_get(JIT_X86CPUID_FEATURES, &info)) + { + return 0; + } + return ((info.edx & feature) != 0); +} + +unsigned int _jit_cpuid_x86_line_size(void) +{ + jit_cpuid_x86_t info; + if(!_jit_cpuid_x86_get(JIT_X86CPUID_FEATURES, &info)) + { + return 0; + } + if((info.edx & JIT_X86FEATURE_CLFSH) == 0) + { + return 0; + } + return ((info.ebx & 0x0000FF00) >> 5); +} + +#endif /* i386 */ diff --git a/jit/jit-cpuid-x86.h b/jit/jit-cpuid-x86.h new file mode 100644 index 0000000..a808738 --- /dev/null +++ b/jit/jit-cpuid-x86.h @@ -0,0 +1,103 @@ +/* + * jit-cpuid-x86.h - Wrapper for the CPUID instruction. + * + * Copyright (C) 2004 Southern Storm Software, Pty Ltd. + * + * 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 + */ + +#ifndef _JIT_CPUID_X86_H +#define _JIT_CPUID_X86_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Structure that is used to return CPU identification information. + */ +typedef struct +{ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + +} jit_cpuid_x86_t; + +/* + * Indexes for querying cpuid information. + */ +#define JIT_X86CPUID_FEATURES 1 +#define JIT_X86CPUID_CACHE_TLB 2 +#define JIT_X86CPUID_SERIAL_NUMBER 3 + +/* + * Feature information. + */ +#define JIT_X86FEATURE_FPU 0x00000001 +#define JIT_X86FEATURE_VME 0x00000002 +#define JIT_X86FEATURE_DE 0x00000004 +#define JIT_X86FEATURE_PSE 0x00000008 +#define JIT_X86FEATURE_TSC 0x00000010 +#define JIT_X86FEATURE_MSR 0x00000020 +#define JIT_X86FEATURE_PAE 0x00000040 +#define JIT_X86FEATURE_MCE 0x00000080 +#define JIT_X86FEATURE_CX8 0x00000100 +#define JIT_X86FEATURE_APIC 0x00000200 +#define JIT_X86FEATURE_RESERVED_1 0x00000400 +#define JIT_X86FEATURE_SEP 0x00000800 +#define JIT_X86FEATURE_MTRR 0x00001000 +#define JIT_X86FEATURE_PGE 0x00002000 +#define JIT_X86FEATURE_MCA 0x00004000 +#define JIT_X86FEATURE_CMOV 0x00008000 +#define JIT_X86FEATURE_PAT 0x00010000 +#define JIT_X86FEATURE_PSE36 0x00020000 +#define JIT_X86FEATURE_PSN 0x00040000 +#define JIT_X86FEATURE_CLFSH 0x00080000 +#define JIT_X86FEATURE_RESERVED_2 0x00100000 +#define JIT_X86FEATURE_DS 0x00200000 +#define JIT_X86FEATURE_ACPI 0x00400000 +#define JIT_X86FEATURE_MMX 0x00800000 +#define JIT_X86FEATURE_FXSR 0x01000000 +#define JIT_X86FEATURE_SSE 0x02000000 +#define JIT_X86FEATURE_SSE2 0x04000000 +#define JIT_X86FEATURE_SS 0x08000000 +#define JIT_X86FEATURE_RESERVED_3 0x10000000 +#define JIT_X86FEATURE_TM 0x20000000 +#define JIT_X86FEATURE_RESERVED_4 0x40000000 +#define JIT_X86FEATURE_RESERVED_5 0x80000000 + +/* + * Get CPU identification information. Returns zero if the requested + * information is not available. + */ +int _jit_cpuid_x86_get(unsigned int index, jit_cpuid_x86_t *info); + +/* + * Determine if the CPU has a particular feature. + */ +int _jit_cpuid_x86_has_feature(unsigned int feature); + +/* + * Get the size of the CPU cache line, or zero if flushing is not required. + */ +unsigned int _jit_cpuid_x86_line_size(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* _JIT_CPUID_X86_H */ -- 2.47.3