1
|
1 |
/*
|
670
|
2 |
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
1
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation.
|
|
8 |
*
|
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
13 |
* accompanied this code).
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License version
|
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 |
*
|
|
19 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 |
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 |
* have any questions.
|
|
22 |
*
|
|
23 |
*/
|
|
24 |
|
|
25 |
# include "incls/_precompiled.incl"
|
|
26 |
# include "incls/_vm_version_x86_64.cpp.incl"
|
|
27 |
|
|
28 |
int VM_Version::_cpu;
|
|
29 |
int VM_Version::_model;
|
|
30 |
int VM_Version::_stepping;
|
|
31 |
int VM_Version::_cpuFeatures;
|
|
32 |
const char* VM_Version::_features_str = "";
|
|
33 |
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
|
|
34 |
|
|
35 |
static BufferBlob* stub_blob;
|
|
36 |
static const int stub_size = 300;
|
|
37 |
|
|
38 |
extern "C" {
|
|
39 |
typedef void (*getPsrInfo_stub_t)(void*);
|
|
40 |
}
|
|
41 |
static getPsrInfo_stub_t getPsrInfo_stub = NULL;
|
|
42 |
|
|
43 |
|
|
44 |
class VM_Version_StubGenerator: public StubCodeGenerator {
|
|
45 |
public:
|
|
46 |
|
|
47 |
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
|
|
48 |
|
|
49 |
address generate_getPsrInfo() {
|
|
50 |
|
|
51 |
Label std_cpuid1, ext_cpuid1, ext_cpuid5, done;
|
|
52 |
|
|
53 |
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
|
|
54 |
# define __ _masm->
|
|
55 |
|
|
56 |
address start = __ pc();
|
|
57 |
|
|
58 |
//
|
|
59 |
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
|
|
60 |
//
|
|
61 |
// rcx and rdx are first and second argument registers on windows
|
|
62 |
|
1066
|
63 |
__ push(rbp);
|
|
64 |
__ mov(rbp, c_rarg0); // cpuid_info address
|
|
65 |
__ push(rbx);
|
|
66 |
__ push(rsi);
|
1
|
67 |
|
|
68 |
//
|
|
69 |
// we have a chip which supports the "cpuid" instruction
|
|
70 |
//
|
|
71 |
__ xorl(rax, rax);
|
|
72 |
__ cpuid();
|
1066
|
73 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset())));
|
1
|
74 |
__ movl(Address(rsi, 0), rax);
|
|
75 |
__ movl(Address(rsi, 4), rbx);
|
|
76 |
__ movl(Address(rsi, 8), rcx);
|
|
77 |
__ movl(Address(rsi,12), rdx);
|
|
78 |
|
|
79 |
__ cmpl(rax, 3); // Is cpuid(0x4) supported?
|
|
80 |
__ jccb(Assembler::belowEqual, std_cpuid1);
|
|
81 |
|
|
82 |
//
|
|
83 |
// cpuid(0x4) Deterministic cache params
|
|
84 |
//
|
|
85 |
__ movl(rax, 4);
|
|
86 |
__ xorl(rcx, rcx); // L1 cache
|
|
87 |
__ cpuid();
|
1066
|
88 |
__ push(rax);
|
1
|
89 |
__ andl(rax, 0x1f); // Determine if valid cache parameters used
|
|
90 |
__ orl(rax, rax); // eax[4:0] == 0 indicates invalid cache
|
1066
|
91 |
__ pop(rax);
|
1
|
92 |
__ jccb(Assembler::equal, std_cpuid1);
|
|
93 |
|
1066
|
94 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::dcp_cpuid4_offset())));
|
1
|
95 |
__ movl(Address(rsi, 0), rax);
|
|
96 |
__ movl(Address(rsi, 4), rbx);
|
|
97 |
__ movl(Address(rsi, 8), rcx);
|
|
98 |
__ movl(Address(rsi,12), rdx);
|
|
99 |
|
|
100 |
//
|
|
101 |
// Standard cpuid(0x1)
|
|
102 |
//
|
|
103 |
__ bind(std_cpuid1);
|
|
104 |
__ movl(rax, 1);
|
|
105 |
__ cpuid();
|
1066
|
106 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
|
1
|
107 |
__ movl(Address(rsi, 0), rax);
|
|
108 |
__ movl(Address(rsi, 4), rbx);
|
|
109 |
__ movl(Address(rsi, 8), rcx);
|
|
110 |
__ movl(Address(rsi,12), rdx);
|
|
111 |
|
|
112 |
__ movl(rax, 0x80000000);
|
|
113 |
__ cpuid();
|
|
114 |
__ cmpl(rax, 0x80000000); // Is cpuid(0x80000001) supported?
|
|
115 |
__ jcc(Assembler::belowEqual, done);
|
|
116 |
__ cmpl(rax, 0x80000004); // Is cpuid(0x80000005) supported?
|
|
117 |
__ jccb(Assembler::belowEqual, ext_cpuid1);
|
|
118 |
__ cmpl(rax, 0x80000007); // Is cpuid(0x80000008) supported?
|
|
119 |
__ jccb(Assembler::belowEqual, ext_cpuid5);
|
|
120 |
//
|
|
121 |
// Extended cpuid(0x80000008)
|
|
122 |
//
|
|
123 |
__ movl(rax, 0x80000008);
|
|
124 |
__ cpuid();
|
1066
|
125 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid8_offset())));
|
1
|
126 |
__ movl(Address(rsi, 0), rax);
|
|
127 |
__ movl(Address(rsi, 4), rbx);
|
|
128 |
__ movl(Address(rsi, 8), rcx);
|
|
129 |
__ movl(Address(rsi,12), rdx);
|
|
130 |
|
|
131 |
//
|
|
132 |
// Extended cpuid(0x80000005)
|
|
133 |
//
|
|
134 |
__ bind(ext_cpuid5);
|
|
135 |
__ movl(rax, 0x80000005);
|
|
136 |
__ cpuid();
|
1066
|
137 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid5_offset())));
|
1
|
138 |
__ movl(Address(rsi, 0), rax);
|
|
139 |
__ movl(Address(rsi, 4), rbx);
|
|
140 |
__ movl(Address(rsi, 8), rcx);
|
|
141 |
__ movl(Address(rsi,12), rdx);
|
|
142 |
|
|
143 |
//
|
|
144 |
// Extended cpuid(0x80000001)
|
|
145 |
//
|
|
146 |
__ bind(ext_cpuid1);
|
|
147 |
__ movl(rax, 0x80000001);
|
|
148 |
__ cpuid();
|
1066
|
149 |
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid1_offset())));
|
1
|
150 |
__ movl(Address(rsi, 0), rax);
|
|
151 |
__ movl(Address(rsi, 4), rbx);
|
|
152 |
__ movl(Address(rsi, 8), rcx);
|
|
153 |
__ movl(Address(rsi,12), rdx);
|
|
154 |
|
|
155 |
//
|
|
156 |
// return
|
|
157 |
//
|
|
158 |
__ bind(done);
|
1066
|
159 |
__ pop(rsi);
|
|
160 |
__ pop(rbx);
|
|
161 |
__ pop(rbp);
|
1
|
162 |
__ ret(0);
|
|
163 |
|
|
164 |
# undef __
|
|
165 |
|
|
166 |
return start;
|
|
167 |
};
|
|
168 |
};
|
|
169 |
|
|
170 |
|
|
171 |
void VM_Version::get_processor_features() {
|
|
172 |
|
|
173 |
_logical_processors_per_package = 1;
|
|
174 |
// Get raw processor info
|
|
175 |
getPsrInfo_stub(&_cpuid_info);
|
|
176 |
assert_is_initialized();
|
|
177 |
_cpu = extended_cpu_family();
|
|
178 |
_model = extended_cpu_model();
|
|
179 |
_stepping = cpu_stepping();
|
|
180 |
_cpuFeatures = feature_flags();
|
|
181 |
// Logical processors are only available on P4s and above,
|
|
182 |
// and only if hyperthreading is available.
|
|
183 |
_logical_processors_per_package = logical_processor_count();
|
|
184 |
_supports_cx8 = supports_cmpxchg8();
|
|
185 |
// OS should support SSE for x64 and hardware should support at least SSE2.
|
|
186 |
if (!VM_Version::supports_sse2()) {
|
|
187 |
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
|
|
188 |
}
|
1437
|
189 |
if (UseSSE < 4) {
|
|
190 |
_cpuFeatures &= ~CPU_SSE4_1;
|
|
191 |
_cpuFeatures &= ~CPU_SSE4_2;
|
|
192 |
}
|
1
|
193 |
if (UseSSE < 3) {
|
|
194 |
_cpuFeatures &= ~CPU_SSE3;
|
|
195 |
_cpuFeatures &= ~CPU_SSSE3;
|
|
196 |
_cpuFeatures &= ~CPU_SSE4A;
|
|
197 |
}
|
|
198 |
if (UseSSE < 2)
|
|
199 |
_cpuFeatures &= ~CPU_SSE2;
|
|
200 |
if (UseSSE < 1)
|
|
201 |
_cpuFeatures &= ~CPU_SSE;
|
|
202 |
|
|
203 |
if (logical_processors_per_package() == 1) {
|
|
204 |
// HT processor could be installed on a system which doesn't support HT.
|
|
205 |
_cpuFeatures &= ~CPU_HT;
|
|
206 |
}
|
|
207 |
|
|
208 |
char buf[256];
|
1437
|
209 |
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
1
|
210 |
cores_per_cpu(), threads_per_core(),
|
|
211 |
cpu_family(), _model, _stepping,
|
|
212 |
(supports_cmov() ? ", cmov" : ""),
|
|
213 |
(supports_cmpxchg8() ? ", cx8" : ""),
|
|
214 |
(supports_fxsr() ? ", fxsr" : ""),
|
|
215 |
(supports_mmx() ? ", mmx" : ""),
|
|
216 |
(supports_sse() ? ", sse" : ""),
|
|
217 |
(supports_sse2() ? ", sse2" : ""),
|
|
218 |
(supports_sse3() ? ", sse3" : ""),
|
|
219 |
(supports_ssse3()? ", ssse3": ""),
|
1437
|
220 |
(supports_sse4_1() ? ", sse4.1" : ""),
|
|
221 |
(supports_sse4_2() ? ", sse4.2" : ""),
|
1
|
222 |
(supports_mmx_ext() ? ", mmxext" : ""),
|
|
223 |
(supports_3dnow() ? ", 3dnow" : ""),
|
|
224 |
(supports_3dnow2() ? ", 3dnowext" : ""),
|
|
225 |
(supports_sse4a() ? ", sse4a": ""),
|
|
226 |
(supports_ht() ? ", ht": ""));
|
|
227 |
_features_str = strdup(buf);
|
|
228 |
|
|
229 |
// UseSSE is set to the smaller of what hardware supports and what
|
|
230 |
// the command line requires. I.e., you cannot set UseSSE to 2 on
|
|
231 |
// older Pentiums which do not support it.
|
|
232 |
if( UseSSE > 4 ) UseSSE=4;
|
|
233 |
if( UseSSE < 0 ) UseSSE=0;
|
1437
|
234 |
if( !supports_sse4_1() ) // Drop to 3 if no SSE4 support
|
1
|
235 |
UseSSE = MIN2((intx)3,UseSSE);
|
|
236 |
if( !supports_sse3() ) // Drop to 2 if no SSE3 support
|
|
237 |
UseSSE = MIN2((intx)2,UseSSE);
|
|
238 |
if( !supports_sse2() ) // Drop to 1 if no SSE2 support
|
|
239 |
UseSSE = MIN2((intx)1,UseSSE);
|
|
240 |
if( !supports_sse () ) // Drop to 0 if no SSE support
|
|
241 |
UseSSE = 0;
|
|
242 |
|
|
243 |
// On new cpus instructions which update whole XMM register should be used
|
|
244 |
// to prevent partial register stall due to dependencies on high half.
|
|
245 |
//
|
|
246 |
// UseXmmLoadAndClearUpper == true --> movsd(xmm, mem)
|
|
247 |
// UseXmmLoadAndClearUpper == false --> movlpd(xmm, mem)
|
|
248 |
// UseXmmRegToRegMoveAll == true --> movaps(xmm, xmm), movapd(xmm, xmm).
|
|
249 |
// UseXmmRegToRegMoveAll == false --> movss(xmm, xmm), movsd(xmm, xmm).
|
|
250 |
|
|
251 |
if( is_amd() ) { // AMD cpus specific settings
|
|
252 |
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
|
|
253 |
// Use it on all AMD cpus starting from Opteron (don't need
|
|
254 |
// a cpu check since only Opteron and new cpus support 64-bits mode).
|
|
255 |
UseAddressNop = true;
|
|
256 |
}
|
|
257 |
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
|
258 |
if( supports_sse4a() ) {
|
|
259 |
UseXmmLoadAndClearUpper = true; // use movsd only on '10h' Opteron
|
|
260 |
} else {
|
|
261 |
UseXmmLoadAndClearUpper = false;
|
|
262 |
}
|
|
263 |
}
|
|
264 |
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
|
265 |
if( supports_sse4a() ) {
|
|
266 |
UseXmmRegToRegMoveAll = true; // use movaps, movapd only on '10h'
|
|
267 |
} else {
|
|
268 |
UseXmmRegToRegMoveAll = false;
|
|
269 |
}
|
|
270 |
}
|
244
|
271 |
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
|
|
272 |
if( supports_sse4a() ) {
|
|
273 |
UseXmmI2F = true;
|
|
274 |
} else {
|
|
275 |
UseXmmI2F = false;
|
|
276 |
}
|
|
277 |
}
|
|
278 |
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
|
|
279 |
if( supports_sse4a() ) {
|
|
280 |
UseXmmI2D = true;
|
|
281 |
} else {
|
|
282 |
UseXmmI2D = false;
|
|
283 |
}
|
|
284 |
}
|
1
|
285 |
}
|
|
286 |
|
|
287 |
if( is_intel() ) { // Intel cpus specific settings
|
|
288 |
if( FLAG_IS_DEFAULT(UseStoreImmI16) ) {
|
|
289 |
UseStoreImmI16 = false; // don't use it on Intel cpus
|
|
290 |
}
|
|
291 |
if( FLAG_IS_DEFAULT(UseAddressNop) ) {
|
|
292 |
// Use it on all Intel cpus starting from PentiumPro
|
|
293 |
// (don't need a cpu check since only new cpus support 64-bits mode).
|
|
294 |
UseAddressNop = true;
|
|
295 |
}
|
|
296 |
if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
|
|
297 |
UseXmmLoadAndClearUpper = true; // use movsd on all Intel cpus
|
|
298 |
}
|
|
299 |
if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
|
|
300 |
if( supports_sse3() ) {
|
|
301 |
UseXmmRegToRegMoveAll = true; // use movaps, movapd on new Intel cpus
|
|
302 |
} else {
|
|
303 |
UseXmmRegToRegMoveAll = false;
|
|
304 |
}
|
|
305 |
}
|
|
306 |
if( cpu_family() == 6 && supports_sse3() ) { // New Intel cpus
|
|
307 |
#ifdef COMPILER2
|
|
308 |
if( FLAG_IS_DEFAULT(MaxLoopPad) ) {
|
|
309 |
// For new Intel cpus do the next optimization:
|
|
310 |
// don't align the beginning of a loop if there are enough instructions
|
|
311 |
// left (NumberOfLoopInstrToAlign defined in c2_globals.hpp)
|
|
312 |
// in current fetch line (OptoLoopAlignment) or the padding
|
|
313 |
// is big (> MaxLoopPad).
|
|
314 |
// Set MaxLoopPad to 11 for new Intel cpus to reduce number of
|
|
315 |
// generated NOP instructions. 11 is the largest size of one
|
|
316 |
// address NOP instruction '0F 1F' (see Assembler::nop(i)).
|
|
317 |
MaxLoopPad = 11;
|
|
318 |
}
|
|
319 |
#endif // COMPILER2
|
1437
|
320 |
if( FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) {
|
|
321 |
UseXMMForArrayCopy = true; // use SSE2 movq on new Intel cpus
|
|
322 |
}
|
|
323 |
if( supports_sse4_2() && supports_ht() ) { // Newest Intel cpus
|
|
324 |
if( FLAG_IS_DEFAULT(UseUnalignedLoadStores) && UseXMMForArrayCopy ) {
|
|
325 |
UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
|
|
326 |
}
|
|
327 |
}
|
1
|
328 |
}
|
|
329 |
}
|
|
330 |
|
|
331 |
assert(0 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value");
|
|
332 |
assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value");
|
|
333 |
|
|
334 |
// set valid Prefetch instruction
|
|
335 |
if( ReadPrefetchInstr < 0 ) ReadPrefetchInstr = 0;
|
|
336 |
if( ReadPrefetchInstr > 3 ) ReadPrefetchInstr = 3;
|
|
337 |
if( ReadPrefetchInstr == 3 && !supports_3dnow() ) ReadPrefetchInstr = 0;
|
|
338 |
|
|
339 |
if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
|
|
340 |
if( AllocatePrefetchInstr > 3 ) AllocatePrefetchInstr = 3;
|
|
341 |
if( AllocatePrefetchInstr == 3 && !supports_3dnow() ) AllocatePrefetchInstr=0;
|
|
342 |
|
|
343 |
// Allocation prefetch settings
|
|
344 |
intx cache_line_size = L1_data_cache_line_size();
|
|
345 |
if( cache_line_size > AllocatePrefetchStepSize )
|
|
346 |
AllocatePrefetchStepSize = cache_line_size;
|
|
347 |
if( FLAG_IS_DEFAULT(AllocatePrefetchLines) )
|
|
348 |
AllocatePrefetchLines = 3; // Optimistic value
|
|
349 |
assert(AllocatePrefetchLines > 0, "invalid value");
|
|
350 |
if( AllocatePrefetchLines < 1 ) // set valid value in product VM
|
|
351 |
AllocatePrefetchLines = 1; // Conservative value
|
|
352 |
|
|
353 |
AllocatePrefetchDistance = allocate_prefetch_distance();
|
|
354 |
AllocatePrefetchStyle = allocate_prefetch_style();
|
|
355 |
|
|
356 |
if( AllocatePrefetchStyle == 2 && is_intel() &&
|
|
357 |
cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
|
|
358 |
AllocatePrefetchDistance = 384;
|
|
359 |
}
|
|
360 |
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
|
|
361 |
|
|
362 |
// Prefetch settings
|
|
363 |
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
|
|
364 |
PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
|
|
365 |
PrefetchFieldsAhead = prefetch_fields_ahead();
|
|
366 |
|
|
367 |
#ifndef PRODUCT
|
|
368 |
if (PrintMiscellaneous && Verbose) {
|
1437
|
369 |
tty->print_cr("Logical CPUs per core: %u",
|
1
|
370 |
logical_processors_per_package());
|
|
371 |
tty->print_cr("UseSSE=%d",UseSSE);
|
|
372 |
tty->print("Allocation: ");
|
|
373 |
if (AllocatePrefetchStyle <= 0) {
|
|
374 |
tty->print_cr("no prefetching");
|
|
375 |
} else {
|
|
376 |
if (AllocatePrefetchInstr == 0) {
|
|
377 |
tty->print("PREFETCHNTA");
|
|
378 |
} else if (AllocatePrefetchInstr == 1) {
|
|
379 |
tty->print("PREFETCHT0");
|
|
380 |
} else if (AllocatePrefetchInstr == 2) {
|
|
381 |
tty->print("PREFETCHT2");
|
|
382 |
} else if (AllocatePrefetchInstr == 3) {
|
|
383 |
tty->print("PREFETCHW");
|
|
384 |
}
|
|
385 |
if (AllocatePrefetchLines > 1) {
|
|
386 |
tty->print_cr(" %d, %d lines with step %d bytes", AllocatePrefetchDistance, AllocatePrefetchLines, AllocatePrefetchStepSize);
|
|
387 |
} else {
|
|
388 |
tty->print_cr(" %d, one line", AllocatePrefetchDistance);
|
|
389 |
}
|
|
390 |
}
|
|
391 |
if (PrefetchCopyIntervalInBytes > 0) {
|
|
392 |
tty->print_cr("PrefetchCopyIntervalInBytes %d", PrefetchCopyIntervalInBytes);
|
|
393 |
}
|
|
394 |
if (PrefetchScanIntervalInBytes > 0) {
|
|
395 |
tty->print_cr("PrefetchScanIntervalInBytes %d", PrefetchScanIntervalInBytes);
|
|
396 |
}
|
|
397 |
if (PrefetchFieldsAhead > 0) {
|
|
398 |
tty->print_cr("PrefetchFieldsAhead %d", PrefetchFieldsAhead);
|
|
399 |
}
|
|
400 |
}
|
|
401 |
#endif // !PRODUCT
|
|
402 |
}
|
|
403 |
|
|
404 |
void VM_Version::initialize() {
|
|
405 |
ResourceMark rm;
|
|
406 |
// Making this stub must be FIRST use of assembler
|
|
407 |
|
|
408 |
stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
|
|
409 |
if (stub_blob == NULL) {
|
|
410 |
vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
|
|
411 |
}
|
|
412 |
CodeBuffer c(stub_blob->instructions_begin(),
|
|
413 |
stub_blob->instructions_size());
|
|
414 |
VM_Version_StubGenerator g(&c);
|
|
415 |
getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
|
|
416 |
g.generate_getPsrInfo());
|
|
417 |
|
|
418 |
get_processor_features();
|
|
419 |
}
|