vm_version_ppc.cpp revision 7575:a7fd2288ce2f
144603Sdcs/*
244603Sdcs * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
344603Sdcs * Copyright 2012, 2014 SAP AG. All rights reserved.
444603Sdcs * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
544603Sdcs *
644603Sdcs * This code is free software; you can redistribute it and/or modify it
744603Sdcs * under the terms of the GNU General Public License version 2 only, as
844603Sdcs * published by the Free Software Foundation.
944603Sdcs *
1044603Sdcs * This code is distributed in the hope that it will be useful, but WITHOUT
1144603Sdcs * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1244603Sdcs * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1344603Sdcs * version 2 for more details (a copy is included in the LICENSE file that
1444603Sdcs * accompanied this code).
1544603Sdcs *
1644603Sdcs * You should have received a copy of the GNU General Public License version
1744603Sdcs * 2 along with this work; if not, write to the Free Software Foundation,
1844603Sdcs * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1944603Sdcs *
2044603Sdcs * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2144603Sdcs * or visit www.oracle.com if you need additional information or have any
2244603Sdcs * questions.
2344603Sdcs *
2444603Sdcs */
2550477Speter
2644603Sdcs#include "precompiled.hpp"
2744603Sdcs#include "asm/assembler.inline.hpp"
2844603Sdcs#include "asm/macroAssembler.inline.hpp"
2944603Sdcs#include "compiler/disassembler.hpp"
3044603Sdcs#include "memory/resourceArea.hpp"
3144603Sdcs#include "runtime/java.hpp"
3244603Sdcs#include "runtime/os.hpp"
3344603Sdcs#include "runtime/stubCodeGenerator.hpp"
3444603Sdcs#include "utilities/defaultStream.hpp"
3544603Sdcs#include "vm_version_ppc.hpp"
3644603Sdcs
3744603Sdcs# include <sys/sysinfo.h>
3844603Sdcs
3944603Sdcsint VM_Version::_features = VM_Version::unknown_m;
4044603Sdcsint VM_Version::_measured_cache_line_size = 128; // default value
4144603Sdcsconst char* VM_Version::_features_str = "";
4244603Sdcsbool VM_Version::_is_determine_features_test_running = false;
4344603Sdcs
4444603Sdcs
4544603Sdcs#define MSG(flag)   \
4644603Sdcs  if (flag && !FLAG_IS_DEFAULT(flag))                                  \
4744603Sdcs      jio_fprintf(defaultStream::error_stream(),                       \
4844603Sdcs                  "warning: -XX:+" #flag " requires -XX:+UseSIGTRAP\n" \
4944603Sdcs                  "         -XX:+" #flag " will be disabled!\n");
5044603Sdcs
5144603Sdcsvoid VM_Version::initialize() {
5244603Sdcs
5344603Sdcs  // Test which instructions are supported and measure cache line size.
5444603Sdcs  determine_features();
5544603Sdcs
5644603Sdcs  // If PowerArchitecturePPC64 hasn't been specified explicitly determine from features.
5744603Sdcs  if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) {
5844603Sdcs    if (VM_Version::has_popcntw()) {
5944603Sdcs      FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7);
6044603Sdcs    } else if (VM_Version::has_cmpb()) {
6144603Sdcs      FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 6);
62186789Sluigi    } else if (VM_Version::has_popcntb()) {
6344603Sdcs      FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 5);
6444603Sdcs    } else {
6544603Sdcs      FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 0);
6644603Sdcs    }
6744603Sdcs  }
6844603Sdcs  guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 ||
6944603Sdcs            PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7,
70186789Sluigi            "PowerArchitecturePPC64 should be 0, 5, 6 or 7");
71186789Sluigi
72186789Sluigi  if (!UseSIGTRAP) {
73186789Sluigi    MSG(TrapBasedICMissChecks);
74186789Sluigi    MSG(TrapBasedNotEntrantChecks);
75186789Sluigi    MSG(TrapBasedNullChecks);
76186789Sluigi    FLAG_SET_ERGO(bool, TrapBasedNotEntrantChecks, false);
77186789Sluigi    FLAG_SET_ERGO(bool, TrapBasedNullChecks,       false);
78186789Sluigi    FLAG_SET_ERGO(bool, TrapBasedICMissChecks,     false);
7944603Sdcs  }
8087636Sjhb
8187636Sjhb#ifdef COMPILER2
8287636Sjhb  if (!UseSIGTRAP) {
8387636Sjhb    MSG(TrapBasedRangeChecks);
8487636Sjhb    FLAG_SET_ERGO(bool, TrapBasedRangeChecks, false);
8587636Sjhb  }
8687636Sjhb
8787636Sjhb  // On Power6 test for section size.
8887636Sjhb  if (PowerArchitecturePPC64 == 6) {
8987636Sjhb    determine_section_size();
9044603Sdcs  // TODO: PPC port } else {
9144603Sdcs  // TODO: PPC port PdScheduling::power6SectorSize = 0x20;
9265615Sdcs  }
9365615Sdcs
9465615Sdcs  MaxVectorSize = 8;
9565615Sdcs#endif
9644603Sdcs
9744603Sdcs  // Create and print feature-string.
9865615Sdcs  char buf[(num_features+1) * 16]; // Max 16 chars per feature.
9965615Sdcs  jio_snprintf(buf, sizeof(buf),
10065615Sdcs               "ppc64%s%s%s%s%s%s%s%s",
10144603Sdcs               (has_fsqrt()   ? " fsqrt"   : ""),
10244603Sdcs               (has_isel()    ? " isel"    : ""),
10344603Sdcs               (has_lxarxeh() ? " lxarxeh" : ""),
10444603Sdcs               (has_cmpb()    ? " cmpb"    : ""),
10544603Sdcs               //(has_mftgpr()? " mftgpr"  : ""),
10644603Sdcs               (has_popcntb() ? " popcntb" : ""),
10744603Sdcs               (has_popcntw() ? " popcntw" : ""),
10844603Sdcs               (has_fcfids()  ? " fcfids"  : ""),
10944603Sdcs               (has_vand()    ? " vand"    : "")
11044603Sdcs               // Make sure number of %s matches num_features!
11165615Sdcs              );
11265615Sdcs  _features_str = os::strdup(buf);
11365615Sdcs  NOT_PRODUCT(if (Verbose) print_features(););
11465615Sdcs
11544603Sdcs  // PPC64 supports 8-byte compare-exchange operations (see
11644603Sdcs  // Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr)
11765615Sdcs  // and 'atomic long memory ops' (see Unsafe_GetLongVolatile).
11844603Sdcs  _supports_cx8 = true;
11944603Sdcs
12044603Sdcs  UseSSE = 0; // Only on x86 and x64
12144603Sdcs
12244603Sdcs  intx cache_line_size = _measured_cache_line_size;
12344603Sdcs
12444603Sdcs  if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) AllocatePrefetchStyle = 1;
12544603Sdcs
12644603Sdcs  if (AllocatePrefetchStyle == 4) {
12744603Sdcs    AllocatePrefetchStepSize = cache_line_size; // Need exact value.
12844603Sdcs    if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 12; // Use larger blocks by default.
12944603Sdcs    if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 2*cache_line_size; // Default is not defined?
13044603Sdcs  } else {
13144603Sdcs    if (cache_line_size > AllocatePrefetchStepSize) AllocatePrefetchStepSize = cache_line_size;
132186789Sluigi    if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) AllocatePrefetchLines = 3; // Optimistic value.
133186789Sluigi    if (AllocatePrefetchDistance < 0) AllocatePrefetchDistance = 3*cache_line_size; // Default is not defined?
13465615Sdcs  }
13565615Sdcs
13665615Sdcs  assert(AllocatePrefetchLines > 0, "invalid value");
13765615Sdcs  if (AllocatePrefetchLines < 1) { // Set valid value in product VM.
13865615Sdcs    AllocatePrefetchLines = 1; // Conservative value.
13965615Sdcs  }
14065615Sdcs
14165615Sdcs  if (AllocatePrefetchStyle == 3 && AllocatePrefetchDistance < cache_line_size) {
14265615Sdcs    AllocatePrefetchStyle = 1; // Fall back if inappropriate.
14365615Sdcs  }
14465615Sdcs
14565615Sdcs  assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive");
14665615Sdcs
14765615Sdcs  if (UseCRC32Intrinsics) {
14865615Sdcs    if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics))
14965615Sdcs      warning("CRC32 intrinsics  are not available on this CPU");
15065615Sdcs    FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
15165615Sdcs  }
15265615Sdcs
15365615Sdcs  // The AES intrinsic stubs require AES instruction support.
15465615Sdcs  if (UseAES) {
15565615Sdcs    warning("AES instructions are not available on this CPU");
15665615Sdcs    FLAG_SET_DEFAULT(UseAES, false);
15765615Sdcs  }
15865615Sdcs  if (UseAESIntrinsics) {
15965615Sdcs    if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
160186789Sluigi      warning("AES intrinsics are not available on this CPU");
16165615Sdcs    FLAG_SET_DEFAULT(UseAESIntrinsics, false);
16244603Sdcs  }
16344603Sdcs
16444603Sdcs  if (UseSHA) {
16597201Sgordon    warning("SHA instructions are not available on this CPU");
16665615Sdcs    FLAG_SET_DEFAULT(UseSHA, false);
16765615Sdcs  }
16844603Sdcs  if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
16997201Sgordon    warning("SHA intrinsics are not available on this CPU");
17044603Sdcs    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
17144603Sdcs    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
172186789Sluigi    FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
173186789Sluigi  }
174186789Sluigi
17544603Sdcs}
17644603Sdcs
17744603Sdcsvoid VM_Version::print_features() {
17844603Sdcs  tty->print_cr("Version: %s cache_line_size = %d", cpu_features(), (int) get_cache_line_size());
17944603Sdcs}
18044603Sdcs
18144603Sdcs#ifdef COMPILER2
182186789Sluigi// Determine section size on power6: If section size is 8 instructions,
18361373Sdcs// there should be a difference between the two testloops of ~15 %. If
184186789Sluigi// no difference is detected the section is assumed to be 32 instructions.
185186789Sluigivoid VM_Version::determine_section_size() {
186186789Sluigi
187186789Sluigi  int unroll = 80;
188186789Sluigi
189186789Sluigi  const int code_size = (2* unroll * 32 + 100)*BytesPerInstWord;
190186789Sluigi
19161373Sdcs  // Allocate space for the code.
19261373Sdcs  ResourceMark rm;
193186789Sluigi  CodeBuffer cb("detect_section_size", code_size, 0);
19444603Sdcs  MacroAssembler* a = new MacroAssembler(&cb);
195186789Sluigi
19644603Sdcs  uint32_t *code = (uint32_t *)a->pc();
19744603Sdcs  // Emit code.
19861373Sdcs  void (*test1)() = (void(*)())(void *)a->function_entry();
19961373Sdcs
20065883Sdcs  Label l1;
20153672Sdcs
202186789Sluigi  a->li(R4, 1);
20365938Sdcs  a->sldi(R4, R4, 28);
204244048Sdteske  a->b(l1);
205244048Sdteske  a->align(CodeEntryAlignment);
206244048Sdteske
207244048Sdteske  a->bind(l1);
208244048Sdteske
209244048Sdteske  for (int i = 0; i < unroll; i++) {
210244089Sdteske    // Schleife 1
211244089Sdteske    // ------- sector 0 ------------
212244048Sdteske    // ;; 0
213244048Sdteske    a->nop();                   // 1
214244048Sdteske    a->fpnop0();                // 2
215244048Sdteske    a->fpnop1();                // 3
216244048Sdteske    a->addi(R4,R4, -1); // 4
217244048Sdteske
218244089Sdteske    // ;;  1
219244048Sdteske    a->nop();                   // 5
220244048Sdteske    a->fmr(F6, F6);             // 6
221244089Sdteske    a->fmr(F7, F7);             // 7
222244089Sdteske    a->endgroup();              // 8
223244089Sdteske    // ------- sector 8 ------------
224244048Sdteske
225244048Sdteske    // ;;  2
226244048Sdteske    a->nop();                   // 9
227244048Sdteske    a->nop();                   // 10
228244048Sdteske    a->fmr(F8, F8);             // 11
229244048Sdteske    a->fmr(F9, F9);             // 12
230244048Sdteske
231244048Sdteske    // ;;  3
232244048Sdteske    a->nop();                   // 13
233244048Sdteske    a->fmr(F10, F10);           // 14
234244048Sdteske    a->fmr(F11, F11);           // 15
235244048Sdteske    a->endgroup();              // 16
236244048Sdteske    // -------- sector 16 -------------
237244048Sdteske
238244048Sdteske    // ;;  4
239244048Sdteske    a->nop();                   // 17
240244048Sdteske    a->nop();                   // 18
241244048Sdteske    a->fmr(F15, F15);           // 19
242244048Sdteske    a->fmr(F16, F16);           // 20
243244048Sdteske
24444603Sdcs    // ;;  5
24544603Sdcs    a->nop();                   // 21
24644603Sdcs    a->fmr(F17, F17);           // 22
24744603Sdcs    a->fmr(F18, F18);           // 23
24844603Sdcs    a->endgroup();              // 24
24944603Sdcs    // ------- sector 24  ------------
25044603Sdcs
25153672Sdcs    // ;;  6
25253672Sdcs    a->nop();                   // 25
25344603Sdcs    a->nop();                   // 26
25444603Sdcs    a->fmr(F19, F19);           // 27
25553672Sdcs    a->fmr(F20, F20);           // 28
25644603Sdcs
25744603Sdcs    // ;;  7
25844603Sdcs    a->nop();                   // 29
25944603Sdcs    a->fmr(F21, F21);           // 30
26044603Sdcs    a->fmr(F22, F22);           // 31
26144603Sdcs    a->brnop0();                // 32
26244603Sdcs
263186789Sluigi    // ------- sector 32 ------------
264186789Sluigi  }
265186789Sluigi
266186789Sluigi  // ;; 8
267186789Sluigi  a->cmpdi(CCR0, R4, unroll);   // 33
268186789Sluigi  a->bge(CCR0, l1);             // 34
269186789Sluigi  a->blr();
27044603Sdcs
27144603Sdcs  // Emit code.
27244603Sdcs  void (*test2)() = (void(*)())(void *)a->function_entry();
27344603Sdcs  // uint32_t *code = (uint32_t *)a->pc();
27444603Sdcs
27544603Sdcs  Label l2;
276186789Sluigi
27744603Sdcs  a->li(R4, 1);
278186789Sluigi  a->sldi(R4, R4, 28);
27944603Sdcs  a->b(l2);
280185746Sluigi  a->align(CodeEntryAlignment);
281185746Sluigi
282185746Sluigi  a->bind(l2);
283186789Sluigi
284185746Sluigi  for (int i = 0; i < unroll; i++) {
285185746Sluigi    // Schleife 2
286185746Sluigi    // ------- sector 0 ------------
287185746Sluigi    // ;; 0
288185746Sluigi    a->brnop0();                  // 1
289185746Sluigi    a->nop();                     // 2
290185746Sluigi    //a->cmpdi(CCR0, R4, unroll);
291186789Sluigi    a->fpnop0();                  // 3
292186789Sluigi    a->fpnop1();                  // 4
293186789Sluigi    a->addi(R4,R4, -1);           // 5
294186789Sluigi
295186789Sluigi    // ;; 1
296186789Sluigi
297186789Sluigi    a->nop();                     // 6
298186789Sluigi    a->fmr(F6, F6);               // 7
299186789Sluigi    a->fmr(F7, F7);               // 8
300186789Sluigi    // ------- sector 8 ---------------
301186789Sluigi
302186789Sluigi    // ;; 2
30344603Sdcs    a->endgroup();                // 9
30444603Sdcs
30544603Sdcs    // ;; 3
30644603Sdcs    a->nop();                     // 10
30744603Sdcs    a->nop();                     // 11
30865615Sdcs    a->fmr(F8, F8);               // 12
30965615Sdcs
31065615Sdcs    // ;; 4
31165615Sdcs    a->fmr(F9, F9);               // 13
31265615Sdcs    a->nop();                     // 14
31365615Sdcs    a->fmr(F10, F10);             // 15
31465615Sdcs
31565615Sdcs    // ;; 5
31665615Sdcs    a->fmr(F11, F11);             // 16
31765615Sdcs    // -------- sector 16 -------------
31865615Sdcs
31965615Sdcs    // ;; 6
32044603Sdcs    a->endgroup();                // 17
32144603Sdcs
32244603Sdcs    // ;; 7
32344603Sdcs    a->nop();                     // 18
32444603Sdcs    a->nop();                     // 19
32544603Sdcs    a->fmr(F15, F15);             // 20
32644603Sdcs
32765615Sdcs    // ;; 8
32865615Sdcs    a->fmr(F16, F16);             // 21
32965615Sdcs    a->nop();                     // 22
33044603Sdcs    a->fmr(F17, F17);             // 23
33144603Sdcs
33244603Sdcs    // ;; 9
33365615Sdcs    a->fmr(F18, F18);             // 24
33465615Sdcs    // -------- sector 24 -------------
33544603Sdcs
33644603Sdcs    // ;; 10
33744603Sdcs    a->endgroup();                // 25
33844603Sdcs
33944603Sdcs    // ;; 11
34044603Sdcs    a->nop();                     // 26
34144603Sdcs    a->nop();                     // 27
34244603Sdcs    a->fmr(F19, F19);             // 28
34344603Sdcs
34444603Sdcs    // ;; 12
34544603Sdcs    a->fmr(F20, F20);             // 29
34644603Sdcs    a->nop();                     // 30
34744603Sdcs    a->fmr(F21, F21);             // 31
34844603Sdcs
34944603Sdcs    // ;; 13
35044603Sdcs    a->fmr(F22, F22);             // 32
35144603Sdcs  }
35244603Sdcs
35344603Sdcs  // -------- sector 32 -------------
35444603Sdcs  // ;; 14
35544603Sdcs  a->cmpdi(CCR0, R4, unroll); // 33
35644603Sdcs  a->bge(CCR0, l2);           // 34
35744603Sdcs
35844603Sdcs  a->blr();
35944603Sdcs  uint32_t *code_end = (uint32_t *)a->pc();
36044603Sdcs  a->flush();
36144603Sdcs
36244603Sdcs  double loop1_seconds,loop2_seconds, rel_diff;
36344603Sdcs  uint64_t start1, stop1;
36444603Sdcs
36544603Sdcs  start1 = os::current_thread_cpu_time(false);
36644603Sdcs  (*test1)();
36744603Sdcs  stop1 = os::current_thread_cpu_time(false);
36844603Sdcs  loop1_seconds = (stop1- start1) / (1000 *1000 *1000.0);
36944603Sdcs
370186789Sluigi
37144603Sdcs  start1 = os::current_thread_cpu_time(false);
372186789Sluigi  (*test2)();
37344603Sdcs  stop1 = os::current_thread_cpu_time(false);
37444603Sdcs
37544603Sdcs  loop2_seconds = (stop1 - start1) / (1000 *1000 *1000.0);
37644603Sdcs
37744603Sdcs  rel_diff = (loop2_seconds - loop1_seconds) / loop1_seconds *100;
37844603Sdcs
379186789Sluigi  if (PrintAssembly) {
38044603Sdcs    ttyLocker ttyl;
38144603Sdcs    tty->print_cr("Decoding section size detection stub at " INTPTR_FORMAT " before execution:", p2i(code));
38244603Sdcs    Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
38344603Sdcs    tty->print_cr("Time loop1 :%f", loop1_seconds);
38444603Sdcs    tty->print_cr("Time loop2 :%f", loop2_seconds);
38544603Sdcs    tty->print_cr("(time2 - time1) / time1 = %f %%", rel_diff);
38644603Sdcs
38744603Sdcs    if (rel_diff > 12.0) {
38844603Sdcs      tty->print_cr("Section Size 8 Instructions");
38944603Sdcs    } else{
39044603Sdcs      tty->print_cr("Section Size 32 Instructions or Power5");
39144603Sdcs    }
39244603Sdcs  }
39344603Sdcs
39444603Sdcs#if 0 // TODO: PPC port
39544603Sdcs  // Set sector size (if not set explicitly).
39644603Sdcs  if (FLAG_IS_DEFAULT(Power6SectorSize128PPC64)) {
39744603Sdcs    if (rel_diff > 12.0) {
39844603Sdcs      PdScheduling::power6SectorSize = 0x20;
399186789Sluigi    } else {
40044603Sdcs      PdScheduling::power6SectorSize = 0x80;
40144603Sdcs    }
40244603Sdcs  } else if (Power6SectorSize128PPC64) {
403186789Sluigi    PdScheduling::power6SectorSize = 0x80;
40444603Sdcs  } else {
40544603Sdcs    PdScheduling::power6SectorSize = 0x20;
40644603Sdcs  }
40744603Sdcs#endif
40865615Sdcs  if (UsePower6SchedulerPPC64) Unimplemented();
40965615Sdcs}
41065615Sdcs#endif // COMPILER2
41165615Sdcs
41265615Sdcsvoid VM_Version::determine_features() {
41365615Sdcs#if defined(ABI_ELFv2)
41444603Sdcs  const int code_size = (num_features+1+2*7)*BytesPerInstWord; // TODO(asmundak): calculation is incorrect.
415186789Sluigi#else
41644603Sdcs  // 7 InstWords for each call (function descriptor + blr instruction).
41744603Sdcs  const int code_size = (num_features+1+2*7)*BytesPerInstWord;
41844603Sdcs#endif
41944603Sdcs  int features = 0;
42044603Sdcs
42144603Sdcs  // create test area
42244603Sdcs  enum { BUFFER_SIZE = 2*4*K }; // Needs to be >=2* max cache line size (cache line size can't exceed min page size).
42344603Sdcs  char test_area[BUFFER_SIZE];
42444603Sdcs  char *mid_of_test_area = &test_area[BUFFER_SIZE>>1];
42565615Sdcs
42665615Sdcs  // Allocate space for the code.
42744603Sdcs  ResourceMark rm;
42844603Sdcs  CodeBuffer cb("detect_cpu_features", code_size, 0);
42944603Sdcs  MacroAssembler* a = new MacroAssembler(&cb);
43044603Sdcs
43144603Sdcs  // Must be set to true so we can generate the test code.
43244603Sdcs  _features = VM_Version::all_features_m;
43344603Sdcs
43465615Sdcs  // Emit code.
43565615Sdcs  void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry();
43665615Sdcs  uint32_t *code = (uint32_t *)a->pc();
43765615Sdcs  // Don't use R0 in ldarx.
43844603Sdcs  // Keep R3_ARG1 unmodified, it contains &field (see below).
43965615Sdcs  // Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
44065615Sdcs  a->fsqrt(F3, F4);                            // code[0] -> fsqrt_m
44165615Sdcs  a->fsqrts(F3, F4);                           // code[1] -> fsqrts_m
44265615Sdcs  a->isel(R7, R5, R6, 0);                      // code[2] -> isel_m
44365615Sdcs  a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
44465615Sdcs  a->cmpb(R7, R5, R6);                         // code[4] -> bcmp
44565615Sdcs  //a->mftgpr(R7, F3);                         // code[5] -> mftgpr
44665615Sdcs  a->popcntb(R7, R5);                          // code[6] -> popcntb
44765615Sdcs  a->popcntw(R7, R5);                          // code[7] -> popcntw
44865615Sdcs  a->fcfids(F3, F4);                           // code[8] -> fcfids
44965615Sdcs  a->vand(VR0, VR0, VR0);                      // code[9] -> vand
45065615Sdcs  a->blr();
45165615Sdcs
45244603Sdcs  // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
45344603Sdcs  void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->function_entry();
45444603Sdcs  a->dcbz(R3_ARG1); // R3_ARG1 = addr
455186789Sluigi  a->blr();
45644603Sdcs
457186789Sluigi  uint32_t *code_end = (uint32_t *)a->pc();
458186789Sluigi  a->flush();
45944603Sdcs  _features = VM_Version::unknown_m;
46044603Sdcs
46144603Sdcs  // Print the detection code.
46244603Sdcs  if (PrintAssembly) {
46344603Sdcs    ttyLocker ttyl;
46444603Sdcs    tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " before execution:", p2i(code));
46544603Sdcs    Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
46644603Sdcs  }
46744603Sdcs
46844603Sdcs  // Measure cache line size.
46944603Sdcs  memset(test_area, 0xFF, BUFFER_SIZE); // Fill test area with 0xFF.
470174777Sambrisko  (*zero_cacheline_func_ptr)(mid_of_test_area); // Call function which executes dcbz to the middle.
47144603Sdcs  int count = 0; // count zeroed bytes
47244603Sdcs  for (int i = 0; i < BUFFER_SIZE; i++) if (test_area[i] == 0) count++;
473174777Sambrisko  guarantee(is_power_of_2(count), "cache line size needs to be a power of 2");
47444603Sdcs  _measured_cache_line_size = count;
47544603Sdcs
476186789Sluigi  // Execute code. Illegal instructions will be replaced by 0 in the signal handler.
47744603Sdcs  VM_Version::_is_determine_features_test_running = true;
478186789Sluigi  (*test)((address)mid_of_test_area, (uint64_t)0);
47944603Sdcs  VM_Version::_is_determine_features_test_running = false;
480186789Sluigi
48144603Sdcs  // determine which instructions are legal.
482186789Sluigi  int feature_cntr = 0;
48344603Sdcs  if (code[feature_cntr++]) features |= fsqrt_m;
484186789Sluigi  if (code[feature_cntr++]) features |= fsqrts_m;
48544603Sdcs  if (code[feature_cntr++]) features |= isel_m;
486186789Sluigi  if (code[feature_cntr++]) features |= lxarxeh_m;
48744603Sdcs  if (code[feature_cntr++]) features |= cmpb_m;
488186789Sluigi  //if(code[feature_cntr++])features |= mftgpr_m;
48944603Sdcs  if (code[feature_cntr++]) features |= popcntb_m;
490186789Sluigi  if (code[feature_cntr++]) features |= popcntw_m;
491186789Sluigi  if (code[feature_cntr++]) features |= fcfids_m;
49244603Sdcs  if (code[feature_cntr++]) features |= vand_m;
493186789Sluigi
49444603Sdcs  // Print the detection code.
49544603Sdcs  if (PrintAssembly) {
49644603Sdcs    ttyLocker ttyl;
497186789Sluigi    tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " after execution:", p2i(code));
49844603Sdcs    Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
49944603Sdcs  }
50044603Sdcs
50144603Sdcs  _features = features;
50244603Sdcs}
50344603Sdcs
50444603Sdcs
50544603Sdcsstatic int saved_features = 0;
506186789Sluigi
50744603Sdcsvoid VM_Version::allow_all() {
50844603Sdcs  saved_features = _features;
50944603Sdcs  _features      = all_features_m;
51044603Sdcs}
51144603Sdcs
51244603Sdcsvoid VM_Version::revert() {
51344603Sdcs  _features = saved_features;
51444603Sdcs}
515186789Sluigi