]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Handle frin, frim, frip, friz, in 64-bit mode only, for now.
authorJulian Seward <jseward@acm.org>
Fri, 8 Aug 2008 08:37:06 +0000 (08:37 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 8 Aug 2008 08:37:06 +0000 (08:37 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1862

VEX/priv/guest-ppc/toIR.c
VEX/priv/host-ppc/hdefs.c
VEX/priv/host-ppc/hdefs.h
VEX/priv/host-ppc/isel.c
VEX/priv/ir/irdefs.c
VEX/pub/libvex_ir.h

index efe771ef6a2d8c7f8def3c253e3d3b18c8820b80..1605a409d6a9328e06583d5bfe7ab45d959d44c3 100644 (file)
@@ -8845,6 +8845,66 @@ static Bool dis_av_fp_convert ( UInt theInstr )
 
 
 
+/*------------------------------------------------------------*/
+/*--- POWER6 Instruction Translation                       ---*/
+/*------------------------------------------------------------*/
+
+static
+Bool dis_P6 ( UInt theInstr,
+              Bool allow_F, Bool allow_V, Bool allow_FX, Bool allow_GX)
+{
+    /* This is a hack.  We should do P6 capability checking properly.
+       But anyway, make a guess at whether we should even try to handle
+       this instruction.  All P6 capable CPUs should be able to handle
+       F, V, FX and GX, so that seems like a good check. */
+   if (! (allow_F && allow_V && allow_FX && allow_GX) )
+      return False;
+   if (!mode64)
+      return False; /* only support P6 in 64-bit mode for now */
+
+   UInt opc  = ifieldOPC(theInstr);     /* primary opcode */
+   UInt rd   = ifieldRegDS(theInstr);   /* dst reg */
+   UInt ra   = ifieldRegA(theInstr);    /* first source reg */
+   UInt rb   = ifieldRegB(theInstr);    /* second source reg */
+   UInt opc2 = ifieldOPClo10(theInstr); /* secondary opc, 10:1 */
+   UInt dot  = ifieldBIT0(theInstr);    /* Rc field, bit 0 */
+
+   if (opc == 63 && ra == 0/*presumably*/ && opc2 == 488) {
+      /* frim (Floating Round to Integer Minus, PPC ISA 2.05 p137) */
+      if (dot) return False;
+      putFReg( rd, unop(Iop_RoundF64toF64_NegINF, getFReg( rb )) );
+      DIP("frim%s fr%u,fr%u\n", dot ? "." : "", rd, rb);
+      return True;
+   }
+
+   if (opc == 63 && ra == 0/*presumably*/ && opc2 == 456) {
+      /* frip (Floating Round to Integer Plus, PPC ISA 2.05 p137) */
+      if (dot) return False;
+      putFReg( rd, unop(Iop_RoundF64toF64_PosINF, getFReg( rb )) );
+      DIP("frip%s fr%u,fr%u\n", dot ? "." : "", rd, rb);
+      return True;
+   }
+
+   if (opc == 63 && ra == 0/*presumably*/ && opc2 == 392) {
+      /* frin (Floating Round to Integer Nearest, PPC ISA 2.05 p137) */
+      if (dot) return False;
+      putFReg( rd, unop(Iop_RoundF64toF64_NEAREST, getFReg( rb )) );
+      DIP("frin%s fr%u,fr%u\n", dot ? "." : "", rd, rb);
+      return True;
+   }
+
+   if (opc == 63 && ra == 0/*presumably*/ && opc2 == 424) {
+      /* frin (Floating Round to Integer Zero, PPC ISA 2.05 p137) */
+      if (dot) return False;
+      putFReg( rd, unop(Iop_RoundF64toF64_ZERO, getFReg( rb )) );
+      DIP("friz%s fr%u,fr%u\n", dot ? "." : "", rd, rb);
+      return True;
+   }
+
+   if (0)
+      vex_printf("dis_P6: %u %u %u %u %u %u\n", opc, rd, ra, rb, opc2, dot);
+   return False;
+}
 
 
 
@@ -9164,6 +9224,15 @@ DisResult disInstr_PPC_WRK (
       case 0x34E: // fcfid
          if (dis_fp_round(theInstr)) goto decode_success;
          goto decode_failure;
+
+      /* Power6 rounding stuff */
+      case 0x1E8: // frim
+      case 0x1C8: // frip
+      case 0x188: // frin
+      case 0x1A8: // friz
+         if (dis_P6(theInstr, allow_F, allow_V, allow_FX, allow_GX))
+            goto decode_success;
+         goto decode_failure;
          
       /* Floating Point Move Instructions */         
       case 0x028: // fneg
index cc5d4788fad8fdb537c5221b4d46d961490961a4..1709a139a8449013512b0e25ced31d06dfdd0091 100644 (file)
@@ -630,6 +630,10 @@ HChar* showPPCFpOp ( PPCFpOp op ) {
       case Pfp_MOV:    return "fmr";
       case Pfp_RES:    return "fres";
       case Pfp_RSQRTE: return "frsqrte";
+      case Pfp_FRIM:   return "frim";
+      case Pfp_FRIN:   return "frin";
+      case Pfp_FRIP:   return "frip";
+      case Pfp_FRIZ:   return "friz";
       default: vpanic("showPPCFpOp");
    }
 }
@@ -3165,6 +3169,18 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
       case Pfp_MOV:   // fmr, PPC32 p410
          p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
          break;
+      case Pfp_FRIM:  // frim, PPC ISA 2.05 p137
+         p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
+         break;
+      case Pfp_FRIP:  // frip, PPC ISA 2.05 p137
+         p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
+         break;
+      case Pfp_FRIN:  // frin, PPC ISA 2.05 p137
+         p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
+         break;
+      case Pfp_FRIZ:  // friz, PPC ISA 2.05 p137
+         p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
+         break;
       default:
          goto bad;
       }
index 51c3bf12117387c258e3c263bf773129052455e7..c36d42dc45640f796580742d2bfea080ad5c201f 100644 (file)
@@ -377,7 +377,8 @@ typedef
       Pfp_ADDS, Pfp_SUBS, Pfp_MULS, Pfp_DIVS, 
 
       /* Unary */
-      Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE
+      Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE,
+      Pfp_FRIN, Pfp_FRIM, Pfp_FRIP, Pfp_FRIZ
    }
    PPCFpOp;
 
index d33b27784b995f9b5099638b6ac0c3fa99369c24..c72c7698920f2c0bdc82b6b8f0eb2110b536d412 100644 (file)
@@ -3242,6 +3242,10 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
          case Iop_NegF64:     fpop = Pfp_NEG; break;
          case Iop_AbsF64:     fpop = Pfp_ABS; break;
          case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break;
+         case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
+         case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
+         case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
+         case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
          default: break;
       }
       if (fpop != Pfp_INVALID) {
index 7539f95bc01a34551e9da5b499e403de1aad83c2..c46e3ed9bb3d51cc6041738748d996cb96bab965 100644 (file)
@@ -277,6 +277,11 @@ void ppIROp ( IROp op )
       case Iop_MSubF64r32: vex_printf("MSubF64r32"); return;
 
       case Iop_Est5FRSqrt:    vex_printf("Est5FRSqrt"); return;
+      case Iop_RoundF64toF64_NEAREST: vex_printf("RoundF64toF64_NEAREST"); return;
+      case Iop_RoundF64toF64_NegINF: vex_printf("RoundF64toF64_NegINF"); return;
+      case Iop_RoundF64toF64_PosINF: vex_printf("RoundF64toF64_PosINF"); return;
+      case Iop_RoundF64toF64_ZERO: vex_printf("RoundF64toF64_ZERO"); return;
+
       case Iop_TruncF64asF32: vex_printf("TruncF64asF32"); return;
       case Iop_CalcFPRF:      vex_printf("CalcFPRF"); return;
 
@@ -1709,6 +1714,8 @@ void typeOfPrimop ( IROp op,
          QUATERNARY(ity_RMode,Ity_F64,Ity_F64,Ity_F64, Ity_F64);
 
       case Iop_Est5FRSqrt:
+      case Iop_RoundF64toF64_NEAREST: case Iop_RoundF64toF64_NegINF:
+      case Iop_RoundF64toF64_PosINF: case Iop_RoundF64toF64_ZERO:
          UNARY(Ity_F64, Ity_F64);
       case Iop_RoundF64toF32:
          BINARY(ity_RMode,Ity_F64, Ity_F64);
index 232f189c9716c3748b7c6f91a7f0ac96f052f81e..4fa195df73313313b86aeedbe91debcc58d4fed1 100644 (file)
@@ -630,6 +630,10 @@ typedef
 
       /* :: F64 -> F64 */
       Iop_Est5FRSqrt,    /* reciprocal square root estimate, 5 good bits */
+      Iop_RoundF64toF64_NEAREST, /* frin */
+      Iop_RoundF64toF64_NegINF,  /* frim */ 
+      Iop_RoundF64toF64_PosINF,  /* frip */
+      Iop_RoundF64toF64_ZERO,    /* friz */
 
       /* :: F64 -> F32 */
       Iop_TruncF64asF32, /* do F64->F32 truncation as per 'fsts' */