From: Julian Seward Date: Sat, 11 Sep 2004 19:43:51 +0000 (+0000) Subject: x86: handle divw/idivw. Needs proper testing. X-Git-Tag: svn/VALGRIND_3_0_1^2~1075 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c47c244e9158c65ed253859c7175f22858fa47cf;p=thirdparty%2Fvalgrind.git x86: handle divw/idivw. Needs proper testing. git-svn-id: svn://svn.valgrind.org/vex/trunk@259 --- diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 79edaa7dc5..53c8bf5031 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -11,6 +11,7 @@ is Iop_Neg* used? MOVAPS fix (vg_to_ucode rev 1.143) check flag settings for cmpxchg + check 16/8 bit div/idiv FUCOMI(P): what happens to A and S flags? Currently are forced to zero. */ @@ -1999,17 +2000,27 @@ UInt dis_movx_E_G ( UChar sorb, static void codegen_div ( Int sz, IRTemp t, Bool signed_divide ) { + IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32; + IRTemp src64 = newTemp(Ity_I64); + IRTemp dst64 = newTemp(Ity_I64); switch (sz) { - case 4: { - IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32; - IRTemp src64 = newTemp(Ity_I64); - IRTemp dst64 = newTemp(Ity_I64); + case 4: assign( src64, binop(Iop_32HLto64, - getIReg(4,R_EDX), getIReg(4,R_EAX)) ); + getIReg(4,R_EDX), getIReg(4,R_EAX)) ); assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) ); putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) ); putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) ); break; + case 2: { + IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64; + IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32; + assign( src64, unop(widen3264, + binop(Iop_16HLto32, + getIReg(2,R_EDX), getIReg(2,R_EAX))) ); + assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) ); + putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) ); + putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) ); + break; } default: vpanic("codegen_div(x86)"); } diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 5092001602..eb406cb3c5 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -1305,6 +1305,19 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) return; } + /* 32Uto64(e) */ + if (e->tag == Iex_Unop + && e->Iex.Unop.op == Iop_32Uto64) { + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); + addInstr(env, mk_MOVsd_RR(src,tLo)); + addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi)); + *rHi = tHi; + *rLo = tLo; + return; + } + /* 64-bit shifts */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Shl64) { diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 1b369a1505..0549ced439 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -94,6 +94,7 @@ void ppIROp ( IROp op ) case Iop_8Sto32: vex_printf("8Sto32"); return; case Iop_16Sto32: vex_printf("16Sto32"); return; case Iop_32Sto64: vex_printf("32Sto64"); return; + case Iop_32Uto64: vex_printf("32Uto64"); return; case Iop_32to8: vex_printf("32to8"); return; case Iop_32to1: vex_printf("32to1"); return; case Iop_1Uto8: vex_printf("1Uto8"); return; @@ -636,6 +637,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_16Uto32: UNARY(Ity_I32,Ity_I16); case Iop_16Sto32: UNARY(Ity_I32,Ity_I16); case Iop_32Sto64: UNARY(Ity_I64,Ity_I32); + case Iop_32Uto64: UNARY(Ity_I64,Ity_I32); case Iop_32to8: UNARY(Ity_I8,Ity_I32); case Iop_PRemF64: diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 60487245e8..6d78e05c27 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -136,7 +136,7 @@ typedef // of which lo half is div and hi half is mod Iop_DivModS64to32, // ditto, signed /* Widening conversions */ - Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, + Iop_8Uto16, Iop_8Uto32, Iop_16Uto32, Iop_32Uto64, Iop_8Sto16, Iop_8Sto32, Iop_16Sto32, Iop_32Sto64, /* Narrowing conversions */ Iop_32to8,