From: Petar Jovanovic Date: Tue, 4 Oct 2016 14:27:18 +0000 (+0000) Subject: mips64: support for fp32 mode X-Git-Tag: svn/VALGRIND_3_12_0^2~13^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5e7e85149262c5c2cb2d0fc0c2f833f8d26c9f5;p=thirdparty%2Fvalgrind.git mips64: support for fp32 mode Support for FP32 emulation on MIPS64 platforms (including prctl(GET/SET_FP_MODE) syscalls). Patch by Aleksandar Rikalo. Implements the remaining parts for BZ #366079. git-svn-id: svn://svn.valgrind.org/vex/trunk@3253 --- diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index c3228315f1..aaa07fa08d 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -1429,8 +1429,8 @@ static IRExpr *getDReg(UInt dregNo) IRTemp t4 = newTemp(Ity_I32); IRTemp t5 = newTemp(Ity_I64); - assign(t0, getFReg(dregNo)); - assign(t1, getFReg(dregNo + 1)); + assign(t0, getFReg(dregNo & (~1))); + assign(t1, getFReg(dregNo | 1)); assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); @@ -1467,8 +1467,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 */ - putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5))); - putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); + putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5))); + putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); } } @@ -12236,7 +12236,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, assign(t1, unop(Iop_64HIto32, mkexpr(t0))); putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); break; - } else if ((fs & 1) == 0) { + } else { putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32, getFReg(fs | 1)), True)); break; @@ -12254,7 +12254,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, getLoFromF64(Ity_F64, getDReg(fs))))); putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0))); break; - } else if ((fs & 1) == 0) { + } else { putFReg(fs | 1, unop(Iop_ReinterpI32asF32, mkNarrowTo32(ty, getIReg(rt)))); break; @@ -12536,55 +12536,25 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, switch (fmt) { case 0x10: /* S */ DIP("movn.s f%u, f%u, r%u", fd, fs, rt); - t1 = newTemp(Ity_F64); - t2 = newTemp(Ity_F64); - t3 = newTemp(Ity_I1); - t4 = newTemp(Ity_F64); - if (mode64) { - assign(t1, getFReg(fs)); - assign(t2, getFReg(fd)); - assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); - } else { - if (fp_mode64) { - assign(t1, getFReg(fs)); - assign(t2, getFReg(fd)); - assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); - } else { - assign(t1, unop(Iop_F32toF64, getFReg(fs))); - assign(t2, unop(Iop_F32toF64, getFReg(fd))); - assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); - } - } - - assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2))); - if (fp_mode64) { - IRTemp f = newTemp(Ity_F64); - IRTemp fd_hi = newTemp(Ity_I32); - t5 = newTemp(Ity_I64); - assign(f, getFReg(fd)); - assign(fd_hi, unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, - mkexpr(f)))); + t1 = newTemp(Ity_I1); - assign(t5, mkWidenFrom32(Ity_I64, unop(Iop_64to32, - unop(Iop_ReinterpF64asI64, mkexpr(t4))), True)); + if (mode64) + assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); + else + assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); - putFReg(fd, unop (Iop_ReinterpI64asF64, mkexpr(t5))); - } else - putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), - mkexpr(t4))); + putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd))); break; case 0x11: /* D */ DIP("movn.d f%u, f%u, r%u", fd, fs, rt); - - t3 = newTemp(Ity_I1); - t4 = newTemp(Ity_F64); + t1 = newTemp(Ity_I1); if (mode64) - assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); + assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); else - assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); + assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); - putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd))); + putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd))); break; default: goto decode_failure; @@ -12595,51 +12565,25 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, switch (fmt) { case 0x10: /* S */ DIP("movz.s f%u, f%u, r%u", fd, fs, rt); + t1 = newTemp(Ity_I1); - t1 = newTemp(Ity_F64); - t2 = newTemp(Ity_F64); - t3 = newTemp(Ity_I1); - t4 = newTemp(Ity_F64); - if (fp_mode64) { - assign(t1, getFReg(fs)); - assign(t2, getFReg(fd)); - if (mode64) - assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); - else - assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); - } else { - assign(t1, unop(Iop_F32toF64, getFReg(fs))); - assign(t2, unop(Iop_F32toF64, getFReg(fd))); - assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); - } - assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2))); - - if (fp_mode64) { - IRTemp f = newTemp(Ity_F64); - IRTemp fd_hi = newTemp(Ity_I32); - t7 = newTemp(Ity_I64); - assign(f, getFReg(fd)); - assign(fd_hi, unop(Iop_64HIto32, - unop(Iop_ReinterpF64asI64, mkexpr(f)))); - assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, - unop(Iop_ReinterpF64asI64, mkexpr(t4))), True)); - - putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); - } else - putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), - mkexpr(t4))); + if (mode64) + assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); + else + assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); + putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd))); break; case 0x11: /* D */ DIP("movz.d f%u, f%u, r%u", fd, fs, rt); - t3 = newTemp(Ity_I1); - t4 = newTemp(Ity_F64); + t1 = newTemp(Ity_I1); + if (mode64) - assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); + assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); else - assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); + assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); - putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd))); + putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd))); break; default: goto decode_failure; @@ -12840,13 +12784,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1))); } else - putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt))); + putFReg(fs, unop(Iop_ReinterpI32asF32, + mkNarrowTo32(ty, getIReg(rt)))); break; case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */ DIP("dmtc1 r%u, f%u", rt, fs); vassert(mode64); - putFReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt))); + putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt))); break; case 0x0: /* MFC1 */ @@ -12858,13 +12803,15 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, assign(t1, unop(Iop_64to32, mkexpr(t0))); putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); } else - putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs))); + putIReg(rt, mkWidenFrom32(ty, + unop(Iop_ReinterpF32asI32, getFReg(fs)), + True)); break; case 0x1: /* Doubleword Move from Floating Point DMFC1; MIPS64 */ DIP("dmfc1 r%u, f%u", rt, fs); - putIReg(rt, unop(Iop_ReinterpF64asI64, getFReg(fs))); + putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs))); break; case 0x6: /* CTC1 */ @@ -13476,29 +13423,16 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x31: /* LWC1 */ /* Load Word to Floating Point - LWC1 (MIPS32) */ DIP("lwc1 f%u, %u(r%u)", ft, imm, rs); + LOAD_STORE_PATTERN; if (fp_mode64) { - t1 = newTemp(Ity_F32); + t0 = newTemp(Ity_F32); t2 = newTemp(Ity_I64); - if (mode64) { - t0 = newTemp(Ity_I64); - /* new LO */ - assign(t0, binop(Iop_Add64, getIReg(rs), - mkU64(extend_s_16to64(imm)))); - } else { - t0 = newTemp(Ity_I32); - /* new LO */ - assign(t0, binop(Iop_Add32, getIReg(rs), - mkU32(extend_s_16to32(imm)))); - } - assign(t1, load(Ity_F32, mkexpr(t0))); + assign(t0, load(Ity_F32, mkexpr(t1))); assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, - mkexpr(t1)), True)); + mkexpr(t0)), True)); putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2))); } else { - t0 = newTemp(Ity_I32); - assign(t0, binop(Iop_Add32, getIReg(rs), - mkU32(extend_s_16to32(imm)))); - putFReg(ft, load(Ity_F32, mkexpr(t0))); + putFReg(ft, load(Ity_F32, mkexpr(t1))); } break; @@ -13591,16 +13525,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x0: { /* LWXC1 */ /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */ DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs); + t2 = newTemp(ty); + assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), + getIReg(rt))); if (fp_mode64) { t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I32); t3 = newTemp(Ity_F32); t4 = newTemp(Ity_I64); - - t2 = newTemp(ty); - /* new LO */ - assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), - getIReg(rt))); assign(t3, load(Ity_F32, mkexpr(t2))); assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, @@ -13608,9 +13540,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4))); } else { - t0 = newTemp(Ity_I32); - assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); - putFReg(fd, load(Ity_F32, mkexpr(t0))); + putFReg(fd, load(Ity_F32, mkexpr(t2))); } break; } @@ -13618,29 +13548,12 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x1: { /* LDXC1 */ /* Load Doubleword Indexed to Floating Point LDXC1 (MIPS32r2 and MIPS64) */ - if (fp_mode64) { - DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs); - t0 = newTemp(ty); - assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), - getIReg(rt))); - putFReg(fd, load(Ity_F64, mkexpr(t0))); - break; - } else { - t0 = newTemp(Ity_I32); - assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); - - t1 = newTemp(Ity_I32); - assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); - -#if defined (_MIPSEL) - putFReg(fd, load(Ity_F32, mkexpr(t0))); - putFReg(fd + 1, load(Ity_F32, mkexpr(t1))); -#elif defined (_MIPSEB) - putFReg(fd + 1, load(Ity_F32, mkexpr(t0))); - putFReg(fd, load(Ity_F32, mkexpr(t1))); -#endif - break; - } + DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs); + t0 = newTemp(ty); + assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), + getIReg(rt))); + putDReg(fd, load(Ity_F64, mkexpr(t0))); + break; } case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1; @@ -13656,42 +13569,22 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */ DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs); + t0 = newTemp(ty); + assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), + getIReg(rt))); if (fp_mode64) { - t0 = newTemp(ty); - assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), - getIReg(rt))); store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs))); - } else { - t0 = newTemp(Ity_I32); - assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); - store(mkexpr(t0), getFReg(fs)); } break; } case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */ - DIP("sdc1 f%u, %u(%u)", ft, imm, rs); - if (fp_mode64) { - t0 = newTemp(ty); - assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), - getIReg(rt))); - store(mkexpr(t0), getFReg(fs)); - } else { - t0 = newTemp(Ity_I32); - assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); - - t1 = newTemp(Ity_I32); - assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); - -#if defined (_MIPSEL) - store(mkexpr(t0), getFReg(fs)); - store(mkexpr(t1), getFReg(fs + 1)); -#elif defined (_MIPSEB) - store(mkexpr(t0), getFReg(fs + 1)); - store(mkexpr(t1), getFReg(fs)); -#endif - } + DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs); + t0 = newTemp(ty); + assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), + getIReg(rt))); + store(mkexpr(t0), getDReg(fs)); break; } case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point -