Thu, 27 May 2010 19:08:38 -0700
6941466: Oracle rebranding changes for Hotspot repositories
Summary: Change all the Sun copyrights to Oracle copyright
Reviewed-by: ohair
twisti@1020 | 1 | /* |
trims@1907 | 2 | * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. |
twisti@1020 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
twisti@1020 | 4 | * |
twisti@1020 | 5 | * This code is free software; you can redistribute it and/or modify it |
twisti@1020 | 6 | * under the terms of the GNU General Public License version 2 only, as |
twisti@1020 | 7 | * published by the Free Software Foundation. |
twisti@1020 | 8 | * |
twisti@1020 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
twisti@1020 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
twisti@1020 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
twisti@1020 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
twisti@1020 | 13 | * accompanied this code). |
twisti@1020 | 14 | * |
twisti@1020 | 15 | * You should have received a copy of the GNU General Public License version |
twisti@1020 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
twisti@1020 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
twisti@1020 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
twisti@1020 | 22 | * |
twisti@1020 | 23 | */ |
twisti@1020 | 24 | |
twisti@1020 | 25 | class VM_Version : public Abstract_VM_Version { |
twisti@1020 | 26 | public: |
twisti@1020 | 27 | // cpuid result register layouts. These are all unions of a uint32_t |
twisti@1020 | 28 | // (in case anyone wants access to the register as a whole) and a bitfield. |
twisti@1020 | 29 | |
twisti@1020 | 30 | union StdCpuid1Eax { |
twisti@1020 | 31 | uint32_t value; |
twisti@1020 | 32 | struct { |
twisti@1020 | 33 | uint32_t stepping : 4, |
twisti@1020 | 34 | model : 4, |
twisti@1020 | 35 | family : 4, |
twisti@1020 | 36 | proc_type : 2, |
twisti@1020 | 37 | : 2, |
twisti@1020 | 38 | ext_model : 4, |
twisti@1020 | 39 | ext_family : 8, |
twisti@1020 | 40 | : 4; |
twisti@1020 | 41 | } bits; |
twisti@1020 | 42 | }; |
twisti@1020 | 43 | |
twisti@1020 | 44 | union StdCpuid1Ebx { // example, unused |
twisti@1020 | 45 | uint32_t value; |
twisti@1020 | 46 | struct { |
twisti@1020 | 47 | uint32_t brand_id : 8, |
twisti@1020 | 48 | clflush_size : 8, |
twisti@1020 | 49 | threads_per_cpu : 8, |
twisti@1020 | 50 | apic_id : 8; |
twisti@1020 | 51 | } bits; |
twisti@1020 | 52 | }; |
twisti@1020 | 53 | |
twisti@1020 | 54 | union StdCpuid1Ecx { |
twisti@1020 | 55 | uint32_t value; |
twisti@1020 | 56 | struct { |
twisti@1020 | 57 | uint32_t sse3 : 1, |
twisti@1020 | 58 | : 2, |
twisti@1020 | 59 | monitor : 1, |
twisti@1020 | 60 | : 1, |
twisti@1020 | 61 | vmx : 1, |
twisti@1020 | 62 | : 1, |
twisti@1020 | 63 | est : 1, |
twisti@1020 | 64 | : 1, |
twisti@1020 | 65 | ssse3 : 1, |
twisti@1020 | 66 | cid : 1, |
twisti@1020 | 67 | : 2, |
twisti@1020 | 68 | cmpxchg16: 1, |
twisti@1020 | 69 | : 4, |
twisti@1020 | 70 | dca : 1, |
twisti@1020 | 71 | sse4_1 : 1, |
twisti@1020 | 72 | sse4_2 : 1, |
twisti@1078 | 73 | : 2, |
twisti@1078 | 74 | popcnt : 1, |
twisti@1078 | 75 | : 8; |
twisti@1020 | 76 | } bits; |
twisti@1020 | 77 | }; |
twisti@1020 | 78 | |
twisti@1020 | 79 | union StdCpuid1Edx { |
twisti@1020 | 80 | uint32_t value; |
twisti@1020 | 81 | struct { |
twisti@1020 | 82 | uint32_t : 4, |
twisti@1020 | 83 | tsc : 1, |
twisti@1020 | 84 | : 3, |
twisti@1020 | 85 | cmpxchg8 : 1, |
twisti@1020 | 86 | : 6, |
twisti@1020 | 87 | cmov : 1, |
twisti@1020 | 88 | : 7, |
twisti@1020 | 89 | mmx : 1, |
twisti@1020 | 90 | fxsr : 1, |
twisti@1020 | 91 | sse : 1, |
twisti@1020 | 92 | sse2 : 1, |
twisti@1020 | 93 | : 1, |
twisti@1020 | 94 | ht : 1, |
twisti@1020 | 95 | : 3; |
twisti@1020 | 96 | } bits; |
twisti@1020 | 97 | }; |
twisti@1020 | 98 | |
twisti@1020 | 99 | union DcpCpuid4Eax { |
twisti@1020 | 100 | uint32_t value; |
twisti@1020 | 101 | struct { |
twisti@1020 | 102 | uint32_t cache_type : 5, |
twisti@1020 | 103 | : 21, |
twisti@1020 | 104 | cores_per_cpu : 6; |
twisti@1020 | 105 | } bits; |
twisti@1020 | 106 | }; |
twisti@1020 | 107 | |
twisti@1020 | 108 | union DcpCpuid4Ebx { |
twisti@1020 | 109 | uint32_t value; |
twisti@1020 | 110 | struct { |
twisti@1020 | 111 | uint32_t L1_line_size : 12, |
twisti@1020 | 112 | partitions : 10, |
twisti@1020 | 113 | associativity : 10; |
twisti@1020 | 114 | } bits; |
twisti@1020 | 115 | }; |
twisti@1020 | 116 | |
twisti@1020 | 117 | union ExtCpuid1Ecx { |
twisti@1020 | 118 | uint32_t value; |
twisti@1020 | 119 | struct { |
twisti@1020 | 120 | uint32_t LahfSahf : 1, |
twisti@1020 | 121 | CmpLegacy : 1, |
twisti@1020 | 122 | : 4, |
twisti@1210 | 123 | lzcnt : 1, |
twisti@1020 | 124 | sse4a : 1, |
twisti@1020 | 125 | misalignsse : 1, |
twisti@1020 | 126 | prefetchw : 1, |
twisti@1020 | 127 | : 22; |
twisti@1020 | 128 | } bits; |
twisti@1020 | 129 | }; |
twisti@1020 | 130 | |
twisti@1020 | 131 | union ExtCpuid1Edx { |
twisti@1020 | 132 | uint32_t value; |
twisti@1020 | 133 | struct { |
twisti@1020 | 134 | uint32_t : 22, |
twisti@1020 | 135 | mmx_amd : 1, |
twisti@1020 | 136 | mmx : 1, |
twisti@1020 | 137 | fxsr : 1, |
twisti@1020 | 138 | : 4, |
twisti@1020 | 139 | long_mode : 1, |
twisti@1020 | 140 | tdnow2 : 1, |
twisti@1020 | 141 | tdnow : 1; |
twisti@1020 | 142 | } bits; |
twisti@1020 | 143 | }; |
twisti@1020 | 144 | |
twisti@1020 | 145 | union ExtCpuid5Ex { |
twisti@1020 | 146 | uint32_t value; |
twisti@1020 | 147 | struct { |
twisti@1020 | 148 | uint32_t L1_line_size : 8, |
twisti@1020 | 149 | L1_tag_lines : 8, |
twisti@1020 | 150 | L1_assoc : 8, |
twisti@1020 | 151 | L1_size : 8; |
twisti@1020 | 152 | } bits; |
twisti@1020 | 153 | }; |
twisti@1020 | 154 | |
twisti@1020 | 155 | union ExtCpuid8Ecx { |
twisti@1020 | 156 | uint32_t value; |
twisti@1020 | 157 | struct { |
twisti@1020 | 158 | uint32_t cores_per_cpu : 8, |
twisti@1020 | 159 | : 24; |
twisti@1020 | 160 | } bits; |
twisti@1020 | 161 | }; |
twisti@1020 | 162 | |
twisti@1020 | 163 | protected: |
twisti@1020 | 164 | static int _cpu; |
twisti@1020 | 165 | static int _model; |
twisti@1020 | 166 | static int _stepping; |
twisti@1020 | 167 | static int _cpuFeatures; // features returned by the "cpuid" instruction |
twisti@1020 | 168 | // 0 if this instruction is not available |
twisti@1020 | 169 | static const char* _features_str; |
twisti@1020 | 170 | |
twisti@1020 | 171 | enum { |
twisti@1020 | 172 | CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) |
twisti@1020 | 173 | CPU_CMOV = (1 << 1), |
twisti@1020 | 174 | CPU_FXSR = (1 << 2), |
twisti@1020 | 175 | CPU_HT = (1 << 3), |
twisti@1020 | 176 | CPU_MMX = (1 << 4), |
twisti@1020 | 177 | CPU_3DNOW = (1 << 5), // 3DNow comes from cpuid 0x80000001 (EDX) |
twisti@1020 | 178 | CPU_SSE = (1 << 6), |
twisti@1020 | 179 | CPU_SSE2 = (1 << 7), |
twisti@1020 | 180 | CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX) |
twisti@1020 | 181 | CPU_SSSE3 = (1 << 9), |
twisti@1020 | 182 | CPU_SSE4A = (1 << 10), |
twisti@1020 | 183 | CPU_SSE4_1 = (1 << 11), |
twisti@1078 | 184 | CPU_SSE4_2 = (1 << 12), |
twisti@1210 | 185 | CPU_POPCNT = (1 << 13), |
twisti@1210 | 186 | CPU_LZCNT = (1 << 14) |
twisti@1020 | 187 | } cpuFeatureFlags; |
twisti@1020 | 188 | |
twisti@1020 | 189 | // cpuid information block. All info derived from executing cpuid with |
twisti@1020 | 190 | // various function numbers is stored here. Intel and AMD info is |
twisti@1020 | 191 | // merged in this block: accessor methods disentangle it. |
twisti@1020 | 192 | // |
twisti@1020 | 193 | // The info block is laid out in subblocks of 4 dwords corresponding to |
twisti@1020 | 194 | // eax, ebx, ecx and edx, whether or not they contain anything useful. |
twisti@1020 | 195 | struct CpuidInfo { |
twisti@1020 | 196 | // cpuid function 0 |
twisti@1020 | 197 | uint32_t std_max_function; |
twisti@1020 | 198 | uint32_t std_vendor_name_0; |
twisti@1020 | 199 | uint32_t std_vendor_name_1; |
twisti@1020 | 200 | uint32_t std_vendor_name_2; |
twisti@1020 | 201 | |
twisti@1020 | 202 | // cpuid function 1 |
twisti@1020 | 203 | StdCpuid1Eax std_cpuid1_eax; |
twisti@1020 | 204 | StdCpuid1Ebx std_cpuid1_ebx; |
twisti@1020 | 205 | StdCpuid1Ecx std_cpuid1_ecx; |
twisti@1020 | 206 | StdCpuid1Edx std_cpuid1_edx; |
twisti@1020 | 207 | |
twisti@1020 | 208 | // cpuid function 4 (deterministic cache parameters) |
twisti@1020 | 209 | DcpCpuid4Eax dcp_cpuid4_eax; |
twisti@1020 | 210 | DcpCpuid4Ebx dcp_cpuid4_ebx; |
twisti@1020 | 211 | uint32_t dcp_cpuid4_ecx; // unused currently |
twisti@1020 | 212 | uint32_t dcp_cpuid4_edx; // unused currently |
twisti@1020 | 213 | |
twisti@1020 | 214 | // cpuid function 0x80000000 // example, unused |
twisti@1020 | 215 | uint32_t ext_max_function; |
twisti@1020 | 216 | uint32_t ext_vendor_name_0; |
twisti@1020 | 217 | uint32_t ext_vendor_name_1; |
twisti@1020 | 218 | uint32_t ext_vendor_name_2; |
twisti@1020 | 219 | |
twisti@1020 | 220 | // cpuid function 0x80000001 |
twisti@1020 | 221 | uint32_t ext_cpuid1_eax; // reserved |
twisti@1020 | 222 | uint32_t ext_cpuid1_ebx; // reserved |
twisti@1020 | 223 | ExtCpuid1Ecx ext_cpuid1_ecx; |
twisti@1020 | 224 | ExtCpuid1Edx ext_cpuid1_edx; |
twisti@1020 | 225 | |
twisti@1020 | 226 | // cpuid functions 0x80000002 thru 0x80000004: example, unused |
twisti@1020 | 227 | uint32_t proc_name_0, proc_name_1, proc_name_2, proc_name_3; |
twisti@1020 | 228 | uint32_t proc_name_4, proc_name_5, proc_name_6, proc_name_7; |
twisti@1020 | 229 | uint32_t proc_name_8, proc_name_9, proc_name_10,proc_name_11; |
twisti@1020 | 230 | |
twisti@1020 | 231 | // cpuid function 0x80000005 //AMD L1, Intel reserved |
twisti@1020 | 232 | uint32_t ext_cpuid5_eax; // unused currently |
twisti@1020 | 233 | uint32_t ext_cpuid5_ebx; // reserved |
twisti@1020 | 234 | ExtCpuid5Ex ext_cpuid5_ecx; // L1 data cache info (AMD) |
twisti@1020 | 235 | ExtCpuid5Ex ext_cpuid5_edx; // L1 instruction cache info (AMD) |
twisti@1020 | 236 | |
twisti@1020 | 237 | // cpuid function 0x80000008 |
twisti@1020 | 238 | uint32_t ext_cpuid8_eax; // unused currently |
twisti@1020 | 239 | uint32_t ext_cpuid8_ebx; // reserved |
twisti@1020 | 240 | ExtCpuid8Ecx ext_cpuid8_ecx; |
twisti@1020 | 241 | uint32_t ext_cpuid8_edx; // reserved |
twisti@1020 | 242 | }; |
twisti@1020 | 243 | |
twisti@1020 | 244 | // The actual cpuid info block |
twisti@1020 | 245 | static CpuidInfo _cpuid_info; |
twisti@1020 | 246 | |
twisti@1020 | 247 | // Extractors and predicates |
twisti@1020 | 248 | static uint32_t extended_cpu_family() { |
twisti@1020 | 249 | uint32_t result = _cpuid_info.std_cpuid1_eax.bits.family; |
twisti@1020 | 250 | result += _cpuid_info.std_cpuid1_eax.bits.ext_family; |
twisti@1020 | 251 | return result; |
twisti@1020 | 252 | } |
twisti@1020 | 253 | static uint32_t extended_cpu_model() { |
twisti@1020 | 254 | uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model; |
twisti@1020 | 255 | result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4; |
twisti@1020 | 256 | return result; |
twisti@1020 | 257 | } |
twisti@1020 | 258 | static uint32_t cpu_stepping() { |
twisti@1020 | 259 | uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping; |
twisti@1020 | 260 | return result; |
twisti@1020 | 261 | } |
twisti@1020 | 262 | static uint logical_processor_count() { |
twisti@1020 | 263 | uint result = threads_per_core(); |
twisti@1020 | 264 | return result; |
twisti@1020 | 265 | } |
twisti@1020 | 266 | static uint32_t feature_flags() { |
twisti@1020 | 267 | uint32_t result = 0; |
twisti@1020 | 268 | if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0) |
twisti@1020 | 269 | result |= CPU_CX8; |
twisti@1020 | 270 | if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0) |
twisti@1020 | 271 | result |= CPU_CMOV; |
twisti@1020 | 272 | if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || is_amd() && |
twisti@1020 | 273 | _cpuid_info.ext_cpuid1_edx.bits.fxsr != 0) |
twisti@1020 | 274 | result |= CPU_FXSR; |
twisti@1020 | 275 | // HT flag is set for multi-core processors also. |
twisti@1020 | 276 | if (threads_per_core() > 1) |
twisti@1020 | 277 | result |= CPU_HT; |
twisti@1020 | 278 | if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || is_amd() && |
twisti@1020 | 279 | _cpuid_info.ext_cpuid1_edx.bits.mmx != 0) |
twisti@1020 | 280 | result |= CPU_MMX; |
twisti@1020 | 281 | if (_cpuid_info.std_cpuid1_edx.bits.sse != 0) |
twisti@1020 | 282 | result |= CPU_SSE; |
twisti@1020 | 283 | if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0) |
twisti@1020 | 284 | result |= CPU_SSE2; |
twisti@1020 | 285 | if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0) |
twisti@1020 | 286 | result |= CPU_SSE3; |
twisti@1020 | 287 | if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0) |
twisti@1020 | 288 | result |= CPU_SSSE3; |
twisti@1020 | 289 | if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0) |
twisti@1020 | 290 | result |= CPU_SSE4_1; |
twisti@1020 | 291 | if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) |
twisti@1020 | 292 | result |= CPU_SSE4_2; |
twisti@1078 | 293 | if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) |
twisti@1078 | 294 | result |= CPU_POPCNT; |
twisti@1210 | 295 | |
twisti@1210 | 296 | // AMD features. |
twisti@1210 | 297 | if (is_amd()) { |
twisti@1210 | 298 | if (_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) |
twisti@1210 | 299 | result |= CPU_3DNOW; |
twisti@1210 | 300 | if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0) |
twisti@1210 | 301 | result |= CPU_LZCNT; |
twisti@1210 | 302 | if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) |
twisti@1210 | 303 | result |= CPU_SSE4A; |
twisti@1210 | 304 | } |
twisti@1210 | 305 | |
twisti@1020 | 306 | return result; |
twisti@1020 | 307 | } |
twisti@1020 | 308 | |
twisti@1020 | 309 | static void get_processor_features(); |
twisti@1020 | 310 | |
twisti@1020 | 311 | public: |
twisti@1020 | 312 | // Offsets for cpuid asm stub |
twisti@1020 | 313 | static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } |
twisti@1020 | 314 | static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } |
twisti@1020 | 315 | static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } |
twisti@1020 | 316 | static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); } |
twisti@1020 | 317 | static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); } |
twisti@1020 | 318 | static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); } |
twisti@1020 | 319 | |
twisti@1020 | 320 | // Initialization |
twisti@1020 | 321 | static void initialize(); |
twisti@1020 | 322 | |
twisti@1020 | 323 | // Asserts |
twisti@1020 | 324 | static void assert_is_initialized() { |
twisti@1020 | 325 | assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized"); |
twisti@1020 | 326 | } |
twisti@1020 | 327 | |
twisti@1020 | 328 | // |
twisti@1020 | 329 | // Processor family: |
twisti@1020 | 330 | // 3 - 386 |
twisti@1020 | 331 | // 4 - 486 |
twisti@1020 | 332 | // 5 - Pentium |
twisti@1020 | 333 | // 6 - PentiumPro, Pentium II, Celeron, Xeon, Pentium III, Athlon, |
twisti@1020 | 334 | // Pentium M, Core Solo, Core Duo, Core2 Duo |
twisti@1020 | 335 | // family 6 model: 9, 13, 14, 15 |
twisti@1020 | 336 | // 0x0f - Pentium 4, Opteron |
twisti@1020 | 337 | // |
twisti@1020 | 338 | // Note: The cpu family should be used to select between |
twisti@1020 | 339 | // instruction sequences which are valid on all Intel |
twisti@1020 | 340 | // processors. Use the feature test functions below to |
twisti@1020 | 341 | // determine whether a particular instruction is supported. |
twisti@1020 | 342 | // |
twisti@1020 | 343 | static int cpu_family() { return _cpu;} |
twisti@1020 | 344 | static bool is_P6() { return cpu_family() >= 6; } |
twisti@1020 | 345 | |
twisti@1020 | 346 | static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' |
twisti@1020 | 347 | static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG' |
twisti@1020 | 348 | |
twisti@1020 | 349 | static uint cores_per_cpu() { |
twisti@1020 | 350 | uint result = 1; |
twisti@1020 | 351 | if (is_intel()) { |
twisti@1020 | 352 | result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1); |
twisti@1020 | 353 | } else if (is_amd()) { |
twisti@1020 | 354 | result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1); |
twisti@1020 | 355 | } |
twisti@1020 | 356 | return result; |
twisti@1020 | 357 | } |
twisti@1020 | 358 | |
twisti@1020 | 359 | static uint threads_per_core() { |
twisti@1020 | 360 | uint result = 1; |
twisti@1020 | 361 | if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) { |
twisti@1020 | 362 | result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu / |
twisti@1020 | 363 | cores_per_cpu(); |
twisti@1020 | 364 | } |
twisti@1020 | 365 | return result; |
twisti@1020 | 366 | } |
twisti@1020 | 367 | |
twisti@1020 | 368 | static intx L1_data_cache_line_size() { |
twisti@1020 | 369 | intx result = 0; |
twisti@1020 | 370 | if (is_intel()) { |
twisti@1020 | 371 | result = (_cpuid_info.dcp_cpuid4_ebx.bits.L1_line_size + 1); |
twisti@1020 | 372 | } else if (is_amd()) { |
twisti@1020 | 373 | result = _cpuid_info.ext_cpuid5_ecx.bits.L1_line_size; |
twisti@1020 | 374 | } |
twisti@1020 | 375 | if (result < 32) // not defined ? |
twisti@1020 | 376 | result = 32; // 32 bytes by default on x86 and other x64 |
twisti@1020 | 377 | return result; |
twisti@1020 | 378 | } |
twisti@1020 | 379 | |
twisti@1020 | 380 | // |
twisti@1020 | 381 | // Feature identification |
twisti@1020 | 382 | // |
twisti@1020 | 383 | static bool supports_cpuid() { return _cpuFeatures != 0; } |
twisti@1020 | 384 | static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; } |
twisti@1020 | 385 | static bool supports_cmov() { return (_cpuFeatures & CPU_CMOV) != 0; } |
twisti@1020 | 386 | static bool supports_fxsr() { return (_cpuFeatures & CPU_FXSR) != 0; } |
twisti@1020 | 387 | static bool supports_ht() { return (_cpuFeatures & CPU_HT) != 0; } |
twisti@1020 | 388 | static bool supports_mmx() { return (_cpuFeatures & CPU_MMX) != 0; } |
twisti@1020 | 389 | static bool supports_sse() { return (_cpuFeatures & CPU_SSE) != 0; } |
twisti@1020 | 390 | static bool supports_sse2() { return (_cpuFeatures & CPU_SSE2) != 0; } |
twisti@1020 | 391 | static bool supports_sse3() { return (_cpuFeatures & CPU_SSE3) != 0; } |
twisti@1020 | 392 | static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } |
twisti@1020 | 393 | static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } |
twisti@1020 | 394 | static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } |
twisti@1078 | 395 | static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } |
twisti@1020 | 396 | // |
twisti@1020 | 397 | // AMD features |
twisti@1020 | 398 | // |
twisti@1020 | 399 | static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; } |
twisti@1020 | 400 | static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } |
twisti@1020 | 401 | static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; } |
twisti@1210 | 402 | static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; } |
twisti@1020 | 403 | static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } |
twisti@1020 | 404 | |
twisti@1020 | 405 | static bool supports_compare_and_exchange() { return true; } |
twisti@1020 | 406 | |
twisti@1020 | 407 | static const char* cpu_features() { return _features_str; } |
twisti@1020 | 408 | |
twisti@1020 | 409 | static intx allocate_prefetch_distance() { |
twisti@1020 | 410 | // This method should be called before allocate_prefetch_style(). |
twisti@1020 | 411 | // |
twisti@1020 | 412 | // Hardware prefetching (distance/size in bytes): |
twisti@1020 | 413 | // Pentium 3 - 64 / 32 |
twisti@1020 | 414 | // Pentium 4 - 256 / 128 |
twisti@1020 | 415 | // Athlon - 64 / 32 ???? |
twisti@1020 | 416 | // Opteron - 128 / 64 only when 2 sequential cache lines accessed |
twisti@1020 | 417 | // Core - 128 / 64 |
twisti@1020 | 418 | // |
twisti@1020 | 419 | // Software prefetching (distance in bytes / instruction with best score): |
twisti@1020 | 420 | // Pentium 3 - 128 / prefetchnta |
twisti@1020 | 421 | // Pentium 4 - 512 / prefetchnta |
twisti@1020 | 422 | // Athlon - 128 / prefetchnta |
twisti@1020 | 423 | // Opteron - 256 / prefetchnta |
twisti@1020 | 424 | // Core - 256 / prefetchnta |
twisti@1020 | 425 | // It will be used only when AllocatePrefetchStyle > 0 |
twisti@1020 | 426 | |
twisti@1020 | 427 | intx count = AllocatePrefetchDistance; |
twisti@1020 | 428 | if (count < 0) { // default ? |
twisti@1020 | 429 | if (is_amd()) { // AMD |
twisti@1020 | 430 | if (supports_sse2()) |
twisti@1020 | 431 | count = 256; // Opteron |
twisti@1020 | 432 | else |
twisti@1020 | 433 | count = 128; // Athlon |
twisti@1020 | 434 | } else { // Intel |
twisti@1020 | 435 | if (supports_sse2()) |
twisti@1020 | 436 | if (cpu_family() == 6) { |
twisti@1020 | 437 | count = 256; // Pentium M, Core, Core2 |
twisti@1020 | 438 | } else { |
twisti@1020 | 439 | count = 512; // Pentium 4 |
twisti@1020 | 440 | } |
twisti@1020 | 441 | else |
twisti@1020 | 442 | count = 128; // Pentium 3 (and all other old CPUs) |
twisti@1020 | 443 | } |
twisti@1020 | 444 | } |
twisti@1020 | 445 | return count; |
twisti@1020 | 446 | } |
twisti@1020 | 447 | static intx allocate_prefetch_style() { |
twisti@1020 | 448 | assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); |
twisti@1020 | 449 | // Return 0 if AllocatePrefetchDistance was not defined. |
twisti@1020 | 450 | return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0; |
twisti@1020 | 451 | } |
twisti@1020 | 452 | |
twisti@1020 | 453 | // Prefetch interval for gc copy/scan == 9 dcache lines. Derived from |
twisti@1020 | 454 | // 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap. |
twisti@1020 | 455 | // Tested intervals from 128 to 2048 in increments of 64 == one cache line. |
twisti@1020 | 456 | // 256 bytes (4 dcache lines) was the nearest runner-up to 576. |
twisti@1020 | 457 | |
twisti@1020 | 458 | // gc copy/scan is disabled if prefetchw isn't supported, because |
twisti@1020 | 459 | // Prefetch::write emits an inlined prefetchw on Linux. |
twisti@1020 | 460 | // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. |
twisti@1020 | 461 | // The used prefetcht0 instruction works for both amd64 and em64t. |
twisti@1020 | 462 | static intx prefetch_copy_interval_in_bytes() { |
twisti@1020 | 463 | intx interval = PrefetchCopyIntervalInBytes; |
twisti@1020 | 464 | return interval >= 0 ? interval : 576; |
twisti@1020 | 465 | } |
twisti@1020 | 466 | static intx prefetch_scan_interval_in_bytes() { |
twisti@1020 | 467 | intx interval = PrefetchScanIntervalInBytes; |
twisti@1020 | 468 | return interval >= 0 ? interval : 576; |
twisti@1020 | 469 | } |
twisti@1020 | 470 | static intx prefetch_fields_ahead() { |
twisti@1020 | 471 | intx count = PrefetchFieldsAhead; |
twisti@1020 | 472 | return count >= 0 ? count : 1; |
twisti@1020 | 473 | } |
twisti@1020 | 474 | }; |