OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |