From: Julian Seward Date: Fri, 10 Sep 2004 16:17:45 +0000 (+0000) Subject: * x86 guest: instead of just tracking the FPU's C3, C2 and C0 flags, X-Git-Tag: svn/VALGRIND_3_0_1^2~1085 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a7c1857b5d398d2c4fe480c18839293cab795c48;p=thirdparty%2Fvalgrind.git * x86 guest: instead of just tracking the FPU's C3, C2 and C0 flags, also track C1. * x86 guest: handle FXAM instruction git-svn-id: svn://svn.valgrind.org/vex/trunk@249 --- diff --git a/VEX/hacked104/vg_include.h b/VEX/hacked104/vg_include.h index aac53657d7..97f74e974d 100644 --- a/VEX/hacked104/vg_include.h +++ b/VEX/hacked104/vg_include.h @@ -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); diff --git a/VEX/hacked104/vg_main.c b/VEX/hacked104/vg_main.c index ea15e1a124..9d1906476f 100644 --- a/VEX/hacked104/vg_main.c +++ b/VEX/hacked104/vg_main.c @@ -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); diff --git a/VEX/hacked104/vg_scheduler.c b/VEX/hacked104/vg_scheduler.c index ab712c10de..7b4d2e644a 100644 --- a/VEX/hacked104/vg_scheduler.c +++ b/VEX/hacked104/vg_scheduler.c @@ -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; diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 6987dc105e..48fd0c6e51 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -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_FC320 (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) diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index dfb9902095..61272925a2 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -13,6 +13,14 @@ #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++) { diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index b11605f86a..d31593ddb5 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -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 */ + vassert(0); //-- case 0xA5: // dis_REP_op ( CondNZ, dis_MOVS, sz, eip_orig, // guest_eip+delta, "repne movs" ); diff --git a/VEX/priv/host-x86/hdefs.c b/VEX/priv/host-x86/hdefs.c index e5254fc6d9..09f72fb61a 100644 --- a/VEX/priv/host-x86/hdefs.c +++ b/VEX/priv/host-x86/hdefs.c @@ -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"); diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 7f68ae4ac7..e9298c4e20 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -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) { diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index c52c4eb342..4570f1b4c4 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -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);