From: Julian Seward Date: Sun, 7 Nov 2004 18:45:15 +0000 (+0000) Subject: x86 code generation for 64-bit integer stuff, required by Memchecking X-Git-Tag: svn/VALGRIND_3_0_1^2~814 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d98dde973905bd7de7fd963c5199f86b6c6cd9bc;p=thirdparty%2Fvalgrind.git x86 code generation for 64-bit integer stuff, required by Memchecking of floating point code. git-svn-id: svn://svn.valgrind.org/vex/trunk@520 --- diff --git a/VEX/priv/host-x86/hdefs.c b/VEX/priv/host-x86/hdefs.c index 93d3b15b63..3b340ab96d 100644 --- a/VEX/priv/host-x86/hdefs.c +++ b/VEX/priv/host-x86/hdefs.c @@ -127,6 +127,18 @@ X86AMode* X86AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) { return am; } +X86AMode* dopyX86AMode ( X86AMode* am ) { + switch (am->tag) { + case Xam_IR: + return X86AMode_IR( am->Xam.IR.imm, am->Xam.IR.reg ); + case Xam_IRRS: + return X86AMode_IRRS( am->Xam.IRRS.imm, am->Xam.IRRS.base, + am->Xam.IRRS.index, am->Xam.IRRS.shift ); + default: + vpanic("dopyX86AMode"); + } +} + void ppX86AMode ( X86AMode* am ) { switch (am->tag) { case Xam_IR: diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index e0ae524118..c0d2c44365 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -93,6 +93,8 @@ typedef extern X86AMode* X86AMode_IR ( UInt, HReg ); extern X86AMode* X86AMode_IRRS ( UInt, HReg, HReg, Int ); +extern X86AMode* dopyX86AMode ( X86AMode* ); + extern void ppX86AMode ( X86AMode* ); diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index bbf400a405..1e8c89fcf2 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -270,6 +270,19 @@ static X86Instr* mk_MOVsd_RR ( HReg src, HReg dst ) } +/* Given an amode, return one which references 4 bytes further + along. */ + +static X86AMode* advance4 ( X86AMode* am ) +{ + X86AMode* am4 = dopyX86AMode(am); + /* Could also advance the _IR form, but no need yet. */ + vassert(am4->tag == Xam_IRRS); + am4->Xam.IRRS.imm += 4; + return am4; +} + + /* Push an arg onto the host stack, in preparation for a call to a helper function of some kind. Returns the number of 32-bit words pushed. */ @@ -849,6 +862,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) addInstr(env, X86Instr_Set32(cond,dst)); return dst; } + case Iop_1Sto16: case Iop_1Sto32: { /* could do better than this, but for now ... */ HReg dst = newVRegI(env); @@ -916,34 +930,6 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) } case Iex_GetI: { -#if 0 - /* special-case: GetI( Add32(y,const:I32) ):I8 */ - { DECLARE_PATTERN(p_Get_FP_tag); - DEFINE_PATTERN(p_Get_FP_tag, - IRExpr_GetI( - binop(Iop_Add32, bind(0), bind(1)), - Ity_I8,120,127 - ) - ); - if (matchIRExpr(&mi, p_Get_FP_tag, e)) { - /* partial match, but we have to ensure bind(1) is a 32-bit - literal. */ - IRExpr* y = mi.bindee[0]; - IRExpr* c = mi.bindee[1]; - if (c->tag == Iex_Const && c->Iex.Const.con->tag == Ico_U32) { - UInt c32 = c->Iex.Const.con->Ico.U32; - HReg dst = newVRegI(env); - HReg ry = iselIntExpr_R(env, y); - addInstr(env, - X86Instr_LoadEX( - 1, False, - X86AMode_IRRS(c32, hregX86_EBP(), ry, 0), - dst )); - return dst; - } - } - } -#endif X86AMode* am = genGuestArrayOffset( env, e->Iex.GetI.descr, @@ -1429,9 +1415,11 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) /* 64-bit load */ if (e->tag == Iex_LDle) { + /* It would be better to generate the address into an amode and + then do advance4 to get the hi-half address. */ vassert(e->Iex.LDle.ty == Ity_I64); - HReg tLo = newVRegI(env); - HReg tHi = newVRegI(env); + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); HReg rA = iselIntExpr_R(env, e->Iex.LDle.addr); addInstr(env, X86Instr_Alu32R( Xalu_MOV, @@ -1444,6 +1432,41 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) return; } + /* 64-bit GETI */ + if (e->tag == Iex_GetI) { + X86AMode* am + = genGuestArrayOffset( env, e->Iex.GetI.descr, + e->Iex.GetI.ix, e->Iex.GetI.bias ); + X86AMode* am4 = advance4(am); + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo )); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi )); + *rHi = tHi; + *rLo = tLo; + return; + } + + /* 64-bit Mux0X */ + if (e->tag == Iex_Mux0X) { + HReg e0Lo, e0Hi, eXLo, eXHi, r8; + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + iselIntExpr64(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0); + iselIntExpr64(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX); + addInstr(env, mk_MOVsd_RR(eXHi, tHi)); + addInstr(env, mk_MOVsd_RR(eXLo, tLo)); + r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); + addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8))); + /* This assumes the first cmov32 doesn't trash the condition + codes, so they are still available for the second cmov32 */ + addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Hi),tHi)); + addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Lo),tLo)); + *rHi = tHi; + *rLo = tLo; + return; + } + /* 32 x 32 -> 64 multiply */ if (e->tag == Iex_Binop && (e->Iex.Binop.op == Iop_MullU32 @@ -1487,6 +1510,23 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) return; } + /* Iop_Or64 */ + if (e->tag == Iex_Binop + && (e->Iex.Binop.op == Iop_Or64)) { + HReg xLo, xHi, yLo, yHi; + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + iselIntExpr64(&xHi, &xLo, env, e->Iex.Binop.arg1); + addInstr(env, mk_MOVsd_RR(xHi, tHi)); + addInstr(env, mk_MOVsd_RR(xLo, tLo)); + iselIntExpr64(&yHi, &yLo, env, e->Iex.Binop.arg2); + addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yHi), tHi)); + addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yLo), tLo)); + *rHi = tHi; + *rLo = tLo; + return; + } + /* 32HLto64(e1,e2) */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_32HLto64) { @@ -2183,6 +2223,14 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) addInstr(env, X86Instr_Store( 1, r, am )); return; } + if (ty == Ity_I64) { + HReg rHi, rLo; + X86AMode* am4 = advance4(am); + iselIntExpr64(&rHi, &rLo, env, stmt->Ist.PutI.data); + addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am )); + addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 )); + return; + } break; }