From: Petar Jovanovic Date: Fri, 19 Apr 2013 12:35:00 +0000 (+0000) Subject: mips: fix endian issues for LWL, LWR, LDR and LDL for mips64 X-Git-Tag: svn/VALGRIND_3_9_0^2~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da0d286e34e7db75d7b60df782572cfc5b391f64;p=thirdparty%2Fvalgrind.git mips: fix endian issues for LWL, LWR, LDR and LDL for mips64 This change: - fixes endian issues for unaligned loads for MIPS64, - (re)moves endian dependencies in guest-to-IR for Iop_ReinterpI32asF32 and Iop_ReinterpI64asF64 to host-mips-isel, - adds minor style changes in the area touched by the code. git-svn-id: svn://svn.valgrind.org/vex/trunk@2709 --- diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index 9c368f4773..62f67f1f98 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -72,6 +72,10 @@ static IRSB *irsb; disInstr_MIPS below. */ static Bool mode64 = False; +/* Define 1.0 in single and double precision. */ +#define ONE_SINGLE 0x3F800000 +#define ONE_DOUBLE 0x3FF0000000000000ULL + /*------------------------------------------------------------*/ /*--- Debugging output ---*/ /*------------------------------------------------------------*/ @@ -1163,13 +1167,8 @@ static IRExpr *getDReg(UInt dregNo) IRTemp t4 = newTemp(Ity_I32); IRTemp t5 = newTemp(Ity_I64); -#if defined (_MIPSEL) assign(t0, getFReg(dregNo)); assign(t1, getFReg(dregNo + 1)); -#elif defined (_MIPSEB) - assign(t0, getFReg(dregNo + 1)); - assign(t1, getFReg(dregNo)); -#endif assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); @@ -1206,13 +1205,8 @@ static void putDReg(UInt dregNo, IRExpr * e) assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1))); assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */ assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */ -#if defined (_MIPSEL) putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5))); putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); -#elif defined (_MIPSEB) - putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t5))); - putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t4))); -#endif } } @@ -1895,7 +1889,7 @@ static Bool dis_instr_branch ( UInt theInstr, DisResult * dres, } /*------------------------------------------------------------*/ -/*--- Disassemble a single instruction ---*/ +/*--- Disassemble a single instruction ---*/ /*------------------------------------------------------------*/ /* Disassemble a single instruction into IR. The instruction is @@ -2360,23 +2354,17 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, IRExpr *rm = get_IR_roundingmode(); putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, unop(Iop_ReinterpI32asF32, - mkU32(0x3F800000)), getLoFromF64(tyF, + mkU32(ONE_SINGLE)), getLoFromF64(tyF, getFReg(fs))))); break; } case 0x11: { /* D */ DIP("recip.d f%d, f%d\n", fd, fs); -#if defined (_MIPSEL) - IRExpr *rm = get_IR_roundingmode(); - putDReg(fd, triop(Iop_DivF64, rm, - unop(Iop_ReinterpI64asF64, - mkU64(0x3FF0000000000000ULL)), getDReg(fs))); -#elif defined (_MIPSEB) IRExpr *rm = get_IR_roundingmode(); + /* putDReg(fd, 1.0/getDreg(fs)); */ putDReg(fd, triop(Iop_DivF64, rm, unop(Iop_ReinterpI64asF64, - mkU64(0x000000003FF00000ULL)), getDReg(fs))); -#endif + mkU64(ONE_DOUBLE)), getDReg(fs))); break; } default: @@ -3239,7 +3227,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("rsqrt.s %d, %d\n", fd, fs); IRExpr *rm = get_IR_roundingmode(); putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, - unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)), + unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)), binop(Iop_SqrtF32, rm, getLoFromF64(tyF, getFReg(fs)))))); break; @@ -3249,7 +3237,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, IRExpr *rm = get_IR_roundingmode(); putDReg(fd, triop(Iop_DivF64, rm, unop(Iop_ReinterpI64asF64, - mkU64(0x3FF0000000000000ULL)), + mkU64(ONE_DOUBLE)), binop(Iop_SqrtF64, rm, getDReg(fs)))); break; } @@ -3615,38 +3603,54 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, break; case 0x22: /* LWL */ - DIP("lwl r%d, %d(r%d)", rt, imm, rs); if (mode64) { /* t1 = addr */ -#if defined (_MIPSEL) t1 = newTemp(Ity_I64); +#if defined (_MIPSEL) assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); + /* t2 = word addr */ + /* t4 = addr mod 4 */ + LWX_SWX_PATTERN64; + + /* t3 = word content - shifted */ + t3 = newTemp(Ity_I32); + assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64, + mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32, + binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3))))); + + /* rt content - adjusted */ + t5 = newTemp(Ity_I32); + assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), + binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, + binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), + mkU8(0x3)))))); + + putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), + mkexpr(t3)), True)); #elif defined (_MIPSEB) - t1 = newTemp(Ity_I64); assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))))); -#endif - /* t2 = word addr */ /* t4 = addr mod 4 */ LWX_SWX_PATTERN64; /* t3 = word content - shifted */ t3 = newTemp(Ity_I32); - assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64, + assign(t3, binop(Iop_Shl32, unop(Iop_64HIto32, load(Ity_I64, mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3))))); - /* rt content - adjusted */ + /* rt content - adjusted */ t5 = newTemp(Ity_I32); - assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), + assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)), binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), mkU8(0x3)))))); putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)), True)); +#endif } else { /* t1 = addr */ t1 = newTemp(Ity_I32); @@ -3658,7 +3662,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, #endif /* t2 = word addr */ - /* t4 = addr mod 4 */ + /* t4 = addr mod 8 */ LWX_SWX_PATTERN; /* t3 = word content - shifted */ @@ -3678,36 +3682,51 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, break; case 0x26: /* LWR */ - DIP("lwr r%d, %d(r%d)", rt, imm, rs); if (mode64) { /* t1 = addr */ -#if defined (_MIPSEL) t1 = newTemp(Ity_I64); +#if defined (_MIPSEL) assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); + /* t2 = word addr */ + /* t4 = addr mod 8 */ + LWX_SWX_PATTERN64; + + /* t3 = word content - shifted */ + t3 = newTemp(Ity_I32); + assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))), + narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3))))); + + /* rt content - adjusted */ + t5 = newTemp(Ity_I32); + assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), + unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF), + narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); + + putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), + mkexpr(t3)), True)); #elif defined (_MIPSEB) - t1 = newTemp(Ity_I64); assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))))); -#endif - /* t2 = word addr */ /* t4 = addr mod 4 */ LWX_SWX_PATTERN64; /* t3 = word content - shifted */ t3 = newTemp(Ity_I32); - assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))), + assign(t3, binop(Iop_Shr32, unop(Iop_64HIto32, load(Ity_I64,mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3))))); /* rt content - adjusted */ t5 = newTemp(Ity_I32); - assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), + assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)), unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), mkexpr(t3)), True)); +#endif + } else { /* t1 = addr */ t1 = newTemp(Ity_I32); @@ -3798,7 +3817,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, #endif /* t2 = word addr */ - /* t4 = addr mod 4 */ + /* t4 = addr mod 8 */ LWX_SWX_PATTERN64_1; /* t3 = rt content - shifted */ @@ -4549,7 +4568,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, } break; case 0x3B: { /* RDHWR */ - DIP("rdhwr r%d, r%d\n", rt, rd); + DIP("rdhwr r%d, r%d", rt, rd); if (rd == 29) { putIReg(rt, getULR()); #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2)) @@ -6102,7 +6121,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, mkU64(extend_s_16to64(imm))))); #endif /* t2 = word addr */ - /* t4 = addr mod 4 */ + /* t4 = addr mod 8 */ LWX_SWX_PATTERN64_1; /* t3 = word content - shifted */ @@ -6138,11 +6157,11 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); #elif defined (_MIPSEB) t1 = newTemp(Ity_I64); - assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs), + assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))))); #endif /* t2 = word addr */ - /* t4 = addr mod 4 */ + /* t4 = addr mod 8 */ LWX_SWX_PATTERN64_1; /* t3 = word content - shifted */ diff --git a/VEX/priv/host_mips_defs.c b/VEX/priv/host_mips_defs.c index 51d41a2acb..cba7f1885a 100644 --- a/VEX/priv/host_mips_defs.c +++ b/VEX/priv/host_mips_defs.c @@ -2734,11 +2734,13 @@ static Bool isLoadImm_EXACTLY2or6 ( UChar* p_to_check, return ret; } -/* Generate a machine-word sized load or store. Simplified version of - the Min_Load and Min_Store cases below. */ -static UChar* do_load_or_store_machine_word ( - UChar* p, Bool isLoad, - UInt reg, MIPSAMode* am, Bool mode64 ) +/* Generate a machine-word sized load or store. Simplified version of + the Min_Load and Min_Store cases below. + This will generate 32-bit load/store on MIPS32, and 64-bit load/store on + MIPS64 platforms. +*/ +static UChar* do_load_or_store_machine_word ( UChar* p, Bool isLoad, UInt reg, + MIPSAMode* am, Bool mode64 ) { if (isLoad) { /* load */ switch (am->tag) { @@ -2778,6 +2780,49 @@ static UChar* do_load_or_store_machine_word ( return p; } +/* Generate a 32-bit sized load or store. Simplified version of + do_load_or_store_machine_word above. */ +static UChar* do_load_or_store_word32 ( UChar* p, Bool isLoad, UInt reg, + MIPSAMode* am, Bool mode64 ) +{ + if (isLoad) { /* load */ + switch (am->tag) { + case Mam_IR: + if (mode64) { + vassert(0 == (am->Mam.IR.index & 3)); + } + p = doAMode_IR(p, 35, reg, am, mode64); + break; + case Mam_RR: + /* we could handle this case, but we don't expect to ever + need to. */ + vassert(0); + break; + default: + vassert(0); + break; + } + } else /* store */ { + switch (am->tag) { + case Mam_IR: + if (mode64) { + vassert(0 == (am->Mam.IR.index & 3)); + } + p = doAMode_IR(p, 43, reg, am, mode64); + break; + case Mam_RR: + /* we could handle this case, but we don't expect to ever + need to. */ + vassert(0); + break; + default: + vassert(0); + break; + } + } + return p; +} + /* Move r_dst to r_src */ static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src) { @@ -3382,7 +3427,7 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc, } /* Update the guest PC. */ - /* sw r-dstGA, amPC */ + /* sw/sd r-dstGA, amPC */ p = do_load_or_store_machine_word(p, False /*!isLoad*/ , iregNo(i->Min.XIndir.dstGA, mode64), i->Min.XIndir.amPC, mode64); @@ -4066,16 +4111,16 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc, */ UChar* p0 = p; /* lw r9, amCounter */ - p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9, + p = do_load_or_store_word32(p, True /*isLoad*/ , /*r*/ 9, i->Min.EvCheck.amCounter, mode64); /* addiu r9,r9,-1 */ p = mkFormI(p, 9, 9, 9, 0xFFFF); /* sw r30, amCounter */ - p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 9, + p = do_load_or_store_word32(p, False /*!isLoad*/ , /*r*/ 9, i->Min.EvCheck.amCounter, mode64); /* bgez t9, nofail */ p = mkFormI(p, 1, 9, 1, 3); - /* lw r9, amFailAddr */ + /* lw/ld r9, amFailAddr */ p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9, i->Min.EvCheck.amFailAddr, mode64); /* jalr $9 */ diff --git a/VEX/priv/host_mips_isel.c b/VEX/priv/host_mips_isel.c index f5045df2f4..0187452c36 100644 --- a/VEX/priv/host_mips_isel.c +++ b/VEX/priv/host_mips_isel.c @@ -1,6 +1,6 @@ /*---------------------------------------------------------------*/ -/*--- begin host_mips_isel.c ---*/ +/*--- begin host_mips_isel.c ---*/ /*---------------------------------------------------------------*/ /* @@ -359,8 +359,13 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo) am_addr1 = MIPSAMode_IR(4, StackPointer(mode64)); /* store hi,lo as Ity_I32's */ +#if defined (_MIPSEL) addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64)); addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64)); +#elif defined (_MIPSEB) + addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64)); + addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64)); +#endif /* load as float */ addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0)); @@ -2317,9 +2322,15 @@ static void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e) addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src, am_addr)); /* load as 2xI32 */ +#if defined (_MIPSEL) addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64)); addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr), mode64)); +#elif defined (_MIPSEB) + addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64)); + addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr), + mode64)); +#endif /* Reset SP */ add_to_sp(env, 16); @@ -2436,7 +2447,7 @@ static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e) HReg r_dst = newVRegF(env); /* Move Doubleword to Floating Point - dmtc1 r_dst, valS */ + dmtc1 r_dst, fr_src */ addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src)); return r_dst;