]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
More FPU stuff.
authorJulian Seward <jseward@acm.org>
Sun, 15 Aug 2004 03:12:41 +0000 (03:12 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 15 Aug 2004 03:12:41 +0000 (03:12 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@168

VEX/hacked104/vg_translate.c
VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/hdefs.c
VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c
VEX/pub/libvex_basictypes.h
VEX/pub/libvex_ir.h

index b62d691d2ceaacc8f026d3ec7c9ada4da619dd27..13f7fb52fefbd1b9986609a778a568f2229fc092 100644 (file)
@@ -3122,7 +3122,7 @@ void VG_(translate) ( ThreadState* tst,
    Bool debugging_translation;
 
    static Int v0thresh = 940;
-   static Int v2thresh = 940;
+   static Int v2thresh = 940000;
 
    TranslateResult tres;
    static Bool vex_init_done = False;
index 1b15922143f588b77769a3f0f1bad0d11b8f833b..6848a29b004588d4bcb612181839611e63a58a8e 100644 (file)
@@ -3127,7 +3127,7 @@ static IRExpr* get_ST ( Int i )
 
 /* Adjust FTOP downwards by one register. */
 
-static IRStmt* do_push ( void )
+static IRStmt* fp_push ( void )
 {
    return
       put_ftop(
@@ -3137,13 +3137,37 @@ static IRStmt* do_push ( void )
       );
 }
 
+/* Adjust FTOP upwards by one register. */
+
+static IRStmt* fp_pop ( void )
+{
+   return
+      put_ftop(
+         binop(Iop_And32,
+               binop(Iop_Add32, get_ftop(), mkU32(1)),
+              mkU32(7))
+      );
+}
+
+static
+void fp_do_op_mem_ST_0 ( IRTemp addr, UChar* op_txt, UChar* dis_buf, 
+                         IROp op, Bool dbl )
+{
+   DIP("f%s%c %s", op_txt, dbl?'l':'s', dis_buf);
+   if (dbl) {
+      stmt( put_ST(0, binop(op, get_ST(0), loadLE(Ity_F64,mkexpr(addr)))));
+   } else {
+      vassert(0);
+   }
+}
+
 
 static
 UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
 {
-   Int  len;
-   UInt src;
-   Char dis_buf[32];
+   Int    len;
+   UInt   r_src, r_dst;
+   Char   dis_buf[32];
    IRTemp t1;
 
    /* On entry, delta points at the second byte of the insn (the modrm
@@ -3166,14 +3190,20 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
          delta++;
          switch (modrm) {
             case 0xC0 ... 0xC7: /* FLD %st(?) */
-               src = (UInt)modrm - 0xC0;
-               DIP("fld %%st(%d)\n", src);
+               r_src = (UInt)modrm - 0xC0;
+               DIP("fld %%st(%d)\n", r_src);
               t1 = newTemp(Ity_F64);
-              assign(t1, get_ST(src));
-              stmt( do_push() );
+              assign(t1, get_ST(r_src));
+              stmt( fp_push() );
               stmt( put_ST(0, mkexpr(t1)) );
                break;
 
+            case 0xEE: /* FLDZ */
+               DIP("fldz");
+               stmt( fp_push() );
+               stmt( put_ST(0, IRExpr_Const(IRConst_F64(0.0))) );
+               break;
+
             default:
                goto decode_fail;
          }
@@ -3221,7 +3251,28 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDC opcodes +-+-+-+-+-+-+-+ */
    else
    if (first_opcode == 0xDC) {
-      goto decode_fail;
+      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 );
+         delta += len;
+
+         switch (gregOfRM(modrm)) {
+
+            case 0: /* FADD double-real */
+               fp_do_op_mem_ST_0 ( addr, "add", dis_buf, Iop_AddF64, True );
+               break;
+
+            default:
+               vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
+               vex_printf("first_opcode == 0xDC\n");
+               goto decode_fail;
+         }
+
+      } else {
+         goto decode_fail;
+      }
    }
 
    /* -+-+-+-+-+-+-+-+-+-+-+-+ 0xDD opcodes +-+-+-+-+-+-+-+ */
@@ -3239,7 +3290,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
 
             case 0: /* FLD double-real */
                DIP("fldD %s\n", dis_buf);
-               stmt( do_push() );
+               stmt( fp_push() );
                stmt( put_ST(0, IRExpr_LDle(Ity_F64, mkexpr(addr))) );
                break;
 
@@ -3254,19 +3305,12 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                }
                setDMem(a_addr,vd_addr);
                break;
-
+#endif
             case 3: /* FSTP double-real */
-               IFDB( if (dis) printf("\tfstpD\t%s\n",t_addr); )
-               if (!fp_is_empty_tag(fp_get_tag_ST(0))) {
-                  vd_addr = fp_pop();
-               } else {
-                  vd_addr = fp_pop(); /* then throw away result */
-                  vd_addr = NAN;
-                  fp_set_stack_underflow();
-               }
-               setDMem(a_addr,vd_addr);
+               DIP("fstpD %s", dis_buf);
+              storeLE(mkexpr(addr), get_ST(0));
+              stmt( fp_pop() );
                break;
-#endif
 
             default:
                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
@@ -3274,7 +3318,17 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                goto decode_fail;
          }
       } else {
-         goto decode_fail;
+         delta++;
+         switch (modrm) {
+            case 0xD8 ... 0xDF: /* FSTP %st(0),%st(?) */
+               r_dst = (UInt)modrm - 0xD8;
+               DIP("fstp %%st(0),%%st(%d)\n", r_dst);
+               stmt( put_ST(r_dst, get_ST(0)) );
+               stmt( fp_pop() );
+               break;
+           default:
+               goto decode_fail;
+        }
       }
    }
 
index 9ae499ffbcf09ef98e00544c0e3e99139d916f27..451bf9bff69504da907c266c5a81919ac76d670d 100644 (file)
@@ -1028,6 +1028,8 @@ static Bool fits8bits ( UInt w32 )
      greg,  d32(ereg)  |  ereg != ESP
                        =  10 greg ereg, d32
 
+     greg,  d8(%esp)   =  01 greg 100, 0x24, d8
+
      -----------------------------------------------
 
      greg,  d8(base,index,scale)  
@@ -1058,6 +1060,13 @@ static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
          p = emit32(p, am->Xam.IR.imm);
          return p;
       }
+      if (am->Xam.IR.reg == hregX86_ESP()
+          && fits8bits(am->Xam.IR.imm)) {
+        *p++ = mkModRegRM(1, iregNo(greg), 4);
+         *p++ = 0x24;
+         *p++ = am->Xam.IR.imm & 0xFF;
+         return p;
+      }
       ppX86AMode(am);
       vpanic("doAMode_M: can't emit amode IR");
       /*NOTREACHED*/
@@ -1127,6 +1136,7 @@ static UChar* do_fop_st ( UChar* p, X86FpOp op, Int i )
 #  define fake(_n) mkHReg((_n), HRcInt, False)
    Int subopc;
    switch (op) {
+      case Xfp_ADD: subopc = 0; break;
       case Xfp_MUL: subopc = 1; break;
       default: vpanic("do_fop_st: unknown op");
    }
@@ -1411,7 +1421,11 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
             *p++ = 0xFF;
             p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
             goto done;
-         default: 
+         case Xrmi_Imm:
+            *p++ = 0x68;
+            p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
+            goto done;
+        default: 
             goto bad;
       }
 
index 622241e970f49400d3cc4c9005d0dcfa1a1273f5..a653da2071f6f81e848dc0595f54358816aaa94f 100644 (file)
@@ -92,6 +92,10 @@ static Bool matchWrk ( MatchInfo* mi, IRExpr* p/*attern*/, IRExpr* e/*xpr*/ )
                                    ? (p->Iex.Const.con->Ico.U64 
                                       == e->Iex.Const.con->Ico.U64) 
                                    : False;
+           case Ico_F64: return e->Iex.Const.con->tag==Ico_F64 
+                                   ? (p->Iex.Const.con->Ico.F64 
+                                      == e->Iex.Const.con->Ico.F64) 
+                                   : False;
        }
         vpanic("matchIRExpr.Iex_Const");
         /*NOTREACHED*/
@@ -967,6 +971,24 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
       return lookupIRTemp(env, e->Iex.Tmp.tmp);
    }
 
+   if (e->tag == Iex_Const) {
+      union { UInt i64[2]; Double f64; } u;
+      HReg freg = newVRegF(env);
+      vassert(sizeof(u) == 8);
+      vassert(sizeof(u.i64) == 8);
+      vassert(sizeof(u.f64) == 8);
+      vassert(e->Iex.Const.con->tag == Ico_F64);
+      u.f64 = e->Iex.Const.con->Ico.F64;
+      addInstr(env, X86Instr_Push(X86RMI_Imm(u.i64[1])));
+      addInstr(env, X86Instr_Push(X86RMI_Imm(u.i64[0])));
+      addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg, 
+                                    X86AMode_IR(0, hregX86_ESP())));
+      addInstr(env, X86Instr_Alu32R(Xalu_ADD,
+                                    X86RMI_Imm(8),
+                                    hregX86_ESP()));
+      return freg;
+   }
+
    if (e->tag == Iex_LDle) {
       X86AMode* am;
       HReg res = newVRegF(env);
@@ -991,6 +1013,7 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Binop) {
       X86FpOp fpop = Xfp_INVALID;
       switch (e->Iex.Binop.op) {
+         case Iop_AddF64: fpop = Xfp_ADD; break;
          case Iop_MulF64: fpop = Xfp_MUL; break;
          default: break;
       }
@@ -1035,22 +1058,27 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
 
    /* --------- STORE --------- */
    case Ist_STle: {
+      X86AMode* am;
       IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.STle.addr);
       IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.STle.data);
       vassert(tya == Ity_I32);
+      am = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
       if (tyd == Ity_I32) {
-         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
-         X86RI* ri    = iselIntExpr_RI(env, stmt->Ist.STle.data);
+         X86RI* ri = iselIntExpr_RI(env, stmt->Ist.STle.data);
          addInstr(env, X86Instr_Alu32M(Xalu_MOV,ri,am));
          return;
       }
       if (tyd == Ity_I8 || tyd == Ity_I16) {
-         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
-         HReg r       = iselIntExpr_R(env, stmt->Ist.STle.data);
+         HReg r = iselIntExpr_R(env, stmt->Ist.STle.data);
          addInstr(env, X86Instr_Store(tyd==Ity_I8 ? 1 : 2,
                                       r,am));
          return;
       }
+      if (tyd == Ity_F64) {
+         HReg r = iselDblExpr(env, stmt->Ist.STle.data);
+         addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
+         return;
+      }
       break;
    }
 
index 2ce5bd97e7eb0517d2ec36a93e8b77370c2117fc..f6862ff040a142fa0e7853d790285b2fa38bf785 100644 (file)
@@ -40,6 +40,7 @@ void ppIRConst ( IRConst* con )
     case Ico_U16: vex_printf( "0x%x",   (UInt)(con->Ico.U16)); break;
     case Ico_U32: vex_printf( "0x%x",   (UInt)(con->Ico.U32)); break;
     case Ico_U64: vex_printf( "0x%llx", (ULong)(con->Ico.U64)); break;
+    case Ico_F64: vex_printf("(f64 value)"); break;
     default: vpanic("ppIRConst");
   }
 }
@@ -117,6 +118,7 @@ void ppIROp ( IROp op )
       case Iop_64to32:   vex_printf("64to32");   return;
       case Iop_32HLto64: vex_printf("32HLto64"); return;
 
+      case Iop_AddF64:   vex_printf("AddF64"); return;
       case Iop_MulF64:   vex_printf("MulF64"); return;
       case Iop_I64toF64: vex_printf("I64toF64"); return;
 
@@ -321,7 +323,13 @@ IRConst* IRConst_U64 ( ULong u64 )
    c->Ico.U64 = u64;
    return c;
 }
-
+IRConst* IRConst_F64 ( Double f64 )
+{
+   IRConst* c = LibVEX_Alloc(sizeof(IRConst));
+   c->tag     = Ico_F64;
+   c->Ico.F64 = f64;
+   return c;
+}
 
 /* Constructors -- IRExpr */
 
@@ -555,7 +563,8 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
       case Iop_32Sto64: UNARY(Ity_I64,Ity_I32);
       case Iop_32to8:   UNARY(Ity_I8,Ity_I32);
 
-      case Iop_MulF64:   BINARY(Ity_F64,Ity_F64,Ity_F64);
+      case Iop_AddF64: case Iop_MulF64:
+         BINARY(Ity_F64,Ity_F64,Ity_F64);
       case Iop_I64toF64: UNARY(Ity_F64,Ity_I64);
 
       default:
@@ -620,6 +629,7 @@ IRType typeOfIRConst ( IRConst* con )
       case Ico_U16: return Ity_I16;
       case Ico_U32: return Ity_I32;
       case Ico_U64: return Ity_I64;
+      case Ico_F64: return Ity_F64;
       default: vpanic("typeOfIRConst");
    }
 }
index bd0860ac9add40b496ac792b77d994734659f059..9505b49149e9106757aa954aecf8c49ca9162c62 100644 (file)
@@ -21,6 +21,9 @@ typedef    signed int    Int;
 typedef  unsigned long long int   ULong;
 typedef    signed long long int   Long;
 
+typedef  float   Float;    /* IEEE754 single-precision (32-bit) value */
+typedef  double  Double;   /* IEEE754 double-precision (64-bit) value */
+
 typedef  unsigned char  Bool;
 #define  True   ((Bool)1)
 #define  False  ((Bool)0)
index 880cfb8e9cf49235868bf85d63f8daffe1035f26..cdcb9fc01d4c468c8ba44ff13ab38f8ccf7b78e8 100644 (file)
@@ -33,7 +33,7 @@ extern void ppIRType ( IRType );
 
 typedef
    enum { Ico_U8=0x12000, 
-          Ico_U16, Ico_U32, Ico_U64 }
+          Ico_U16, Ico_U32, Ico_U64, Ico_F64 }
    IRConstTag;
 
 typedef
@@ -44,6 +44,7 @@ typedef
          UShort U16;
          UInt   U32;
          ULong  U64;
+         Double F64;
       } Ico;
    }
    IRConst;
@@ -52,6 +53,7 @@ extern IRConst* IRConst_U8  ( UChar );
 extern IRConst* IRConst_U16 ( UShort );
 extern IRConst* IRConst_U32 ( UInt );
 extern IRConst* IRConst_U64 ( ULong );
+extern IRConst* IRConst_F64 ( Double );
 
 extern void ppIRConst ( IRConst* );