Handle fre and frsqrtes.  Even though the IBM docs manage to
contradict themselves about whether these insns exist or not.



git-svn-id: svn://svn.valgrind.org/vex/trunk@1559 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest-ppc/toIR.c b/priv/guest-ppc/toIR.c
index 47355c6..0014ffb 100644
--- a/priv/guest-ppc/toIR.c
+++ b/priv/guest-ppc/toIR.c
@@ -5710,7 +5710,9 @@
          }
          DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
              frD_addr, frB_addr);
-         assign( frD, roundToSgl( unop(Iop_SqrtF64, mkexpr(frB)) ));
+         // however illogically, on ppc970 this insn behaves identically
+         // to fsqrt (double-precision).  So don't do round-to-single.
+         assign( frD, unop(Iop_SqrtF64, mkexpr(frB)) );
          break;
 
       case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
@@ -5735,6 +5737,18 @@
                                         mkexpr(frA), mkexpr(frC)) ));
          break;
 
+      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
+         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
+         // Undocumented instruction?
+         if (frA_addr != 0 || frC_addr != 0) {
+            vex_printf("dis_fp_arith(ppc)(instr,frsqrte)\n");
+            return False;
+         }
+         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
+             frD_addr, frB_addr);
+         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
+         break;
+
       default:
          vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
          return False;
@@ -5809,6 +5823,19 @@
          break;
       }
 
+      case 0x18: // fre (Floating Reciprocal Estimate)
+         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
+         // Note: unclear whether this insn really exists or not
+         // ppc970 doesn't have it, but POWER5 does
+         if (frA_addr != 0 || frC_addr != 0) {
+            vex_printf("dis_fp_arith(ppc)(instr,fres)\n");
+            return False;
+         }
+         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
+             frD_addr, frB_addr);
+         assign( frD, unop(Iop_Est8FRecip, mkexpr(frB)) );
+         break;
+
       case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
          if (frB_addr != 0) {
             vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
@@ -8645,6 +8672,11 @@
       case 0x1F:                       // fnmadds
          if (dis_fp_multadd(theInstr)) goto decode_success;
          goto decode_failure;
+
+      case 0x1A:                       // frsqrtes
+         if (!allow_GX) goto decode_noGX;
+         if (dis_fp_arith(theInstr)) goto decode_success;
+         goto decode_failure;
          
       default:
          goto decode_failure;
@@ -8683,6 +8715,11 @@
       case 0x1F:                       // fnmadd
          if (dis_fp_multadd(theInstr)) goto decode_success;
          goto decode_failure;
+
+      case 0x18:                       // fre
+         if (!allow_GX) goto decode_noGX;
+         if (dis_fp_arith(theInstr)) goto decode_success;
+         goto decode_failure;
          
       default:
          break; // Fall through