/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef CPU_X86_VM_VM_VERSION_X86_HPP
#define CPU_X86_VM_VM_VERSION_X86_HPP
#include "runtime/globals_extension.hpp"
#include "runtime/vm_version.hpp"
public:
// cpuid result register layouts. These are all unions of a uint32_t
// (in case anyone wants access to the register as a whole) and a bitfield.
union StdCpuid1Eax {
struct {
: 2,
: 4;
} bits;
};
struct {
} bits;
};
union StdCpuid1Ecx {
struct {
: 2,
: 1,
: 1,
: 1,
: 2,
: 4,
: 2,
: 1,
: 1,
: 3;
} bits;
};
union StdCpuid1Edx {
struct {
: 3,
: 6,
: 3,
: 3,
: 1,
: 3;
} bits;
};
union DcpCpuid4Eax {
struct {
: 21,
} bits;
};
union DcpCpuid4Ebx {
struct {
} bits;
};
union TplCpuidBEbx {
struct {
: 16;
} bits;
};
union ExtCpuid1Ecx {
struct {
: 4,
: 22;
} bits;
};
union ExtCpuid1Edx {
struct {
: 4,
} bits;
};
union ExtCpuid5Ex {
struct {
} bits;
};
union ExtCpuid7Edx {
struct {
: 23;
} bits;
};
union ExtCpuid8Ecx {
struct {
: 24;
} bits;
};
union SefCpuid7Eax {
};
union SefCpuid7Ebx {
struct {
: 2,
: 1,
: 2,
: 22;
} bits;
};
union XemXcr0Eax {
struct {
: 29;
} bits;
};
protected:
static int _cpu;
static int _model;
static int _stepping;
// 0 if this instruction is not available
static const char* _features_str;
enum {
// may not necessarily support other 3dnow instructions
enum {
// AMD
// Intel
// cpuid information block. All info derived from executing cpuid with
// various function numbers is stored here. Intel and AMD info is
// merged in this block: accessor methods disentangle it.
//
// The info block is laid out in subblocks of 4 dwords corresponding to
// eax, ebx, ecx and edx, whether or not they contain anything useful.
struct CpuidInfo {
// cpuid function 0
// cpuid function 1
// cpuid function 4 (deterministic cache parameters)
// cpuid function 7 (structured extended features)
// cpuid function 0xB (processor topology)
// ecx = 0
// ecx = 1
// ecx = 2
// cpuid function 0x80000000 // example, unused
// cpuid function 0x80000001
// cpuid functions 0x80000002 thru 0x80000004: example, unused
// cpuid function 0x80000005 // AMD L1, Intel reserved
// cpuid function 0x80000007
// cpuid function 0x80000008
// extended control register XCR0 (the XFEATURE_ENABLED_MASK register)
};
// The actual cpuid info block
// Extractors and predicates
return result;
}
return result;
}
return result;
}
return result;
}
// HT flag is set for multi-core processors also.
if (threads_per_core() > 1)
result |= CPU_SSE4_1;
result |= CPU_SSE4_2;
result |= CPU_POPCNT;
}
result |= CPU_TSCINV;
// AMD features.
if (is_amd()) {
}
return result;
}
static void get_processor_features();
public:
// Offsets for cpuid asm stub
// Initialization
static void initialize();
// Asserts
static void assert_is_initialized() {
}
//
// Processor family:
// 3 - 386
// 4 - 486
// 5 - Pentium
// 6 - PentiumPro, Pentium II, Celeron, Xeon, Pentium III, Athlon,
// Pentium M, Core Solo, Core Duo, Core2 Duo
// family 6 model: 9, 13, 14, 15
// 0x0f - Pentium 4, Opteron
//
// Note: The cpu family should be used to select between
// instruction sequences which are valid on all Intel
// processors. Use the feature test functions below to
// determine whether a particular instruction is supported.
//
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
static bool supports_processor_topology() {
// eax[4:0] | ebx[0:15] == 0 indicates invalid topology level.
// Some cpus have max cpuid >= 0xB but do not support processor topology.
}
if (is_intel()) {
if (supports_processor_topology()) {
} else {
}
} else if (is_amd()) {
}
return result;
}
if (is_intel() && supports_processor_topology()) {
}
return result;
}
if (is_intel()) {
} else if (is_amd()) {
}
return result;
}
//
// Feature identification
//
// Intel features
static bool is_intel_tsc_synched_at_init() {
if (is_intel_family_core()) {
if (ext_model == CPU_MODEL_NEHALEM_EP ||
// <= 2-socket invariant tsc support. EX versions are usually used
// in > 2-socket systems and likely don't synchronize tscs at
// initialization.
// Code that uses tsc values must be prepared for them to arbitrarily
// jump forward or backward.
return true;
}
}
return false;
}
// AMD features
// Intel and AMD newer cores support fast timestamps well
static bool supports_tscinv_bit() {
return (_cpuFeatures & CPU_TSCINV) != 0;
}
static bool supports_tscinv() {
return supports_tscinv_bit() &&
( (is_amd() && !is_amd_Barcelona()) ||
}
// Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
static bool supports_compare_and_exchange() { return true; }
// This method should be called before allocate_prefetch_style().
//
// Pentium 3 - 64 / 32
// Pentium 4 - 256 / 128
// Athlon - 64 / 32 ????
// Opteron - 128 / 64 only when 2 sequential cache lines accessed
// Core - 128 / 64
//
// Software prefetching (distance in bytes / instruction with best score):
// Pentium 3 - 128 / prefetchnta
// Pentium 4 - 512 / prefetchnta
// Athlon - 128 / prefetchnta
// Opteron - 256 / prefetchnta
// Core - 256 / prefetchnta
// It will be used only when AllocatePrefetchStyle > 0
if (count < 0) { // default ?
if (is_amd()) { // AMD
if (supports_sse2())
else
} else { // Intel
if (supports_sse2())
if (cpu_family() == 6) {
} else {
}
else
}
}
return count;
}
// Return 0 if AllocatePrefetchDistance was not defined.
return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0;
}
// 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap.
// Tested intervals from 128 to 2048 in increments of 64 == one cache line.
// 256 bytes (4 dcache lines) was the nearest runner-up to 576.
// Prefetch::write emits an inlined prefetchw on Linux.
// Do not use the 3dnow prefetchw instruction. It isn't supported on em64t.
// The used prefetcht0 instruction works for both amd64 and em64t.
}
}
}
};
#endif // CPU_X86_VM_VM_VERSION_X86_HPP