changeset 7676:4374388bcbbb

8068724: ppc64: update assembler: SPR access, CR logic, HTM Summary: Fix bug in encoding of special purpose registers. Provide more convenient version of condition register logic instructions. Enhance support for hardware transactional memory. Reviewed-by: kvn, goetz
author mdoerr
date Mon, 12 Jan 2015 11:14:49 +0100
parents cfd30024b3c6
children 84a175c4858d 6de45a355478
files src/cpu/ppc/vm/assembler_ppc.hpp src/cpu/ppc/vm/assembler_ppc.inline.hpp src/cpu/ppc/vm/interp_masm_ppc_64.cpp src/cpu/ppc/vm/stubGenerator_ppc.cpp src/cpu/ppc/vm/templateTable_ppc_64.cpp
diffstat 5 files changed, 121 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/ppc/vm/assembler_ppc.hpp	Fri Jan 09 17:43:02 2015 -0500
+++ b/src/cpu/ppc/vm/assembler_ppc.hpp	Mon Jan 12 11:14:49 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -284,19 +284,20 @@
     MTCTR_OPCODE  = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT),
     MFCTR_OPCODE  = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT),
 
-    MTTFHAR_OPCODE   = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT),
-    MFTFHAR_OPCODE   = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT),
-    MTTFIAR_OPCODE   = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT),
-    MFTFIAR_OPCODE   = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT),
-    MTTEXASR_OPCODE  = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT),
-    MFTEXASR_OPCODE  = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT),
-    MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT),
-    MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT),
+    // Attention: Higher and lower half are inserted in reversed order.
+    MTTFHAR_OPCODE   = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+    MFTFHAR_OPCODE   = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+    MTTFIAR_OPCODE   = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+    MFTFIAR_OPCODE   = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+    MTTEXASR_OPCODE  = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+    MFTEXASR_OPCODE  = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+    MTTEXASRU_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
+    MFTEXASRU_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
 
-    MTVRSAVE_OPCODE  = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT),
-    MFVRSAVE_OPCODE  = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT),
+    MTVRSAVE_OPCODE  = (MTSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+    MFVRSAVE_OPCODE  = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
 
-    MFTB_OPCODE   = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT),
+    MFTB_OPCODE   = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 12 << SPR_0_4_SHIFT),
 
     MTCRF_OPCODE  = (31u << OPCODE_SHIFT | 144u << 1),
     MFCR_OPCODE   = (31u << OPCODE_SHIFT | 19u << 1),
@@ -1494,6 +1495,26 @@
   inline void mftexasr(Register d);
   inline void mftexasru(Register d);
 
+  // TEXASR bit description
+  enum transaction_failure_reason {
+    // Upper half (TEXASRU):
+    tm_failure_persistent =  7, // The failure is likely to recur on each execution.
+    tm_disallowed         =  8, // The instruction is not permitted.
+    tm_nesting_of         =  9, // The maximum transaction level was exceeded.
+    tm_footprint_of       = 10, // The tracking limit for transactional storage accesses was exceeded.
+    tm_self_induced_cf    = 11, // A self-induced conflict occurred in Suspended state.
+    tm_non_trans_cf       = 12, // A conflict occurred with a non-transactional access by another processor.
+    tm_trans_cf           = 13, // A conflict occurred with another transaction.
+    tm_translation_cf     = 14, // A conflict occurred with a TLB invalidation.
+    tm_inst_fetch_cf      = 16, // An instruction fetch was performed from a block that was previously written transactionally.
+    tm_tabort             = 31, // Termination was caused by the execution of an abort instruction.
+    // Lower half:
+    tm_suspended          = 32, // Failure was recorded in Suspended state.
+    tm_failure_summary    = 36, // Failure has been detected and recorded.
+    tm_tfiar_exact        = 37, // Value in the TFIAR is exact.
+    tm_rot                = 38, // Rollback-only transaction.
+  };
+
   // PPC 1, section 2.4.1 Branch Instructions
   inline void b(  address a, relocInfo::relocType rt = relocInfo::none);
   inline void b(  Label& L);
@@ -1581,6 +1602,7 @@
   inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none);
 
   // condition register logic instructions
+  // NOTE: There's a preferred form: d and s2 should point into the same condition register.
   inline void crand( int d, int s1, int s2);
   inline void crnand(int d, int s1, int s2);
   inline void cror(  int d, int s1, int s2);
@@ -1590,6 +1612,19 @@
   inline void crandc(int d, int s1, int s2);
   inline void crorc( int d, int s1, int s2);
 
+  // More convenient version.
+  int condition_register_bit(ConditionRegister cr, Condition c) {
+    return 4 * (int)(intptr_t)cr + c;
+  }
+  void crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void cror(  ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+  void crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+
   // icache and dcache related instructions
   inline void icbi(  Register s1, Register s2);
   //inline void dcba(Register s1, Register s2); // Instruction for embedded processor only.
@@ -1673,6 +1708,10 @@
   inline void smt_prio_low();
   inline void smt_prio_medium_low();
   inline void smt_prio_medium();
+  // >= Power7
+  inline void smt_yield();
+  inline void smt_mdoio();
+  inline void smt_mdoom();
 
   // trap instructions
   inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur)
@@ -1958,6 +1997,7 @@
   inline void tbeginrot_(); // R=1 Rollback-Only Transaction
   inline void tend_();    // A=0
   inline void tendall_(); // A=1
+  inline void tabort_();
   inline void tabort_(Register a);
   inline void tabortwc_(int t, Register a, Register b);
   inline void tabortwci_(int t, Register a, int si);
@@ -1967,6 +2007,10 @@
   inline void tresume_();  // tsr with L=1
   inline void tcheck(int f);
 
+  static bool is_tbegin(int x) {
+    return TBEGIN_OPCODE == (x & (0x3f << OPCODE_SHIFT | 0x3ff << 1));
+  }
+
   // The following encoders use r0 as second operand. These instructions
   // read r0 as '0'.
   inline void lwzx( Register d, Register s2);
--- a/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Fri Jan 09 17:43:02 2015 -0500
+++ b/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Mon Jan 12 11:14:49 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -453,6 +453,48 @@
 inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
 inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE  | bt(d) | ba(s1) | bb(s2)); }
 
+// More convenient version.
+inline void Assembler::crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crnand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::cror(  ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  cror(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crxor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crnor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  creqv(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crandc(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+  int dst_bit = condition_register_bit(crdst, cdst),
+      src_bit = condition_register_bit(crsrc, csrc);
+  crorc(dst_bit, src_bit, dst_bit);
+}
+
 // Conditional move (>= Power7)
 inline void Assembler::isel(Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b) {
   if (b == noreg) {
@@ -516,6 +558,10 @@
 inline void Assembler::smt_prio_medium()      { Assembler::or_unchecked(R2,  R2,  R2); }
 inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5,  R5,  R5); }
 inline void Assembler::smt_prio_high()        { Assembler::or_unchecked(R3,  R3,  R3); }
+// >= Power7
+inline void Assembler::smt_yield()            { Assembler::or_unchecked(R27, R27, R27); }
+inline void Assembler::smt_mdoio()            { Assembler::or_unchecked(R29, R29, R29); }
+inline void Assembler::smt_mdoom()            { Assembler::or_unchecked(R30, R30, R30); }
 
 inline void Assembler::twi_0(Register a)      { twi_unchecked(0, a, 0);}
 
@@ -778,7 +824,8 @@
 inline void Assembler::tbeginrot_()                             { emit_int32( TBEGIN_OPCODE | /*R=1*/ 1u << (31-10) | rc(1)); }
 inline void Assembler::tend_()                                  { emit_int32( TEND_OPCODE | rc(1)); }
 inline void Assembler::tendall_()                               { emit_int32( TEND_OPCODE | /*A=1*/ 1u << (31-6) | rc(1)); }
-inline void Assembler::tabort_(Register a)                      { emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
+inline void Assembler::tabort_()                                { emit_int32( TABORT_OPCODE | rc(1)); }
+inline void Assembler::tabort_(Register a)                      { assert(a != R0, "r0 not allowed"); emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
 inline void Assembler::tabortwc_(int t, Register a, Register b) { emit_int32( TABORTWC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
 inline void Assembler::tabortwci_(int t, Register a, int si)    { emit_int32( TABORTWCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); }
 inline void Assembler::tabortdc_(int t, Register a, Register b) { emit_int32( TABORTDC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
--- a/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Fri Jan 09 17:43:02 2015 -0500
+++ b/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Mon Jan 12 11:14:49 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1712,7 +1712,7 @@
   andi_(R0, klass, TypeEntries::type_unknown);
   // Already unknown. Nothing to do anymore.
   //bne(CCR0, do_nothing);
-  crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne
+  crorc(CCR0, Assembler::equal, CCR1, Assembler::equal); // cr0 eq = cr1 eq or cr0 ne
   beq(CCR0, do_nothing);
 
   clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask));
@@ -1826,9 +1826,9 @@
       lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method);
       cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic);
       cmpwi(CCR1, tmp1, Bytecodes::_invokehandle);
-      cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+      cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
       cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm);
-      cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+      cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
       bne(CCR0, profile_continue);
     }
 
--- a/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Fri Jan 09 17:43:02 2015 -0500
+++ b/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Mon Jan 12 11:14:49 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1079,7 +1079,7 @@
     __ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes
     __ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison!
     __ cmpld(CCR1, tmp1, tmp2);
-    __ crand(/*CCR0 lt*/0, /*CCR1 lt*/4+0, /*CCR0 lt*/0);
+    __ crand(CCR0, Assembler::less, CCR1, Assembler::less);
     __ blt(CCR0, l_overlap); // Src before dst and distance smaller than size.
 
     // need to copy forwards
--- a/src/cpu/ppc/vm/templateTable_ppc_64.cpp	Fri Jan 09 17:43:02 2015 -0500
+++ b/src/cpu/ppc/vm/templateTable_ppc_64.cpp	Mon Jan 12 11:14:49 2015 +0100
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, 2015 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -335,11 +335,11 @@
 
   __ cmpwi(CCR0, Rscratch2, JVM_CONSTANT_UnresolvedClass); // Unresolved class?
   __ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_UnresolvedClassInError); // Unresolved class in error state?
-  __ cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+  __ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
 
   // Resolved class - need to call vm to get java mirror of the class.
   __ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_Class);
-  __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // Neither resolved class nor unresolved case from above?
+  __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal); // Neither resolved class nor unresolved case from above?
   __ beq(CCR0, notClass);
 
   __ li(R4, wide ? 1 : 0);
@@ -2611,7 +2611,7 @@
           __ cmpwi(CCR0, Rflags, ltos);
           __ cmpwi(CCR1, Rflags, dtos);
           __ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(1));
-          __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+          __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal);
           __ beq(CCR0, is_one_slot);
           __ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(2));
           __ bind(is_one_slot);
@@ -3563,7 +3563,7 @@
     // Make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class.
     __ andi_(R0, Rinstance_size, Klass::_lh_instance_slow_path_bit); // slow path bit equals 0?
 
-    __ crnand(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // slow path bit set or not fully initialized?
+    __ crnand(CCR0, Assembler::equal, CCR1, Assembler::equal); // slow path bit set or not fully initialized?
     __ beq(CCR0, Lslow_case);
 
     // --------------------------------------------------------------------------