Commit 5768fcf1 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Fix the CPU feature detection.

Move all of the CPU detection logic to the CPU class, and make
all other code use the CPU class for feature detection.

This also fixes the ARM CPU feature detection logic, which was
based on fragile string search in /proc/cpuinfo. Now we use
ELF hwcaps if available, falling back to sane(!!) parsing of
/proc/cpuinfo for CPU features.

The ia32 and x64 code was also cleaned up to make it usable
outside the assembler.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/23401002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16315 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f9f11f91
......@@ -152,7 +152,8 @@ void CpuFeatures::Probe() {
#else // __arm__
// Probe for additional features not already known to be available.
if (!IsSupported(VFP3) && FLAG_enable_vfp3 && OS::ArmCpuHasFeature(VFP3)) {
CPU cpu;
if (!IsSupported(VFP3) && FLAG_enable_vfp3 && cpu.has_vfp3()) {
// This implementation also sets the VFP flags if runtime
// detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
// 0406B, page A1-6.
......@@ -161,38 +162,40 @@ void CpuFeatures::Probe() {
static_cast<uint64_t>(1) << ARMv7;
}
if (!IsSupported(NEON) && FLAG_enable_neon && OS::ArmCpuHasFeature(NEON)) {
if (!IsSupported(NEON) && FLAG_enable_neon && cpu.has_neon()) {
found_by_runtime_probing_only_ |= 1u << NEON;
}
if (!IsSupported(ARMv7) && FLAG_enable_armv7 && OS::ArmCpuHasFeature(ARMv7)) {
if (!IsSupported(ARMv7) && FLAG_enable_armv7 && cpu.architecture() >= 7) {
found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7;
}
if (!IsSupported(SUDIV) && FLAG_enable_sudiv && OS::ArmCpuHasFeature(SUDIV)) {
if (!IsSupported(SUDIV) && FLAG_enable_sudiv && cpu.has_idiva()) {
found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV;
}
if (!IsSupported(UNALIGNED_ACCESSES) && FLAG_enable_unaligned_accesses
&& OS::ArmCpuHasFeature(ARMv7)) {
&& cpu.architecture() >= 7) {
found_by_runtime_probing_only_ |=
static_cast<uint64_t>(1) << UNALIGNED_ACCESSES;
}
CpuImplementer implementer = OS::GetCpuImplementer();
if (implementer == QUALCOMM_IMPLEMENTER &&
FLAG_enable_movw_movt && OS::ArmCpuHasFeature(ARMv7)) {
// Use movw/movt for QUALCOMM ARMv7 cores.
if (cpu.implementer() == CPU::QUALCOMM &&
cpu.architecture() >= 7 &&
FLAG_enable_movw_movt) {
found_by_runtime_probing_only_ |=
static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
}
CpuPart part = OS::GetCpuPart(implementer);
if ((part == CORTEX_A9) || (part == CORTEX_A5)) {
// ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
if (cpu.implementer() == CPU::ARM &&
(cpu.part() == CPU::ARM_CORTEX_A5 ||
cpu.part() == CPU::ARM_CORTEX_A9)) {
cache_line_size_ = 32;
}
if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs
&& OS::ArmCpuHasFeature(VFP32DREGS)) {
if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs && cpu.has_vfp3_d32()) {
found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS;
}
......
This diff is collapsed.
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -44,14 +44,61 @@ namespace internal {
// ----------------------------------------------------------------------------
// CPU
//
// This class has static methods for the architecture specific functions. Add
// methods here to cope with differences between the supported architectures.
// Query information about the processor.
//
// For each architecture the file cpu_<arch>.cc contains the implementation of
// these functions.
// This class also has static methods for the architecture specific functions.
// Add methods here to cope with differences between the supported
// architectures. For each architecture the file cpu_<arch>.cc contains the
// implementation of these static functions.
class CPU : public AllStatic {
class CPU V8_FINAL BASE_EMBEDDED {
public:
CPU();
// x86 CPUID information
const char* vendor() const { return vendor_; }
int stepping() const { return stepping_; }
int model() const { return model_; }
int ext_model() const { return ext_model_; }
int family() const { return family_; }
int ext_family() const { return ext_family_; }
int type() const { return type_; }
// arm implementer/part information
int implementer() const { return implementer_; }
static const int ARM = 0x41;
static const int QUALCOMM = 0x51;
int architecture() const { return architecture_; }
int part() const { return part_; }
static const int ARM_CORTEX_A5 = 0xc05;
static const int ARM_CORTEX_A7 = 0xc07;
static const int ARM_CORTEX_A8 = 0xc08;
static const int ARM_CORTEX_A9 = 0xc09;
static const int ARM_CORTEX_A12 = 0xc0c;
static const int ARM_CORTEX_A15 = 0xc0f;
// General features
bool has_fpu() const { return has_fpu_; }
// x86 features
bool has_cmov() const { return has_cmov_; }
bool has_sahf() const { return has_sahf_; }
bool has_mmx() const { return has_mmx_; }
bool has_sse() const { return has_sse_; }
bool has_sse2() const { return has_sse2_; }
bool has_sse3() const { return has_sse3_; }
bool has_ssse3() const { return has_ssse3_; }
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
// arm features
bool has_idiva() const { return has_idiva_; }
bool has_neon() const { return has_neon_; }
bool has_thumbee() const { return has_thumbee_; }
bool has_vfp() const { return has_vfp_; }
bool has_vfp3() const { return has_vfp3_; }
bool has_vfp3_d32() const { return has_vfp3_d32_; }
// Initializes the cpu architecture support. Called once at VM startup.
static void SetUp();
......@@ -59,6 +106,34 @@ class CPU : public AllStatic {
// Flush instruction cache.
static void FlushICache(void* start, size_t size);
private:
char vendor_[13];
int stepping_;
int model_;
int ext_model_;
int family_;
int ext_family_;
int type_;
int implementer_;
int architecture_;
int part_;
bool has_fpu_;
bool has_cmov_;
bool has_sahf_;
bool has_mmx_;
bool has_sse_;
bool has_sse2_;
bool has_sse3_;
bool has_ssse3_;
bool has_sse41_;
bool has_sse42_;
bool has_idiva_;
bool has_neon_;
bool has_thumbee_;
bool has_vfp_;
bool has_vfp3_;
bool has_vfp3_d32_;
};
} } // namespace v8::internal
......
......@@ -101,80 +101,28 @@ void CpuFeatures::Probe() {
return; // No features if we might serialize.
}
const int kBufferSize = 4 * KB;
VirtualMemory* memory = new VirtualMemory(kBufferSize);
if (!memory->IsReserved()) {
delete memory;
return;
uint64_t probed_features = 0;
CPU cpu;
if (cpu.has_sse41()) {
probed_features |= static_cast<uint64_t>(1) << SSE4_1;
}
ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
delete memory;
return;
if (cpu.has_sse3()) {
probed_features |= static_cast<uint64_t>(1) << SSE3;
}
Assembler assm(NULL, memory->address(), kBufferSize);
Label cpuid, done;
#define __ assm.
// Save old esp, since we are going to modify the stack.
__ push(ebp);
__ pushfd();
__ push(ecx);
__ push(ebx);
__ mov(ebp, esp);
// If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
__ pushfd();
__ pop(eax);
__ mov(edx, eax);
__ xor_(eax, 0x200000); // Flip bit 21.
__ push(eax);
__ popfd();
__ pushfd();
__ pop(eax);
__ xor_(eax, edx); // Different if CPUID is supported.
__ j(not_zero, &cpuid);
// CPUID not supported. Clear the supported features in edx:eax.
__ xor_(eax, eax);
__ xor_(edx, edx);
__ jmp(&done);
// Invoke CPUID with 1 in eax to get feature information in
// ecx:edx. Temporarily enable CPUID support because we know it's
// safe here.
__ bind(&cpuid);
__ mov(eax, 1);
supported_ = (1 << CPUID);
{ CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
if (cpu.has_sse2()) {
probed_features |= static_cast<uint64_t>(1) << SSE2;
}
if (cpu.has_cmov()) {
probed_features |= static_cast<uint64_t>(1) << CMOV;
}
supported_ = 0;
// Move the result from ecx:edx to edx:eax and make sure to mark the
// CPUID feature as supported.
__ mov(eax, edx);
__ or_(eax, 1 << CPUID);
__ mov(edx, ecx);
// Done.
__ bind(&done);
__ mov(esp, ebp);
__ pop(ebx);
__ pop(ecx);
__ popfd();
__ pop(ebp);
__ ret(0);
#undef __
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
uint64_t probed_features = probe();
// SAHF must be available in compat/legacy mode.
ASSERT(cpu.has_sahf());
probed_features |= static_cast<uint64_t>(1) << SAHF;
uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
supported_ = probed_features | platform_features;
found_by_runtime_probing_only_ = probed_features & ~platform_features;
delete memory;
}
......@@ -474,7 +422,6 @@ void Assembler::CodeTargetAlign() {
void Assembler::cpuid() {
ASSERT(IsEnabled(CPUID));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0xA2);
......
......@@ -126,7 +126,8 @@ void CpuFeatures::Probe() {
supported_ |= static_cast<uint64_t>(1) << FPU;
#else
// Probe for additional features not already known to be available.
if (OS::MipsCpuHasFeature(FPU)) {
CPU cpu;
if (cpu.has_fpu()) {
// This implementation also sets the FPU flags if
// runtime detection of FPU returns true.
supported_ |= static_cast<uint64_t>(1) << FPU;
......
......@@ -80,139 +80,6 @@ static Mutex* limit_mutex = NULL;
#ifdef __arm__
static bool CPUInfoContainsString(const char * search_string) {
const char* file_name = "/proc/cpuinfo";
// This is written as a straight shot one pass parser
// and not using STL string and ifstream because,
// on Linux, it's reading from a (non-mmap-able)
// character special device.
FILE* f = NULL;
const char* what = search_string;
if (NULL == (f = fopen(file_name, "r"))) {
OS::PrintError("Failed to open /proc/cpuinfo\n");
return false;
}
int k;
while (EOF != (k = fgetc(f))) {
if (k == *what) {
++what;
while ((*what != '\0') && (*what == fgetc(f))) {
++what;
}
if (*what == '\0') {
fclose(f);
return true;
} else {
what = search_string;
}
}
}
fclose(f);
// Did not find string in the proc file.
return false;
}
bool OS::ArmCpuHasFeature(CpuFeature feature) {
const char* search_string = NULL;
// Simple detection of VFP at runtime for Linux.
// It is based on /proc/cpuinfo, which reveals hardware configuration
// to user-space applications. According to ARM (mid 2009), no similar
// facility is universally available on the ARM architectures,
// so it's up to individual OSes to provide such.
switch (feature) {
case VFP3:
search_string = "vfpv3";
break;
case NEON:
search_string = "neon";
break;
case ARMv7:
search_string = "ARMv7";
break;
case SUDIV:
search_string = "idiva";
break;
case VFP32DREGS:
// This case is handled specially below.
break;
default:
UNREACHABLE();
}
if (feature == VFP32DREGS) {
return ArmCpuHasFeature(VFP3) && !CPUInfoContainsString("d16");
}
if (CPUInfoContainsString(search_string)) {
return true;
}
if (feature == VFP3) {
// Some old kernels will report vfp not vfpv3. Here we make a last attempt
// to detect vfpv3 by checking for vfp *and* neon, since neon is only
// available on architectures with vfpv3.
// Checking neon on its own is not enough as it is possible to have neon
// without vfp.
if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
return true;
}
}
return false;
}
CpuImplementer OS::GetCpuImplementer() {
static bool use_cached_value = false;
static CpuImplementer cached_value = UNKNOWN_IMPLEMENTER;
if (use_cached_value) {
return cached_value;
}
if (CPUInfoContainsString("CPU implementer\t: 0x41")) {
cached_value = ARM_IMPLEMENTER;
} else if (CPUInfoContainsString("CPU implementer\t: 0x51")) {
cached_value = QUALCOMM_IMPLEMENTER;
} else {
cached_value = UNKNOWN_IMPLEMENTER;
}
use_cached_value = true;
return cached_value;
}
CpuPart OS::GetCpuPart(CpuImplementer implementer) {
static bool use_cached_value = false;
static CpuPart cached_value = CPU_UNKNOWN;
if (use_cached_value) {
return cached_value;
}
if (implementer == ARM_IMPLEMENTER) {
if (CPUInfoContainsString("CPU part\t: 0xc0f")) {
cached_value = CORTEX_A15;
} else if (CPUInfoContainsString("CPU part\t: 0xc0c")) {
cached_value = CORTEX_A12;
} else if (CPUInfoContainsString("CPU part\t: 0xc09")) {
cached_value = CORTEX_A9;
} else if (CPUInfoContainsString("CPU part\t: 0xc08")) {
cached_value = CORTEX_A8;
} else if (CPUInfoContainsString("CPU part\t: 0xc07")) {
cached_value = CORTEX_A7;
} else if (CPUInfoContainsString("CPU part\t: 0xc05")) {
cached_value = CORTEX_A5;
} else {
cached_value = CPU_UNKNOWN;
}
} else {
cached_value = CPU_UNKNOWN;
}
use_cached_value = true;
return cached_value;
}
bool OS::ArmUsingHardFloat() {
// GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
......@@ -255,60 +122,6 @@ bool OS::ArmUsingHardFloat() {
#endif // def __arm__
#ifdef __mips__
bool OS::MipsCpuHasFeature(CpuFeature feature) {
const char* search_string = NULL;
const char* file_name = "/proc/cpuinfo";
// Simple detection of FPU at runtime for Linux.
// It is based on /proc/cpuinfo, which reveals hardware configuration
// to user-space applications. According to MIPS (early 2010), no similar
// facility is universally available on the MIPS architectures,
// so it's up to individual OSes to provide such.
//
// This is written as a straight shot one pass parser
// and not using STL string and ifstream because,
// on Linux, it's reading from a (non-mmap-able)
// character special device.
switch (feature) {
case FPU:
search_string = "FPU";
break;
default:
UNREACHABLE();
}
FILE* f = NULL;
const char* what = search_string;
if (NULL == (f = fopen(file_name, "r"))) {
OS::PrintError("Failed to open /proc/cpuinfo\n");
return false;
}
int k;
while (EOF != (k = fgetc(f))) {
if (k == *what) {
++what;
while ((*what != '\0') && (*what == fgetc(f))) {
++what;
}
if (*what == '\0') {
fclose(f);
return true;
} else {
what = search_string;
}
}
}
fclose(f);
// Did not find string in the proc file.
return false;
}
#endif // def __mips__
const char* OS::LocalTimezone(double time) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(floor(time/msPerSecond));
......
......@@ -215,21 +215,6 @@ double OS::nan_value() {
}
CpuImplementer OS::GetCpuImplementer() {
UNIMPLEMENTED();
}
CpuPart OS::GetCpuPart(CpuImplementer implementer) {
UNIMPLEMENTED();
}
bool OS::ArmCpuHasFeature(CpuFeature feature) {
UNIMPLEMENTED();
}
bool OS::ArmUsingHardFloat() {
UNIMPLEMENTED();
}
......
......@@ -79,11 +79,11 @@ static const pthread_t kNoThread = (pthread_t) 0;
uint64_t OS::CpuFeaturesImpliedByPlatform() {
#if defined(__APPLE__)
#if V8_OS_MACOSX
// Mac OS X requires all these to install so we can assume they are present.
// These constants are defined by the CPUid instructions.
const uint64_t one = 1;
return (one << SSE2) | (one << CMOV) | (one << CPUID);
return (one << SSE2) | (one << CMOV);
#else
return 0; // Nothing special about the other systems.
#endif
......
......@@ -365,22 +365,10 @@ class OS {
// Returns the double constant NAN
static double nan_value();
// Support runtime detection of Cpu implementer
static CpuImplementer GetCpuImplementer();
// Support runtime detection of Cpu implementer
static CpuPart GetCpuPart(CpuImplementer implementer);
// Support runtime detection of VFP3 on ARM CPUs.
static bool ArmCpuHasFeature(CpuFeature feature);
// Support runtime detection of whether the hard float option of the
// EABI is used.
static bool ArmUsingHardFloat();
// Support runtime detection of FPU on MIPS CPUs.
static bool MipsCpuHasFeature(CpuFeature feature);
// Returns the activation frame alignment constraint or zero if
// the platform doesn't care. Guaranteed to be a power of two.
static int ActivationFrameAlignment();
......
......@@ -412,33 +412,12 @@ enum StateTag {
#endif
enum CpuImplementer {
UNKNOWN_IMPLEMENTER,
ARM_IMPLEMENTER,
QUALCOMM_IMPLEMENTER
};
enum CpuPart {
CPU_UNKNOWN,
CORTEX_A15,
CORTEX_A12,
CORTEX_A9,
CORTEX_A8,
CORTEX_A7,
CORTEX_A5
};
// Feature flags bit positions. They are mostly based on the CPUID spec.
// (We assign CPUID itself to one of the currently reserved bits --
// feel free to change this if needed.)
// On X86/X64, values below 32 are bits in EDX, values above 32 are bits in ECX.
enum CpuFeature { SSE4_1 = 32 + 19, // x86
SSE3 = 32 + 0, // x86
SSE2 = 26, // x86
CMOV = 15, // x86
CPUID = 10, // x86
VFP3 = 1, // ARM
ARMv7 = 2, // ARM
SUDIV = 3, // ARM
......
......@@ -63,98 +63,32 @@ void CpuFeatures::Probe() {
return; // No features if we might serialize.
}
const int kBufferSize = 4 * KB;
VirtualMemory* memory = new VirtualMemory(kBufferSize);
if (!memory->IsReserved()) {
delete memory;
return;
uint64_t probed_features = 0;
CPU cpu;
if (cpu.has_sse41()) {
probed_features |= static_cast<uint64_t>(1) << SSE4_1;
}
ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
delete memory;
return;
if (cpu.has_sse3()) {
probed_features |= static_cast<uint64_t>(1) << SSE3;
}
Assembler assm(NULL, memory->address(), kBufferSize);
Label cpuid, done;
#define __ assm.
// Save old rsp, since we are going to modify the stack.
__ push(rbp);
__ pushfq();
__ push(rdi);
__ push(rcx);
__ push(rbx);
__ movq(rbp, rsp);
// If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
__ pushfq();
__ pop(rax);
__ movq(rdx, rax);
__ xor_(rax, Immediate(0x200000)); // Flip bit 21.
__ push(rax);
__ popfq();
__ pushfq();
__ pop(rax);
__ xor_(rax, rdx); // Different if CPUID is supported.
__ j(not_zero, &cpuid);
// CPUID not supported. Clear the supported features in rax.
__ xor_(rax, rax);
__ jmp(&done);
// Invoke CPUID with 1 in eax to get feature information in
// ecx:edx. Temporarily enable CPUID support because we know it's
// safe here.
__ bind(&cpuid);
__ movl(rax, Immediate(1));
supported_ = kDefaultCpuFeatures | (1 << CPUID);
{ CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
// Move the result from ecx:edx to rdi.
__ movl(rdi, rdx); // Zero-extended to 64 bits.
__ shl(rcx, Immediate(32));
__ or_(rdi, rcx);
// Get the sahf supported flag, from CPUID(0x80000001)
__ movq(rax, 0x80000001, RelocInfo::NONE64);
__ cpuid();
// SSE2 must be available on every x64 CPU.
ASSERT(cpu.has_sse2());
probed_features |= static_cast<uint64_t>(1) << SSE2;
// CMOD must be available on every x64 CPU.
ASSERT(cpu.has_cmov());
probed_features |= static_cast<uint64_t>(1) << CMOV;
// SAHF is not generally available in long mode.
if (cpu.has_sahf()) {
probed_features |= static_cast<uint64_t>(1) << SAHF;
}
supported_ = kDefaultCpuFeatures;
// Put the CPU flags in rax.
// rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
__ movl(rax, Immediate(1));
__ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
__ not_(rax);
__ and_(rax, rdi);
__ or_(rax, rcx);
__ or_(rax, Immediate(1 << CPUID));
// Done.
__ bind(&done);
__ movq(rsp, rbp);
__ pop(rbx);
__ pop(rcx);
__ pop(rdi);
__ popfq();
__ pop(rbp);
__ ret(0);
#undef __
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
uint64_t probed_features = probe();
uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
supported_ = probed_features | platform_features;
found_by_runtime_probing_only_
= probed_features & ~kDefaultCpuFeatures & ~platform_features;
// CMOV must be available on an X64 CPU.
ASSERT(IsSupported(CPUID));
ASSERT(IsSupported(CMOV));
delete memory;
}
......@@ -987,7 +921,6 @@ void Assembler::cmpb_al(Immediate imm8) {
void Assembler::cpuid() {
ASSERT(IsEnabled(CPUID));
EnsureSpace ensure_space(this);
emit(0x0F);
emit(0xA2);
......
......@@ -56,6 +56,7 @@
'test-circular-queue.cc',
'test-compiler.cc',
'test-conversions.cc',
'test-cpu.cc',
'test-cpu-profiler.cc',
'test-dataflow.cc',
'test-date.cc',
......@@ -113,6 +114,7 @@
'test-assembler-ia32.cc',
'test-code-stubs.cc',
'test-code-stubs-ia32.cc',
'test-cpu-ia32.cc',
'test-disasm-ia32.cc',
'test-log-stack-tracer.cc'
],
......@@ -122,6 +124,7 @@
'test-assembler-x64.cc',
'test-code-stubs.cc',
'test-code-stubs-x64.cc',
'test-cpu-x64.cc',
'test-macro-assembler-x64.cc',
'test-log-stack-tracer.cc'
],
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "cctest.h"
#include "cpu.h"
using namespace v8::internal;
TEST(RequiredFeaturesX64) {
// Test for the features required by every x86 CPU in compat/legacy mode.
CPU cpu;
CHECK(cpu.has_sahf());
}
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "cctest.h"
#include "cpu.h"
using namespace v8::internal;
TEST(RequiredFeaturesX64) {
// Test for the features required by every x64 CPU.
CPU cpu;
CHECK(cpu.has_fpu());
CHECK(cpu.has_cmov());
CHECK(cpu.has_mmx());
CHECK(cpu.has_sse());
CHECK(cpu.has_sse2());
}
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "cctest.h"
#include "cpu.h"
using namespace v8::internal;
TEST(FeatureImplications) {
// Test for features implied by other features.
CPU cpu;
// ia32 and x64 features
CHECK(!cpu.has_sse() || cpu.has_mmx());
CHECK(!cpu.has_sse2() || cpu.has_sse());
CHECK(!cpu.has_sse3() || cpu.has_sse2());
CHECK(!cpu.has_ssse3() || cpu.has_sse3());
CHECK(!cpu.has_sse41() || cpu.has_sse3());
CHECK(!cpu.has_sse42() || cpu.has_sse41());
// arm features
CHECK(!cpu.has_vfp3_d32() || cpu.has_vfp3());
}
......@@ -99,11 +99,7 @@ TEST(DisasmIa320) {
__ or_(edx, 3);
__ xor_(edx, 3);
__ nop();
{
CHECK(CpuFeatures::IsSupported(CPUID));
CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
}
__ cpuid();
__ movsx_b(edx, ecx);
__ movsx_w(edx, ecx);
__ movzx_b(edx, ecx);
......
......@@ -257,6 +257,7 @@
'../../src/cpu-profiler-inl.h',
'../../src/cpu-profiler.cc',
'../../src/cpu-profiler.h',
'../../src/cpu.cc',
'../../src/cpu.h',
'../../src/data-flow.cc',
'../../src/data-flow.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment