Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/x64/assembler-x64.cc

Issue 23401002: Fix the CPU feature detection. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Improve cpuinfo parsing. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/v8globals.h ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 ASSERT(supported_ == CpuFeatures::kDefaultCpuFeatures); 56 ASSERT(supported_ == CpuFeatures::kDefaultCpuFeatures);
57 #ifdef DEBUG 57 #ifdef DEBUG
58 initialized_ = true; 58 initialized_ = true;
59 #endif 59 #endif
60 supported_ = kDefaultCpuFeatures; 60 supported_ = kDefaultCpuFeatures;
61 if (Serializer::enabled()) { 61 if (Serializer::enabled()) {
62 supported_ |= OS::CpuFeaturesImpliedByPlatform(); 62 supported_ |= OS::CpuFeaturesImpliedByPlatform();
63 return; // No features if we might serialize. 63 return; // No features if we might serialize.
64 } 64 }
65 65
66 const int kBufferSize = 4 * KB; 66 uint64_t probed_features = 0;
67 VirtualMemory* memory = new VirtualMemory(kBufferSize); 67 CPU cpu;
68 if (!memory->IsReserved()) { 68 if (cpu.has_sse41()) {
69 delete memory; 69 probed_features |= static_cast<uint64_t>(1) << SSE4_1;
70 return;
71 } 70 }
72 ASSERT(memory->size() >= static_cast<size_t>(kBufferSize)); 71 if (cpu.has_sse3()) {
73 if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) { 72 probed_features |= static_cast<uint64_t>(1) << SSE3;
74 delete memory;
75 return;
76 } 73 }
77 74
78 Assembler assm(NULL, memory->address(), kBufferSize); 75 // SSE2 must be available on every x64 CPU.
79 Label cpuid, done; 76 ASSERT(cpu.has_sse2());
80 #define __ assm. 77 probed_features |= static_cast<uint64_t>(1) << SSE2;
81 // Save old rsp, since we are going to modify the stack.
82 __ push(rbp);
83 __ pushfq();
84 __ push(rdi);
85 __ push(rcx);
86 __ push(rbx);
87 __ movq(rbp, rsp);
88 78
89 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. 79 // CMOD must be available on every x64 CPU.
90 __ pushfq(); 80 ASSERT(cpu.has_cmov());
91 __ pop(rax); 81 probed_features |= static_cast<uint64_t>(1) << CMOV;
92 __ movq(rdx, rax);
93 __ xor_(rax, Immediate(0x200000)); // Flip bit 21.
94 __ push(rax);
95 __ popfq();
96 __ pushfq();
97 __ pop(rax);
98 __ xor_(rax, rdx); // Different if CPUID is supported.
99 __ j(not_zero, &cpuid);
100 82
101 // CPUID not supported. Clear the supported features in rax. 83 // SAHF is not generally available in long mode.
102 __ xor_(rax, rax); 84 if (cpu.has_sahf()) {
103 __ jmp(&done); 85 probed_features |= static_cast<uint64_t>(1) << SAHF;
86 }
104 87
105 // Invoke CPUID with 1 in eax to get feature information in
106 // ecx:edx. Temporarily enable CPUID support because we know it's
107 // safe here.
108 __ bind(&cpuid);
109 __ movl(rax, Immediate(1));
110 supported_ = kDefaultCpuFeatures | (1 << CPUID);
111 { CpuFeatureScope fscope(&assm, CPUID);
112 __ cpuid();
113 // Move the result from ecx:edx to rdi.
114 __ movl(rdi, rdx); // Zero-extended to 64 bits.
115 __ shl(rcx, Immediate(32));
116 __ or_(rdi, rcx);
117
118 // Get the sahf supported flag, from CPUID(0x80000001)
119 __ movq(rax, 0x80000001, RelocInfo::NONE64);
120 __ cpuid();
121 }
122 supported_ = kDefaultCpuFeatures;
123
124 // Put the CPU flags in rax.
125 // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
126 __ movl(rax, Immediate(1));
127 __ and_(rcx, rax); // Bit 0 is set if SAHF instruction supported.
128 __ not_(rax);
129 __ and_(rax, rdi);
130 __ or_(rax, rcx);
131 __ or_(rax, Immediate(1 << CPUID));
132
133 // Done.
134 __ bind(&done);
135 __ movq(rsp, rbp);
136 __ pop(rbx);
137 __ pop(rcx);
138 __ pop(rdi);
139 __ popfq();
140 __ pop(rbp);
141 __ ret(0);
142 #undef __
143
144 typedef uint64_t (*F0)();
145 F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
146
147 uint64_t probed_features = probe();
148 uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform(); 88 uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
149 supported_ = probed_features | platform_features; 89 supported_ = probed_features | platform_features;
150 found_by_runtime_probing_only_ 90 found_by_runtime_probing_only_
151 = probed_features & ~kDefaultCpuFeatures & ~platform_features; 91 = probed_features & ~kDefaultCpuFeatures & ~platform_features;
152
153 // CMOV must be available on an X64 CPU.
154 ASSERT(IsSupported(CPUID));
155 ASSERT(IsSupported(CMOV));
156
157 delete memory;
158 } 92 }
159 93
160 94
161 // ----------------------------------------------------------------------------- 95 // -----------------------------------------------------------------------------
162 // Implementation of RelocInfo 96 // Implementation of RelocInfo
163 97
164 // Patch the code at the current PC with a call to the target address. 98 // Patch the code at the current PC with a call to the target address.
165 // Additional guard int3 instructions can be added if required. 99 // Additional guard int3 instructions can be added if required.
166 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 100 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
167 int code_size = Assembler::kCallSequenceLength + guard_bytes; 101 int code_size = Assembler::kCallSequenceLength + guard_bytes;
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 914
981 void Assembler::cmpb_al(Immediate imm8) { 915 void Assembler::cmpb_al(Immediate imm8) {
982 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_)); 916 ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
983 EnsureSpace ensure_space(this); 917 EnsureSpace ensure_space(this);
984 emit(0x3c); 918 emit(0x3c);
985 emit(imm8.value_); 919 emit(imm8.value_);
986 } 920 }
987 921
988 922
989 void Assembler::cpuid() { 923 void Assembler::cpuid() {
990 ASSERT(IsEnabled(CPUID));
991 EnsureSpace ensure_space(this); 924 EnsureSpace ensure_space(this);
992 emit(0x0F); 925 emit(0x0F);
993 emit(0xA2); 926 emit(0xA2);
994 } 927 }
995 928
996 929
997 void Assembler::cqo() { 930 void Assembler::cqo() {
998 EnsureSpace ensure_space(this); 931 EnsureSpace ensure_space(this);
999 emit_rex_64(); 932 emit_rex_64();
1000 emit(0x99); 933 emit(0x99);
(...skipping 2102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3103 bool RelocInfo::IsCodedSpecially() { 3036 bool RelocInfo::IsCodedSpecially() {
3104 // The deserializer needs to know whether a pointer is specially coded. Being 3037 // The deserializer needs to know whether a pointer is specially coded. Being
3105 // specially coded on x64 means that it is a relative 32 bit address, as used 3038 // specially coded on x64 means that it is a relative 32 bit address, as used
3106 // by branch instructions. 3039 // by branch instructions.
3107 return (1 << rmode_) & kApplyMask; 3040 return (1 << rmode_) & kApplyMask;
3108 } 3041 }
3109 3042
3110 } } // namespace v8::internal 3043 } } // namespace v8::internal
3111 3044
3112 #endif // V8_TARGET_ARCH_X64 3045 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/v8globals.h ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698