Blob Blame History Raw
commit 85d259b468099f38b5241241b92fee07530b53d9
Author: carll <carll@8f6e269a-dfd6-0310-a8e1-e2731360e62c>
Date:   Wed Sep 16 22:26:59 2015 +0000

    Add support for the Power PC Program Priority Register
    
    Added the Program Priority Register (PPR), support to read and write it
    via the mfspr and mtspr instructions as well as the special OR instruction
    No Op instructions.  The setting of the PPR is dependent on the value in
    the Problem State Priority Boost register.  Basic support for this register
    was added.  Not all of the PSPB register functionality was added.
    
    This patch fixes bugzilla 352769.
    
    
    git-svn-id: svn://svn.valgrind.org/vex/trunk@3189 8f6e269a-dfd6-0310-a8e1-e2731360e62c

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