]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
The 32-bit DFP value is stored in a 64-bit register in
authorCarl Love <cel@us.ibm.com>
Mon, 21 Jan 2013 18:12:31 +0000 (18:12 +0000)
committerCarl Love <cel@us.ibm.com>
Mon, 21 Jan 2013 18:12:31 +0000 (18:12 +0000)
 ppc. The D32 to D64 and D64 to D32 definitions for the
 Iop type was specified in VEX/priv/ir_defs.c, function
 typeOfPrimop() as:

   case Iop_D32toD64:
      UNARY(Ity_64, Ity_D64);
   case Iop_D64toD32:
      BINARY(ity_RMode, Ity_D64, Ity_D64);

since the values resided in a 64-bit register. As part of the s390 DFP support
the definitions were changed to:

   case Iop_D32toD64:
      UNARY(Ity_32, Ity_D64);
   case Iop_D64toD32:
      BINARY(ity_RMode, Ity_D64, Ity_D32);

to reflect what they really should be. However, this broke the ppc
implementation. Valgrind would fail and report a mismatch on the types as the
ppc code was using a D64 instead of a D32.

This patch adds support for fetching and storing the Dfp32 operand as a 32-bit
value.  The support includes adding the functions iselDfp32Expr() and
iselDfp32Expr_wrk() and additional code to support the DFP32 bit iops.

This patch is for Bugzilla 312620.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2650

VEX/priv/guest_ppc_toIR.c
VEX/priv/host_ppc_isel.c

index 165aaafcbc4ecd93a2312d2761afdec93f7d3cb3..cab2a43788885a646bf87190d87168d1576858cd 100644 (file)
@@ -1128,6 +1128,12 @@ static IRExpr* getDReg(UInt archreg) {
    e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
    return e;
 }
+static IRExpr* getDReg32(UInt archreg) {
+   IRExpr *e;
+   vassert( archreg < 32 );
+   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
+   return e;
+}
 
 /* Read a floating point register pair and combine their contents into a
  128-bit value */
@@ -1139,6 +1145,12 @@ static IRExpr *getDReg_pair(UInt archreg) {
 }
 
 /* Ditto, but write to a reg instead. */
+static void putDReg32(UInt archreg, IRExpr* e) {
+   vassert( archreg < 32 );
+   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
+   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
+}
+
 static void putDReg(UInt archreg, IRExpr* e) {
    vassert( archreg < 32 );
    vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
@@ -9498,9 +9510,9 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) {
       DIP( "dctdp%s fr%u,fr%u\n",
            flag_rC ? ".":"", frS_addr, frB_addr );
 
-      frB = newTemp( Ity_D64 );
+      frB = newTemp( Ity_D32 );
       frS = newTemp( Ity_D64 );
-      assign( frB, getDReg( frB_addr ) );
+      assign( frB, getDReg32( frB_addr ) );
       assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
       putDReg( frS_addr, mkexpr( frS ) );
       break;
@@ -9508,10 +9520,10 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) {
       DIP( "drsp%s fr%u,fr%u\n",
            flag_rC ? ".":"", frS_addr, frB_addr );
       frB = newTemp( Ity_D64 );
-      frS = newTemp( Ity_D64 );
+      frS = newTemp( Ity_D32 );
       assign( frB, getDReg( frB_addr ) );
       assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
-      putDReg( frS_addr, mkexpr( frS ) );
+      putDReg32( frS_addr, mkexpr( frS ) );
       break;
    case 0x122: // dctfix
       DIP( "dctfix%s fr%u,fr%u\n",
index 6a281bb3dc2e9b1ba7f982ceef1cc80e58ad891f..50dd9b86396ff4c59ab9785ee07922d0f016959c 100644 (file)
@@ -453,6 +453,8 @@ static HReg          iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
 static HReg          iselVecExpr     ( ISelEnv* env, IRExpr* e );
 
 /* 64-bit mode ONLY. */
+static HReg          iselDfp32Expr_wrk ( ISelEnv* env, IRExpr* e );
+static HReg          iselDfp32Expr     ( ISelEnv* env, IRExpr* e );
 static HReg          iselDfp64Expr_wrk ( ISelEnv* env, IRExpr* e );
 static HReg          iselDfp64Expr     ( ISelEnv* env, IRExpr* e );
 
@@ -3822,6 +3824,57 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
    vpanic("iselDblExpr_wrk(ppc)");
 }
 
+static HReg iselDfp32Expr(ISelEnv* env, IRExpr* e)
+{
+   HReg r = iselDfp32Expr_wrk( env, e );
+   vassert(hregClass(r) == HRcFlt64);
+   vassert( hregIsVirtual(r) );
+   return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselDfp32Expr_wrk(ISelEnv* env, IRExpr* e)
+{
+   Bool mode64 = env->mode64;
+   IRType ty = typeOfIRExpr( env->type_env, e );
+
+   vassert( e );
+   vassert( ty == Ity_D32 );
+
+   /* --------- GET --------- */
+   if (e->tag == Iex_Get) {
+      HReg r_dst = newVRegF( env );
+      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
+                                       GuestStatePtr(mode64) );
+      addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
+      return r_dst;
+   }
+
+   /* --------- LOAD --------- */
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
+      PPCAMode* am_addr;
+      HReg r_dst = newVRegF(env);
+      vassert(e->Iex.Load.ty == Ity_D32);
+      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/);
+      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
+      return r_dst;
+   }
+
+   /* --------- OPS --------- */
+   if (e->tag == Iex_Binop) {
+      if (e->Iex.Binop.op == Iop_D64toD32) {
+         HReg fr_dst = newVRegF(env);
+         HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
+         set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
+         addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
+         return fr_dst;
+      }
+   }
+
+   ppIRExpr( e );
+   vpanic( "iselDfp32Expr_wrk(ppc)" );
+}
+
 static HReg iselDfp64Expr(ISelEnv* env, IRExpr* e)
 {
    HReg r = iselDfp64Expr_wrk( env, e );
@@ -3853,6 +3906,15 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e)
       return r_dst;
    }
 
+   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
+      PPCAMode* am_addr;
+      HReg r_dst = newVRegF(env);
+      vassert(e->Iex.Load.ty == Ity_D64);
+      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/);
+      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
+      return r_dst;
+   }
+
    /* --------- OPS --------- */
    if (e->tag == Iex_Qop) {
       HReg r_dst = newVRegF( env );
@@ -3892,7 +3954,7 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e)
          return fr_dst;
       }
       case Iop_D32toD64: {
-         HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+         HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg);
          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
          return fr_dst;
       }
@@ -3962,7 +4024,6 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e)
       HReg fr_dst = newVRegF(env);
 
       switch (e->Iex.Binop.op) {
-      case Iop_D64toD32:     fpop = Pfp_DRSP;   break;
       case Iop_I64StoD64:    fpop = Pfp_DCFFIX; break;
       case Iop_D64toI64S:    fpop = Pfp_DCTFIX; break;
       default: break;
@@ -4732,6 +4793,22 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
          return;
       }
+      if (tyd == Ity_D64) {
+         PPCAMode* am_addr
+            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
+         HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data);
+         addInstr(env,
+                  PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
+         return;
+      }
+      if (tyd == Ity_D32) {
+         PPCAMode* am_addr
+            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
+         HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data);
+         addInstr(env,
+                  PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
+         return;
+      }
       if (tyd == Ity_V128) {
          PPCAMode* am_addr
             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
@@ -4800,6 +4877,15 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
                                         fr_src, am_addr ));
          return;
       }
+      if (ty == Ity_D32) {
+         /* The 32-bit value is stored in a 64-bit register */
+         HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data );
+         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
+                                          GuestStatePtr(mode64) );
+         addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
+                                         fr_src, am_addr ) );
+         return;
+      }
       if (ty == Ity_D64) {
          HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data );
          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
@@ -4897,6 +4983,12 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
          return;
       }
+      if (ty == Ity_D32) {
+         HReg fr_dst = lookupIRTemp(env, tmp);
+         HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data);
+         addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
+         return;
+      }
       if (ty == Ity_V128) {
          HReg v_dst = lookupIRTemp(env, tmp);
          HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data);
@@ -5350,6 +5442,7 @@ HInstrArray* iselSB_PPC ( IRSB* bb,
       case Ity_F32:
       case Ity_F64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
       case Ity_V128:   hregLo    = mkHReg(j++, HRcVec128, True); break;
+      case Ity_D32:
       case Ity_D64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
       case Ity_D128:   hregLo    = mkHReg(j++, HRcFlt64,  True);
       hregMedLo = mkHReg(j++, HRcFlt64,  True); break;