Mark Wielaard 5f750d
commit 85d259b468099f38b5241241b92fee07530b53d9
Mark Wielaard 5f750d
Author: carll <carll@8f6e269a-dfd6-0310-a8e1-e2731360e62c>
Mark Wielaard 5f750d
Date:   Wed Sep 16 22:26:59 2015 +0000
Mark Wielaard 5f750d
Mark Wielaard 5f750d
    Add support for the Power PC Program Priority Register
Mark Wielaard 5f750d
    
Mark Wielaard 5f750d
    Added the Program Priority Register (PPR), support to read and write it
Mark Wielaard 5f750d
    via the mfspr and mtspr instructions as well as the special OR instruction
Mark Wielaard 5f750d
    No Op instructions.  The setting of the PPR is dependent on the value in
Mark Wielaard 5f750d
    the Problem State Priority Boost register.  Basic support for this register
Mark Wielaard 5f750d
    was added.  Not all of the PSPB register functionality was added.
Mark Wielaard 5f750d
    
Mark Wielaard 5f750d
    This patch fixes bugzilla 352769.
Mark Wielaard 5f750d
    
Mark Wielaard 5f750d
    
Mark Wielaard 5f750d
    git-svn-id: svn://svn.valgrind.org/vex/trunk@3189 8f6e269a-dfd6-0310-a8e1-e2731360e62c
Mark Wielaard 5f750d
Mark Wielaard 5f750d
diff --git a/VEX/priv/guest_ppc_helpers.c b/VEX/priv/guest_ppc_helpers.c
Mark Wielaard 5f750d
index 00137e4..08a0753 100644
Mark Wielaard 5f750d
--- a/VEX/priv/guest_ppc_helpers.c
Mark Wielaard 5f750d
+++ b/VEX/priv/guest_ppc_helpers.c
Mark Wielaard 5f750d
@@ -521,6 +521,8 @@ void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state )
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
    vex_state->guest_IP_AT_SYSCALL = 0;
Mark Wielaard 5f750d
    vex_state->guest_SPRG3_RO = 0;
Mark Wielaard 5f750d
+   vex_state->guest_PPR = 0x4ULL << 50;  // medium priority
Mark Wielaard 5f750d
+   vex_state->guest_PSPB = 0x100;  // an arbitrary non-zero value to start with
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
    vex_state->padding1 = 0;
Mark Wielaard 5f750d
    vex_state->padding2 = 0;
Mark Wielaard 5f750d
@@ -691,6 +693,8 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state )
Mark Wielaard 5f750d
    vex_state->guest_TFHAR  = 0;
Mark Wielaard 5f750d
    vex_state->guest_TFIAR  = 0;
Mark Wielaard 5f750d
    vex_state->guest_TEXASR = 0;
Mark Wielaard 5f750d
+   vex_state->guest_PPR = 0x4ULL << 50;  // medium priority
Mark Wielaard 5f750d
+   vex_state->guest_PSPB = 0x00;  // an arbitrary non-zero value to start with
Mark Wielaard 5f750d
 }
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 5f750d
index bc0bdcb..a0ee34a 100644
Mark Wielaard 5f750d
--- a/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 5f750d
+++ b/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 5f750d
@@ -288,6 +288,8 @@ static void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
Mark Wielaard 5f750d
 #define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
Mark Wielaard 5f750d
 #define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
Mark Wielaard 5f750d
 #define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
Mark Wielaard 5f750d
+#define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
Mark Wielaard 5f750d
+#define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
 /*------------------------------------------------------------*/
Mark Wielaard 5f750d
@@ -438,6 +440,14 @@ typedef enum {
Mark Wielaard 5f750d
     PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
Mark Wielaard 5f750d
     PPC_GST_TEXASR, // Transactional EXception And Summary Register
Mark Wielaard 5f750d
     PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
Mark Wielaard 5f750d
+    PPC_GST_PPR,     // Program Priority register
Mark Wielaard 5f750d
+    PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
Mark Wielaard 5f750d
+    PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
Mark Wielaard 5f750d
+                      * register is initialized to a non-zero value.  Currently
Mark Wielaard 5f750d
+                      * Valgrind is not supporting the register value to
Mark Wielaard 5f750d
+                      * automatically decrement. Could be added later if
Mark Wielaard 5f750d
+                      * needed.
Mark Wielaard 5f750d
+                      */
Mark Wielaard 5f750d
     PPC_GST_MAX
Mark Wielaard 5f750d
 } PPC_GST;
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
@@ -2747,6 +2757,15 @@ static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
Mark Wielaard 5f750d
    case PPC_GST_TFIAR:
Mark Wielaard 5f750d
       return IRExpr_Get( OFFB_TFIAR, ty );
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
+   case PPC_GST_PPR:
Mark Wielaard 5f750d
+      return IRExpr_Get( OFFB_PPR, ty );
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+   case PPC_GST_PPR32:
Mark Wielaard 5f750d
+      return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+   case PPC_GST_PSPB:
Mark Wielaard 5f750d
+      return IRExpr_Get( OFFB_PSPB, ty );
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
    default:
Mark Wielaard 5f750d
       vex_printf("getGST(ppc): reg = %u", reg);
Mark Wielaard 5f750d
       vpanic("getGST(ppc)");
Mark Wielaard 5f750d
@@ -2926,6 +2945,95 @@ static void putGST ( PPC_GST reg, IRExpr* src )
Mark Wielaard 5f750d
       vassert( ty_src == Ity_I64 );
Mark Wielaard 5f750d
       stmt( IRStmt_Put( OFFB_TFHAR, src ) );
Mark Wielaard 5f750d
       break;
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+   case PPC_GST_PPR32:
Mark Wielaard 5f750d
+   case PPC_GST_PPR:
Mark Wielaard 5f750d
+      {
Mark Wielaard 5f750d
+         /* The Program Priority Register (PPR) stores the priority in
Mark Wielaard 5f750d
+          * bits [52:50].  The user setable priorities are:
Mark Wielaard 5f750d
+          *
Mark Wielaard 5f750d
+          *    001  very low
Mark Wielaard 5f750d
+          *    010  low
Mark Wielaard 5f750d
+          *    011  medium low
Mark Wielaard 5f750d
+          *    100  medium
Mark Wielaard 5f750d
+          *    101  medium high
Mark Wielaard 5f750d
+          *
Mark Wielaard 5f750d
+          * If the argument is not between 0b001 and 0b100 the priority is set
Mark Wielaard 5f750d
+          * to 0b100.  The priority can only be set to 0b101 if the the Problem
Mark Wielaard 5f750d
+          * State Boost Register is non-zero.  The value of the PPR is not
Mark Wielaard 5f750d
+          * changed if the input is not valid.
Mark Wielaard 5f750d
+          */
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+         IRTemp not_valid = newTemp(Ity_I64);
Mark Wielaard 5f750d
+         IRTemp has_perm = newTemp(Ity_I64);
Mark Wielaard 5f750d
+         IRTemp new_src  = newTemp(Ity_I64);
Mark Wielaard 5f750d
+         IRTemp PSPB_val = newTemp(Ity_I64);
Mark Wielaard 5f750d
+         IRTemp value    = newTemp(Ity_I64);
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+         vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
Mark Wielaard 5f750d
+         assign( PSPB_val, binop( Iop_32HLto64,
Mark Wielaard 5f750d
+                                  mkU32( 0 ),
Mark Wielaard 5f750d
+                                  IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
Mark Wielaard 5f750d
+         if( reg == PPC_GST_PPR32 ) {
Mark Wielaard 5f750d
+            vassert( ty_src == Ity_I32 );
Mark Wielaard 5f750d
+            assign( value, binop( Iop_32HLto64,
Mark Wielaard 5f750d
+                                  mkU32(0),
Mark Wielaard 5f750d
+                                  binop( Iop_And32,
Mark Wielaard 5f750d
+                                         binop( Iop_Shr32, src,  mkU8( 18 ) ),
Mark Wielaard 5f750d
+                                         mkU32( 0x7 ) ) ) );
Mark Wielaard 5f750d
+         } else {
Mark Wielaard 5f750d
+            vassert( ty_src == Ity_I64 );
Mark Wielaard 5f750d
+            assign( value, binop( Iop_And64,
Mark Wielaard 5f750d
+                                  binop( Iop_Shr64, src,  mkU8( 50 ) ),
Mark Wielaard 5f750d
+                                  mkU64( 0x7 ) ) );
Mark Wielaard 5f750d
+         }
Mark Wielaard 5f750d
+         assign( has_perm,
Mark Wielaard 5f750d
+                 binop( Iop_And64,
Mark Wielaard 5f750d
+                        unop( Iop_1Sto64,
Mark Wielaard 5f750d
+                              binop( Iop_CmpEQ64,
Mark Wielaard 5f750d
+                                     mkexpr( PSPB_val ),
Mark Wielaard 5f750d
+                                     mkU64( 0 ) ) ),
Mark Wielaard 5f750d
+                        unop( Iop_1Sto64,
Mark Wielaard 5f750d
+                              binop( Iop_CmpEQ64,
Mark Wielaard 5f750d
+                                     mkU64( 0x5 ),
Mark Wielaard 5f750d
+                                     mkexpr( value ) ) ) ) );
Mark Wielaard 5f750d
+         assign( not_valid,
Mark Wielaard 5f750d
+                 binop( Iop_Or64,
Mark Wielaard 5f750d
+                        unop( Iop_1Sto64,
Mark Wielaard 5f750d
+                              binop( Iop_CmpEQ64,
Mark Wielaard 5f750d
+                                     mkexpr( value ),
Mark Wielaard 5f750d
+                                     mkU64( 0 ) ) ),
Mark Wielaard 5f750d
+                        unop( Iop_1Sto64,
Mark Wielaard 5f750d
+                              binop( Iop_CmpLT64U,
Mark Wielaard 5f750d
+                                     mkU64( 0x5 ),
Mark Wielaard 5f750d
+                                     mkexpr( value ) ) ) ) );
Mark Wielaard 5f750d
+         assign( new_src,
Mark Wielaard 5f750d
+                 binop( Iop_Or64,
Mark Wielaard 5f750d
+                        binop( Iop_And64,
Mark Wielaard 5f750d
+                               unop( Iop_Not64,
Mark Wielaard 5f750d
+                                     mkexpr( not_valid ) ),
Mark Wielaard 5f750d
+                               src ),
Mark Wielaard 5f750d
+                        binop( Iop_And64,
Mark Wielaard 5f750d
+                               mkexpr( not_valid ),
Mark Wielaard 5f750d
+                               binop( Iop_Or64,
Mark Wielaard 5f750d
+                                      binop( Iop_And64,
Mark Wielaard 5f750d
+                                             mkexpr( has_perm),
Mark Wielaard 5f750d
+                                             binop( Iop_Shl64,
Mark Wielaard 5f750d
+                                                    mkexpr( value ),
Mark Wielaard 5f750d
+                                                    mkU8( 50 ) ) ),
Mark Wielaard 5f750d
+                                      binop( Iop_And64,
Mark Wielaard 5f750d
+                                             IRExpr_Get( OFFB_PPR, ty ),
Mark Wielaard 5f750d
+                                             unop( Iop_Not64,
Mark Wielaard 5f750d
+                                                   mkexpr( has_perm )
Mark Wielaard 5f750d
+                                                   ) ) ) ) ) );
Mark Wielaard 5f750d
+
Mark Wielaard 5f750d
+                 /* make sure we only set the valid bit field [52:50] */
Mark Wielaard 5f750d
+                 stmt( IRStmt_Put( OFFB_PPR,
Mark Wielaard 5f750d
+                                   binop( Iop_And64,
Mark Wielaard 5f750d
+                                          mkexpr( new_src ),
Mark Wielaard 5f750d
+                                          mkU64( 0x1C000000000000) ) ) );
Mark Wielaard 5f750d
+      break;
Mark Wielaard 5f750d
+      }
Mark Wielaard 5f750d
    default:
Mark Wielaard 5f750d
       vex_printf("putGST(ppc): reg = %u", reg);
Mark Wielaard 5f750d
       vpanic("putGST(ppc)");
Mark Wielaard 5f750d
@@ -7131,6 +7239,18 @@ static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
Mark Wielaard 5f750d
          DIP("mfspr r%u (TEXASRU)\n", rD_addr);
Mark Wielaard 5f750d
          putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
Mark Wielaard 5f750d
          break;
Mark Wielaard 5f750d
+      case 0x9F:  // 159
Mark Wielaard 5f750d
+         DIP("mfspr r%u (PSPB)\n", rD_addr);
Mark Wielaard 5f750d
+         putIReg( rD_addr, getGST( PPC_GST_PSPB) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
+      case 0x380:  // 896
Mark Wielaard 5f750d
+         DIP("mfspr r%u (PPR)\n", rD_addr);
Mark Wielaard 5f750d
+         putIReg( rD_addr, getGST( PPC_GST_PPR) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
+      case 0x382:  // 898
Mark Wielaard 5f750d
+         DIP("mfspr r%u (PPR)32\n", rD_addr);
Mark Wielaard 5f750d
+         putIReg( rD_addr, getGST( PPC_GST_PPR32) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
       case 0x100: 
Mark Wielaard 5f750d
          DIP("mfvrsave r%u\n", rD_addr);
Mark Wielaard 5f750d
          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
Mark Wielaard 5f750d
@@ -7287,6 +7407,18 @@ static Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
Mark Wielaard 5f750d
          DIP("mtspr r%u (TEXASR)\n", rS_addr);
Mark Wielaard 5f750d
          putGST( PPC_GST_TEXASR, mkexpr(rS) );
Mark Wielaard 5f750d
          break;
Mark Wielaard 5f750d
+      case 0x9F:  // 159
Mark Wielaard 5f750d
+         DIP("mtspr r%u (PSPB)\n", rS_addr);
Mark Wielaard 5f750d
+         putGST( PPC_GST_PSPB, mkexpr(rS) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
+      case 0x380:  // 896
Mark Wielaard 5f750d
+         DIP("mtspr r%u (PPR)\n", rS_addr);
Mark Wielaard 5f750d
+         putGST( PPC_GST_PPR, mkexpr(rS) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
+      case 0x382:  // 898
Mark Wielaard 5f750d
+         DIP("mtspr r%u (PPR32)\n", rS_addr);
Mark Wielaard 5f750d
+         putGST( PPC_GST_PPR32, mkexpr(rS) );
Mark Wielaard 5f750d
+         break;
Mark Wielaard 5f750d
       default:
Mark Wielaard 5f750d
          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
Mark Wielaard 5f750d
          return False;
Mark Wielaard 5f750d
diff --git a/pub/libvex_guest_ppc32.h b/pub/libvex_guest_ppc32.h
Mark Wielaard 5f750d
index 2489d55..5bebef8 100644
Mark Wielaard 5f750d
--- a/VEX/pub/libvex_guest_ppc32.h
Mark Wielaard 5f750d
+++ b/VEX/pub/libvex_guest_ppc32.h
Mark Wielaard 5f750d
@@ -241,11 +241,12 @@ typedef
Mark Wielaard 5f750d
       /* 1360 */ ULong guest_TFHAR;     // Transaction Failure Handler Address Register 
Mark Wielaard 5f750d
       /* 1368 */ ULong guest_TEXASR;    // Transaction EXception And Summary Register
Mark Wielaard 5f750d
       /* 1376 */ ULong guest_TFIAR;     // Transaction Failure Instruction Address Register
Mark Wielaard 5f750d
-      /* 1384 */ UInt  guest_TEXASRU;   // Transaction EXception And Summary Register Upper
Mark Wielaard 5f750d
-
Mark Wielaard 5f750d
+      /* 1384 */ ULong guest_PPR;       // Program Priority register
Mark Wielaard 5f750d
+      /* 1392 */ UInt  guest_TEXASRU;   // Transaction EXception And Summary Register Upper
Mark Wielaard 5f750d
+      /* 1396 */ UInt  guest_PSPB;      // Problem State Priority Boost register
Mark Wielaard 5f750d
       /* Padding to make it have an 16-aligned size */
Mark Wielaard 5f750d
-      /* 1388 */ UInt  padding2;
Mark Wielaard 5f750d
-
Mark Wielaard 5f750d
+      /* 1400 */ UInt  padding2;
Mark Wielaard 5f750d
+      /* 1404 */ UInt  padding3;
Mark Wielaard 5f750d
    }
Mark Wielaard 5f750d
    VexGuestPPC32State;
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
diff --git a/VEX/pub/libvex_guest_ppc64.h b/VEX/pub/libvex_guest_ppc64.h
Mark Wielaard 5f750d
index dea2bba..f3310cb 100644
Mark Wielaard 5f750d
--- a/VEX/pub/libvex_guest_ppc64.h
Mark Wielaard 5f750d
+++ b/VEX/pub/libvex_guest_ppc64.h
Mark Wielaard 5f750d
@@ -282,12 +282,14 @@ typedef
Mark Wielaard 5f750d
       /* 1656 */ ULong guest_TFHAR;     // Transaction Failure Handler Address Register 
Mark Wielaard 5f750d
       /* 1664 */ ULong guest_TEXASR;    // Transaction EXception And Summary Register
Mark Wielaard 5f750d
       /* 1672 */ ULong guest_TFIAR;     // Transaction Failure Instruction Address Register
Mark Wielaard 5f750d
-      /* 1680 */ UInt  guest_TEXASRU;   // Transaction EXception And Summary Register Upper
Mark Wielaard 5f750d
+      /* 1680 */ ULong guest_PPR;       // Program Priority register
Mark Wielaard 5f750d
+      /* 1688 */ UInt  guest_TEXASRU;   // Transaction EXception And Summary Register Upper
Mark Wielaard 5f750d
+      /* 1692 */ UInt  guest_PSPB;      // Problem State Priority Boost register
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
       /* Padding to make it have an 16-aligned size */
Mark Wielaard 5f750d
-      /* 1684 */  UInt  padding1;
Mark Wielaard 5f750d
-      /* 1688 */  UInt  padding2;
Mark Wielaard 5f750d
-      /* 1692 */  UInt  padding3;
Mark Wielaard 5f750d
+      /* 1696   UInt  padding1;  currently not needed */
Mark Wielaard 5f750d
+      /* 1700   UInt  padding2;  currently not needed */
Mark Wielaard 5f750d
+      /* 1708   UInt  padding3;  currently not needed */
Mark Wielaard 5f750d
 
Mark Wielaard 5f750d
    }
Mark Wielaard 5f750d
    VexGuestPPC64State;