/*
* 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.
*
*/
#include "precompiled.hpp"
#include "assembler_x86.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_x86.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
extern "C" {
typedef void (*getPsrInfo_stub_t)(void*);
}
public:
// Flags to test CPU type.
// Values for when we don't have a CPUID instruction.
//
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
//
// LP64: rcx and rdx are first and second argument registers on windows
#ifdef _LP64
#else
#endif
//
// if we are unable to change the AC flag, we have a 386
//
//
// If we are unable to change the ID flag, we have a 486 which does
// not support the "cpuid" instruction.
//
//
// At this point, we have a chip which supports the "cpuid" instruction
//
// value of at least 1, we give up and
// assume a 486
//
// cpuid(0xB) Processor Topology
//
//
// cpuid(0x4) Deterministic cache params
//
//
// Standard cpuid(0x1)
//
//
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports AVX
//
//
// XCR0, XFEATURE_ENABLED_MASK register
//
//
// cpuid(0x7) Structured Extended Features
//
//
// Extended cpuid(0x80000000)
//
//
// Extended cpuid(0x80000008)
//
//
// Extended cpuid(0x80000007)
//
//
// Extended cpuid(0x80000005)
//
//
// Extended cpuid(0x80000001)
//
//
// return
//
return start;
};
};
_model = 0;
_stepping = 0;
_cpuFeatures = 0;
if (!Use486InstrsOnly) {
// Get raw processor info
_cpu = extended_cpu_family();
_model = extended_cpu_model();
_stepping = cpu_stepping();
// Logical processors are only available on P4s and above,
// and only if hyperthreading is available.
}
}
// xchg and xadd instructions
_supports_atomic_getset4 = true;
_supports_atomic_getadd4 = true;
LP64_ONLY(_supports_atomic_getset8 = true);
LP64_ONLY(_supports_atomic_getadd8 = true);
#ifdef _LP64
// OS should support SSE for x64 and hardware should support at least SSE2.
if (!VM_Version::supports_sse2()) {
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
}
// in 64 bit the use of SSE2 is the minimum
#endif
#ifdef AMD64
// flush_icache_stub have to be generated first.
// That is why Icache line size is hard coded in ICache class,
// see icache_x86.hpp. It is also the reason why we can't use
// clflush instruction in 32-bit VM since it could be running
// on CPU which does not support it.
//
// The only thing we can do is to verify that flushed
// ICache::line_size has correct value.
// clflush_size is size in quadwords (8 bytes).
#endif
// If the OS doesn't support SSE, we can't use this feature even if the HW does
if (!os::supports_sse())
if (UseSSE < 4) {
_cpuFeatures &= ~CPU_SSE4_1;
_cpuFeatures &= ~CPU_SSE4_2;
}
if (UseSSE < 3) {
_cpuFeatures &= ~CPU_SSE3;
_cpuFeatures &= ~CPU_SSSE3;
_cpuFeatures &= ~CPU_SSE4A;
}
if (UseSSE < 2)
_cpuFeatures &= ~CPU_SSE2;
if (UseSSE < 1)
_cpuFeatures &= ~CPU_SSE;
if (UseAVX < 2)
_cpuFeatures &= ~CPU_AVX2;
if (UseAVX < 1)
_cpuFeatures &= ~CPU_AVX;
_cpuFeatures &= ~CPU_AES;
if (logical_processors_per_package() == 1) {
// HT processor could be installed on a system which doesn't support HT.
_cpuFeatures &= ~CPU_HT;
}
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
// UseSSE is set to the smaller of what hardware supports and what
// the command line requires. I.e., you cannot set UseSSE to 2 on
// older Pentiums which do not support it.
if (!supports_sse4_1()) // Drop to 3 if no SSE4 support
if (!supports_sse3()) // Drop to 2 if no SSE3 support
if (!supports_sse2()) // Drop to 1 if no SSE2 support
if (!supports_sse ()) // Drop to 0 if no SSE support
UseSSE = 0;
if (!supports_avx2()) // Drop to 1 if no AVX2 support
if (!supports_avx ()) // Drop to 0 if no AVX support
UseAVX = 0;
// Use AES instructions if available.
if (supports_aes()) {
if (FLAG_IS_DEFAULT(UseAES)) {
UseAES = true;
}
} else if (UseAES) {
if (!FLAG_IS_DEFAULT(UseAES))
warning("AES instructions not available on this CPU");
FLAG_SET_DEFAULT(UseAES, false);
}
// The AES intrinsic stubs require AES instruction support (of course)
// but also require sse3 mode for instructions it use.
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
UseAESIntrinsics = true;
}
} else if (UseAESIntrinsics) {
if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
warning("AES intrinsics not available on this CPU");
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
}
#ifdef COMPILER2
if (UseFPUForSpilling) {
if (UseSSE < 2) {
// Only supported with SSE2+
FLAG_SET_DEFAULT(UseFPUForSpilling, false);
}
}
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
}
if (MaxVectorSize > 32) {
}
// Only supported with AVX+
}
if (UseSSE < 2) {
// Only supported with SSE2+
}
}
#endif
// On new cpus instructions which update whole XMM register should be used
// to prevent partial register stall due to dependencies on high half.
//
// UseXmmLoadAndClearUpper == true --> movsd(xmm, mem)
// UseXmmLoadAndClearUpper == false --> movlpd(xmm, mem)
// UseXmmRegToRegMoveAll == true --> movaps(xmm, xmm), movapd(xmm, xmm).
// UseXmmRegToRegMoveAll == false --> movss(xmm, xmm), movsd(xmm, xmm).
if( is_amd() ) { // AMD cpus specific settings
// Use it on new AMD cpus starting from Opteron.
UseAddressNop = true;
}
// Use it on new AMD cpus starting from Opteron.
UseNewLongLShift = true;
}
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
if( supports_sse4a() ) {
UseXmmLoadAndClearUpper = true; // use movsd only on '10h' Opteron
} else {
UseXmmLoadAndClearUpper = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
if( supports_sse4a() ) {
UseXmmRegToRegMoveAll = true; // use movaps, movapd only on '10h'
} else {
UseXmmRegToRegMoveAll = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
if( supports_sse4a() ) {
UseXmmI2F = true;
} else {
UseXmmI2F = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
if( supports_sse4a() ) {
UseXmmI2D = true;
} else {
UseXmmI2D = false;
}
}
if( FLAG_IS_DEFAULT(UseSSE42Intrinsics) ) {
UseSSE42Intrinsics = true;
}
}
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
UseCountLeadingZerosInstruction = true;
}
}
// some defaults for AMD family 15h
if ( cpu_family() == 0x15 ) {
// On family 15h processors default is no sw prefetch
if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
}
// Also, if some other prefetch style is specified, default instruction type is PREFETCHW
if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
}
// On family 15h processors use XMM and UnalignedLoadStores for Array Copy
UseXMMForArrayCopy = true;
}
UseUnalignedLoadStores = true;
}
}
#ifdef COMPILER2
if (MaxVectorSize > 16) {
// Limit vectors size to 16 bytes on current AMD cpus.
}
#endif // COMPILER2
}
if( is_intel() ) { // Intel cpus specific settings
if( FLAG_IS_DEFAULT(UseStoreImmI16) ) {
UseStoreImmI16 = false; // don't use it on Intel cpus
}
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
// Use it on all Intel cpus starting from PentiumPro
UseAddressNop = true;
}
}
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
UseXmmLoadAndClearUpper = true; // use movsd on all Intel cpus
}
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
if( supports_sse3() ) {
UseXmmRegToRegMoveAll = true; // use movaps, movapd on new Intel cpus
} else {
UseXmmRegToRegMoveAll = false;
}
}
#ifdef COMPILER2
if( FLAG_IS_DEFAULT(MaxLoopPad) ) {
// For new Intel cpus do the next optimization:
// don't align the beginning of a loop if there are enough instructions
// left (NumberOfLoopInstrToAlign defined in c2_globals.hpp)
// in current fetch line (OptoLoopAlignment) or the padding
// is big (> MaxLoopPad).
// Set MaxLoopPad to 11 for new Intel cpus to reduce number of
// generated NOP instructions. 11 is the largest size of one
// address NOP instruction '0F 1F' (see Assembler::nop(i)).
MaxLoopPad = 11;
}
#endif // COMPILER2
if (FLAG_IS_DEFAULT(UseXMMForArrayCopy)) {
UseXMMForArrayCopy = true; // use SSE2 movq on new Intel cpus
}
UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
}
}
if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) {
UseSSE42Intrinsics = true;
}
}
}
}
#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
if (MaxVectorSize > 16) {
// Limit vectors size to 16 bytes on BSD until it fixes
// restoring upper 128bit of YMM registers on return
// from signal handler.
}
#endif // COMPILER2
// Use population count instruction if available.
if (supports_popcnt()) {
UsePopCountInstruction = true;
}
} else if (UsePopCountInstruction) {
warning("POPCNT instruction is not available on this CPU");
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
}
// Use fast-string operations if available.
if (supports_erms()) {
if (FLAG_IS_DEFAULT(UseFastStosb)) {
UseFastStosb = true;
}
} else if (UseFastStosb) {
warning("fast-string operations are not available on this CPU");
FLAG_SET_DEFAULT(UseFastStosb, false);
}
#ifdef COMPILER2
if (FLAG_IS_DEFAULT(AlignVector)) {
// Modern processors allow misaligned memory operations for vectors.
}
#endif // COMPILER2
// set valid Prefetch instruction
if( ReadPrefetchInstr < 0 ) ReadPrefetchInstr = 0;
if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
// Allocation prefetch settings
#ifdef _LP64
AllocatePrefetchDistance = 384;
#else
AllocatePrefetchDistance = 320;
#endif
}
AllocatePrefetchDistance = 192;
#ifdef COMPILER2
FLAG_SET_DEFAULT(UseFPUForSpilling, true);
}
#endif
}
}
#ifdef _LP64
// Prefetch settings
#endif
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
if (UseAVX > 0) {
}
if (UseAES) {
}
} else {
if (UseSSE == 0 && supports_3dnow_prefetch()) {
} else if (UseSSE >= 1) {
if (AllocatePrefetchInstr == 0) {
} else if (AllocatePrefetchInstr == 1) {
} else if (AllocatePrefetchInstr == 2) {
} else if (AllocatePrefetchInstr == 3) {
}
}
if (AllocatePrefetchLines > 1) {
tty->print_cr(" at distance %d, %d lines of %d bytes", AllocatePrefetchDistance, AllocatePrefetchLines, AllocatePrefetchStepSize);
} else {
tty->print_cr(" at distance %d, one line of %d bytes", AllocatePrefetchDistance, AllocatePrefetchStepSize);
}
}
if (PrefetchCopyIntervalInBytes > 0) {
}
if (PrefetchScanIntervalInBytes > 0) {
}
if (PrefetchFieldsAhead > 0) {
}
}
#endif // !PRODUCT
}
// Making this stub must be FIRST use of assembler
vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
}
CodeBuffer c(stub_blob);
VM_Version_StubGenerator g(&c);
g.generate_getPsrInfo());
}