]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix many amd64 floating point cases that were missing.
authorJulian Seward <jseward@acm.org>
Sun, 27 Mar 2005 04:01:15 +0000 (04:01 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 27 Mar 2005 04:01:15 +0000 (04:01 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1103

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

index f325b65a0e8e715c7325eb22e73396603cbd6fa2..f054f2c1102ac8e3977815b88ec77048c6c03efb 100644 (file)
@@ -4339,21 +4339,21 @@ void fp_do_op_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
       fp_pop();
 }
 
-//.. /* ST(dst) = ST(src) `op` ST(dst).
-//..    Check dst and src tags when reading but not on write.
-//.. */
-//.. static
-//.. void fp_do_oprev_ST_ST ( UChar* op_txt, IROp op, UInt st_src, UInt st_dst,
-//..                          Bool pop_after )
-//.. {
-//..    DIP("f%s%s st(%d), st(%d)\n", op_txt, pop_after?"p":"", st_src, st_dst );
-//..    put_ST_UNCHECKED( 
-//..       st_dst, 
-//..       binop(op, get_ST(st_src), get_ST(st_dst) ) 
-//..    );
-//..    if (pop_after)
-//..       fp_pop();
-//.. }
+/* ST(dst) = ST(src) `op` ST(dst).
+   Check dst and src tags when reading but not on write.
+*/
+static
+void fp_do_oprev_ST_ST ( HChar* op_txt, IROp op, UInt st_src, UInt st_dst,
+                         Bool pop_after )
+{
+   DIP("f%s%s st(%u), st(%u)\n", op_txt, pop_after?"p":"", st_src, st_dst );
+   put_ST_UNCHECKED( 
+      st_dst, 
+      binop(op, get_ST(st_src), get_ST(st_dst) ) 
+   );
+   if (pop_after)
+      fp_pop();
+}
 
 /* %rflags(Z,P,C) = UCOMI( st(0), st(i) ) */
 static void fp_do_ucomi_ST0_STi ( UInt i, Bool pop_after )
@@ -4473,10 +4473,10 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
                fp_do_op_ST_ST ( "add", Iop_AddF64, modrm - 0xC0, 0, False );
                break;
 
-//..             case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
-//..                fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
-//..                break;
-//.. 
+            case 0xC8 ... 0xCF: /* FMUL %st(?),%st(0) */
+               fp_do_op_ST_ST ( "mul", Iop_MulF64, modrm - 0xC8, 0, False );
+               break;
+
 //.. #if 1
 //..             /* Dunno if this is right */
 //..             case 0xD0 ... 0xD7: /* FCOM %st(?),%st(0) */
@@ -4508,18 +4508,18 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..                fp_pop();
 //..                break;
 //.. #endif
-//..             case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
-//..                fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
-//..                break;
-//.. 
+            case 0xE0 ... 0xE7: /* FSUB %st(?),%st(0) */
+               fp_do_op_ST_ST ( "sub", Iop_SubF64, modrm - 0xE0, 0, False );
+               break;
+
 //..             case 0xE8 ... 0xEF: /* FSUBR %st(?),%st(0) */
 //..                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, modrm - 0xE8, 0, False );
 //..                break;
-//.. 
-//..             case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
-//..                fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
-//..                break;
-//.. 
+
+            case 0xF0 ... 0xF7: /* FDIV %st(?),%st(0) */
+               fp_do_op_ST_ST ( "div", Iop_DivF64, modrm - 0xF0, 0, False );
+               break;
+
 //..             case 0xF8 ... 0xFF: /* FDIVR %st(?),%st(0) */
 //..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, modrm - 0xF8, 0, False );
 //..                break;
@@ -4754,11 +4754,11 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
                put_ST_UNCHECKED(0, unop(Iop_NegF64, get_ST(0)));
                break;
 
-//..             case 0xE1: /* FABS */
-//..                DIP("fabs\n");
-//..                put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
-//..                break;
-//.. 
+            case 0xE1: /* FABS */
+               DIP("fabs\n");
+               put_ST_UNCHECKED(0, unop(Iop_AbsF64, get_ST(0)));
+               break;
+
 //..             case 0xE5: { /* FXAM */
 //..                /* This is an interesting one.  It examines %st(0),
 //..                   regardless of whether the tag says it's empty or not.
@@ -5171,23 +5171,31 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
             case 0xC8 ... 0xCF: /* FCMOVNE(NZ) ST(i), ST(0) */
                r_src = (UInt)modrm - 0xC8;
                DIP("fcmovnz %%st(%d), %%st(0)\n", r_src);
-               put_ST_UNCHECKED(0, 
-                                IRExpr_Mux0X( 
-                                    unop(Iop_1Uto8,
-                                         mk_amd64g_calculate_condition(AMD64CondNZ)), 
-                                    get_ST(0), get_ST(r_src)) );
+               put_ST_UNCHECKED(
+                  0, 
+                  IRExpr_Mux0X( 
+                     unop(Iop_1Uto8,
+                          mk_amd64g_calculate_condition(AMD64CondNZ)), 
+                     get_ST(0), 
+                     get_ST(r_src)
+                  )
+               );
+               break;
+
+            case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
+               r_src = (UInt)modrm - 0xD0;
+               DIP("fcmovnbe %%st(%d), %%st(0)\n", r_src);
+               put_ST_UNCHECKED(
+                  0, 
+                  IRExpr_Mux0X( 
+                     unop(Iop_1Uto8,
+                          mk_amd64g_calculate_condition(AMD64CondNBE)), 
+                     get_ST(0), 
+                     get_ST(r_src)
+                  ) 
+               );
                break;
 
-//..             case 0xD0 ... 0xD7: /* FCMOVNBE ST(i), ST(0) */
-//..                r_src = (UInt)modrm - 0xD0;
-//..                DIP("fcmovnbe %%st(%d), %%st(0)\n", r_src);
-//..                put_ST_UNCHECKED(0, 
-//..                                 IRExpr_Mux0X( 
-//..                                     unop(Iop_1Uto8,
-//..                                          mk_x86g_calculate_condition(X86CondNBE)), 
-//..                                     get_ST(0), get_ST(r_src)) );
-//..                break;
-//.. 
 //..             case 0xE2:
 //..                DIP("fnclex\n");
 //..                break;
@@ -5246,11 +5254,11 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
       }
    }
 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDC) {
-//..       if (modrm < 0xC0) {
-//.. 
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDC) {
+      if (modrm < 0xC0) {
+
 //..          /* bits 5,4,3 are an opcode extension, and the modRM also
 //..             specifies an address. */
 //..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
@@ -5316,16 +5324,16 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..                vex_printf("first_opcode == 0xDC\n");
 //..                goto decode_fail;
 //..          }
-//.. 
-//..       } else {
-//.. 
-//..          delta++;
-//..          switch (modrm) {
-//.. 
-//..             case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
-//..                break;
-//.. 
+
+      } else {
+
+         delta++;
+         switch (modrm) {
+
+            case 0xC0 ... 0xC7: /* FADD %st(0),%st(?) */
+               fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, False );
+               break;
+
 //..             case 0xC8 ... 0xCF: /* FMUL %st(0),%st(?) */
 //..                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, False );
 //..                break;
@@ -5341,17 +5349,17 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..             case 0xF0 ... 0xF7: /* FDIVR %st(0),%st(?) */
 //..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, False );
 //..                break;
-//.. 
-//..             case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
-//..                break;
-//.. 
-//..             default:
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       }
-//..    }
+
+            case 0xF8 ... 0xFF: /* FDIV %st(0),%st(?) */
+               fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, False );
+               break;
+
+            default:
+               goto decode_fail;
+         }
+
+      }
+   }
 
    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
    else
@@ -5547,19 +5555,18 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
       }
    }
 
-//..    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
-//..    else
-//..    if (first_opcode == 0xDE) {
-//.. 
-//..       if (modrm < 0xC0) {
-//.. 
+   /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDE opcodes +-+-+-+-+-+-+-+ */
+   else
+   if (first_opcode == 0xDE) {
+
+      if (modrm < 0xC0) {
+
 //..          /* bits 5,4,3 are an opcode extension, and the modRM also
 //..             specifies an address. */
-//..          IROp   fop;
-//..          IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
+//..          IRTemp addr = disAMode( &len, pfx, delta, dis_buf, 0 );
 //..          delta += len;
 //.. 
-//..          switch (gregOfRM(modrm)) {
+//..          switch (gregLO3ofRM(modrm)) {
 //.. 
 //..             case 0: /* FIADD m16int */ /* ST(0) += m16int */
 //..                DIP("fiaddw %s\n", dis_buf);
@@ -5610,24 +5617,24 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..                break;
 //.. 
 //..             default:
-//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+//..                vex_printf("unhandled opc_aux = 0x%2x\n", gregLO3ofRM(modrm));
 //..                vex_printf("first_opcode == 0xDE\n");
 //..                goto decode_fail;
 //..          }
-//.. 
-//..       } else {
-//.. 
-//..          delta++;
-//..          switch (modrm) {
-//.. 
-//..             case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
-//..                break;
-//.. 
-//..             case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
-//..                break;
-//.. 
+
+      } else {
+
+         delta++;
+         switch (modrm) {
+
+            case 0xC0 ... 0xC7: /* FADDP %st(0),%st(?) */
+               fp_do_op_ST_ST ( "add", Iop_AddF64, 0, modrm - 0xC0, True );
+               break;
+
+            case 0xC8 ... 0xCF: /* FMULP %st(0),%st(?) */
+               fp_do_op_ST_ST ( "mul", Iop_MulF64, 0, modrm - 0xC8, True );
+               break;
+
 //..             case 0xD9: /* FCOMPP %st(0),%st(1) */
 //..                DIP("fuompp %%st(0),%%st(1)\n");
 //..                /* This forces C1 to zero, which isn't right. */
@@ -5641,29 +5648,29 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 //..                fp_pop();
 //..                fp_pop();
 //..                break;
-//.. 
-//..             case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
-//..                fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
-//..                break;
-//.. 
-//..             case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
-//..                break;
-//.. 
-//..             case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
-//..                fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
-//..                break;
-//.. 
-//..             case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
-//..                fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
-//..                break;
-//.. 
-//..             default: 
-//..                goto decode_fail;
-//..          }
-//.. 
-//..       }
-//..    }
+
+            case 0xE0 ... 0xE7: /* FSUBRP %st(0),%st(?) */
+               fp_do_oprev_ST_ST ( "subr", Iop_SubF64, 0,  modrm - 0xE0, True );
+               break;
+
+            case 0xE8 ... 0xEF: /* FSUBP %st(0),%st(?) */
+               fp_do_op_ST_ST ( "sub", Iop_SubF64, 0,  modrm - 0xE8, True );
+               break;
+
+            case 0xF0 ... 0xF7: /* FDIVRP %st(0),%st(?) */
+               fp_do_oprev_ST_ST ( "divr", Iop_DivF64, 0, modrm - 0xF0, True );
+               break;
+
+            case 0xF8 ... 0xFF: /* FDIVP %st(0),%st(?) */
+               fp_do_op_ST_ST ( "div", Iop_DivF64, 0, modrm - 0xF8, True );
+               break;
+
+            default: 
+               goto decode_fail;
+         }
+
+      }
+   }
 
    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDF opcodes +-+-+-+-+-+-+-+ */
    else
@@ -5764,7 +5771,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
    }
 
    else
-      goto decode_fail; //vpanic("dis_FPU(amd64): invalid primary opcode");
+      goto decode_fail;
 
    *decode_ok = True;
    return delta;
@@ -11857,9 +11864,10 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
       delta = dis_op_imm_A( sz, Iop_And8, True, delta, "and" );
       break;
 
-//..    case 0x2C: /* SUB Ib, AL */
-//..       delta = dis_op_imm_A(1, Iop_Sub8, True, delta, "sub" );
-//..       break;
+   case 0x2C: /* SUB Ib, AL */
+      if (haveF2orF3(pfx)) goto decode_failure;
+      delta = dis_op_imm_A(1, Iop_Sub8, True, delta, "sub" );
+      break;
    case 0x2D: /* SUB Iv, eAX */
       if (haveF2orF3(pfx)) goto decode_failure;
       delta = dis_op_imm_A( sz, Iop_Sub8, True, delta, "sub" );
index 7dc0cc61b12efc8175fd1f1f26b6c1e42d7d1e69..d22ee707d767499559e34bfc77f2845b810bcf75 100644 (file)
@@ -3136,9 +3136,9 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
 //..          case Xsse_RSQRTF: *p++ = 0x52; break;
          case Asse_SQRTF:  *p++ = 0x51; break;
          case Asse_SUBF:   *p++ = 0x5C; break;
-//..          case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
+         case Asse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
          case Asse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
-//..          case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
+         case Asse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
          default: goto bad;
       }
       p = doAMode_R(p, vreg2ireg(i->Ain.Sse64FLo.dst),
@@ -3159,6 +3159,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i )
          case Asse_OR:                 XX(rex); XX(0x0F); XX(0x56); break;
          case Asse_XOR:                XX(rex); XX(0x0F); XX(0x57); break;
          case Asse_AND:                XX(rex); XX(0x0F); XX(0x54); break;
+         case Asse_ANDN:               XX(rex); XX(0x0F); XX(0x55); break;
 //..          case Xsse_PACKSSD:  XX(0x66); XX(rex); XX(0x0F); XX(0x6B); break;
 //..          case Xsse_PACKSSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x63); break;
 //..          case Xsse_PACKUSW:  XX(0x66); XX(rex); XX(0x0F); XX(0x67); break;
index c231f6d300f57630ef82e007e1b5a71769e5b367..f2d28b80e18330018811a69b9b9dd72776eca3e6 100644 (file)
@@ -2723,6 +2723,25 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return res;
    }
 
+   if (e->tag == Iex_Binop) {
+      AMD64SseOp op = Asse_INVALID;
+      switch (e->Iex.Binop.op) {
+         case Iop_AddF64: op = Asse_ADDF; break;
+         case Iop_SubF64: op = Asse_SUBF; break;
+         case Iop_MulF64: op = Asse_MULF; break;
+         case Iop_DivF64: op = Asse_DIVF; break;
+         default: break;
+      }
+      if (op != Asse_INVALID) {
+         HReg dst  = newVRegV(env);
+         HReg argL = iselDblExpr(env, e->Iex.Binop.arg1);
+         HReg argR = iselDblExpr(env, e->Iex.Binop.arg2);
+         addInstr(env, mk_vMOVsd_RR(argL, dst));
+         addInstr(env, AMD64Instr_Sse64FLo(op, argR, dst));
+         return dst;
+      }
+   }
+
 //..    if (e->tag == Iex_Binop) {
 //..       X86FpOp fpop = Xfp_INVALID;
 //..       switch (e->Iex.Binop.op) {
@@ -2786,19 +2805,28 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
       return dst;
    }
 
-   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_NegF64) {
+   if (e->tag == Iex_Unop 
+       && (e->Iex.Unop.op == Iop_NegF64
+           || e->Iex.Unop.op == Iop_AbsF64)) {
       /* Sigh ... very rough code.  Could do much better. */
+      /* Get the 128-bit literal 00---0 10---0 into a register
+         and xor/nand it with the value to be negated. */
       HReg r1  = newVRegI(env);
       HReg dst = newVRegV(env);
-      HReg t = newVRegV(env);
+      HReg tmp = newVRegV(env);
       HReg src = iselDblExpr(env, e->Iex.Unop.arg);
       AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
-      addInstr(env, mk_vMOVsd_RR(src,dst));
+      addInstr(env, mk_vMOVsd_RR(src,tmp));
       addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
       addInstr(env, AMD64Instr_Imm64( 1ULL<<63, r1 ));
       addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1)));
-      addInstr(env, AMD64Instr_SseLdSt(True, 16, tv, rsp0));
-      addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tv, dst));
+      addInstr(env, AMD64Instr_SseLdSt(True, 16, dst, rsp0));
+
+      if (e->Iex.Unop.op == Iop_NegF64)
+         addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tmp, dst));
+      else
+         addInstr(env, AMD64Instr_SseReRg(Asse_ANDN, tmp, dst));
+
       add_to_rsp(env, 16);
       return dst;
    }
@@ -3227,9 +3255,9 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
          return dst;
       }
 
-//..       case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
+      case Iop_CmpEQ64F0x2: op = Asse_CMPEQF; goto do_64F0x2;
       case Iop_CmpLT64F0x2: op = Asse_CMPLTF; goto do_64F0x2;
-//..       case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
+      case Iop_CmpLE64F0x2: op = Asse_CMPLEF; goto do_64F0x2;
       case Iop_Add64F0x2:   op = Asse_ADDF;   goto do_64F0x2;
       case Iop_Div64F0x2:   op = Asse_DIVF;   goto do_64F0x2;
       case Iop_Max64F0x2:   op = Asse_MAXF;   goto do_64F0x2;