]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add ISA 3.1 VSX 32-byte Storage Access Operations
authorWill Schmidt <will_schmidt@vnet.ibm.com>
Mon, 22 Jun 2020 14:57:21 +0000 (09:57 -0500)
committerCarl Love <cel@us.ibm.com>
Wed, 7 Oct 2020 15:52:21 +0000 (10:52 -0500)
Add support for the new ISA 3.1 load and store
instructions:

lxvpx Load VSX Vector Paired Indexed
plxvp Prefixed Load VSX Vector Paired
pstxvp Prefixed Store VSX Vector Paired
stxvpx Store VSX Vector Paired Indexed

Update the parsing of the lxvp and stxvp instructions that
were previously added.

lxvp Load VSX Vector Paired
stxvp Store VSX Vector Paired

A couple of format changes for the arguments to the
calculate_prefix_EA function.

Add comments to the else if and case statement to
clarify which instructions meet this condition.

VEX/priv/guest_ppc_toIR.c

index aae8664ea5278bfb6c2eccaa861afeb0e84c3534..7f5d5ba1c5807d9911f742c19718f297506169aa 100644 (file)
@@ -8172,21 +8172,20 @@ static Bool dis_int_store_ds_prefix ( UInt prefix,
       b0 = 0;
       b1 = 1;
       assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr,
-                                       ptype, DSFORM_IMMASK,
-                                       &immediate_val, &R ) );
+                                       ptype, DSFORM_IMMASK, &immediate_val,
+                                       &R ) );
    } else if (opc1 == 0x3D) {
       // force opc2 to 0 to map pstd to std inst
       b0 = 0;
       b1 = 0;
       assign( EA, calculate_prefix_EA( prefix, theInstr, rA_addr,
-                                       ptype, DSFORM_IMMASK,
-                                       &immediate_val, &R ) );
+                                       ptype, DSFORM_IMMASK, &immediate_val,
+                                       &R ) );
 
    } else if ( opc1 == 0x3 ) {
-
       assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
 
-   } else if ( opc1 == 0x3E ) {
+   } else if ( opc1 == 0x3E ) {  // std, stdu, stq
       // lowest 2 bits of immediate before forming EA
       immediate_val = simm16 & 0xFFFFFFFC;
       assign( EA, ea_rAor0_simm( rA_addr, immediate_val ) );
@@ -12564,18 +12563,11 @@ static Bool dis_fp_pair_prefix ( UInt prefix, UInt theInstr )
       case 0:
       {
          /* Endian aware load */
-         pDIP( is_prefix, "lxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr );
-         DIPp( is_prefix, ",%u", R );
-
-         if (is_prefix && (R == 1) ) {
-            vex_printf("Illegal instruction R = 1; plxvp %u,%u(%u)\n",
-                       XTp, immediate_val, rA_addr );
-            return False;
-         }
+         DIP( "lxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr );
 
          // address of next 128bits
-         assign( EA_16, binop( Iop_Add64, mkU64( 16), mkexpr( EA ) ) );
-         if (host_endness == VexEndnessLE) {
+         assign( EA_16, binop( Iop_Add64, mkU64( 16 ), mkexpr( EA ) ) );
+         if (host_endness == VexEndnessBE) {
             putVSReg( XTp, load( Ity_V128, mkexpr( EA ) ) );
             putVSReg( XTp+1, load( Ity_V128, mkexpr( EA_16 ) ) );
          } else {
@@ -12590,14 +12582,7 @@ static Bool dis_fp_pair_prefix ( UInt prefix, UInt theInstr )
          IRTemp EA_8  = newTemp(ty);
          IRTemp EA_24 = newTemp(ty);
          /* Endian aware store */
-         pDIP( is_prefix, "stxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr );
-         DIPp( is_prefix, ",%u", R );
-
-         if ( is_prefix && ( R == 1 ) ) {
-            vex_printf("Illegal instruction R = 1; pstxvp %u,%u(%u)\n",
-                       XTp, immediate_val, rA_addr );
-            return False;
-         }
+         DIP("stxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr );
 
          // address of next 128bits
          assign( EA_8, binop( Iop_Add64, mkU64( 8 ), mkexpr( EA ) ) );
@@ -12817,6 +12802,74 @@ static Bool dis_fp_pair_prefix ( UInt prefix, UInt theInstr )
       break;
    }
 
+   case 0x3A:  // plxvp
+   {
+      UChar XTp = ifieldRegXTp(theInstr);
+
+      /* Endian aware prefixed load */
+      pDIP( is_prefix, "lxvp %u,%u(%u)", XTp, immediate_val, rA_addr );
+      DIPp( is_prefix, ",%u", R );
+
+      if (R == 1 ) {
+         vex_printf("Illegal instruction R = 1; plxvp %u,%u(%u)\n",
+                    XTp, immediate_val, rA_addr );
+         return False;
+      }
+
+      assign( EA, calculate_prefix_EA( prefix, theInstr,
+                                       rA_addr, ptype, DFORM_IMMASK,
+                                       &immediate_val, &R ) );
+
+      // address of next 128bits
+      assign( EA_16, binop( Iop_Add64, mkU64( 16 ), mkexpr( EA ) ) );
+      if (host_endness == VexEndnessBE) {
+         putVSReg( XTp, load( Ity_V128, mkexpr( EA ) ) );
+         putVSReg( XTp+1, load( Ity_V128, mkexpr( EA_16 ) ) );
+      } else {
+         putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) );
+         putVSReg( XTp, load( Ity_V128, mkexpr( EA_16 ) ) );
+      }
+      return True;
+   }
+
+   case 0x3E:  // pstxvp
+   {
+      IRTemp EA_8  = newTemp(ty);
+      IRTemp EA_24 = newTemp(ty);
+      UChar XTp = ifieldRegXTp(theInstr);
+
+      /* Endian aware prefixed load */
+      pDIP( is_prefix, "stxvp %u,%u(%u)\n", XTp, immediate_val, rA_addr );
+      DIPp( is_prefix, ",%u", R );
+
+      if ( R == 1 ) {
+         vex_printf("Illegal instruction R = 1; pstxvp %u,%u(%u)\n",
+                    XTp, immediate_val, rA_addr );
+         return False;
+      }
+
+      assign( EA, calculate_prefix_EA( prefix, theInstr,
+                                       rA_addr, ptype, DFORM_IMMASK,
+                                       &immediate_val, &R ) );
+
+      assign( EA_8, binop( Iop_Add64, mkU64( 8 ), mkexpr( EA ) ) );
+      assign( EA_16, binop( Iop_Add64, mkU64( 16 ), mkexpr( EA ) ) );
+      assign( EA_24, binop( Iop_Add64, mkU64( 24 ), mkexpr( EA ) ) );
+
+      if (host_endness == VexEndnessBE) {
+         store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) );
+     } else {
+         store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) );
+      }
+      return True;
+   }
+
    default:
       vex_printf("dis_fp_pair_prefix(ppc)(instr)\n");
       return False;
@@ -22419,6 +22472,67 @@ dis_vx_move ( UInt prefix, UInt theInstr )
  * VSX Store Instructions
  * NOTE: VSX supports word-aligned storage access.
  */
+static Bool
+dis_vsx_vector_paired_load_store ( UInt prefix, UInt theInstr )
+{
+   /* X-Form/DS-Form */
+   UInt   opc2    = ifieldOPClo9(theInstr);
+   UChar  rA_addr = ifieldRegA(theInstr);
+   UChar  rB_addr = ifieldRegB(theInstr);
+   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
+   IRTemp EA      = newTemp(ty);
+   IRTemp EA_16        = newTemp(ty);
+   UChar XTp      = ifieldRegXTp(theInstr);
+
+   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
+
+   // address of next 128bits
+   assign( EA_16, binop( Iop_Add64, mkU64( 16), mkexpr( EA ) ) );
+
+   switch (opc2) {
+   case 0x14D:  // lxvpx
+      DIP( "lxvpx %u,%d(%u)\n", XTp, rA_addr, rB_addr );
+      if ( host_endness == VexEndnessBE ) {
+         putVSReg( XTp,   load( Ity_V128, mkexpr( EA ) ) );
+         putVSReg( XTp+1, load( Ity_V128, mkexpr( EA_16 ) ) );
+      } else {
+         putVSReg( XTp+1, load( Ity_V128, mkexpr( EA ) ) );
+         putVSReg( XTp,   load( Ity_V128, mkexpr( EA_16 ) ) );
+      }
+      break;
+
+   case 0x1CD: { // stxvpx
+      IRTemp EA_8  = newTemp(ty);
+      IRTemp EA_24 = newTemp(ty);
+
+      DIP( "stxvpx %u,%d(%u)\n", XTp, rA_addr, rB_addr );
+
+      assign( EA_8, binop( Iop_Add64, mkU64( 8 ), mkexpr( EA ) ) );
+      assign( EA_24, binop( Iop_Add64, mkU64( 24 ), mkexpr( EA ) ) );
+
+      if ( host_endness == VexEndnessBE ) {
+         store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) );
+
+      } else {
+         store( mkexpr( EA ), unop( Iop_V128to64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_8 ), unop( Iop_V128HIto64, getVSReg( XTp+1 ) ) );
+         store( mkexpr( EA_16 ), unop( Iop_V128to64, getVSReg( XTp ) ) );
+         store( mkexpr( EA_24 ), unop( Iop_V128HIto64, getVSReg( XTp ) ) );
+      }
+      break;
+   }
+
+   default:
+      vex_printf("dis_vsx_vector_paired_load_store\n");
+      return False;
+   }
+
+   return True;
+}
+
 static Bool
 dis_vx_store ( UInt prefix, UInt theInstr )
 {
@@ -29997,6 +30111,11 @@ DisResult disInstr_PPC_WRK (
       if (dis_trapi( prefix, theInstr, &dres)) goto decode_success;
       goto decode_failure;
 
+   case 0x06:   // lxvp, stxvp
+      if (dis_fp_pair_prefix( prefix, theInstr ))
+         goto decode_success;
+      goto decode_failure;
+
    /* Floating Point Load Instructions */
    case 0x30:                      // lfs
       if (!allow_F) goto decode_noF;
@@ -30137,13 +30256,19 @@ DisResult disInstr_PPC_WRK (
       goto decode_failure;
 
    /* 64bit Integer Loads */
-   case 0x3A:  // word inst: ld, pld, ldu, lwa, plwa
+   case 0x3A:  // word inst: ld, ldu, lwa
       {
          UChar   b1_0  = IFIELD(theInstr, 0, 2);
 
          if (!mode64) goto decode_failure;
-         ISA_3_1_PREFIX_CHECK
-         if ((b1_0 >= 0) && (b1_0 <= 2)) {
+         if (prefix_instruction( prefix )) {  // plxvp
+            if ( !(allow_isa_3_1) ) goto decode_noIsa3_1;
+            if (dis_fp_pair_prefix( prefix, theInstr ))
+               goto decode_success;
+
+         } else if ((b1_0 >= 0) && (b1_0 <= 2)) {  // ld, ldu, lwa,
+            /* Note, here we only deal with the non prefix versions
+               of the instructions.  Hence do not check for ISA 3.1.  */
             if (dis_int_load_ds_form_prefix( prefix, theInstr ))
                goto decode_success;
          }
@@ -30485,9 +30610,23 @@ DisResult disInstr_PPC_WRK (
    }
 
    /* 64bit Integer Stores */
-   case 0x3E:  // std, stdu, stq
-      if (dis_int_store_ds_prefix( prefix, theInstr, abiinfo ))
-         goto decode_success;
+   case 0x3E:  // std, stdu, stq, pstxvp
+      {
+         UChar b1_0 = IFIELD(theInstr, 2, 0);
+
+         if (prefix_instruction( prefix)) {   // pstxvp
+            if (dis_fp_pair_prefix( prefix, theInstr ))
+               goto decode_success;
+
+         } else if (b1_0 != 3) {   // std, stdu, stq
+            if (dis_int_store_ds_prefix( prefix, theInstr, abiinfo ))
+               goto decode_success;
+
+         } else {
+            vex_printf("No mapping for instruction, opc1 = 0x3E, theInstr = 0x%x\n",
+               theInstr);
+         }
+      }
       goto decode_failure;
 
    case 0x3F:
@@ -30833,6 +30972,12 @@ DisResult disInstr_PPC_WRK (
             goto decode_success;
          goto decode_failure;
 
+      case 0x14D:                         // lxvpx
+      case 0x1CD:                         // stxvpx
+         if (dis_vsx_vector_paired_load_store( prefix, theInstr ))
+            goto decode_success;
+         goto decode_failure;
+
       default:
          break;  // Fall through...
       }