8172231: SPARC ISA/CPU feature detection is broken/insufficient (on Solaris)
authorneliasso
Tue, 27 Jun 2017 15:27:54 +0200
changeset 46592 6e357e2c8143
parent 46591 3f3105af599e
child 46593 97c895b9bec4
8172231: SPARC ISA/CPU feature detection is broken/insufficient (on Solaris) Summary: Update for new platforms Reviewed-by: kvn Contributed-by: phedlin@oracle.com
hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/sparc.ad
hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp
hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp
hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java
hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java
hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java
hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Tue Jun 27 15:27:54 2017 +0200
@@ -4613,7 +4613,7 @@
 
 // Use BIS for zeroing (count is in bytes).
 void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) {
-  assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing");
+  assert(UseBlockZeroing && VM_Version::has_blk_zeroing(), "only works with BIS zeroing");
   Register end = count;
   int cache_line_size = VM_Version::prefetch_data_size();
   assert(cache_line_size > 0, "cache line size should be known for this code");
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Tue Jun 27 15:27:54 2017 +0200
@@ -1760,7 +1760,10 @@
   return true;
 }
 
-// USII supports fxtof through the whole range of number, USIII doesn't
+/* NOTE: All currently supported SPARC HW provides fast conversion.
+ * 
+ * TODO: Clean-out code depending on 'has_fast_fxtof'.
+ */
 const bool Matcher::convL2FSupported(void) {
   return VM_Version::has_fast_fxtof();
 }
@@ -1789,9 +1792,9 @@
 // No additional cost for CMOVL.
 const int Matcher::long_cmove_cost() { return 0; }
 
-// CMOVF/CMOVD are expensive on T4 and on SPARC64.
+// CMOVF/CMOVD are expensive on e.g., T4 and SPARC64.
 const int Matcher::float_cmove_cost() {
-  return (VM_Version::is_T4() || VM_Version::is_sparc64()) ? ConditionalMoveLimit : 0;
+  return VM_Version::has_fast_cmove() ? 0 : ConditionalMoveLimit;
 }
 
 // Does the CPU require late expand (see block.cpp for description of late expand)?
@@ -3194,7 +3197,7 @@
 
 // Pointer Immediate: 64-bit
 operand immP_set() %{
-  predicate(!VM_Version::is_niagara_plus());
+  predicate(!VM_Version::has_fast_ld());
   match(ConP);
 
   op_cost(5);
@@ -3206,7 +3209,7 @@
 // Pointer Immediate: 64-bit
 // From Niagara2 processors on a load should be better than materializing.
 operand immP_load() %{
-  predicate(VM_Version::is_niagara_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3)));
+  predicate(VM_Version::has_fast_ld() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3)));
   match(ConP);
 
   op_cost(5);
@@ -3217,7 +3220,7 @@
 
 // Pointer Immediate: 64-bit
 operand immP_no_oop_cheap() %{
-  predicate(VM_Version::is_niagara_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3));
+  predicate(VM_Version::has_fast_ld() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3));
   match(ConP);
 
   op_cost(5);
@@ -3341,7 +3344,7 @@
 
 // Long Immediate: cheap (materialize in <= 3 instructions)
 operand immL_cheap() %{
-  predicate(!VM_Version::is_niagara_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3);
+  predicate(!VM_Version::has_fast_ld() || MacroAssembler::insts_for_set64(n->get_long()) <= 3);
   match(ConL);
   op_cost(0);
 
@@ -3351,7 +3354,7 @@
 
 // Long Immediate: expensive (materialize in > 3 instructions)
 operand immL_expensive() %{
-  predicate(VM_Version::is_niagara_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3);
+  predicate(VM_Version::has_fast_ld() && MacroAssembler::insts_for_set64(n->get_long()) > 3);
   match(ConL);
   op_cost(0);
 
--- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp	Tue Jun 27 15:27:54 2017 +0200
@@ -71,28 +71,43 @@
   declare_c2_constant(R_G5_num)                                           \
   declare_c2_constant(R_G6_num)                                           \
   declare_c2_constant(R_G7_num)                                           \
-  declare_constant(VM_Version::vis1_instructions_m)                       \
-  declare_constant(VM_Version::vis2_instructions_m)                       \
-  declare_constant(VM_Version::vis3_instructions_m)                       \
-  declare_constant(VM_Version::cbcond_instructions_m)                     \
-  declare_constant(VM_Version::v8_instructions_m)                         \
-  declare_constant(VM_Version::hardware_mul32_m)                          \
-  declare_constant(VM_Version::hardware_div32_m)                          \
-  declare_constant(VM_Version::hardware_fsmuld_m)                         \
-  declare_constant(VM_Version::hardware_popc_m)                           \
-  declare_constant(VM_Version::v9_instructions_m)                         \
-  declare_constant(VM_Version::sun4v_m)                                   \
-  declare_constant(VM_Version::blk_init_instructions_m)                   \
-  declare_constant(VM_Version::fmaf_instructions_m)                       \
-  declare_constant(VM_Version::sparc64_family_m)                          \
-  declare_constant(VM_Version::M_family_m)                                \
-  declare_constant(VM_Version::T_family_m)                                \
-  declare_constant(VM_Version::T1_model_m)                                \
-  declare_constant(VM_Version::sparc5_instructions_m)                     \
-  declare_constant(VM_Version::aes_instructions_m)                        \
-  declare_constant(VM_Version::sha1_instruction_m)                        \
-  declare_constant(VM_Version::sha256_instruction_m)                      \
-  declare_constant(VM_Version::sha512_instruction_m)
+  declare_constant(VM_Version::ISA_V9)                  \
+  declare_constant(VM_Version::ISA_POPC)                \
+  declare_constant(VM_Version::ISA_VIS1)                \
+  declare_constant(VM_Version::ISA_VIS2)                \
+  declare_constant(VM_Version::ISA_BLK_INIT)            \
+  declare_constant(VM_Version::ISA_FMAF)                \
+  declare_constant(VM_Version::ISA_VIS3)                \
+  declare_constant(VM_Version::ISA_HPC)                 \
+  declare_constant(VM_Version::ISA_IMA)                 \
+  declare_constant(VM_Version::ISA_AES)                 \
+  declare_constant(VM_Version::ISA_DES)                 \
+  declare_constant(VM_Version::ISA_KASUMI)              \
+  declare_constant(VM_Version::ISA_CAMELLIA)            \
+  declare_constant(VM_Version::ISA_MD5)                 \
+  declare_constant(VM_Version::ISA_SHA1)                \
+  declare_constant(VM_Version::ISA_SHA256)              \
+  declare_constant(VM_Version::ISA_SHA512)              \
+  declare_constant(VM_Version::ISA_MPMUL)               \
+  declare_constant(VM_Version::ISA_MONT)                \
+  declare_constant(VM_Version::ISA_PAUSE)               \
+  declare_constant(VM_Version::ISA_CBCOND)              \
+  declare_constant(VM_Version::ISA_CRC32C)              \
+  declare_constant(VM_Version::ISA_VIS3B)               \
+  declare_constant(VM_Version::ISA_ADI)                 \
+  declare_constant(VM_Version::ISA_SPARC5)              \
+  declare_constant(VM_Version::ISA_MWAIT)               \
+  declare_constant(VM_Version::ISA_XMPMUL)              \
+  declare_constant(VM_Version::ISA_XMONT)               \
+  declare_constant(VM_Version::ISA_PAUSE_NSEC)          \
+  declare_constant(VM_Version::ISA_VAMASK)              \
+  declare_constant(VM_Version::CPU_FAST_IDIV)           \
+  declare_constant(VM_Version::CPU_FAST_RDPC)           \
+  declare_constant(VM_Version::CPU_FAST_BIS)            \
+  declare_constant(VM_Version::CPU_FAST_LD)             \
+  declare_constant(VM_Version::CPU_FAST_CMOVE)          \
+  declare_constant(VM_Version::CPU_FAST_IND_BR)         \
+  declare_constant(VM_Version::CPU_BLK_ZEROING)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Tue Jun 27 15:27:54 2017 +0200
@@ -32,7 +32,9 @@
 #include "runtime/stubCodeGenerator.hpp"
 #include "vm_version_sparc.hpp"
 
-unsigned int VM_Version::_L2_data_cache_line_size = 0;
+#include <sys/mman.h>
+
+uint VM_Version::_L2_data_cache_line_size = 0;
 
 void VM_Version::initialize() {
   assert(_features != 0, "System pre-initialization is not complete.");
@@ -69,77 +71,84 @@
   _supports_cx8 = true;             // All SPARC V9 implementations.
   _supports_atomic_getset4 = true;  // Using the 'swap' instruction.
 
-  if (is_niagara()) {
-    // Indirect branch is the same cost as direct
-    if (FLAG_IS_DEFAULT(UseInlineCaches)) {
-      FLAG_SET_DEFAULT(UseInlineCaches, false);
-    }
-    // Align loops on a single instruction boundary.
-    if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
-      FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
-    }
-    // 32-bit oops don't make sense for the 64-bit VM on sparc
-    // since the 32-bit VM has the same registers and smaller objects.
-    Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
-    Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
+  if (has_fast_ind_br() && FLAG_IS_DEFAULT(UseInlineCaches)) {
+    // Indirect and direct branches are cost equivalent.
+    FLAG_SET_DEFAULT(UseInlineCaches, false);
+  }
+  // Align loops on the proper instruction boundary to fill the instruction
+  // fetch buffer.
+  if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
+    FLAG_SET_DEFAULT(OptoLoopAlignment, VM_Version::insn_fetch_alignment);
+  }
+
+  // 32-bit oops don't make sense for the 64-bit VM on SPARC since the 32-bit
+  // VM has the same registers and smaller objects.
+  Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
+  Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
+
 #ifdef COMPILER2
-    // Indirect branch is the same cost as direct
-    if (FLAG_IS_DEFAULT(UseJumpTables)) {
-      FLAG_SET_DEFAULT(UseJumpTables, true);
-    }
-    // Single-issue, so entry and loop tops are
-    // aligned on a single instruction boundary
-    if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
-      FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
+  if (has_fast_ind_br() && FLAG_IS_DEFAULT(UseJumpTables)) {
+    // Indirect and direct branches are cost equivalent.
+    FLAG_SET_DEFAULT(UseJumpTables, true);
+  }
+  // Entry and loop tops are aligned to fill the instruction fetch buffer.
+  if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
+    FLAG_SET_DEFAULT(InteriorEntryAlignment, VM_Version::insn_fetch_alignment);
+  }
+  if (UseTLAB && cache_line_size > 0 &&
+      FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
+    if (has_fast_bis()) {
+      // Use BIS instruction for TLAB allocation prefetch.
+      FLAG_SET_DEFAULT(AllocatePrefetchInstr, 1);
     }
-    if (is_niagara_plus()) {
-      if (has_blk_init() && (cache_line_size > 0) && UseTLAB &&
-          FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
-        if (!has_sparc5_instr()) {
-          // Use BIS instruction for TLAB allocation prefetch
-          // on Niagara plus processors other than those based on CoreS4
-          FLAG_SET_DEFAULT(AllocatePrefetchInstr, 1);
-        } else {
-          // On CoreS4 processors use prefetch instruction
-          // to avoid partial RAW issue, also use prefetch style 3
-          FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0);
-          if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
-            FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3);
-          }
-        }
-      }
-      if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
-        if (AllocatePrefetchInstr == 0) {
-          // Use different prefetch distance without BIS
-          FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
-        } else {
-          // Use smaller prefetch distance with BIS
-          FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64);
-        }
-      }
-      if (is_T4()) {
-        // Double number of prefetched cache lines on T4
-        // since L2 cache line size is smaller (32 bytes).
-        if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) {
-          FLAG_SET_ERGO(intx, AllocatePrefetchLines, AllocatePrefetchLines*2);
-        }
-        if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) {
-          FLAG_SET_ERGO(intx, AllocateInstancePrefetchLines, AllocateInstancePrefetchLines*2);
-        }
+    else if (has_sparc5()) {
+      // Use prefetch instruction to avoid partial RAW issue on Core S4 processors,
+      // also use prefetch style 3.
+      FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0);
+      if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
+        FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3);
       }
     }
-
-    if ((AllocatePrefetchInstr == 1) && (AllocatePrefetchStyle != 3)) {
-      if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
-        warning("AllocatePrefetchStyle set to 3 because BIS instructions require aligned memory addresses");
-      }
-      FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3);
+  }
+  if (AllocatePrefetchInstr == 1) {
+    // Use allocation prefetch style 3 because BIS instructions require
+    // aligned memory addresses.
+    FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3);
+  }
+  if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
+    if (AllocatePrefetchInstr == 0) {
+      // Use different prefetch distance without BIS
+      FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
+    } else {
+      // Use smaller prefetch distance with BIS
+      FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64);
     }
-#endif /* COMPILER2 */
   }
 
+  // We increase the number of prefetched cache lines, to use just a bit more
+  // aggressive approach, when the L2-cache line size is small (32 bytes), or
+  // when running on newer processor implementations, such as the Core S4.
+  bool inc_prefetch = cache_line_size > 0 && (cache_line_size < 64 || has_sparc5());
+
+  if (inc_prefetch) {
+    // We use a factor two for small cache line sizes (as before) but a slightly
+    // more conservative increase when running on more recent hardware that will
+    // benefit from just a bit more aggressive prefetching.
+    if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) {
+      const int ap_lns = AllocatePrefetchLines;
+      const int ap_inc = cache_line_size < 64 ? ap_lns : (ap_lns + 1) / 2;
+      FLAG_SET_ERGO(intx, AllocatePrefetchLines, ap_lns + ap_inc);
+    }
+    if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) {
+      const int ip_lns = AllocateInstancePrefetchLines;
+      const int ip_inc = cache_line_size < 64 ? ip_lns : (ip_lns + 1) / 2;
+      FLAG_SET_ERGO(intx, AllocateInstancePrefetchLines, ip_lns + ip_inc);
+    }
+  }
+#endif /* COMPILER2 */
+
   // Use hardware population count instruction if available.
-  if (has_hardware_popc()) {
+  if (has_popc()) {
     if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
       FLAG_SET_DEFAULT(UsePopCountInstruction, true);
     }
@@ -148,7 +157,7 @@
     FLAG_SET_DEFAULT(UsePopCountInstruction, false);
   }
 
-  // T4 and newer Sparc cpus have new compare and branch instruction.
+  // Use compare and branch instructions if available.
   if (has_cbcond()) {
     if (FLAG_IS_DEFAULT(UseCBCond)) {
       FLAG_SET_DEFAULT(UseCBCond, true);
@@ -159,7 +168,8 @@
   }
 
   assert(BlockZeroingLowLimit > 0, "invalid value");
-  if (has_block_zeroing() && cache_line_size > 0) {
+
+  if (has_blk_zeroing() && cache_line_size > 0) {
     if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
       FLAG_SET_DEFAULT(UseBlockZeroing, true);
     }
@@ -169,7 +179,8 @@
   }
 
   assert(BlockCopyLowLimit > 0, "invalid value");
-  if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
+
+  if (has_blk_zeroing() && cache_line_size > 0) {
     if (FLAG_IS_DEFAULT(UseBlockCopy)) {
       FLAG_SET_DEFAULT(UseBlockCopy, true);
     }
@@ -179,7 +190,6 @@
   }
 
 #ifdef COMPILER2
-  // T4 and newer Sparc cpus have fast RDPC.
   if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) {
     FLAG_SET_DEFAULT(UseRDPCForConstantTableBase, true);
   }
@@ -196,44 +206,68 @@
   assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 
   char buf[512];
-  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-               (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
-               (has_hardware_popc() ? ", popc" : ""),
-               (has_vis1() ? ", vis1" : ""),
-               (has_vis2() ? ", vis2" : ""),
-               (has_vis3() ? ", vis3" : ""),
-               (has_blk_init() ? ", blk_init" : ""),
-               (has_cbcond() ? ", cbcond" : ""),
-               (has_aes() ? ", aes" : ""),
-               (has_sha1() ? ", sha1" : ""),
-               (has_sha256() ? ", sha256" : ""),
-               (has_sha512() ? ", sha512" : ""),
-               (has_crc32c() ? ", crc32c" : ""),
-               (is_ultra3() ? ", ultra3" : ""),
-               (has_sparc5_instr() ? ", sparc5" : ""),
-               (is_sun4v() ? ", sun4v" : ""),
-               (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
-               (is_sparc64() ? ", sparc64" : ""),
-               (!has_hardware_mul32() ? ", no-mul32" : ""),
-               (!has_hardware_div32() ? ", no-div32" : ""),
-               (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
+  jio_snprintf(buf, sizeof(buf),
+               "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+               (has_v9()          ? "v9" : ""),
+               (has_popc()        ? ", popc" : ""),
+               (has_vis1()        ? ", vis1" : ""),
+               (has_vis2()        ? ", vis2" : ""),
+               (has_blk_init()    ? ", blk_init" : ""),
+               (has_fmaf()        ? ", fmaf" : ""),
+               (has_hpc()         ? ", hpc" : ""),
+               (has_ima()         ? ", ima" : ""),
+               (has_aes()         ? ", aes" : ""),
+               (has_des()         ? ", des" : ""),
+               (has_kasumi()      ? ", kas" : ""),
+               (has_camellia()    ? ", cam" : ""),
+               (has_md5()         ? ", md5" : ""),
+               (has_sha1()        ? ", sha1" : ""),
+               (has_sha256()      ? ", sha256" : ""),
+               (has_sha512()      ? ", sha512" : ""),
+               (has_mpmul()       ? ", mpmul" : ""),
+               (has_mont()        ? ", mont" : ""),
+               (has_pause()       ? ", pause" : ""),
+               (has_cbcond()      ? ", cbcond" : ""),
+               (has_crc32c()      ? ", crc32c" : ""),
 
-  // buf is started with ", " or is empty
-  _features_string = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
+               (has_athena_plus() ? ", athena_plus" : ""),
+               (has_vis3b()       ? ", vis3b" : ""),
+               (has_adi()         ? ", adi" : ""),
+               (has_sparc5()      ? ", sparc5" : ""),
+               (has_mwait()       ? ", mwait" : ""),
+               (has_xmpmul()      ? ", xmpmul" : ""),
+               (has_xmont()       ? ", xmont" : ""),
+               (has_pause_nsec()  ? ", pause_nsec" : ""),
+               (has_vamask()      ? ", vamask" : ""),
 
-  // UseVIS is set to the smallest of what hardware supports and what
-  // the command line requires.  I.e., you cannot set UseVIS to 3 on
-  // older UltraSparc which do not support it.
-  if (UseVIS > 3) UseVIS=3;
-  if (UseVIS < 0) UseVIS=0;
+               (has_fast_idiv()   ? ", *idiv" : ""),
+               (has_fast_rdpc()   ? ", *rdpc" : ""),
+               (has_fast_bis()    ? ", *bis" : ""),
+               (has_fast_ld()     ? ", *ld" : ""),
+               (has_fast_cmove()  ? ", *cmove" : ""),
+               (has_fast_fxtof()  ? ", *fxtof" : ""),
+               (has_fast_ind_br() ? ", *ind_br" : ""),
+               (has_blk_zeroing() ? ", *blk_zeroing" : ""));
+
+  assert(strlen(buf) >= 2, "must be");
+
+  _features_string = os::strdup(buf);
+
+  log_info(os, cpu)("SPARC features detected: %s", _features_string);
+
+  // UseVIS is set to the smallest of what hardware supports and what the command
+  // line requires, i.e. you cannot set UseVIS to 3 on older UltraSparc which do
+  // not support it.
+
+  if (UseVIS > 3) UseVIS = 3;
+  if (UseVIS < 0) UseVIS = 0;
   if (!has_vis3()) // Drop to 2 if no VIS3 support
-    UseVIS = MIN2((intx)2,UseVIS);
+    UseVIS = MIN2((intx)2, UseVIS);
   if (!has_vis2()) // Drop to 1 if no VIS2 support
-    UseVIS = MIN2((intx)1,UseVIS);
+    UseVIS = MIN2((intx)1, UseVIS);
   if (!has_vis1()) // Drop to 0 if no VIS1 support
     UseVIS = 0;
 
-  // SPARC T4 and above should have support for AES instructions
   if (has_aes()) {
     if (FLAG_IS_DEFAULT(UseAES)) {
       FLAG_SET_DEFAULT(UseAES, true);
@@ -289,7 +323,7 @@
     FLAG_SET_DEFAULT(UseFMA, false);
   }
 
-  // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
+  // SHA1, SHA256, and SHA512 instructions were added to SPARC at different times
   if (has_sha1() || has_sha256() || has_sha512()) {
     if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
       if (FLAG_IS_DEFAULT(UseSHA)) {
@@ -337,7 +371,6 @@
     FLAG_SET_DEFAULT(UseSHA, false);
   }
 
-  // SPARC T4 and above should have support for CRC32C instruction
   if (has_crc32c()) {
     if (UseVIS > 2) { // CRC32C intrinsics use VIS3 instructions
       if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
@@ -425,96 +458,46 @@
 }
 
 void VM_Version::print_features() {
-  tty->print_cr("Version:%s", _features);
+  tty->print("ISA features [0x%0" PRIx64 "]:", _features);
+  if (_features_string != NULL) {
+    tty->print(" %s", _features_string);
+  }
+  tty->cr();
 }
 
-int VM_Version::determine_features() {
+void VM_Version::determine_features() {
   if (UseV8InstrsOnly) {
-    log_info(os, cpu)("Version is Forced-V8");
-    return generic_v8_m;
-  }
-
-  int features = platform_features(unknown_m); // platform_features() is os_arch specific
-
-  if (features == unknown_m) {
-    features = generic_v9_m;
-    log_info(os)("Cannot recognize SPARC version. Default to V9");
+    log_info(os, cpu)("SPARC V8 not supported");
   }
 
-  assert(is_T_family(features) == is_niagara(features), "Niagara should be T series");
-  if (UseNiagaraInstrs) { // Force code generation for Niagara
-    if (is_T_family(features)) {
-      // Happy to accomodate...
-    } else {
-      log_info(os, cpu)("Version is Forced-Niagara");
-      features |= T_family_m;
-    }
-  } else {
-    if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) {
-      log_info(os, cpu)("Version is Forced-Not-Niagara");
-      features &= ~(T_family_m | T1_model_m);
-    } else {
-      // Happy to accomodate...
-    }
+  platform_features(); // platform_features() is os_arch specific
+
+  assert(has_v9(), "must be");
+
+  if (UseNiagaraInstrs) { // Limit code generation to Niagara.
+    _features &= niagara1_msk;
   }
-
-  return features;
 }
 
 static uint64_t saved_features = 0;
 
 void VM_Version::allow_all() {
   saved_features = _features;
-  _features      = all_features_m;
+  _features      = full_feature_msk;
 }
 
 void VM_Version::revert() {
   _features = saved_features;
 }
 
+/* Determine a suitable number of threads on this particular machine.
+ *
+ * FIXME: Simply checking the processor family is insufficient.
+ */
 unsigned int VM_Version::calc_parallel_worker_threads() {
-  unsigned int result;
-  if (is_M_series() || is_S_series()) {
-    // for now, use same gc thread calculation for M-series and S-series as for
-    // niagara-plus. In future, we may want to tweak parameters for
-    // nof_parallel_worker_thread
-    result = nof_parallel_worker_threads(5, 16, 8);
-  } else if (is_niagara_plus()) {
-    result = nof_parallel_worker_threads(5, 16, 8);
-  } else {
-    result = nof_parallel_worker_threads(5, 8, 8);
-  }
-  return result;
-}
-
-
-int VM_Version::parse_features(const char* implementation) {
-  int features = unknown_m;
-  // Convert to UPPER case before compare.
-  char* impl = os::strdup_check_oom(implementation);
+  const int num = 5;
+  const int den = is_post_niagara() ? 16 : 8;
+  const int threshold = 8;
 
-  for (int i = 0; impl[i] != 0; i++)
-    impl[i] = (char)toupper((uint)impl[i]);
-
-  if (strstr(impl, "SPARC64") != NULL) {
-    features |= sparc64_family_m;
-  } else if (strstr(impl, "SPARC-M") != NULL) {
-    // M-series SPARC is based on T-series.
-    features |= (M_family_m | T_family_m);
-  } else if (strstr(impl, "SPARC-S") != NULL) {
-    // S-series SPARC is based on T-series.
-    features |= (S_family_m | T_family_m);
-  } else if (strstr(impl, "SPARC-T") != NULL) {
-    features |= T_family_m;
-    if (strstr(impl, "SPARC-T1") != NULL) {
-      features |= T1_model_m;
-    }
-  } else if (strstr(impl, "SUN4V-CPU") != NULL) {
-    // Generic or migration class LDOM
-    features |= T_family_m;
-  } else {
-    log_info(os, cpu)("Failed to parse CPU implementation = '%s'", impl);
-  }
-  os::free((void*)impl);
-  return features;
+  return nof_parallel_worker_threads(num, den, threshold);
 }
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Tue Jun 27 15:27:54 2017 +0200
@@ -33,150 +33,241 @@
   friend class JVMCIVMStructs;
 
 protected:
-  enum Feature_Flag {
-    v8_instructions       = 0,
-    hardware_mul32        = 1,
-    hardware_div32        = 2,
-    hardware_fsmuld       = 3,
-    hardware_popc         = 4,
-    v9_instructions       = 5,
-    vis1_instructions     = 6,
-    vis2_instructions     = 7,
-    sun4v_instructions    = 8,
-    blk_init_instructions = 9,
-    fmaf_instructions     = 10,
-    vis3_instructions     = 11,
-    cbcond_instructions   = 12,
-    sparc64_family        = 13,
-    M_family              = 14,
-    S_family              = 15,
-    T_family              = 16,
-    T1_model              = 17,
-    sparc5_instructions   = 18,
-    aes_instructions      = 19,
-    sha1_instruction      = 20,
-    sha256_instruction    = 21,
-    sha512_instruction    = 22,
-    crc32c_instruction    = 23
+  enum {
+    ISA_V9,
+    ISA_POPC,
+    ISA_VIS1,
+    ISA_VIS2,
+    ISA_BLK_INIT,
+    ISA_FMAF,
+    ISA_VIS3,
+    ISA_HPC,
+    ISA_IMA,
+    ISA_AES,
+    ISA_DES,
+    ISA_KASUMI,
+    ISA_CAMELLIA,
+    ISA_MD5,
+    ISA_SHA1,
+    ISA_SHA256,
+    ISA_SHA512,
+    ISA_MPMUL,
+    ISA_MONT,
+    ISA_PAUSE,
+    ISA_CBCOND,
+    ISA_CRC32C,
+
+    ISA_FJATHPLUS,
+    ISA_VIS3B,
+    ISA_ADI,
+    ISA_SPARC5,
+    ISA_MWAIT,
+    ISA_XMPMUL,
+    ISA_XMONT,
+    ISA_PAUSE_NSEC,
+    ISA_VAMASK,
+
+    // Synthesised properties:
+
+    CPU_FAST_IDIV,
+    CPU_FAST_RDPC,
+    CPU_FAST_BIS,
+    CPU_FAST_LD,
+    CPU_FAST_CMOVE,
+    CPU_FAST_IND_BR,
+    CPU_BLK_ZEROING
   };
 
-  enum Feature_Flag_Set {
-    unknown_m           = 0,
-    all_features_m      = -1,
+private:
+  enum { ISA_last_feature = ISA_VAMASK,
+         CPU_last_feature = CPU_BLK_ZEROING };
+
+  enum {
+    ISA_unknown_msk     = 0,
+
+    ISA_v9_msk          = UINT64_C(1) << ISA_V9,
 
-    v8_instructions_m       = 1 << v8_instructions,
-    hardware_mul32_m        = 1 << hardware_mul32,
-    hardware_div32_m        = 1 << hardware_div32,
-    hardware_fsmuld_m       = 1 << hardware_fsmuld,
-    hardware_popc_m         = 1 << hardware_popc,
-    v9_instructions_m       = 1 << v9_instructions,
-    vis1_instructions_m     = 1 << vis1_instructions,
-    vis2_instructions_m     = 1 << vis2_instructions,
-    sun4v_m                 = 1 << sun4v_instructions,
-    blk_init_instructions_m = 1 << blk_init_instructions,
-    fmaf_instructions_m     = 1 << fmaf_instructions,
-    vis3_instructions_m     = 1 << vis3_instructions,
-    cbcond_instructions_m   = 1 << cbcond_instructions,
-    sparc64_family_m        = 1 << sparc64_family,
-    M_family_m              = 1 << M_family,
-    S_family_m              = 1 << S_family,
-    T_family_m              = 1 << T_family,
-    T1_model_m              = 1 << T1_model,
-    sparc5_instructions_m   = 1 << sparc5_instructions,
-    aes_instructions_m      = 1 << aes_instructions,
-    sha1_instruction_m      = 1 << sha1_instruction,
-    sha256_instruction_m    = 1 << sha256_instruction,
-    sha512_instruction_m    = 1 << sha512_instruction,
-    crc32c_instruction_m    = 1 << crc32c_instruction,
+    ISA_popc_msk        = UINT64_C(1) << ISA_POPC,
+    ISA_vis1_msk        = UINT64_C(1) << ISA_VIS1,
+    ISA_vis2_msk        = UINT64_C(1) << ISA_VIS2,
+    ISA_blk_init_msk    = UINT64_C(1) << ISA_BLK_INIT,
+    ISA_fmaf_msk        = UINT64_C(1) << ISA_FMAF,
+    ISA_vis3_msk        = UINT64_C(1) << ISA_VIS3,
+    ISA_hpc_msk         = UINT64_C(1) << ISA_HPC,
+    ISA_ima_msk         = UINT64_C(1) << ISA_IMA,
+    ISA_aes_msk         = UINT64_C(1) << ISA_AES,
+    ISA_des_msk         = UINT64_C(1) << ISA_DES,
+    ISA_kasumi_msk      = UINT64_C(1) << ISA_KASUMI,
+    ISA_camellia_msk    = UINT64_C(1) << ISA_CAMELLIA,
+    ISA_md5_msk         = UINT64_C(1) << ISA_MD5,
+    ISA_sha1_msk        = UINT64_C(1) << ISA_SHA1,
+    ISA_sha256_msk      = UINT64_C(1) << ISA_SHA256,
+    ISA_sha512_msk      = UINT64_C(1) << ISA_SHA512,
+    ISA_mpmul_msk       = UINT64_C(1) << ISA_MPMUL,
+    ISA_mont_msk        = UINT64_C(1) << ISA_MONT,
+    ISA_pause_msk       = UINT64_C(1) << ISA_PAUSE,
+    ISA_cbcond_msk      = UINT64_C(1) << ISA_CBCOND,
+    ISA_crc32c_msk      = UINT64_C(1) << ISA_CRC32C,
 
-    generic_v8_m        = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
-    generic_v9_m        = generic_v8_m | v9_instructions_m,
-    ultra3_m            = generic_v9_m | vis1_instructions_m | vis2_instructions_m,
+    ISA_fjathplus_msk   = UINT64_C(1) << ISA_FJATHPLUS,
+    ISA_vis3b_msk       = UINT64_C(1) << ISA_VIS3B,
+    ISA_adi_msk         = UINT64_C(1) << ISA_ADI,
+    ISA_sparc5_msk      = UINT64_C(1) << ISA_SPARC5,
+    ISA_mwait_msk       = UINT64_C(1) << ISA_MWAIT,
+    ISA_xmpmul_msk      = UINT64_C(1) << ISA_XMPMUL,
+    ISA_xmont_msk       = UINT64_C(1) << ISA_XMONT,
+    ISA_pause_nsec_msk  = UINT64_C(1) << ISA_PAUSE_NSEC,
+    ISA_vamask_msk      = UINT64_C(1) << ISA_VAMASK,
 
-    // Temporary until we have something more accurate
-    niagara1_unique_m   = sun4v_m,
-    niagara1_m          = generic_v9_m | niagara1_unique_m
+    CPU_fast_idiv_msk   = UINT64_C(1) << CPU_FAST_IDIV,
+    CPU_fast_rdpc_msk   = UINT64_C(1) << CPU_FAST_RDPC,
+    CPU_fast_bis_msk    = UINT64_C(1) << CPU_FAST_BIS,
+    CPU_fast_ld_msk     = UINT64_C(1) << CPU_FAST_LD,
+    CPU_fast_cmove_msk  = UINT64_C(1) << CPU_FAST_CMOVE,
+    CPU_fast_ind_br_msk = UINT64_C(1) << CPU_FAST_IND_BR,
+    CPU_blk_zeroing_msk = UINT64_C(1) << CPU_BLK_ZEROING,
+
+    last_feature_msk    = CPU_blk_zeroing_msk,
+    full_feature_msk    = (last_feature_msk << 1) - 1
   };
 
-  static unsigned int _L2_data_cache_line_size;
-  static unsigned int L2_data_cache_line_size() { return _L2_data_cache_line_size; }
-
-  static void print_features();
-  static int  determine_features();
-  static int  platform_features(int features);
+/* The following, previously supported, SPARC implementations are no longer
+ * supported.
+ *
+ *  UltraSPARC I/II:
+ *    SPARC-V9, VIS
+ *  UltraSPARC III/+:  (Cheetah/+)
+ *    SPARC-V9, VIS
+ *  UltraSPARC IV:     (Jaguar)
+ *    SPARC-V9, VIS
+ *  UltraSPARC IV+:    (Panther)
+ *    SPARC-V9, VIS, POPC
+ *
+ * The currently supported SPARC implementations are listed below (including
+ * generic V9 support).
+ *
+ *  UltraSPARC T1:     (Niagara)
+ *    SPARC-V9, VIS, ASI_BIS                (Crypto/hash in SPU)
+ *  UltraSPARC T2:     (Niagara-2)
+ *    SPARC-V9, VIS, ASI_BIS, POPC          (Crypto/hash in SPU)
+ *  UltraSPARC T2+:    (Victoria Falls, etc.)
+ *    SPARC-V9, VIS, VIS2, ASI_BIS, POPC    (Crypto/hash in SPU)
+ *
+ *  UltraSPARC T3:     (Rainbow Falls/S2)
+ *    SPARC-V9, VIS, VIS2, ASI_BIS, POPC    (Crypto/hash in SPU)
+ *
+ *  Oracle SPARC T4/T5/M5:  (Core S3)
+ *    SPARC-V9, VIS, VIS2, VIS3, ASI_BIS, HPC, POPC, FMAF, IMA, PAUSE, CBCOND,
+ *    AES, DES, Kasumi, Camellia, MD5, SHA1, SHA256, SHA512, CRC32C, MONT, MPMUL
+ *
+ *  Oracle SPARC M7:   (Core S4)
+ *    SPARC-V9, VIS, VIS2, VIS3, ASI_BIS, HPC, POPC, FMAF, IMA, PAUSE, CBCOND,
+ *    AES, DES, Camellia, MD5, SHA1, SHA256, SHA512, CRC32C, MONT, MPMUL, VIS3b,
+ *    ADI, SPARC5, MWAIT, XMPMUL, XMONT, PAUSE_NSEC, VAMASK
+ *
+ */
+  enum {
+    niagara1_msk = ISA_v9_msk | ISA_vis1_msk | ISA_blk_init_msk,
+    niagara2_msk = niagara1_msk | ISA_popc_msk,
 
-  // Returns true if the platform is in the niagara line (T series)
-  static bool is_M_family(int features) { return (features & M_family_m) != 0; }
-  static bool is_S_family(int features) { return (features & S_family_m) != 0; }
-  static bool is_T_family(int features) { return (features & T_family_m) != 0; }
-  static bool is_niagara() { return is_T_family(_features); }
-#ifdef ASSERT
-  static bool is_niagara(int features)  {
-    // 'sun4v_m' may be defined on both Sun/Oracle Sparc CPUs as well as
-    // on Fujitsu Sparc64 CPUs, but only Sun/Oracle Sparcs can be 'niagaras'.
-    return (features & sun4v_m) != 0 && (features & sparc64_family_m) == 0;
-  }
-#endif
+    core_S2_msk  = niagara2_msk | ISA_vis2_msk,
+
+    core_S3_msk  = core_S2_msk | ISA_fmaf_msk | ISA_vis3_msk | ISA_hpc_msk |
+        ISA_ima_msk | ISA_aes_msk | ISA_des_msk | ISA_kasumi_msk |
+        ISA_camellia_msk | ISA_md5_msk | ISA_sha1_msk | ISA_sha256_msk |
+        ISA_sha512_msk | ISA_mpmul_msk | ISA_mont_msk | ISA_pause_msk |
+        ISA_cbcond_msk | ISA_crc32c_msk,
+
+    core_S4_msk  = core_S3_msk - ISA_kasumi_msk |
+        ISA_vis3b_msk | ISA_adi_msk | ISA_sparc5_msk | ISA_mwait_msk |
+        ISA_xmpmul_msk | ISA_xmont_msk | ISA_pause_nsec_msk | ISA_vamask_msk,
+
+    ultra_sparc_t1_msk = niagara1_msk,
+    ultra_sparc_t2_msk = niagara2_msk,
+    ultra_sparc_t3_msk = core_S2_msk,
+    ultra_sparc_m5_msk = core_S3_msk,   // NOTE: First out-of-order pipeline.
+    ultra_sparc_m7_msk = core_S4_msk
+  };
 
-  // Returns true if it is niagara1 (T1).
-  static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); }
+  static uint _L2_data_cache_line_size;
+  static uint L2_data_cache_line_size() { return _L2_data_cache_line_size; }
+
+  static void determine_features();
+  static void platform_features();
+  static void print_features();
 
-  static int maximum_niagara1_processor_count() { return 32; }
-  static int parse_features(const char* implementation);
 public:
-  // Initialization
+  enum {
+    // Adopt a conservative behaviour (modelling single-insn-fetch-n-issue) for
+    // Niagara (and SPARC64). While there are at least two entries/slots in the
+    // instruction fetch buffer on any Niagara core (and as many as eight on a
+    // SPARC64), the performance improvement from keeping hot branch targets on
+    // optimally aligned addresses is such a small one (if any) that we choose
+    // not to use the extra code space required.
+
+    insn_fetch_alignment = 4    // Byte alignment in L1 insn. cache.
+  };
+
   static void initialize();
 
-  static void init_before_ergo()        { _features = determine_features(); }
+  static void init_before_ergo() { determine_features(); }
+
+  // Instruction feature support:
 
-  // Instruction support
-  static bool has_v8()                  { return (_features & v8_instructions_m) != 0; }
-  static bool has_v9()                  { return (_features & v9_instructions_m) != 0; }
-  static bool has_hardware_mul32()      { return (_features & hardware_mul32_m) != 0; }
-  static bool has_hardware_div32()      { return (_features & hardware_div32_m) != 0; }
-  static bool has_hardware_fsmuld()     { return (_features & hardware_fsmuld_m) != 0; }
-  static bool has_hardware_popc()       { return (_features & hardware_popc_m) != 0; }
-  static bool has_vis1()                { return (_features & vis1_instructions_m) != 0; }
-  static bool has_vis2()                { return (_features & vis2_instructions_m) != 0; }
-  static bool has_vis3()                { return (_features & vis3_instructions_m) != 0; }
-  static bool has_blk_init()            { return (_features & blk_init_instructions_m) != 0; }
-  static bool has_cbcond()              { return (_features & cbcond_instructions_m) != 0; }
-  static bool has_sparc5_instr()        { return (_features & sparc5_instructions_m) != 0; }
-  static bool has_aes()                 { return (_features & aes_instructions_m) != 0; }
-  static bool has_sha1()                { return (_features & sha1_instruction_m) != 0; }
-  static bool has_sha256()              { return (_features & sha256_instruction_m) != 0; }
-  static bool has_sha512()              { return (_features & sha512_instruction_m) != 0; }
-  static bool has_crc32c()              { return (_features & crc32c_instruction_m) != 0; }
-
-  static bool supports_compare_and_exchange()
-                                        { return has_v9(); }
+  static bool has_v9()           { return (_features & ISA_v9_msk) != 0; }
+  static bool has_popc()         { return (_features & ISA_popc_msk) != 0; }
+  static bool has_vis1()         { return (_features & ISA_vis1_msk) != 0; }
+  static bool has_vis2()         { return (_features & ISA_vis2_msk) != 0; }
+  static bool has_blk_init()     { return (_features & ISA_blk_init_msk) != 0; }
+  static bool has_fmaf()         { return (_features & ISA_fmaf_msk) != 0; }
+  static bool has_vis3()         { return (_features & ISA_vis3_msk) != 0; }
+  static bool has_hpc()          { return (_features & ISA_hpc_msk) != 0; }
+  static bool has_ima()          { return (_features & ISA_ima_msk) != 0; }
+  static bool has_aes()          { return (_features & ISA_aes_msk) != 0; }
+  static bool has_des()          { return (_features & ISA_des_msk) != 0; }
+  static bool has_kasumi()       { return (_features & ISA_kasumi_msk) != 0; }
+  static bool has_camellia()     { return (_features & ISA_camellia_msk) != 0; }
+  static bool has_md5()          { return (_features & ISA_md5_msk) != 0; }
+  static bool has_sha1()         { return (_features & ISA_sha1_msk) != 0; }
+  static bool has_sha256()       { return (_features & ISA_sha256_msk) != 0; }
+  static bool has_sha512()       { return (_features & ISA_sha512_msk) != 0; }
+  static bool has_mpmul()        { return (_features & ISA_mpmul_msk) != 0; }
+  static bool has_mont()         { return (_features & ISA_mont_msk) != 0; }
+  static bool has_pause()        { return (_features & ISA_pause_msk) != 0; }
+  static bool has_cbcond()       { return (_features & ISA_cbcond_msk) != 0; }
+  static bool has_crc32c()       { return (_features & ISA_crc32c_msk) != 0; }
 
-  // Returns true if the platform is in the niagara line (T series)
-  // and newer than the niagara1.
-  static bool is_niagara_plus()         { return is_T_family(_features) && !is_T1_model(_features); }
-
-  static bool is_M_series()             { return is_M_family(_features); }
-  static bool is_S_series()             { return is_S_family(_features); }
-  static bool is_T4()                   { return is_T_family(_features) && has_cbcond(); }
-  static bool is_T7()                   { return is_T_family(_features) && has_sparc5_instr(); }
-
-  // Fujitsu SPARC64
-  static bool is_sparc64()              { return (_features & sparc64_family_m) != 0; }
+  static bool has_athena_plus()  { return (_features & ISA_fjathplus_msk) != 0; }
+  static bool has_vis3b()        { return (_features & ISA_vis3b_msk) != 0; }
+  static bool has_adi()          { return (_features & ISA_adi_msk) != 0; }
+  static bool has_sparc5()       { return (_features & ISA_sparc5_msk) != 0; }
+  static bool has_mwait()        { return (_features & ISA_mwait_msk) != 0; }
+  static bool has_xmpmul()       { return (_features & ISA_xmpmul_msk) != 0; }
+  static bool has_xmont()        { return (_features & ISA_xmont_msk) != 0; }
+  static bool has_pause_nsec()   { return (_features & ISA_pause_nsec_msk) != 0; }
+  static bool has_vamask()       { return (_features & ISA_vamask_msk) != 0; }
 
-  static bool is_sun4v()                { return (_features & sun4v_m) != 0; }
-  static bool is_ultra3()               { return (_features & ultra3_m) == ultra3_m && !is_sun4v() && !is_sparc64(); }
-
-  static bool has_fast_fxtof()          { return is_niagara() || is_sparc64() || has_v9() && !is_ultra3(); }
-  static bool has_fast_idiv()           { return is_niagara_plus() || is_sparc64(); }
+  static bool has_fast_idiv()    { return (_features & CPU_fast_idiv_msk) != 0; }
+  static bool has_fast_rdpc()    { return (_features & CPU_fast_rdpc_msk) != 0; }
+  static bool has_fast_bis()     { return (_features & CPU_fast_bis_msk) != 0; }
+  static bool has_fast_ld()      { return (_features & CPU_fast_ld_msk) != 0; }
+  static bool has_fast_cmove()   { return (_features & CPU_fast_cmove_msk) != 0; }
+  static bool has_fast_fxtof()   { return true; }
 
-  // T4 and newer Sparc have fast RDPC instruction.
-  static bool has_fast_rdpc()           { return is_T4(); }
+  // If indirect and direct branching is equally fast.
+  static bool has_fast_ind_br()  { return (_features & CPU_fast_ind_br_msk) != 0; }
+  // If SPARC BIS to the beginning of cache line always zeros it.
+  static bool has_blk_zeroing()  { return (_features & CPU_blk_zeroing_msk) != 0; }
+
+  static bool supports_compare_and_exchange() { return true; }
 
-  // On T4 and newer Sparc BIS to the beginning of cache line always zeros it.
-  static bool has_block_zeroing()       { return has_blk_init() && is_T4(); }
+  // FIXME: To be removed.
+  static bool is_post_niagara()  {
+    return (_features & niagara2_msk) == niagara2_msk;
+  }
 
-  // default prefetch block size on sparc
-  static intx prefetch_data_size()      { return L2_data_cache_line_size();  }
+  // Default prefetch block size on SPARC.
+  static uint prefetch_data_size() { return L2_data_cache_line_size(); }
 
  private:
   // Prefetch policy and characteristics:
@@ -228,7 +319,11 @@
   static void revert();
 
   // Override the Abstract_VM_Version implementation.
-  static uint page_size_count() { return is_sun4v() ? 4 : 2; }
+  //
+  // FIXME: Removed broken test on sun4v (always false when invoked prior to the
+  //        proper capability setup), thus always returning 2. Still need to fix
+  //        this properly in order to enable complete page size support.
+  static uint page_size_count() { return 2; }
 
   // Calculates the number of parallel threads
   static unsigned int calc_parallel_worker_threads();
--- a/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp	Tue Jun 27 15:27:54 2017 +0200
@@ -27,9 +27,8 @@
 
 inline bool is_Register() { return value() >= 0 && value() < ConcreteRegisterImpl::max_gpr; }
 inline bool is_FloatRegister() { return value() >= ConcreteRegisterImpl::max_gpr &&
-                                                   value() < ConcreteRegisterImpl::max_fpr; }
+                                        value()  < ConcreteRegisterImpl::max_fpr; }
 inline Register as_Register() {
-
   assert( is_Register() && is_even(value()), "even-aligned GPR name" );
   // Yuk
   return ::as_Register(value()>>1);
--- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Tue Jun 27 15:27:54 2017 +0200
@@ -57,72 +57,120 @@
 
     protected EnumSet<CPUFeature> computeFeatures(SPARCHotSpotVMConfig config) {
         EnumSet<CPUFeature> features = EnumSet.noneOf(CPUFeature.class);
-        if ((config.vmVersionFeatures & config.sparcVis1Instructions) != 0) {
-            features.add(CPUFeature.VIS1);
+
+        if ((config.vmVersionFeatures & 1L << config.sparc_ADI) != 0) {
+            features.add(CPUFeature.ADI);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_AES) != 0) {
+            features.add(CPUFeature.AES);
         }
-        if ((config.vmVersionFeatures & config.sparcVis2Instructions) != 0) {
-            features.add(CPUFeature.VIS2);
+        if ((config.vmVersionFeatures & 1L << config.sparc_BLK_INIT) != 0) {
+            features.add(CPUFeature.BLK_INIT);
         }
-        if ((config.vmVersionFeatures & config.sparcVis3Instructions) != 0) {
-            features.add(CPUFeature.VIS3);
+        if ((config.vmVersionFeatures & 1L << config.sparc_CAMELLIA) != 0) {
+            features.add(CPUFeature.CAMELLIA);
         }
-        if ((config.vmVersionFeatures & config.sparcCbcondInstructions) != 0) {
+        if ((config.vmVersionFeatures & 1L << config.sparc_CBCOND) != 0) {
             features.add(CPUFeature.CBCOND);
         }
-        if ((config.vmVersionFeatures & config.sparcV8Instructions) != 0) {
-            features.add(CPUFeature.V8);
+        if ((config.vmVersionFeatures & 1L << config.sparc_CRC32C) != 0) {
+            features.add(CPUFeature.CRC32C);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_DES) != 0) {
+            features.add(CPUFeature.DES);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_FMAF) != 0) {
+            features.add(CPUFeature.FMAF);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_HPC) != 0) {
+            features.add(CPUFeature.HPC);
         }
-        if ((config.vmVersionFeatures & config.sparcHardwareMul32) != 0) {
-            features.add(CPUFeature.HARDWARE_MUL32);
+        if ((config.vmVersionFeatures & 1L << config.sparc_IMA) != 0) {
+            features.add(CPUFeature.IMA);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_KASUMI) != 0) {
+            features.add(CPUFeature.KASUMI);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_MD5) != 0) {
+            features.add(CPUFeature.MD5);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_MONT) != 0) {
+            features.add(CPUFeature.MONT);
         }
-        if ((config.vmVersionFeatures & config.sparcHardwareDiv32) != 0) {
-            features.add(CPUFeature.HARDWARE_DIV32);
+        if ((config.vmVersionFeatures & 1L << config.sparc_MPMUL) != 0) {
+            features.add(CPUFeature.MPMUL);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_MWAIT) != 0) {
+            features.add(CPUFeature.MWAIT);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_PAUSE) != 0) {
+            features.add(CPUFeature.PAUSE);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_PAUSE_NSEC) != 0) {
+            features.add(CPUFeature.PAUSE_NSEC);
         }
-        if ((config.vmVersionFeatures & config.sparcHardwareFsmuld) != 0) {
-            features.add(CPUFeature.HARDWARE_FSMULD);
+        if ((config.vmVersionFeatures & 1L << config.sparc_POPC) != 0) {
+            features.add(CPUFeature.POPC);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_SHA1) != 0) {
+            features.add(CPUFeature.SHA1);
         }
-        if ((config.vmVersionFeatures & config.sparcHardwarePopc) != 0) {
-            features.add(CPUFeature.HARDWARE_POPC);
+        if ((config.vmVersionFeatures & 1L << config.sparc_SHA256) != 0) {
+            features.add(CPUFeature.SHA256);
         }
-        if ((config.vmVersionFeatures & config.sparcV9Instructions) != 0) {
+        if ((config.vmVersionFeatures & 1L << config.sparc_SHA512) != 0) {
+            features.add(CPUFeature.SHA512);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_SPARC5) != 0) {
+            features.add(CPUFeature.SPARC5);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_V9) != 0) {
             features.add(CPUFeature.V9);
         }
-        if ((config.vmVersionFeatures & config.sparcSun4v) != 0) {
-            features.add(CPUFeature.SUN4V);
+        if ((config.vmVersionFeatures & 1L << config.sparc_VAMASK) != 0) {
+            features.add(CPUFeature.VAMASK);
         }
-        if ((config.vmVersionFeatures & config.sparcBlkInitInstructions) != 0) {
-            features.add(CPUFeature.BLK_INIT_INSTRUCTIONS);
+        if ((config.vmVersionFeatures & 1L << config.sparc_VIS1) != 0) {
+            features.add(CPUFeature.VIS1);
         }
-        if ((config.vmVersionFeatures & config.sparcFmafInstructions) != 0) {
-            features.add(CPUFeature.FMAF);
+        if ((config.vmVersionFeatures & 1L << config.sparc_VIS2) != 0) {
+            features.add(CPUFeature.VIS2);
         }
-        if ((config.vmVersionFeatures & config.sparcSparc64Family) != 0) {
-            features.add(CPUFeature.SPARC64_FAMILY);
+        if ((config.vmVersionFeatures & 1L << config.sparc_VIS3) != 0) {
+            features.add(CPUFeature.VIS3);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_VIS3B) != 0) {
+            features.add(CPUFeature.VIS3B);
         }
-        if ((config.vmVersionFeatures & config.sparcMFamily) != 0) {
-            features.add(CPUFeature.M_FAMILY);
+        if ((config.vmVersionFeatures & 1L << config.sparc_XMONT) != 0) {
+            features.add(CPUFeature.XMONT);
         }
-        if ((config.vmVersionFeatures & config.sparcTFamily) != 0) {
-            features.add(CPUFeature.T_FAMILY);
+        if ((config.vmVersionFeatures & 1L << config.sparc_XMPMUL) != 0) {
+            features.add(CPUFeature.XMPMUL);
         }
-        if ((config.vmVersionFeatures & config.sparcT1Model) != 0) {
-            features.add(CPUFeature.T1_MODEL);
+
+        if ((config.vmVersionFeatures & 1L << config.sparc_BLK_ZEROING) != 0) {
+            features.add(CPUFeature.BLK_ZEROING);
         }
-        if ((config.vmVersionFeatures & config.sparcSparc5Instructions) != 0) {
-            features.add(CPUFeature.SPARC5);
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_BIS) != 0) {
+            features.add(CPUFeature.FAST_BIS);
         }
-        if ((config.vmVersionFeatures & config.sparcAesInstructions) != 0) {
-            features.add(CPUFeature.SPARC64_FAMILY);
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_CMOVE) != 0) {
+            features.add(CPUFeature.FAST_CMOVE);
         }
-        if ((config.vmVersionFeatures & config.sparcSha1Instruction) != 0) {
-            features.add(CPUFeature.SHA1);
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_IDIV) != 0) {
+            features.add(CPUFeature.FAST_IDIV);
+        }
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_IND_BR) != 0) {
+            features.add(CPUFeature.FAST_IND_BR);
         }
-        if ((config.vmVersionFeatures & config.sparcSha256Instruction) != 0) {
-            features.add(CPUFeature.SHA256);
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_LD) != 0) {
+            features.add(CPUFeature.FAST_LD);
         }
-        if ((config.vmVersionFeatures & config.sparcSha512Instruction) != 0) {
-            features.add(CPUFeature.SHA512);
+        if ((config.vmVersionFeatures & 1L << config.sparc_FAST_RDPC) != 0) {
+            features.add(CPUFeature.FAST_RDPC);
         }
+
         return features;
     }
 
--- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java	Tue Jun 27 15:27:54 2017 +0200
@@ -38,32 +38,54 @@
 
     final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
 
-    // CPU capabilities
+    // CPU capabilities:
+    //
+    // FIXME: Using a 64-bit value is insufficient to support future capability
+    //        sets (including co-processor capabilities such as DAX).
     final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
 
-    // SPARC specific values
-    final int sparcVis3Instructions = getConstant("VM_Version::vis3_instructions_m", Integer.class);
-    final int sparcVis2Instructions = getConstant("VM_Version::vis2_instructions_m", Integer.class);
-    final int sparcVis1Instructions = getConstant("VM_Version::vis1_instructions_m", Integer.class);
-    final int sparcCbcondInstructions = getConstant("VM_Version::cbcond_instructions_m", Integer.class);
-    final int sparcV8Instructions = getConstant("VM_Version::v8_instructions_m", Integer.class);
-    final int sparcHardwareMul32 = getConstant("VM_Version::hardware_mul32_m", Integer.class);
-    final int sparcHardwareDiv32 = getConstant("VM_Version::hardware_div32_m", Integer.class);
-    final int sparcHardwareFsmuld = getConstant("VM_Version::hardware_fsmuld_m", Integer.class);
-    final int sparcHardwarePopc = getConstant("VM_Version::hardware_popc_m", Integer.class);
-    final int sparcV9Instructions = getConstant("VM_Version::v9_instructions_m", Integer.class);
-    final int sparcSun4v = getConstant("VM_Version::sun4v_m", Integer.class);
-    final int sparcBlkInitInstructions = getConstant("VM_Version::blk_init_instructions_m", Integer.class);
-    final int sparcFmafInstructions = getConstant("VM_Version::fmaf_instructions_m", Integer.class);
-    final int sparcSparc64Family = getConstant("VM_Version::sparc64_family_m", Integer.class);
-    final int sparcMFamily = getConstant("VM_Version::M_family_m", Integer.class);
-    final int sparcTFamily = getConstant("VM_Version::T_family_m", Integer.class);
-    final int sparcT1Model = getConstant("VM_Version::T1_model_m", Integer.class);
-    final int sparcSparc5Instructions = getConstant("VM_Version::sparc5_instructions_m", Integer.class);
-    final int sparcAesInstructions = getConstant("VM_Version::aes_instructions_m", Integer.class);
-    final int sparcSha1Instruction = getConstant("VM_Version::sha1_instruction_m", Integer.class);
-    final int sparcSha256Instruction = getConstant("VM_Version::sha256_instruction_m", Integer.class);
-    final int sparcSha512Instruction = getConstant("VM_Version::sha512_instruction_m", Integer.class);
+    // SPARC specific values:
+    //
+    // NOTE: Values changed into an enumeration (that do indeed fit within a
+    //       32-bit integer) instead of the exported (64-bit wide) bit-masks.
+    final int sparc_ADI      = getConstant("VM_Version::ISA_ADI",      Integer.class);
+    final int sparc_AES      = getConstant("VM_Version::ISA_AES",      Integer.class);
+    final int sparc_BLK_INIT = getConstant("VM_Version::ISA_BLK_INIT", Integer.class);
+    final int sparc_CAMELLIA = getConstant("VM_Version::ISA_CAMELLIA", Integer.class);
+    final int sparc_CBCOND   = getConstant("VM_Version::ISA_CBCOND",   Integer.class);
+    final int sparc_CRC32C   = getConstant("VM_Version::ISA_CRC32C",   Integer.class);
+    final int sparc_DES      = getConstant("VM_Version::ISA_DES",      Integer.class);
+    final int sparc_FMAF     = getConstant("VM_Version::ISA_FMAF",     Integer.class);
+    final int sparc_HPC      = getConstant("VM_Version::ISA_HPC",      Integer.class);
+    final int sparc_IMA      = getConstant("VM_Version::ISA_IMA",      Integer.class);
+    final int sparc_KASUMI   = getConstant("VM_Version::ISA_KASUMI",   Integer.class);
+    final int sparc_MD5      = getConstant("VM_Version::ISA_MD5",      Integer.class);
+    final int sparc_MONT     = getConstant("VM_Version::ISA_MONT",     Integer.class);
+    final int sparc_MPMUL    = getConstant("VM_Version::ISA_MPMUL",    Integer.class);
+    final int sparc_MWAIT    = getConstant("VM_Version::ISA_MWAIT",    Integer.class);
+    final int sparc_PAUSE    = getConstant("VM_Version::ISA_PAUSE",    Integer.class);
+    final int sparc_PAUSE_NSEC = getConstant("VM_Version::ISA_PAUSE_NSEC", Integer.class);
+    final int sparc_POPC     = getConstant("VM_Version::ISA_POPC",     Integer.class);
+    final int sparc_SHA1     = getConstant("VM_Version::ISA_SHA1",     Integer.class);
+    final int sparc_SHA256   = getConstant("VM_Version::ISA_SHA256",   Integer.class);
+    final int sparc_SHA512   = getConstant("VM_Version::ISA_SHA512",   Integer.class);
+    final int sparc_SPARC5   = getConstant("VM_Version::ISA_SPARC5",   Integer.class);
+    final int sparc_V9       = getConstant("VM_Version::ISA_V9",       Integer.class);
+    final int sparc_VAMASK   = getConstant("VM_Version::ISA_VAMASK",   Integer.class);
+    final int sparc_VIS1     = getConstant("VM_Version::ISA_VIS1",     Integer.class);
+    final int sparc_VIS2     = getConstant("VM_Version::ISA_VIS2",     Integer.class);
+    final int sparc_VIS3     = getConstant("VM_Version::ISA_VIS3",     Integer.class);
+    final int sparc_VIS3B    = getConstant("VM_Version::ISA_VIS3B",    Integer.class);
+    final int sparc_XMONT    = getConstant("VM_Version::ISA_XMONT",    Integer.class);
+    final int sparc_XMPMUL   = getConstant("VM_Version::ISA_XMPMUL",   Integer.class);
+
+    final int sparc_BLK_ZEROING = getConstant("VM_Version::CPU_BLK_ZEROING", Integer.class);
+    final int sparc_FAST_BIS    = getConstant("VM_Version::CPU_FAST_BIS",    Integer.class);
+    final int sparc_FAST_CMOVE  = getConstant("VM_Version::CPU_FAST_CMOVE",  Integer.class);
+    final int sparc_FAST_IDIV   = getConstant("VM_Version::CPU_FAST_IDIV",   Integer.class);
+    final int sparc_FAST_IND_BR = getConstant("VM_Version::CPU_FAST_IND_BR", Integer.class);
+    final int sparc_FAST_LD     = getConstant("VM_Version::CPU_FAST_LD",     Integer.class);
+    final int sparc_FAST_RDPC   = getConstant("VM_Version::CPU_FAST_RDPC",   Integer.class);
 
     final boolean useBlockZeroing = getFlag("UseBlockZeroing", Boolean.class);
     final int blockZeroingLowLimit = getFlag("BlockZeroingLowLimit", Integer.class);
--- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Tue Jun 27 15:27:54 2017 +0200
@@ -336,27 +336,44 @@
     }
 
     public enum CPUFeature {
+        // ISA determined properties:
+        ADI,
+        AES,
+        BLK_INIT,
+        CAMELLIA,
+        CBCOND,
+        CRC32C,
+        DES,
+        FMAF,
+        HPC,
+        IMA,
+        KASUMI,
+        MD5,
+        MONT,
+        MPMUL,
+        MWAIT,
+        PAUSE,
+        PAUSE_NSEC,
+        POPC,
+        SHA1,
+        SHA256,
+        SHA512,
+        SPARC5,
+        V9,
+        VAMASK,
         VIS1,
         VIS2,
         VIS3,
-        CBCOND,
-        V8,
-        HARDWARE_MUL32,
-        HARDWARE_DIV32,
-        HARDWARE_FSMULD,
-        HARDWARE_POPC,
-        V9,
-        SUN4V,
-        BLK_INIT_INSTRUCTIONS,
-        FMAF,
-        SPARC64_FAMILY,
-        M_FAMILY,
-        T_FAMILY,
-        T1_MODEL,
-        SPARC5,
-        AES,
-        SHA1,
-        SHA256,
-        SHA512
+        VIS3B,
+        XMONT,
+        XMPMUL,
+        // Synthesised CPU properties:
+        BLK_ZEROING,
+        FAST_BIS,
+        FAST_CMOVE,
+        FAST_IDIV,
+        FAST_IND_BR,
+        FAST_LD,
+        FAST_RDPC
     }
 }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Tue Jun 27 15:27:54 2017 +0200
@@ -30,9 +30,7 @@
 #include "vm_version_sparc.hpp"
 
 #include <sys/auxv.h>
-#include <sys/auxv_SPARC.h>
 #include <sys/systeminfo.h>
-#include <kstat.h>
 #include <picl.h>
 #include <dlfcn.h>
 #include <link.h>
@@ -263,21 +261,6 @@
   _dl_handle = NULL;
 }
 
-// We need to keep these here as long as we have to build on Solaris
-// versions before 10.
-
-#ifndef SI_ARCHITECTURE_32
-#define SI_ARCHITECTURE_32      516     /* basic 32-bit SI_ARCHITECTURE */
-#endif
-
-#ifndef SI_ARCHITECTURE_64
-#define SI_ARCHITECTURE_64      517     /* basic 64-bit SI_ARCHITECTURE */
-#endif
-
-#ifndef SI_CPUBRAND
-#define SI_CPUBRAND             523     /* return cpu brand string */
-#endif
-
 class Sysinfo {
   char* _string;
 public:
@@ -343,115 +326,156 @@
 #define _SC_L2CACHE_LINESZ      527     /* Size of L2 cache line */
 #endif
 
-// Hardware capability bits that appeared after Solaris 11.1
-#ifndef AV_SPARC_FMAF
-#define AV_SPARC_FMAF    0x00000100 /* Fused Multiply-Add */
-#endif
-#ifndef AV2_SPARC_SPARC5
-#define AV2_SPARC_SPARC5 0x00000008 /* The 29 new fp and sub instructions */
-#endif
-
-int VM_Version::platform_features(int features) {
+void VM_Version::platform_features() {
+  uint64_t features = ISA_v9_msk;   // Basic SPARC-V9 required (V8 not supported).
 
-  // Check 32-bit architecture.
-  if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) {
-    features |= v8_instructions_m;
-  }
-
-  // Check 64-bit architecture.
-  if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) {
-    features |= generic_v9_m;
-  }
+  assert(Sysinfo(SI_ARCHITECTURE_64).match("sparcv9"), "must be");
 
   // Extract valid instruction set extensions.
-  uint_t avs[AV_HW2_IDX + 1];
-  uint_t avn = getisax(avs, ARRAY_SIZE(avs));
+  uint32_t avs[AV_HW2_IDX + 1];
+  uint_t avn = getisax(avs, AV_HW2_IDX + 1);
+  assert(avn <= 2, "should return two or less av's");
 
   log_info(os, cpu)("getisax(2) returned %d words:", avn);
   for (int i = 0; i < avn; i++) {
     log_info(os, cpu)("    word %d: " PTR32_FORMAT, i, avs[i]);
   }
 
-  uint_t av1 = avs[AV_HW1_IDX];
-  if (av1 & AV_SPARC_MUL32)        features |= hardware_mul32_m;
-  if (av1 & AV_SPARC_DIV32)        features |= hardware_div32_m;
-  if (av1 & AV_SPARC_FSMULD)       features |= hardware_fsmuld_m;
-  if (av1 & AV_SPARC_V8PLUS)       features |= v9_instructions_m;
-  if (av1 & AV_SPARC_POPC)         features |= hardware_popc_m;
-  if (av1 & AV_SPARC_VIS)          features |= vis1_instructions_m;
-  if (av1 & AV_SPARC_VIS2)         features |= vis2_instructions_m;
-  if (av1 & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
-  if (av1 & AV_SPARC_FMAF)         features |= fmaf_instructions_m;
-  if (av1 & AV_SPARC_VIS3)         features |= vis3_instructions_m;
-  if (av1 & AV_SPARC_CBCOND)       features |= cbcond_instructions_m;
-  if (av1 & AV_SPARC_CRC32C)       features |= crc32c_instruction_m;
-  if (av1 & AV_SPARC_AES)          features |= aes_instructions_m;
-  if (av1 & AV_SPARC_SHA1)         features |= sha1_instruction_m;
-  if (av1 & AV_SPARC_SHA256)       features |= sha256_instruction_m;
-  if (av1 & AV_SPARC_SHA512)       features |= sha512_instruction_m;
+  uint32_t av = avs[AV_HW1_IDX];
+
+  // These are SPARC V8 legacy features.
+
+  assert((av & AV_SPARC_MUL32)  == 0, "unsupported V8");
+  assert((av & AV_SPARC_DIV32)  == 0, "unsupported V8");
+  assert((av & AV_SPARC_FSMULD) == 0, "unsupported V8");
+  assert((av & AV_SPARC_V8PLUS) == 0, "unsupported V8");
+
+  if (av & AV_SPARC_POPC) features |= ISA_popc_msk;
+  if (av & AV_SPARC_VIS)  features |= ISA_vis1_msk;
+  if (av & AV_SPARC_VIS2) features |= ISA_vis2_msk;
+
+  // Hardware capability defines introduced after Solaris 11.1:
+
+#ifndef AV_SPARC_FMAF
+#define AV_SPARC_FMAF         0x00000100 // Fused Multiply-Add
+#endif
+
+  if (av & AV_SPARC_ASI_BLK_INIT) features |= ISA_blk_init_msk;
+  if (av & AV_SPARC_FMAF)         features |= ISA_fmaf_msk;
+  if (av & AV_SPARC_VIS3)         features |= ISA_vis3_msk;
+  if (av & AV_SPARC_HPC)          features |= ISA_hpc_msk;
+  if (av & AV_SPARC_IMA)          features |= ISA_ima_msk;
+  if (av & AV_SPARC_AES)          features |= ISA_aes_msk;
+  if (av & AV_SPARC_DES)          features |= ISA_des_msk;
+  if (av & AV_SPARC_KASUMI)       features |= ISA_kasumi_msk;
+  if (av & AV_SPARC_CAMELLIA)     features |= ISA_camellia_msk;
+  if (av & AV_SPARC_MD5)          features |= ISA_md5_msk;
+  if (av & AV_SPARC_SHA1)         features |= ISA_sha1_msk;
+  if (av & AV_SPARC_SHA256)       features |= ISA_sha256_msk;
+  if (av & AV_SPARC_SHA512)       features |= ISA_sha512_msk;
+  if (av & AV_SPARC_MPMUL)        features |= ISA_mpmul_msk;
+  if (av & AV_SPARC_MONT)         features |= ISA_mont_msk;
+  if (av & AV_SPARC_PAUSE)        features |= ISA_pause_msk;
+  if (av & AV_SPARC_CBCOND)       features |= ISA_cbcond_msk;
+  if (av & AV_SPARC_CRC32C)       features |= ISA_crc32c_msk;
 
-  if (avn > AV_HW2_IDX) {
-    uint_t av2 = avs[AV_HW2_IDX];
-    if (av2 & AV2_SPARC_SPARC5)    features |= sparc5_instructions_m;
-  }
+#ifndef AV2_SPARC_FJATHPLUS
+#define AV2_SPARC_FJATHPLUS  0x00000001 // Fujitsu Athena+
+#endif
+#ifndef AV2_SPARC_VIS3B
+#define AV2_SPARC_VIS3B      0x00000002 // VIS3 present on multiple chips
+#endif
+#ifndef AV2_SPARC_ADI
+#define AV2_SPARC_ADI        0x00000004 // Application Data Integrity
+#endif
+#ifndef AV2_SPARC_SPARC5
+#define AV2_SPARC_SPARC5     0x00000008 // The 29 new fp and sub instructions
+#endif
+#ifndef AV2_SPARC_MWAIT
+#define AV2_SPARC_MWAIT      0x00000010 // mwait instruction and load/monitor ASIs
+#endif
+#ifndef AV2_SPARC_XMPMUL
+#define AV2_SPARC_XMPMUL     0x00000020 // XOR multiple precision multiply
+#endif
+#ifndef AV2_SPARC_XMONT
+#define AV2_SPARC_XMONT      0x00000040 // XOR Montgomery mult/sqr instructions
+#endif
+#ifndef AV2_SPARC_PAUSE_NSEC
+#define AV2_SPARC_PAUSE_NSEC 0x00000080 // pause instruction with support for nsec timings
+#endif
+#ifndef AV2_SPARC_VAMASK
+#define AV2_SPARC_VAMASK     0x00000100 // Virtual Address masking
+#endif
 
-  // Determine the machine type.
-  if (Sysinfo(SI_MACHINE).match("sun4v")) {
-    features |= sun4v_m;
+  if (avn > 1) {
+    uint32_t av2 = avs[AV_HW2_IDX];
+
+    if (av2 & AV2_SPARC_FJATHPLUS)  features |= ISA_fjathplus_msk;
+    if (av2 & AV2_SPARC_VIS3B)      features |= ISA_vis3b_msk;
+    if (av2 & AV2_SPARC_ADI)        features |= ISA_adi_msk;
+    if (av2 & AV2_SPARC_SPARC5)     features |= ISA_sparc5_msk;
+    if (av2 & AV2_SPARC_MWAIT)      features |= ISA_mwait_msk;
+    if (av2 & AV2_SPARC_XMPMUL)     features |= ISA_xmpmul_msk;
+    if (av2 & AV2_SPARC_XMONT)      features |= ISA_xmont_msk;
+    if (av2 & AV2_SPARC_PAUSE_NSEC) features |= ISA_pause_nsec_msk;
+    if (av2 & AV2_SPARC_VAMASK)     features |= ISA_vamask_msk;
   }
 
-  // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes
-  // is available to us as well
-  Sysinfo cpu_info(SI_CPUBRAND);
-  bool use_solaris_12_api = cpu_info.valid();
-  const char* impl = "unknown";
-  int impl_m = 0;
-  if (use_solaris_12_api) {
-    impl = cpu_info.value();
-    log_info(os, cpu)("Parsing CPU implementation from %s", impl);
-    impl_m = parse_features(impl);
+  _features = features;     // ISA feature set completed, update state.
+
+  Sysinfo machine(SI_MACHINE);
+
+  bool is_sun4v = machine.match("sun4v");   // All Oracle SPARC + Fujitsu Athena+
+  bool is_sun4u = machine.match("sun4u");   // All other Fujitsu
+
+  // Handle Athena+ conservatively (simply because we are lacking info.).
+
+  bool do_sun4v = is_sun4v && !has_athena_plus();
+  bool do_sun4u = is_sun4u ||  has_athena_plus();
+
+  uint64_t synthetic = 0;
+
+  if (do_sun4v) {
+    // Indirect and direct branches are equally fast.
+    synthetic = CPU_fast_ind_br_msk;
+    // Fast IDIV, BIS and LD available on Niagara Plus.
+    if (has_vis2()) {
+      synthetic |= (CPU_fast_idiv_msk | CPU_fast_ld_msk);
+      // ...on Core S4 however, we prefer not to use BIS.
+      if (!has_sparc5()) {
+        synthetic |= CPU_fast_bis_msk;
+      }
+    }
+    // Niagara Core S3 supports fast RDPC and block zeroing.
+    if (has_ima()) {
+      synthetic |= (CPU_fast_rdpc_msk | CPU_blk_zeroing_msk);
+    }
+    // Niagara Core S3 and S4 have slow CMOVE.
+    if (!has_ima()) {
+      synthetic |= CPU_fast_cmove_msk;
+    }
+  } else if (do_sun4u) {
+    // SPARC64 only have fast IDIV and RDPC.
+    synthetic |= (CPU_fast_idiv_msk | CPU_fast_rdpc_msk);
   } else {
-    // Otherwise use kstat to determine the machine type.
-    kstat_ctl_t* kc = kstat_open();
-    if (kc != NULL) {
-      kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
-      if (ksp != NULL) {
-        if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
-          kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
-          for (int i = 0; i < ksp->ks_ndata; i++) {
-            if (strcmp((const char*)&(knm[i].name), "implementation") == 0) {
-              impl = KSTAT_NAMED_STR_PTR(&knm[i]);
-              log_info(os, cpu)("Parsing CPU implementation from %s", impl);
-              impl_m = parse_features(impl);
-              break;
-            }
-          }
-        }
-      }
-      kstat_close(kc);
-    }
+    log_info(os, cpu)("Unable to derive CPU features: %s", machine.value());
   }
-  assert(impl_m != 0, "Unrecognized CPU implementation: %s", impl);
-  features |= impl_m;
+
+  _features += synthetic;   // Including CPU derived/synthetic features.
+
+  Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ);
+  Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ);
+
+  // Require both Sysconf requests to be valid or use fall-back.
 
-  bool is_sun4v = (features & sun4v_m) != 0;
-  if (use_solaris_12_api && is_sun4v) {
-    // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes
-    Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ);
-    if (l1_dcache_line_size.valid()) {
-      _L1_data_cache_line_size =  l1_dcache_line_size.value();
-    }
-
-    Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ);
-    if (l2_dcache_line_size.valid()) {
-      _L2_data_cache_line_size = l2_dcache_line_size.value();
-    }
+  if (l1_dcache_line_size.valid() &&
+      l2_dcache_line_size.valid()) {
+    _L1_data_cache_line_size = l1_dcache_line_size.value();
+    _L2_data_cache_line_size = l2_dcache_line_size.value();
   } else {
-    // Otherwise figure out the cache line sizes using PICL
-    bool is_fujitsu = (features & sparc64_family_m) != 0;
-    PICL picl(is_fujitsu, is_sun4v);
+    // Otherwise figure out the cache line sizes using PICL.
+    PICL picl(is_sun4u, is_sun4v);
     _L1_data_cache_line_size = picl.L1_data_cache_line_size();
     _L2_data_cache_line_size = picl.L2_data_cache_line_size();
   }
-  return features;
 }
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Tue Jun 27 15:22:23 2017 +0200
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Tue Jun 27 15:27:54 2017 +0200
@@ -731,29 +731,43 @@
   volatile_nonstatic_field(JavaFrameAnchor, _flags, int)
 
 #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
-  declare_constant(VM_Version::vis1_instructions_m)                       \
-  declare_constant(VM_Version::vis2_instructions_m)                       \
-  declare_constant(VM_Version::vis3_instructions_m)                       \
-  declare_constant(VM_Version::cbcond_instructions_m)                     \
-  declare_constant(VM_Version::v8_instructions_m)                         \
-  declare_constant(VM_Version::hardware_mul32_m)                          \
-  declare_constant(VM_Version::hardware_div32_m)                          \
-  declare_constant(VM_Version::hardware_fsmuld_m)                         \
-  declare_constant(VM_Version::hardware_popc_m)                           \
-  declare_constant(VM_Version::v9_instructions_m)                         \
-  declare_constant(VM_Version::sun4v_m)                                   \
-  declare_constant(VM_Version::blk_init_instructions_m)                   \
-  declare_constant(VM_Version::fmaf_instructions_m)                       \
-  declare_constant(VM_Version::sparc64_family_m)                          \
-  declare_constant(VM_Version::M_family_m)                                \
-  declare_constant(VM_Version::T_family_m)                                \
-  declare_constant(VM_Version::T1_model_m)                                \
-  declare_constant(VM_Version::sparc5_instructions_m)                     \
-  declare_constant(VM_Version::aes_instructions_m)                        \
-  declare_constant(VM_Version::sha1_instruction_m)                        \
-  declare_constant(VM_Version::sha256_instruction_m)                      \
-  declare_constant(VM_Version::sha512_instruction_m)
-
+  declare_constant(VM_Version::ISA_V9)                  \
+  declare_constant(VM_Version::ISA_POPC)                \
+  declare_constant(VM_Version::ISA_VIS1)                \
+  declare_constant(VM_Version::ISA_VIS2)                \
+  declare_constant(VM_Version::ISA_BLK_INIT)            \
+  declare_constant(VM_Version::ISA_FMAF)                \
+  declare_constant(VM_Version::ISA_VIS3)                \
+  declare_constant(VM_Version::ISA_HPC)                 \
+  declare_constant(VM_Version::ISA_IMA)                 \
+  declare_constant(VM_Version::ISA_AES)                 \
+  declare_constant(VM_Version::ISA_DES)                 \
+  declare_constant(VM_Version::ISA_KASUMI)              \
+  declare_constant(VM_Version::ISA_CAMELLIA)            \
+  declare_constant(VM_Version::ISA_MD5)                 \
+  declare_constant(VM_Version::ISA_SHA1)                \
+  declare_constant(VM_Version::ISA_SHA256)              \
+  declare_constant(VM_Version::ISA_SHA512)              \
+  declare_constant(VM_Version::ISA_MPMUL)               \
+  declare_constant(VM_Version::ISA_MONT)                \
+  declare_constant(VM_Version::ISA_PAUSE)               \
+  declare_constant(VM_Version::ISA_CBCOND)              \
+  declare_constant(VM_Version::ISA_CRC32C)              \
+  declare_constant(VM_Version::ISA_VIS3B)               \
+  declare_constant(VM_Version::ISA_ADI)                 \
+  declare_constant(VM_Version::ISA_SPARC5)              \
+  declare_constant(VM_Version::ISA_MWAIT)               \
+  declare_constant(VM_Version::ISA_XMPMUL)              \
+  declare_constant(VM_Version::ISA_XMONT)               \
+  declare_constant(VM_Version::ISA_PAUSE_NSEC)          \
+  declare_constant(VM_Version::ISA_VAMASK)              \
+  declare_constant(VM_Version::CPU_FAST_IDIV)           \
+  declare_constant(VM_Version::CPU_FAST_RDPC)           \
+  declare_constant(VM_Version::CPU_FAST_BIS)            \
+  declare_constant(VM_Version::CPU_FAST_LD)             \
+  declare_constant(VM_Version::CPU_FAST_CMOVE)          \
+  declare_constant(VM_Version::CPU_FAST_IND_BR)         \
+  declare_constant(VM_Version::CPU_BLK_ZEROING)
 #endif