| 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 |