| 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 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1912 emitl(imm32); | 1845 emitl(imm32); |
| 1913 } | 1846 } |
| 1914 | 1847 |
| 1915 | 1848 |
| 1916 void Assembler::pushfq() { | 1849 void Assembler::pushfq() { |
| 1917 EnsureSpace ensure_space(this); | 1850 EnsureSpace ensure_space(this); |
| 1918 emit(0x9C); | 1851 emit(0x9C); |
| 1919 } | 1852 } |
| 1920 | 1853 |
| 1921 | 1854 |
| 1922 void Assembler::rdtsc() { | |
| 1923 EnsureSpace ensure_space(this); | |
| 1924 emit(0x0F); | |
| 1925 emit(0x31); | |
| 1926 } | |
| 1927 | |
| 1928 | |
| 1929 void Assembler::ret(int imm16) { | 1855 void Assembler::ret(int imm16) { |
| 1930 EnsureSpace ensure_space(this); | 1856 EnsureSpace ensure_space(this); |
| 1931 ASSERT(is_uint16(imm16)); | 1857 ASSERT(is_uint16(imm16)); |
| 1932 if (imm16 == 0) { | 1858 if (imm16 == 0) { |
| 1933 emit(0xC3); | 1859 emit(0xC3); |
| 1934 } else { | 1860 } else { |
| 1935 emit(0xC2); | 1861 emit(0xC2); |
| 1936 emit(imm16 & 0xFF); | 1862 emit(imm16 & 0xFF); |
| 1937 emit((imm16 >> 8) & 0xFF); | 1863 emit((imm16 >> 8) & 0xFF); |
| 1938 } | 1864 } |
| (...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2985 void Assembler::ucomisd(XMMRegister dst, const Operand& src) { | 2911 void Assembler::ucomisd(XMMRegister dst, const Operand& src) { |
| 2986 EnsureSpace ensure_space(this); | 2912 EnsureSpace ensure_space(this); |
| 2987 emit(0x66); | 2913 emit(0x66); |
| 2988 emit_optional_rex_32(dst, src); | 2914 emit_optional_rex_32(dst, src); |
| 2989 emit(0x0f); | 2915 emit(0x0f); |
| 2990 emit(0x2e); | 2916 emit(0x2e); |
| 2991 emit_sse_operand(dst, src); | 2917 emit_sse_operand(dst, src); |
| 2992 } | 2918 } |
| 2993 | 2919 |
| 2994 | 2920 |
| 2921 void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) { |
| 2922 EnsureSpace ensure_space(this); |
| 2923 emit(0xF2); |
| 2924 emit_optional_rex_32(dst, src); |
| 2925 emit(0x0F); |
| 2926 emit(0xC2); |
| 2927 emit_sse_operand(dst, src); |
| 2928 emit(0x01); // LT == 1 |
| 2929 } |
| 2930 |
| 2931 |
| 2995 void Assembler::roundsd(XMMRegister dst, XMMRegister src, | 2932 void Assembler::roundsd(XMMRegister dst, XMMRegister src, |
| 2996 Assembler::RoundingMode mode) { | 2933 Assembler::RoundingMode mode) { |
| 2997 ASSERT(IsEnabled(SSE4_1)); | 2934 ASSERT(IsEnabled(SSE4_1)); |
| 2998 EnsureSpace ensure_space(this); | 2935 EnsureSpace ensure_space(this); |
| 2999 emit(0x66); | 2936 emit(0x66); |
| 3000 emit_optional_rex_32(dst, src); | 2937 emit_optional_rex_32(dst, src); |
| 3001 emit(0x0f); | 2938 emit(0x0f); |
| 3002 emit(0x3a); | 2939 emit(0x3a); |
| 3003 emit(0x0b); | 2940 emit(0x0b); |
| 3004 emit_sse_operand(dst, src); | 2941 emit_sse_operand(dst, src); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3110 bool RelocInfo::IsCodedSpecially() { | 3047 bool RelocInfo::IsCodedSpecially() { |
| 3111 // The deserializer needs to know whether a pointer is specially coded. Being | 3048 // The deserializer needs to know whether a pointer is specially coded. Being |
| 3112 // specially coded on x64 means that it is a relative 32 bit address, as used | 3049 // specially coded on x64 means that it is a relative 32 bit address, as used |
| 3113 // by branch instructions. | 3050 // by branch instructions. |
| 3114 return (1 << rmode_) & kApplyMask; | 3051 return (1 << rmode_) & kApplyMask; |
| 3115 } | 3052 } |
| 3116 | 3053 |
| 3117 } } // namespace v8::internal | 3054 } } // namespace v8::internal |
| 3118 | 3055 |
| 3119 #endif // V8_TARGET_ARCH_X64 | 3056 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |