]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Support FPREM1 on amd64. Fixes #172563.
authorJulian Seward <jseward@acm.org>
Sat, 11 Oct 2008 10:07:55 +0000 (10:07 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 11 Oct 2008 10:07:55 +0000 (10:07 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1865

VEX/priv/guest-amd64/toIR.c
VEX/priv/host-amd64/hdefs.c
VEX/priv/host-amd64/hdefs.h
VEX/priv/host-amd64/isel.c

index 0e644ccbebbaf9413c176dabbc1528dcfa125d95..1a578f6f0383d1e940b1f1dcc060b26617930a4d 100644 (file)
@@ -4937,19 +4937,27 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
                break;
             }
 
-//..             case 0xF5: { /* FPREM1 -- IEEE compliant */
-//..                IRTemp a1 = newTemp(Ity_F64);
-//..                IRTemp a2 = newTemp(Ity_F64);
-//..                DIP("fprem1\n");
-//..                /* Do FPREM1 twice, once to get the remainder, and once
-//..                   to get the C3210 flag values. */
-//..                assign( a1, get_ST(0) );
-//..                assign( a2, get_ST(1) );
-//..                put_ST_UNCHECKED(0, binop(Iop_PRem1F64,
-//..                                          mkexpr(a1), mkexpr(a2)));
-//..                put_C3210( binop(Iop_PRem1C3210F64, mkexpr(a1), mkexpr(a2)) );
-//..                break;
-//..             }
+            case 0xF5: { /* FPREM1 -- IEEE compliant */
+               IRTemp a1 = newTemp(Ity_F64);
+               IRTemp a2 = newTemp(Ity_F64);
+               DIP("fprem1\n");
+               /* Do FPREM1 twice, once to get the remainder, and once
+                  to get the C3210 flag values. */
+               assign( a1, get_ST(0) );
+               assign( a2, get_ST(1) );
+               put_ST_UNCHECKED(0,
+                  triop(Iop_PRem1F64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        mkexpr(a1),
+                        mkexpr(a2)));
+               put_C3210(
+                  unop(Iop_32Uto64,
+                  triop(Iop_PRem1C3210F64,
+                        get_FAKE_roundingmode(), /* XXXROUNDINGFIXME */
+                        mkexpr(a1),
+                        mkexpr(a2)) ));
+               break;
+            }
 
             case 0xF7: /* FINCSTP */
                DIP("fincstp\n");
index c5327aa0adfad8d08d93d8f0aacea35230a6da53..55707c8818179dbc7a84388d0a673c17a6452180 100644 (file)
@@ -549,7 +549,7 @@ HChar* showA87FpOp ( A87FpOp op ) {
       case Afp_YL2X:   return "yl2x";
       case Afp_YL2XP1: return "yl2xp1";
       case Afp_PREM:   return "prem";
-//..       case Xfp_PREM1:  return "prem1";
+      case Afp_PREM1:  return "prem1";
       case Afp_SQRT:   return "sqrt";
 //..       case Xfp_ABS:    return "abs";
 //..       case Xfp_NEG:    return "chs";
@@ -2885,6 +2885,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
          case Afp_YL2X:   *p++ = 0xD9; *p++ = 0xF1; break;
          case Afp_YL2XP1: *p++ = 0xD9; *p++ = 0xF9; break;
          case Afp_PREM:   *p++ = 0xD9; *p++ = 0xF8; break;
+         case Afp_PREM1:  *p++ = 0xD9; *p++ = 0xF5; break;
          default: goto bad;
       }
       goto done;
index bc88687b5e26c6c7c64481897e75c619ee280469..eace7b3d5947e531e317e622200af72635c97c73 100644 (file)
@@ -307,7 +307,7 @@ typedef
    enum {
       Afp_INVALID,
       /* Binary */
-      Afp_SCALE, Afp_ATAN, Afp_YL2X, Afp_YL2XP1, Afp_PREM,
+      Afp_SCALE, Afp_ATAN, Afp_YL2X, Afp_YL2XP1, Afp_PREM, Afp_PREM1,
       /* Unary */
       Afp_SQRT,
       Afp_SIN, Afp_COS, Afp_TAN,
index 26af4935bad97d0bfec105673615a1145d87495c..88777b8823e2cdc04e305638ea18f41f5036cf0d 100644 (file)
@@ -1761,7 +1761,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
    case Iex_Triop: {
       /* C3210 flags following FPU partial remainder (fprem), both
          IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
-      if (e->Iex.Triop.op == Iop_PRemC3210F64) {
+      if (e->Iex.Triop.op == Iop_PRemC3210F64
+          || e->Iex.Triop.op == Iop_PRem1C3210F64) {
          AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
          HReg        arg1   = iselDblExpr(env, e->Iex.Triop.arg2);
          HReg        arg2   = iselDblExpr(env, e->Iex.Triop.arg3);
@@ -1780,6 +1781,9 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
             case Iop_PRemC3210F64:
                addInstr(env, AMD64Instr_A87FpOp(Afp_PREM));
                break;
+            case Iop_PRem1C3210F64:
+               addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1));
+               break;
             default: 
                vassert(0);
          }
@@ -2936,14 +2940,16 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
            || e->Iex.Triop.op == Iop_AtanF64
            || e->Iex.Triop.op == Iop_Yl2xF64
            || e->Iex.Triop.op == Iop_Yl2xp1F64
-           || e->Iex.Triop.op == Iop_PRemF64)
+           || e->Iex.Triop.op == Iop_PRemF64
+           || e->Iex.Triop.op == Iop_PRem1F64)
       ) {
       AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
       HReg        arg1   = iselDblExpr(env, e->Iex.Triop.arg2);
       HReg        arg2   = iselDblExpr(env, e->Iex.Triop.arg3);
       HReg        dst    = newVRegV(env);
       Bool     arg2first = toBool(e->Iex.Triop.op == Iop_ScaleF64 
-                                  || e->Iex.Triop.op == Iop_PRemF64);
+                                  || e->Iex.Triop.op == Iop_PRemF64
+                                  || e->Iex.Triop.op == Iop_PRem1F64);
       addInstr(env, AMD64Instr_A87Free(2));
 
       /* one arg -> top of x87 stack */
@@ -2975,6 +2981,9 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
          case Iop_PRemF64:
             addInstr(env, AMD64Instr_A87FpOp(Afp_PREM));
             break;
+         case Iop_PRem1F64:
+            addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1));
+            break;
          default: 
             vassert(0);
       }