]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
* x86 guest: instead of just tracking the FPU's C3, C2 and C0 flags,
authorJulian Seward <jseward@acm.org>
Fri, 10 Sep 2004 16:17:45 +0000 (16:17 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 10 Sep 2004 16:17:45 +0000 (16:17 +0000)
  also track C1.
* x86 guest: handle FXAM instruction

git-svn-id: svn://svn.valgrind.org/vex/trunk@249

VEX/hacked104/vg_include.h
VEX/hacked104/vg_main.c
VEX/hacked104/vg_scheduler.c
VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/hdefs.c
VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c

index aac53657d78105be74d7ec90ba2ed45d603cfb38..97f74e974d4b81f754390a2e19c9d461eb6ddb89 100644 (file)
@@ -744,7 +744,7 @@ typedef
       UInt  m_fpucw;
       UInt  m_ftag74;
       UInt  m_ftag30;
-      UInt  m_fc320;
+      UInt  m_fc3210;
 
       UInt sh_eax;
       UInt sh_ebx;
@@ -1989,7 +1989,7 @@ extern Int VGOFF_(m_f6);
 extern Int VGOFF_(m_f7);
 extern Int VGOFF_(m_ftag0);
 extern Int VGOFF_(m_fpucw);
-extern Int VGOFF_(m_fc320);
+extern Int VGOFF_(m_fc3210);
 
 /* Reg-alloc spill area (VG_MAX_SPILLSLOTS words long). */
 extern Int VGOFF_(spillslots);
index ea15e1a124f438acc039c82b14b8b1fe314381df..9d1906476f644c1b4737669bd3bf885d74328c83 100644 (file)
@@ -69,7 +69,7 @@ Int VGOFF_(m_f6) = INVALID_OFFSET;
 Int VGOFF_(m_f7) = INVALID_OFFSET;
 Int VGOFF_(m_ftag0) = INVALID_OFFSET;
 Int VGOFF_(m_fpucw) = INVALID_OFFSET;
-Int VGOFF_(m_fc320) = INVALID_OFFSET;
+Int VGOFF_(m_fc3210) = INVALID_OFFSET;
 
 Int VGOFF_(spillslots) = INVALID_OFFSET;
 Int VGOFF_(sh_eax) = INVALID_OFFSET;
@@ -186,18 +186,18 @@ static void vg_init_baseBlock ( void )
 
    /* 12  */ VGOFF_(m_eip)      = alloc_BaB(1);
 
-   /* 13 */ VGOFF_(m_ftop)  = alloc_BaB(1);
-   /* 14 */ VGOFF_(m_f0)    = alloc_BaB(2);
-   /* 16 */ VGOFF_(m_f1)    = alloc_BaB(2);
-   /* 18 */ VGOFF_(m_f2)    = alloc_BaB(2);
-   /* 20 */ VGOFF_(m_f3)    = alloc_BaB(2);
-   /* 22 */ VGOFF_(m_f4)    = alloc_BaB(2);
-   /* 24 */ VGOFF_(m_f5)    = alloc_BaB(2);
-   /* 26 */ VGOFF_(m_f6)    = alloc_BaB(2);
-   /* 28 */ VGOFF_(m_f7)    = alloc_BaB(2);
-   /* 30 */ VGOFF_(m_ftag0) = alloc_BaB(2);
-   /* 32 */ VGOFF_(m_fpucw) = alloc_BaB(1);
-   /* 33 */ VGOFF_(m_fc320) = alloc_BaB(1);
+   /* 13 */ VGOFF_(m_ftop)   = alloc_BaB(1);
+   /* 14 */ VGOFF_(m_f0)     = alloc_BaB(2);
+   /* 16 */ VGOFF_(m_f1)     = alloc_BaB(2);
+   /* 18 */ VGOFF_(m_f2)     = alloc_BaB(2);
+   /* 20 */ VGOFF_(m_f3)     = alloc_BaB(2);
+   /* 22 */ VGOFF_(m_f4)     = alloc_BaB(2);
+   /* 24 */ VGOFF_(m_f5)     = alloc_BaB(2);
+   /* 26 */ VGOFF_(m_f6)     = alloc_BaB(2);
+   /* 28 */ VGOFF_(m_f7)     = alloc_BaB(2);
+   /* 30 */ VGOFF_(m_ftag0)  = alloc_BaB(2);
+   /* 32 */ VGOFF_(m_fpucw)  = alloc_BaB(1);
+   /* 33 */ VGOFF_(m_fc3210) = alloc_BaB(1);
 
    /* 34  */ VGOFF_(sh_eax)    = alloc_BaB(1);
    /* 35  */ VGOFF_(sh_ecx)    = alloc_BaB(1);
index ab712c10dee0bc0feace9ab8c4a76d8d63018c5e..7b4d2e644a2209bc5ec4cbe6c932b1609c7d0540 100644 (file)
@@ -401,7 +401,7 @@ void VG_(load_thread_state) ( ThreadId tid )
    *(ULong*)(&VG_(baseBlock)[VGOFF_(m_f7)]) = VG_(threads)[tid].m_f7;
    VG_(baseBlock)[VGOFF_(m_ftop)]    = VG_(threads)[tid].m_ftop;
    VG_(baseBlock)[VGOFF_(m_fpucw)]   = VG_(threads)[tid].m_fpucw;
-   VG_(baseBlock)[VGOFF_(m_fc320)]   = VG_(threads)[tid].m_fc320;
+   VG_(baseBlock)[VGOFF_(m_fc3210)]  = VG_(threads)[tid].m_fc3210;
    VG_(baseBlock)[VGOFF_(m_ftag0)+0] = VG_(threads)[tid].m_ftag30;
    VG_(baseBlock)[VGOFF_(m_ftag0)+1] = VG_(threads)[tid].m_ftag74;
 
@@ -459,7 +459,7 @@ void VG_(save_thread_state) ( ThreadId tid )
    VG_(threads)[tid].m_f7     = *(ULong*)(&VG_(baseBlock)[VGOFF_(m_f7)]);
    VG_(threads)[tid].m_ftop   = VG_(baseBlock)[VGOFF_(m_ftop)];
    VG_(threads)[tid].m_fpucw  = VG_(baseBlock)[VGOFF_(m_fpucw)];
-   VG_(threads)[tid].m_fc320  = VG_(baseBlock)[VGOFF_(m_fc320)];
+   VG_(threads)[tid].m_fc3210 = VG_(baseBlock)[VGOFF_(m_fc3210)];
    VG_(threads)[tid].m_ftag30 = VG_(baseBlock)[VGOFF_(m_ftag0)+0];
    VG_(threads)[tid].m_ftag74 = VG_(baseBlock)[VGOFF_(m_ftag0)+1];
 
@@ -498,7 +498,7 @@ void VG_(save_thread_state) ( ThreadId tid )
    *(ULong*)(&VG_(baseBlock)[VGOFF_(m_f7)]) = junk64;
    VG_(baseBlock)[VGOFF_(m_ftop)]    = junk;
    VG_(baseBlock)[VGOFF_(m_fpucw)]   = junk;
-   VG_(baseBlock)[VGOFF_(m_fc320)]   = junk;
+   VG_(baseBlock)[VGOFF_(m_fc3210)]  = junk;
    VG_(baseBlock)[VGOFF_(m_ftag0)+0] = junk;
    VG_(baseBlock)[VGOFF_(m_ftag0)+1] = junk;
 
index 6987dc105e5f965458da3343e6c833409f542737..48fd0c6e516629f8300f2d2fbca21863d8d05119 100644 (file)
@@ -49,6 +49,12 @@ IRExpr* x86guest_spechelper ( Char* function_name,
 #define CC_MASK_S    0x0080
 #define CC_MASK_O    0x0800
 
+/* FPU flag masks */
+#define FC_MASK_C3   (1 << 14)
+#define FC_MASK_C2   (1 << 10)
+#define FC_MASK_C1   (1 << 9)
+#define FC_MASK_C0   (1 << 8)
+
 /* eflags thunk descriptors. */
 enum {
     CC_OP_COPY, /* nothing to do -- ccs are in CC_SRC and up to date */
@@ -206,10 +212,11 @@ typedef
 
    FPUCW[15:0] is the FPU's control word.  FPUCW[31:16] is unused.
 
-   FC320 contains the C3, C2 and C0 bits in the same place they are in
-   the FPU's status word.  (bits 14, 10 and 8 respectively).  All other
-   bits should be zero.  The relevant mask to select just those bits
-   is 0x4500.
+   FC3210 contains the C3, C2, C1 and C0 bits in the same place they
+   are in the FPU's status word.  (bits 14, 10, 9, 8 respectively).
+   All other bits should be zero.  The relevant mask to select just
+   those bits is 0x4700.  To select C3, C2 and C0 only, the mask is
+   0x4500.
 */
 #define OFFB_FTOP    (13*4)
 #define OFFB_F0      (14*4)
@@ -222,10 +229,10 @@ typedef
 #define OFFB_F7      (28*4)
 #define OFFB_FTAG0   (30*4) // up to 30*4 + 7
 #define OFFB_FPUCW   (32*4)
-#define OFFB_FC32  (33*4)
+#define OFFB_FC3210  (33*4)
 
 /* Don't forget to keep this up to date. */
-#define SIZEOF_X86H_STATE  (OFFB_FC320 + 4)
+#define SIZEOF_X86H_STATE  (OFFB_FC3210 + 4)
 
 
 
index dfb990209574ac13ee9e1ac1ee4cded3256edfdd..61272925a200cb172e70278cfa8a3a8a359e6aa8 100644 (file)
 #include "main/vex_util.h"
 #include "guest-x86/gdefs.h"
 
+/* --- Forwardses --- */
+UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst );
+UInt calculate_eflags_c   ( UInt cc_op, UInt cc_src, UInt cc_dst );
+UInt calculate_condition  ( UInt/*Condcode*/ cond, 
+                            UInt cc_op, UInt cc_src, UInt cc_dst );
+UInt calculate_FXAM ( UInt tag, ULong dbl );
+
+
 /* This file contains helper functions for x86 guest code.
    Calls to these functions are generated by the back end.
    These calls are of course in the host machine code and 
@@ -578,6 +586,8 @@ Addr64 x86guest_findhelper ( Char* function_name )
       return (Addr64)(& calculate_eflags_c);
    if (vex_streq(function_name, "calculate_condition"))
       return (Addr64)(& calculate_condition);
+   if (vex_streq(function_name, "calculate_FXAM"))
+      return (Addr64)(& calculate_FXAM);
    vex_printf("\nx86 guest: can't find helper: %s\n", function_name);
    vpanic("x86guest_findhelper");
 }
@@ -814,6 +824,81 @@ IRExpr* x86guest_spechelper ( Char* function_name,
    sign bit, giving 64 in total.
 */
 
+static inline Bool host_is_little_endian ( void )
+{
+   UInt x = 0x76543210;
+   UChar* p = (UChar*)(&x);
+   return (*p == 0x10);
+}
+
+UInt calculate_FXAM ( UInt tag, ULong dbl ) 
+{
+   Bool   mantissaIsZero;
+   Int    bexp;
+   UChar  sign;
+   UInt   c1;
+   UChar* f64;
+
+   if (!host_is_little_endian) {
+      vassert(0);
+   }
+
+   /* vex_printf("calculate_FXAM ( %d, %llx ) .. ", tag, dbl ); */
+
+   f64  = (UChar*)(&dbl);
+   sign = (f64[7] >> 7) & 1;
+
+   /* First off, if the tag indicates the register was empty,
+      return 1,0,sign,1 */
+   if (tag == 0) {
+      /* vex_printf("Empty\n"); */
+      return FC_MASK_C3 | 0 | sign | FC_MASK_C0;
+   }
+
+   bexp = (f64[7] << 4) | ((f64[6] >> 4) & 0x0F);
+   bexp &= 0x7FF;
+
+   c1 = ((UInt)sign) << 9;
+
+   mantissaIsZero
+      = (f64[6] & 0x0F) == 0 
+        && (f64[5] | f64[4] | f64[3] | f64[2] | f64[1] | f64[0]) == 0;
+
+   /* If both exponent and mantissa are zero, the value is zero.
+      Return 1,0,sign,0. */
+   if (bexp == 0 && mantissaIsZero) {
+      /* vex_printf("Zero\n"); */
+      return FC_MASK_C3 | 0 | sign | 0;
+   }
+   
+   /* If exponent is zero but mantissa isn't, it's a denormal.
+      Return 1,1,sign,0. */
+   if (bexp == 0 && !mantissaIsZero) {
+      /* vex_printf("Denormal\n"); */
+      return FC_MASK_C3 | FC_MASK_C2 | sign | 0;
+   }
+
+   /* If the exponent is 7FF and the mantissa is zero, this is an infinity.
+      Return 0,1,sign,1. */
+   if (bexp == 0x7FF && mantissaIsZero) {
+      /* vex_printf("Inf\n"); */
+      return 0 | FC_MASK_C2 | sign | FC_MASK_C0;
+   }
+
+   /* If the exponent is 7FF and the mantissa isn't zero, this is a NaN.
+      Return 0,0,sign,1. */
+   if (bexp == 0x7FF && !mantissaIsZero) {
+      /* vex_printf("NaN\n"); */
+      return 0 | 0 | sign | FC_MASK_C0;
+   }
+
+   /* Uh, ok, we give up.  It must be a normal finite number.
+      Return 0,1,sign,0.
+   */
+   /* vex_printf("normal\n"); */
+   return 0 | FC_MASK_C2 | sign | 0;
+}
+
 
 /* Convert a IEEE754 double (64-bit) into an x87 extended double
    (80-bit), mimicing the hardware fairly closely.  Both numbers are
@@ -1114,7 +1199,7 @@ void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
    UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
    UInt       tagw    = x87->env[FP_ENV_TAG];
    UInt       fpucw   = x87->env[FP_ENV_CTRL];
-   UInt       c320    = x87->env[FP_ENV_STAT] & 0x4500;
+   UInt       c3210   = x87->env[FP_ENV_STAT] & 0x4700;
 
    /* Copy registers and tags */
    for (r = 0; r < 8; r++) {
@@ -1137,7 +1222,7 @@ void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
    *(UInt*)(vex_state + OFFB_FPUCW) = fpucw;
 
    /* status word */
-   *(UInt*)(vex_state + OFFB_FC320) = c320;
+   *(UInt*)(vex_state + OFFB_FC3210) = c3210;
 }
 
 
@@ -1150,14 +1235,14 @@ void vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
    UChar*     vexTags = (UChar*)(vex_state + OFFB_FTAG0);
    Fpu_State* x87     = (Fpu_State*)x87_state;
    UInt       ftop    = *(UInt*)(vex_state + OFFB_FTOP);
-   UInt       c320    = *(UInt*)(vex_state + OFFB_FC320);
+   UInt       c3210   = *(UInt*)(vex_state + OFFB_FC3210);
 
    for (i = 0; i < 14; i++)
       x87->env[i] = 0;
 
    x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
    x87->env[FP_ENV_CTRL] = (UShort)( *(UInt*)(vex_state + OFFB_FPUCW) );
-   x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c320 & 0x4500);
+   x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
 
    tagw = 0;
    for (r = 0; r < 8; r++) {
index b11605f86af28be15df0d1c76ef4d732e261bd07..d31593ddb5d0796ba01a4319135f07a2404e584a 100644 (file)
@@ -3099,16 +3099,16 @@ static void put_ftop ( IRExpr* e )
    stmt( IRStmt_Put( OFFB_FTOP, e ) );
 }
 
-/* --------- Get/set the C320 bits of the control word. --------- */
+/* --------- Get/set the C3210 bits of the control word. --------- */
 
-static IRExpr* get_C320 ( void )
+static IRExpr* get_C3210 ( void )
 {
-   return IRExpr_Get( OFFB_FC320, Ity_I32 );
+   return IRExpr_Get( OFFB_FC3210, Ity_I32 );
 }
 
-static void put_C320 ( IRExpr* e )
+static void put_C3210 ( IRExpr* e )
 {
-   stmt( IRStmt_Put( OFFB_FC320, e ) );
+   stmt( IRStmt_Put( OFFB_FC3210, e ) );
 }
 
 /* --------- Get/set the FPU control word. --------- */
@@ -3239,6 +3239,12 @@ static IRExpr* get_ST_UNCHECKED ( Int i )
       IRExpr_GetI( off_ST(i), Ity_F64, OFFB_F0, OFFB_F7+8-1 );
 }
 
+static IRExpr* get_ST_UNCHECKED_as_ULong ( Int i )
+{
+   return
+      IRExpr_GetI( off_ST(i), Ity_I64, OFFB_F0, OFFB_F7+8-1 );
+}
+
 /* Given i, generate an expression yielding 
   is_full(i) ? ST(i) : NaN
 */
@@ -3506,6 +3512,22 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                put_ST_UNCHECKED(0, unop(Iop_NegF64, 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.
+                 Here, just pass both the tag (in our format) and the
+                 value (as a double, actually a ULong) to a helper
+                 function. */
+              IRExpr** args;
+              DIP("fxam");
+              args = LibVEX_Alloc(3 * sizeof(IRExpr*));
+              args[0] = unop(Iop_8Uto32, get_ST_TAG(0));
+              args[1] = get_ST_UNCHECKED_as_ULong(0);
+              args[2] = NULL;
+              put_C3210(IRExpr_CCall("calculate_FXAM", Ity_I32, args));
+              break;
+           }
+
            case 0xE8: /* FLD1 */
                DIP("fld1");
                fp_push();
@@ -3537,6 +3559,11 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                fp_pop();
                break;
 
+            case 0xFA: /* FSQRT */
+               DIP("fsqrt\n");
+               put_ST_UNCHECKED(0, unop(Iop_SqrtF64, get_ST(0)));
+               break;
+
             case 0xFE: /* FSIN */
                DIP("fsin\n");
                put_ST_UNCHECKED(0, unop(Iop_SinF64, get_ST(0)));
@@ -3615,9 +3642,14 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
 
             case 0xE9: /* FUCOMPP %st(0),%st(1) */
                DIP("fucompp %%st(0),%%st(1)\n");
-               put_C320( binop(Iop_Shl32, 
-                               binop(Iop_CmpF64, get_ST(0), get_ST(1)),
-                               mkU8(8)) );
+               /* This forces C1 to zero, which isn't right. */
+               put_C3210( 
+                   binop( Iop_And32,
+                          binop(Iop_Shl32, 
+                                binop(Iop_CmpF64, get_ST(0), get_ST(1)),
+                                mkU8(8)),
+                          mkU32(0x4500)
+                   ));
                fp_pop();
                fp_pop();
                break;
@@ -3790,17 +3822,27 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
             case 0xE0 ... 0xE7: /* FUCOM %st(0),%st(?) */
                r_dst = (UInt)modrm - 0xE0;
                DIP("fucom %%st(0),%%st(%d)\n", r_dst);
-               put_C320( binop(Iop_Shl32, 
-                               binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
-                               mkU8(8)) );
+               /* This forces C1 to zero, which isn't right. */
+               put_C3210( 
+                   binop( Iop_And32,
+                          binop(Iop_Shl32, 
+                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+                                mkU8(8)),
+                          mkU32(0x4500)
+                   ));
                break;
 
             case 0xE8 ... 0xEF: /* FUCOMP %st(0),%st(?) */
                r_dst = (UInt)modrm - 0xE8;
                DIP("fucomp %%st(0),%%st(%d)\n", r_dst);
-               put_C320( binop(Iop_Shl32, 
-                               binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
-                               mkU8(8)) );
+               /* This forces C1 to zero, which isn't right. */
+               put_C3210( 
+                   binop( Iop_And32,
+                          binop(Iop_Shl32, 
+                                binop(Iop_CmpF64, get_ST(0), get_ST(r_dst)),
+                                mkU8(8)),
+                          mkU32(0x4500)
+                   ));
                fp_pop();
                break;
 
@@ -3902,7 +3944,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                DIP("fnstsw %%ax\n");
                /* Invent a plausible-looking FPU status word value and
                   dump it in %AX:
-                     ((ftop & 7) << 11) | (c320 & 0x4500)
+                     ((ftop & 7) << 11) | (c3210 & 0x4700)
                */
                putIReg(2, R_EAX,
                   unop(Iop_32to16,
@@ -3910,7 +3952,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                              binop(Iop_Shl32, 
                                    binop(Iop_And32, get_ftop(), mkU32(7)), 
                                    mkU8(11)),
-                             binop(Iop_And32, get_C320(), mkU32(0x4500))
+                             binop(Iop_And32, get_C3210(), mkU32(0x4700))
                )));
                break;
 
@@ -7944,6 +7986,7 @@ static UInt disInstr ( UInt delta, Bool* isEnd )
       /* According to the Intel manual, "repne movs" should never occur, but
        * in practice it has happened, so allow for it here... */
       case 0xA4: sz = 1;   /* REPNE MOVS<sz> */
+       vassert(0);
 //--       case 0xA5: 
        //         dis_REP_op ( CondNZ, dis_MOVS, sz, eip_orig,
        //                              guest_eip+delta, "repne movs" );
index e5254fc6d932c4025e3c660b561df01608e2c5a3..09f72fb61aa93f2d9be8958b41fc36bbe66699bb 100644 (file)
@@ -1259,6 +1259,7 @@ static UChar* do_fop1_st ( UChar* p, X86FpOp op )
 {
    switch (op) {
       case Xfp_NEGATE: *p++ = 0xD9; *p++ = 0xE0; break;
+      case Xfp_SQRT:   *p++ = 0xD9; *p++ = 0xFA; break;
       case Xfp_SIN:    *p++ = 0xD9; *p++ = 0xFE; break;
       case Xfp_COS:    *p++ = 0xD9; *p++ = 0xFF; break;
       default: vpanic("do_fop1_st: unknown op");
index 7f68ae4ac79e01fd6d6073fed4020025d6267d2f..e9298c4e205006f974a2c2a928a580334812c826 100644 (file)
@@ -736,24 +736,39 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
    /* --------- CCALL --------- */
    case Iex_CCall: {
       Addr64 helper;
-      Int    i, nargs;
-      UInt   target;
+      Int     i, n_args, n_arg_ws;
+      UInt    target;
       IRExpr* arg;
+      IRType  arg_ty;
       HReg    dst = newVRegI(env);
       vassert(ty == Ity_I32);
-      /* be very restrictive for now.  Only 32-bit ints allowed
-         for args and return type. */
+
+      /* be very restrictive for now.  Only 32/64-bit ints allowed
+         for args, and 32 bits for return type. */
       if (e->Iex.CCall.retty != Ity_I32)
          goto irreducible;
+
       /* push args on the stack, right to left. */
-      nargs = 0;
-      while (e->Iex.CCall.args[nargs]) nargs++;
-      for (i = nargs-1; i >= 0; i--) {
-         arg = e->Iex.CCall.args[i];
-         if (typeOfIRExpr(env->type_env,arg) != Ity_I32)
-            goto irreducible;
-         addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
+      n_arg_ws = n_args = 0;
+      while (e->Iex.CCall.args[n_args]) n_args++;
+
+      for (i = n_args-1; i >= 0; i--) {
+         arg    = e->Iex.CCall.args[i];
+         arg_ty = typeOfIRExpr(env->type_env, arg);
+         if (arg_ty == Ity_I32) {
+            addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
+            n_arg_ws ++;
+        } else 
+         if (arg_ty == Ity_I64) {
+            HReg rHi, rLo;
+            iselIntExpr64(&rHi, &rLo, env, arg);
+            addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
+            addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
+            n_arg_ws += 2;
+         }
+         else goto irreducible;
       }
+
       /* Find the function to call.  Since the host -- for which we
          are generating code -- is a 32-bit machine (x86) -- the upper
          32 bit of the helper address should be zero. */
@@ -765,9 +780,9 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
                        X86RMI_Imm(target),
                        hregX86_EAX()));
       addInstr(env, X86Instr_Call(hregX86_EAX()));
-      if (nargs > 0)
+      if (n_arg_ws > 0)
          addInstr(env, X86Instr_Alu32R(Xalu_ADD,
-                          X86RMI_Imm(4*nargs),
+                          X86RMI_Imm(4*n_arg_ws),
                           hregX86_ESP()));
       addInstr(env, mk_MOVsd_RR(hregX86_EAX(), dst));
       return dst;
@@ -1370,7 +1385,6 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
       HReg rf   = iselDblExpr(env, e->Iex.Binop.arg2);
       HReg rrm  = iselIntExpr_R(env, e->Iex.Binop.arg1);
       HReg rrm2 = newVRegI(env);
-      HReg dst  = newVRegI(env);
       HReg tLo  = newVRegI(env);
       HReg tHi  = newVRegI(env);
 
@@ -1428,7 +1442,33 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
 
       *rHi = tHi;
       *rLo = tLo;
-      return dst;
+      return;
+   }
+
+   if (e->tag == Iex_GetI) {
+      /* First off, compute the index expression into an integer reg.
+         The referenced address will then be 0 + ebp + reg*1, that is,
+         an X86AMode_IRRS. */
+      vassert(e->Iex.GetI.ty == Ity_I64);
+      HReg tLo = newVRegI(env);
+      HReg tHi = newVRegI(env);
+      HReg idx = iselIntExpr_R(env, e->Iex.GetI.offset);
+
+      /* This (x86) is a little-endian target.  The front end will
+        have laid out the baseblock in accordance with the back-end's
+        endianness, so this hardwired assumption here that the 64-bit
+        value is stored little-endian is OK. */
+      addInstr(env, X86Instr_Alu32R(
+                       Xalu_MOV, 
+                       X86RMI_Mem(X86AMode_IRRS(0, hregX86_EBP(), idx, 0)), 
+                       tLo));
+      addInstr(env, X86Instr_Alu32R(
+                       Xalu_MOV, 
+                       X86RMI_Mem(X86AMode_IRRS(4, hregX86_EBP(), idx, 0)), 
+                       tHi));
+      *rHi = tHi;
+      *rLo = tLo;
+      return;
    }
 
    ppIRExpr(e);
@@ -1577,9 +1617,10 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
    if (e->tag == Iex_Unop) {
       X86FpOp fpop = Xfp_INVALID;
       switch (e->Iex.Unop.op) {
-         case Iop_NegF64: fpop = Xfp_NEGATE; break;
-         case Iop_SinF64: fpop = Xfp_SIN; break;
-         case Iop_CosF64: fpop = Xfp_COS; break;
+         case Iop_NegF64:  fpop = Xfp_NEGATE; break;
+         case Iop_SqrtF64: fpop = Xfp_SQRT; break;
+         case Iop_SinF64:  fpop = Xfp_SIN; break;
+         case Iop_CosF64:  fpop = Xfp_COS; break;
          default: break;
       }
       if (fpop != Xfp_INVALID) {
index c52c4eb3429782381c1125e776827704d7b950a2..4570f1b4c4653bfe43e69a084ea60c3f5444cc1b 100644 (file)
@@ -136,6 +136,7 @@ void ppIROp ( IROp op )
       case Iop_DivF64:    vex_printf("DivF64"); return;
       case Iop_CmpF64:    vex_printf("CmpF64"); return;
       case Iop_NegF64:    vex_printf("NegF64"); return;
+      case Iop_SqrtF64:   vex_printf("SqrtF64"); return;
       case Iop_SinF64:    vex_printf("SinF64"); return;
       case Iop_CosF64:    vex_printf("CosF64"); return;
 
@@ -635,7 +636,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
          BINARY(Ity_F64,Ity_F64,Ity_F64);
       case Iop_CmpF64:
          BINARY(Ity_I32,Ity_F64,Ity_F64);
-      case Iop_NegF64: case Iop_SinF64: case Iop_CosF64:
+      case Iop_NegF64: case Iop_SqrtF64: case Iop_SinF64: case Iop_CosF64:
          UNARY(Ity_F64,Ity_F64);
 
       case Iop_I32toF64: UNARY(Ity_F64,Ity_I32);