From: Julian Seward Date: Mon, 26 Jul 2004 22:39:11 +0000 (+0000) Subject: Fix enough bits and pieces so "int main (void) { return 0; }" works. X-Git-Tag: svn/VALGRIND_3_0_1^2~1204 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=282c0efa61bcfb87b6b726ab17e60e946496ea8f;p=thirdparty%2Fvalgrind.git Fix enough bits and pieces so "int main (void) { return 0; }" works. git-svn-id: svn://svn.valgrind.org/vex/trunk@130 --- diff --git a/VEX/priv/guest-x86/x86helpers.c b/VEX/priv/guest-x86/x86helpers.c index cf21b37794..f37ae8a7f2 100644 --- a/VEX/priv/guest-x86/x86helpers.c +++ b/VEX/priv/guest-x86/x86helpers.c @@ -160,9 +160,25 @@ static inline int lshift(int x, int n) return cf | pf | af | zf | sf | of; \ } +#define ACTIONS_INC(DATA_BITS,DATA_TYPE,DATA_STYPE) \ +{ \ + PREAMBLE(DATA_BITS); \ + int cf, pf, af, zf, sf, of; \ + int src1, src2; \ + src1 = CC_DST - 1; \ + src2 = 1; \ + cf = CC_SRC; \ + pf = parity_table[(uint8_t)CC_DST]; \ + af = (CC_DST ^ src1 ^ src2) & 0x10; \ + zf = ((DATA_TYPE)CC_DST == 0) << 6; \ + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; \ + of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11; \ + return cf | pf | af | zf | sf | of; \ +} + #define ACTIONS_DEC(DATA_BITS,DATA_TYPE,DATA_STYPE) \ { \ - PREAMBLE(DATA_BITS); \ + PREAMBLE(DATA_BITS); \ int cf, pf, af, zf, sf, of; \ int src1, src2; \ src1 = CC_DST + 1; \ @@ -189,11 +205,14 @@ static inline int lshift(int x, int n) case CC_OP_ADDL: ACTIONS_ADD(32,UInt,Int); case CC_OP_SUBB: ACTIONS_SUB(8,UChar,Char); + case CC_OP_SUBW: ACTIONS_SUB(16,UShort,Short); case CC_OP_SUBL: ACTIONS_SUB(32,UInt,Int); case CC_OP_LOGICB: ACTIONS_LOGIC(8,UChar,Char); case CC_OP_LOGICL: ACTIONS_LOGIC(32,UInt,Int); + case CC_OP_INCL: ACTIONS_INC(32,UInt,Int); + case CC_OP_DECL: ACTIONS_DEC(32,UInt,Int); case CC_OP_SHLL: ACTIONS_SHL(32,UInt,Int); diff --git a/VEX/priv/guest-x86/x86toIR.c b/VEX/priv/guest-x86/x86toIR.c index c95cfe32ca..8805a21715 100644 --- a/VEX/priv/guest-x86/x86toIR.c +++ b/VEX/priv/guest-x86/x86toIR.c @@ -433,7 +433,7 @@ static void setFlags_SRC_DST1 ( IROp op8, /* This is for shl/shr/sar, where we store the result value and the result except shifted one bit less. And then only when the guard - says we can. */ + is non-zero. */ static void setFlags_DSTus_DST1 ( IROp op8, IRTemp dstUS, @@ -1988,6 +1988,27 @@ UInt dis_Grp1 ( UChar sorb, /* Group 2 extended opcodes. shift_expr must be an 8-bit typed expression. */ +/* Generate specialised inline versions of this function: + static inline int lshift(int x, int n) + { + if (n >= 0) + return x << n; + else + return x >> (-n); + } +*/ +static IRExpr* mkLShift ( IRType ty, IRExpr* e, Int shift ) +{ + if (shift > 0) + /* left */ + return binop(mkSizedOp(ty,Iop_Shl8), e, mkU8(shift)); + if (shift < 0) + /* right */ + return binop(mkSizedOp(ty,Iop_Sar8), e, mkU8(-shift)); + /* shift == 0 */ + return e; +} + static UInt dis_Grp2 ( UChar sorb, UInt delta, UChar modrm, @@ -1998,7 +2019,7 @@ UInt dis_Grp2 ( UChar sorb, UChar dis_buf[50]; Int len; IROp op8; - Bool isShift; + Bool isShift, isRotate; IRType ty = szToITy(sz); IRTemp dst0 = newTemp(ty); IRTemp dst1 = newTemp(ty); @@ -2029,11 +2050,13 @@ UInt dis_Grp2 ( UChar sorb, isShift = False; switch (gregOfRM(modrm)) { case 4: case 5: case 7: isShift = True; } + isRotate = False; + switch (gregOfRM(modrm)) { case 0: case 1: isRotate = True; } + if (isShift) { IRTemp subshift = newTemp(ty); IRTemp shift_amt = newTemp(Ity_I8); - // IRTemp guard = newTemp(Ity_Bit); switch (gregOfRM(modrm)) { case 4: op8 = Iop_Shl8; break; @@ -2056,15 +2079,90 @@ UInt dis_Grp2 ( UChar sorb, binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)), mkU8(8*sz-1)))); - /* guard = (shift_amt != 0) */ - // assign(guard, binop(Iop_CmpNE8, - // mkexpr(shift_amt), mkU8(0))); /* Build the flags thunk. */ setFlags_DSTus_DST1(op8, subshift, dst1, ty, shift_amt); - } else { - /* Rotate */ - vpanic("dis_Grp2: rotate"); + } + else + + if (isRotate) { + vassert(0); +#if 0 + Bool left = gregOfRM(modrm) == 0; + IRTemp rot_amt = newTemp(Ity_I8); + IRTemp flags1 = newTemp(Ity_I32), + flags2 = newTemp(Ity_I32), + flags3 = newTemp(Ity_I32); + + /* rot_amt = shift_expr & mask */ + assign(rot_amt, binop(Iop_And8, + shift_expr, mkU8(8*sz-1))); + + if (left) { + /* dst1 = (dst0 << rot_amt) | (dst0 >>u (wordsize-rot_amt)) */ + assign(dst1, + binop( mkSizedOp(ty,Iop_Or8), + binop( mkSizedOp(ty,Iop_Shl8), + mkexpr(dst0), + mkexpr(rot_amt) + ), + binop( mkSizedOp(ty,Iop_Shr8), + mkexpr(dst0), + binop(Iop_Sub8,mkU8(8*sz), mkexpr(rot_amt)) + ) + ) + ); + + /* dst1 now holds the rotated value. Figure out new flags. */ + /* Get old flags and clear C and O bits. */ + /* flags1 = compute_flags & ~(CC_O | CC_C) */ + assign(flags1, binop( Iop_And32, + mk_calculate_eflags_all(), + mkU32(~(CC_MASK_O | CC_MASK_C)))); + + /* Copy in C bit from lowest bit of result. */ + /* flags2 = flags1 | (dst1 & CC_MASK_C) */ + assign(flags2, + binop( Iop_Or32, + mkexpr(flags1), + binop(Iop_And32, mkexpr(dst1), mkU32(CC_MASK_C)))); + + /* Set the O bit by mysterious means. */ + assign(flags3, + binop( Iop_Or32, + mkexpr(flags2), + binop( Iop_And32, + mkLShift(ty, binop( mkSizedOp(ty,Iop_Xor8), + mkexpr(dst0), + mkexpr(dst1) + ), + 11 - (8*sz - 1) + ), + mkU32(CC_MASK_O) + ) + ) + ); + + /* Rebuild the thunk, if the rotate-amount is non-zero */ + stmt( IRStmt_Put( + OFFB_CC_OP, + IRExpr_Mux0X( mkexpr(rot_amt), + IRExpr_Get(OFFB_CC_OP,Ity_I32), + mkU32(CC_OP_COPY))) ); + stmt( IRStmt_Put( + OFFB_CC_SRC, + IRExpr_Mux0X( mkexpr(rot_amt), + IRExpr_Get(OFFB_CC_SRC,Ity_I32), + mkexpr(flags3))) ); + stmt( IRStmt_Put( + OFFB_CC_DST, + IRExpr_Mux0X( mkexpr(rot_amt), + IRExpr_Get(OFFB_CC_DST,Ity_I32), + mkU32(0))) ); + } else { /* !left */ + vassert(0); + } + #endif } /* Save result, and finish up. */ @@ -4510,32 +4608,31 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) DIP("\t0x%x: ", guest_eip+delta); -//-- /* Spot the client-request magic sequence. */ -//-- { -//-- UChar* myeip = (UChar*)eip; -//-- /* Spot this: -//-- C1C01D roll $29, %eax -//-- C1C003 roll $3, %eax -//-- C1C81B rorl $27, %eax -//-- C1C805 rorl $5, %eax -//-- C1C00D roll $13, %eax -//-- C1C013 roll $19, %eax -//-- */ -//-- if (myeip[ 0] == 0xC1 && myeip[ 1] == 0xC0 && myeip[ 2] == 0x1D && -//-- myeip[ 3] == 0xC1 && myeip[ 4] == 0xC0 && myeip[ 5] == 0x03 && -//-- myeip[ 6] == 0xC1 && myeip[ 7] == 0xC8 && myeip[ 8] == 0x1B && -//-- myeip[ 9] == 0xC1 && myeip[10] == 0xC8 && myeip[11] == 0x05 && -//-- myeip[12] == 0xC1 && myeip[13] == 0xC0 && myeip[14] == 0x0D && -//-- myeip[15] == 0xC1 && myeip[16] == 0xC0 && myeip[17] == 0x13 -//-- ) { -//-- eip += 18; -//-- jmp_lit(cb, eip); -//-- LAST_UINSTR(cb).jmpkind = JmpClientReq; -//-- *isEnd = True; -//-- DIP("%%edx = client_request ( %%eax )\n"); -//-- return eip; -//-- } -//-- } + /* Spot the client-request magic sequence. */ + { + UChar* code = (UChar*)(guest_code + delta); + /* Spot this: + C1C01D roll $29, %eax + C1C003 roll $3, %eax + C1C81B rorl $27, %eax + C1C805 rorl $5, %eax + C1C00D roll $13, %eax + C1C013 roll $19, %eax + */ + if (code[ 0] == 0xC1 && code[ 1] == 0xC0 && code[ 2] == 0x1D && + code[ 3] == 0xC1 && code[ 4] == 0xC0 && code[ 5] == 0x03 && + code[ 6] == 0xC1 && code[ 7] == 0xC8 && code[ 8] == 0x1B && + code[ 9] == 0xC1 && code[10] == 0xC8 && code[11] == 0x05 && + code[12] == 0xC1 && code[13] == 0xC0 && code[14] == 0x0D && + code[15] == 0xC1 && code[16] == 0xC0 && code[17] == 0x13 + ) { + delta += 18; + jmp_lit(Ijk_ClientReq, guest_eip+delta); + *isEnd = True; + DIP("%%edx = client_request ( %%eax )\n"); + return delta; + } + } /* Skip a LOCK prefix. */ if (getIByte(delta) == 0xF0) { @@ -6268,17 +6365,15 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) //-- case 0xA2: /* MOV AL,Ob */ //-- sz = 1; //-- /* Fall through ... */ -//-- case 0xA3: /* MOV eAX,Ov */ -//-- d32 = getUDisp32(eip); eip += 4; -//-- t1 = newTemp(cb); t2 = newTemp(cb); -//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1); -//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2); -//-- uLiteral(cb, d32); -//-- handleSegOverride(cb, sorb, t2); -//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2); -//-- DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX), -//-- sorbTxt(sorb), d32); -//-- break; + case 0xA3: /* MOV eAX,Ov */ + d32 = getUDisp32(delta); delta += 4; + ty = szToITy(sz); + addr = newTemp(Ity_I32); + assign( addr, handleSegOverride(sorb, mkU32(d32)) ); + storeLE( mkexpr(addr), getIReg(sz,R_EAX) ); + DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX), + sorbTxt(sorb), d32); + break; #if 0 case 0xB0: /* MOV imm,AL */ @@ -7382,15 +7477,10 @@ static UInt disInstr ( UInt delta, Bool* isEnd ) DIP("set%s %s\n", name_Condcode(opc-0x90), nameIReg(1,eregOfRM(modrm))); } else { - vassert(0); -//-- pair = disAMode ( cb, sorb, eip, dis_buf ); -//-- t2 = LOW24(pair); -//-- eip += HI8(pair); -//-- uInstr1(cb, CC2VAL, 1, TempReg, t1); -//-- uCond(cb, (Condcode)(opc-0x90)); -//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty); -//-- uInstr2(cb, STORE, 1, TempReg, t1, TempReg, t2); -//-- DIP("set%s %s\n", VG_(name_UCondcode)(opc-0x90), dis_buf); + addr = disAMode ( &alen, sorb, delta, dis_buf ); + delta += alen; + storeLE( mkexpr(addr), mkexpr(t1) ); + DIP("set%s %s\n", name_Condcode(opc-0x90), dis_buf); } break; diff --git a/VEX/priv/host-x86/isel_x86.c b/VEX/priv/host-x86/isel_x86.c index 5ae49d0b10..34c0937b38 100644 --- a/VEX/priv/host-x86/isel_x86.c +++ b/VEX/priv/host-x86/isel_x86.c @@ -290,7 +290,7 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) case Iop_And8: case Iop_And16: case Iop_And32: aluOp = Xalu_AND; break; - case Iop_Or8: case Iop_Or32: + case Iop_Or8: case Iop_Or16: case Iop_Or32: aluOp = Xalu_OR; break; case Iop_Xor8: case Iop_Xor32: @@ -880,7 +880,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value"); dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst)); cc = iselCondCode(env,stmt->Ist.Exit.cond); - addInstr(env, X86Instr_Goto(cc, dst)); + addInstr(env, X86Instr_Goto(Ijk_Boring, cc, dst)); return; } @@ -899,13 +899,14 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) { X86RI* ri; if (vex_verbosity > 0) { - vex_printf("-- goto "); + vex_printf("-- goto {"); + ppIRJumpKind(jk); + vex_printf("} "); ppIRExpr(next); vex_printf("\n"); } - ri = iselIntExpr_RI(env, next); - addInstr(env, X86Instr_Goto(Xcc_ALWAYS,ri)); + addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri)); } diff --git a/VEX/priv/host-x86/x86host_defs.c b/VEX/priv/host-x86/x86host_defs.c index fa2274012d..c72416e9d4 100644 --- a/VEX/priv/host-x86/x86host_defs.c +++ b/VEX/priv/host-x86/x86host_defs.c @@ -476,11 +476,14 @@ X86Instr* X86Instr_Call ( HReg target ) { i->Xin.Call.target = target; return i; } -X86Instr* X86Instr_Goto ( X86CondCode cond, X86RI* dst ) { +X86Instr* X86Instr_Goto ( IRJumpKind jk, X86CondCode cond, X86RI* dst ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_Goto; i->Xin.Goto.cond = cond; i->Xin.Goto.dst = dst; + i->Xin.Goto.jk = jk; + /* non-Boring conditional jumps are not allowed. */ + vassert(jk == Ijk_Boring || cond == Xcc_ALWAYS); return i; } X86Instr* X86Instr_CMov32 ( X86CondCode cond, X86RM* src, HReg dst ) { @@ -577,6 +580,12 @@ void ppX86Instr ( X86Instr* i ) { ppHRegX86(i->Xin.Call.target); break; case Xin_Goto: + if (i->Xin.Goto.jk == Ijk_ClientReq + || i->Xin.Goto.jk == Ijk_Syscall) { + vex_printf("movl $"); + ppIRJumpKind(i->Xin.Goto.jk); + vex_printf(", %%ebp ; "); + } if (i->Xin.Goto.cond == Xcc_ALWAYS) { vex_printf("movl "); ppX86RI(i->Xin.Goto.dst); @@ -678,6 +687,9 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i) case Xin_Goto: addRegUsage_X86RI(u, i->Xin.Goto.dst); addHRegUse(u, HRmWrite, hregX86_EAX()); + if (i->Xin.Goto.jk == Ijk_ClientReq + || i->Xin.Goto.jk == Ijk_Syscall) + addHRegUse(u, HRmWrite, hregX86_EBP()); return; case Xin_CMov32: addRegUsage_X86RM(u, i->Xin.CMov32.src, HRmRead); @@ -944,6 +956,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) UInt opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc; UChar* p = &buf[0]; + UChar* ptmp; vassert(nbuf >= 32); /* Wrap an integer as a int register, for use assembling @@ -962,10 +975,10 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32); goto done; case Xrmi_Reg: - *p++ = 0x89; - p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg, - i->Xin.Alu32R.dst); - goto done; + *p++ = 0x89; + p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg, + i->Xin.Alu32R.dst); + goto done; case Xrmi_Mem: *p++ = 0x8B; p = doAMode_M(p, i->Xin.Alu32R.dst, @@ -1210,6 +1223,26 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) goto done; case Xin_Goto: + /* If a non-boring unconditional jump, set %ebp appropriately. + The magic numbers here have to match those defined in + vg_constants.h. */ + if (i->Xin.Goto.cond == Xcc_ALWAYS + && (i->Xin.Goto.jk == Ijk_ClientReq + || i->Xin.Goto.jk == Ijk_Syscall)) { + /* movl $magic_number, %ebp */ + *p++ = 0xBD; + switch (i->Xin.Goto.jk) { + case Ijk_ClientReq: + /* 23 == VG_TRC_EBP_JMP_CLIENTREQ */ + p = emit32(p, 23); break; + case Ijk_Syscall: + /* 19 == VG_TRC_EBP_JMP_SYSCALL */ + p = emit32(p, 19); break; + default: + ppIRJumpKind(i->Xin.Goto.jk); + vpanic("emit_X86Instr.Xin_Goto: unknown jump kind"); + } + } /* unconditional jump to immediate */ if (i->Xin.Goto.cond == Xcc_ALWAYS && i->Xin.Goto.dst->tag == Xri_Imm) { @@ -1233,6 +1266,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) /* conditional jump to immediate */ if (i->Xin.Goto.cond != Xcc_ALWAYS && i->Xin.Goto.dst->tag == Xri_Imm) { + vassert(i->Xin.Goto.jk == Ijk_Boring); /* jmp fwds if !condition */ *p++ = 0x70 + (i->Xin.Goto.cond ^ 1); *p++ = 6; /* # of bytes in the next bit */ @@ -1246,6 +1280,8 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) case Xin_CMov32: vassert(i->Xin.CMov32.cond != Xcc_ALWAYS); +#if 0 + /* This generates cmov, which is illegal on P5. */ *p++ = 0x0F; *p++ = 0x40 + i->Xin.CMov32.cond; if (i->Xin.CMov32.src->tag == Xrm_Reg) { @@ -1256,6 +1292,33 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) p = doAMode_M(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Mem.am); goto done; } +#else + /* P5 friendly version: conditional jump over an unconditional + move. */ + /* jmp fwds if !condition */ + *p++ = 0x70 + (i->Xin.CMov32.cond ^ 1); + *p++ = 0; /* # of bytes in the next bit, which we don't know yet */ + ptmp = p; + + switch (i->Xin.CMov32.src->tag) { + case Xrm_Reg: + vassert(0); // waiting for test case + *p++ = 0x89; + p = doAMode_R(p, i->Xin.CMov32.src->Xrm.Reg.reg, + i->Xin.CMov32.dst); + break; + case Xrm_Mem: + *p++ = 0x8B; + p = doAMode_M(p, i->Xin.CMov32.dst, + i->Xin.CMov32.src->Xrm.Mem.am); + break; + default: + goto bad; + } + /* Fill in the jump offset. */ + *(ptmp-1) = p - ptmp; + goto done; +#endif break; case Xin_LoadEX: diff --git a/VEX/priv/host-x86/x86host_defs.h b/VEX/priv/host-x86/x86host_defs.h index 0801377006..76924117c0 100644 --- a/VEX/priv/host-x86/x86host_defs.h +++ b/VEX/priv/host-x86/x86host_defs.h @@ -318,8 +318,12 @@ typedef HReg target; } Call; /* Pseudo-insn. Goto dst, on given condition (which could be - Xcc_ALWAYS). */ + Xcc_ALWAYS). Note importantly that if the jump is + conditional (not Xcc_ALWAYS) the jump kind *must* be + Ijk_Boring. Ie non-Boring conditional jumps are + not allowed. */ struct { + IRJumpKind jk; X86CondCode cond; X86RI* dst; } Goto; @@ -358,7 +362,7 @@ extern X86Instr* X86Instr_Div ( Bool syned, X86ScalarSz, X86RM* ); extern X86Instr* X86Instr_Sh3232 ( X86ShiftOp, UInt amt, HReg rHi, HReg rLo ); extern X86Instr* X86Instr_Push ( X86RMI* ); extern X86Instr* X86Instr_Call ( HReg ); -extern X86Instr* X86Instr_Goto ( X86CondCode cond, X86RI* dst ); +extern X86Instr* X86Instr_Goto ( IRJumpKind, X86CondCode cond, X86RI* dst ); extern X86Instr* X86Instr_CMov32 ( X86CondCode, X86RM* src, HReg dst ); extern X86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned, X86AMode* src, HReg dst ); diff --git a/VEX/test_main.c b/VEX/test_main.c index 75ba22434d..61e03f5ef9 100644 --- a/VEX/test_main.c +++ b/VEX/test_main.c @@ -65,7 +65,7 @@ int main ( int argc, char** argv ) LibVEX_Init ( &failure_exit, &log_bytes, 1, /* debug_paranoia */ - 1, /* verbosity */ + 0, /* verbosity */ //False, True, 100 );