|
From: Petar J. <pe...@so...> - 2018-02-01 18:06:20
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=6e7f9c9ef405e8d5289fbb6d960e220311ebe110 commit 6e7f9c9ef405e8d5289fbb6d960e220311ebe110 Author: Petar Jovanovic <mip...@gm...> Date: Thu Feb 1 18:19:24 2018 +0100 mips: add support for mips32/mips64 R6 to VEX Full support of MIPS R6 instruction set. Special implementation for MIPS R6 has been added for following IOPs: Iop_Max32U, Iop_Mul32, Iop_Mul64, Iop_MullS32, Iop_MullU32, Iop_MullU8, Iop_MullS8, Iop_MullU16, Iop_MullS16, Iop_CmpF64, Iop_DivModU32to32, Iop_DivModS32to32, Iop_DivS32, Iop_DivU32, Iop_DivS64, Iop_DivU64, Iop_MullU64, Iop_MullS64, Iop_DivModU64to64, Iop_DivModS64to64, Iop_Shr64, Iop_Shl64, Iop_Sar64, Iop_RoundF32toInt, Iop_RoundF64toInt, Iop_MAddF32, Iop_MAddF64, Iop_MSubF32, Iop_MSubF64 Following IOPs have been implemented using MIPS R6 instructions: Iop_MaxNumF32, Iop_MaxNumF64 Iop_MinNumF32, Iop_MinNumF64, Iop_CmpF32, Iop_Rotx32, Iop_Rotx64 Following IOPs have been implemented without using MIPS R6 instructions: Iop_F64toI64S, Iop_F32toI32S, Iop_I64StoF64. Part of MIPS32/64 Revision 6 changes. Contributed by: Tamara Vlahovic, Aleksandar Rikalo and Aleksandra Karadzic. Related BZ issue - #387410. Diff: --- VEX/priv/guest_mips_defs.h | 6 +- VEX/priv/guest_mips_helpers.c | 45 + VEX/priv/guest_mips_toIR.c | 2989 ++++++++++++++++++++++++++++++++++++----- VEX/priv/host_mips_defs.c | 512 ++++++- VEX/priv/host_mips_defs.h | 65 +- VEX/priv/host_mips_isel.c | 775 ++++++++--- VEX/pub/libvex.h | 8 +- VEX/pub/libvex_guest_mips32.h | 10 +- 8 files changed, 3833 insertions(+), 577 deletions(-) diff --git a/VEX/priv/guest_mips_defs.h b/VEX/priv/guest_mips_defs.h index 6ee6728..bbdbc4d 100644 --- a/VEX/priv/guest_mips_defs.h +++ b/VEX/priv/guest_mips_defs.h @@ -91,7 +91,11 @@ typedef enum { CVTDS, CVTDW, CVTSD, CVTSW, CVTWS, CVTWD, CVTDL, CVTLS, CVTLD, CVTSL, ADDS, ADDD, - SUBS, SUBD, DIVS + SUBS, SUBD, DIVS, + RINTS, RINTD, + MAXS, MAXD, MINS, MIND, + MAXAS, MAXAD, MINAS, MINAD, + CMPAFS, CMPAFD, CMPSAFS, CMPSAFD, } flt_op; typedef enum { diff --git a/VEX/priv/guest_mips_helpers.c b/VEX/priv/guest_mips_helpers.c index 3f21512..4f74593 100644 --- a/VEX/priv/guest_mips_helpers.c +++ b/VEX/priv/guest_mips_helpers.c @@ -172,6 +172,7 @@ void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state) vex_state->guest_COND = 0; vex_state->guest_CP0_status = 0; + vex_state->guest_CP0_Config5 = 0; vex_state->guest_LLaddr = 0xFFFFFFFF; vex_state->guest_LLdata = 0; @@ -812,6 +813,50 @@ extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs, UInt fs, UInt ft, case DIVS: ASM_VOLATILE_BINARY64(div.s) break; +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6) + case RINTS: + ASM_VOLATILE_UNARY64(rint.s) + break; + case RINTD: + ASM_VOLATILE_UNARY64(rint.d) + break; + case MAXS: + ASM_VOLATILE_BINARY64(max.s) + break; + case MAXD: + ASM_VOLATILE_BINARY64(max.d) + break; + case MINS: + ASM_VOLATILE_BINARY64(min.s) + break; + case MIND: + ASM_VOLATILE_BINARY64(min.d) + break; + case MAXAS: + ASM_VOLATILE_BINARY64(maxa.s) + break; + case MAXAD: + ASM_VOLATILE_BINARY64(maxa.d) + break; + case MINAS: + ASM_VOLATILE_BINARY64(mina.s) + break; + case MINAD: + ASM_VOLATILE_BINARY64(mina.d) + break; + case CMPAFS: + ASM_VOLATILE_BINARY64(cmp.af.s) + break; + case CMPAFD: + ASM_VOLATILE_BINARY64(cmp.af.d) + break; + case CMPSAFS: + ASM_VOLATILE_BINARY64(cmp.saf.s) + break; + case CMPSAFD: + ASM_VOLATILE_BINARY64(cmp.saf.d) + break; +#endif default: vassert(0); break; diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index 0063ae3..8421126 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -75,6 +75,9 @@ static Bool mode64 = False; /* CPU has FPU and 32 dbl. prec. FP registers. */ static Bool fp_mode64 = False; +/* FPU works in FRE mode */ +static Bool fp_mode64_fre = False; + /* CPU has MSA unit */ static Bool has_msa = False; @@ -1076,6 +1079,17 @@ static Bool branch_or_jump(const UChar * addr) if (fmt == 0x0b) { return True; } + + /* R6 branches */ + /* bc1eqz */ + if (fmt == 0x09) { + return True; + } + + /* bc1nez */ + if (fmt == 0x0D) { + return True; + } } /* bposge32 */ @@ -1105,7 +1119,7 @@ static Bool is_Branch_or_Jump_and_Link(const UChar * addr) return True; } - /* bgezal */ + /* bgezal or bal(r6) */ if (opcode == 0x01 && rt == 0x11) { return True; } @@ -1265,6 +1279,12 @@ static IRExpr *genRORV32(IRExpr * src, IRExpr * rs) binop(Iop_Shr32, src, mkexpr(t0))); } + +static UShort extend_s_9to16(UInt x) +{ + return (UShort) ((((Int) x) << 23) >> 23); +} + static UShort extend_s_10to16(UInt x) { return (UShort) ((((Int) x) << 22) >> 22); @@ -1290,6 +1310,21 @@ static UInt extend_s_18to32(UInt x) return (UInt) ((((Int) x) << 14) >> 14); } +static UInt extend_s_19to32(UInt x) +{ + return (UInt) ((((Int) x) << 13) >> 13); +} + +static UInt extend_s_23to32(UInt x) +{ + return (UInt) ((((Int) x) << 9) >> 9); +} + +static UInt extend_s_26to32(UInt x) +{ + return (UInt) ((((Int) x) << 6) >> 6); +} + static ULong extend_s_16to64 ( UInt x ) { return (ULong) ((((Long) x) << 48) >> 48); @@ -1300,6 +1335,21 @@ static ULong extend_s_18to64 ( UInt x ) return (ULong) ((((Long) x) << 46) >> 46); } +static ULong extend_s_19to64(UInt x) +{ + return (ULong) ((((Long) x) << 45) >> 45); +} + +static ULong extend_s_23to64(UInt x) +{ + return (ULong) ((((Long) x) << 41) >> 41); +} + +static ULong extend_s_26to64(UInt x) +{ + return (ULong) ((((Long) x) << 38) >> 38); +} + static ULong extend_s_32to64 ( UInt x ) { return (ULong) ((((Long) x) << 32) >> 32); @@ -1757,6 +1807,13 @@ static IRExpr *getLoFromF64(IRType ty, IRExpr * src) return src; } +static inline IRExpr *getHiFromF64(IRExpr * src) +{ + vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_F64); + return unop(Iop_ReinterpI32asF32, unop(Iop_64HIto32, + unop(Iop_ReinterpF64asI64, src))); +} + static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src) { vassert(ty == Ity_F32 || ty == Ity_F64); @@ -1848,6 +1905,51 @@ static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set) (UInt) branch_offset), OFFB_PC); } +static void dis_branch_compact(Bool link, IRExpr * guard, UInt imm, + DisResult *dres) +{ + ULong branch_offset; + IRTemp t0; + + if (link) { /* LR (GPR31) = addr of the instr after branch instr */ + if (mode64) + putIReg(31, mkU64(guest_PC_curr_instr + 4)); + else + putIReg(31, mkU32(guest_PC_curr_instr + 4)); + dres->jk_StopHere = Ijk_Call; + } else { + dres->jk_StopHere = Ijk_Boring; + } + + dres->whatNext = Dis_StopHere; + + /* PC = PC + (SignExtend(signed_immed_24) << 2) + An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) + is added to the address of the instruction following + the branch (not the branch itself), in the branch delay slot, to form + a PC-relative effective target address. */ + + if (mode64) + branch_offset = extend_s_18to64(imm << 2); + else + branch_offset = extend_s_18to32(imm << 2); + + t0 = newTemp(Ity_I1); + assign(t0, guard); + + if (mode64) { + stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, + IRConst_U64(guest_PC_curr_instr + 4 + branch_offset), + OFFB_PC)); + putPC(mkU64(guest_PC_curr_instr + 4)); + } else { + stmt(IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, + IRConst_U32(guest_PC_curr_instr + 4 + + (UInt) branch_offset), OFFB_PC)); + putPC(mkU32(guest_PC_curr_instr + 4)); + } +} + static IRExpr *getFReg(UInt fregNo) { vassert(fregNo < 32); @@ -1887,11 +1989,28 @@ static void putFReg(UInt dregNo, IRExpr * e) vassert(dregNo < 32); IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; vassert(typeOfIRExpr(irsb->tyenv, e) == ty); - stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); + + if (fp_mode64_fre) { + IRTemp t0 = newTemp(Ity_F32); + assign(t0, getLoFromF64(ty, e)); +#if defined (_MIPSEL) + stmt(IRStmt_Put(floatGuestRegOffset(dregNo), mkexpr(t0))); + if (dregNo & 1) + stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0))); +#else + stmt(IRStmt_Put(floatGuestRegOffset(dregNo) + 4, mkexpr(t0))); + if (dregNo & 1) + stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0))); +#endif + } else { + stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); + } + if (has_msa && fp_mode64) { stmt(IRStmt_Put(msaGuestRegOffset(dregNo), binop(Iop_64HLtoV128, - mkU64(0), unop(Iop_ReinterpF64asI64, e)))); + unop(Iop_ReinterpF64asI64, e), + unop(Iop_ReinterpF64asI64, e)))); } } @@ -1902,10 +2021,29 @@ static void putDReg(UInt dregNo, IRExpr * e) IRType ty = Ity_F64; vassert(typeOfIRExpr(irsb->tyenv, e) == ty); stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); + if (fp_mode64_fre) { + IRTemp t0 = newTemp(Ity_F32); + if (dregNo & 1) { + assign(t0, getLoFromF64(ty, e)); +#if defined (_MIPSEL) + stmt(IRStmt_Put(floatGuestRegOffset(dregNo) - 4, mkexpr(t0))); +#else + stmt(IRStmt_Put(floatGuestRegOffset(dregNo & (~1)), mkexpr(t0))); +#endif + } else { + assign(t0, getHiFromF64(e)); +#if defined (_MIPSEL) + stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1), mkexpr(t0))); +#else + stmt(IRStmt_Put(floatGuestRegOffset(dregNo | 1) + 4, mkexpr(t0))); +#endif + } + } if (has_msa) stmt(IRStmt_Put(msaGuestRegOffset(dregNo), binop(Iop_64HLtoV128, - mkU64(0), unop(Iop_ReinterpF64asI64, e)))); + unop(Iop_ReinterpF64asI64, e), + unop(Iop_ReinterpF64asI64, e)))); } else { vassert(dregNo < 32); vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); @@ -24645,19 +24783,13 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ mkU64(0xC3E0000000000000), mkU64(0xC3E0000000000000))))); assign(t1, - unop(Iop_ReinterpF64asI64, - binop(Iop_RoundF64toInt, - mkU32(0x3), - unop(Iop_ReinterpI64asF64, - unop(Iop_V128to64, - mkexpr(t3)))))); + binop(Iop_F64toI64S, mkU32(0x3), + unop(Iop_ReinterpI64asF64, + unop(Iop_V128to64, mkexpr(t3))))); assign(t2, - unop(Iop_ReinterpF64asI64, - binop(Iop_RoundF64toInt, - mkU32(0x3), - unop(Iop_ReinterpI64asF64, - unop(Iop_V128HIto64, - mkexpr(t3)))))); + binop(Iop_F64toI64S, mkU32(0x3), + unop(Iop_ReinterpI64asF64, + unop(Iop_V128HIto64, mkexpr(t3))))); putWReg(wd, binop(Iop_64HLtoV128, mkexpr(t2), mkexpr(t1))); @@ -24825,13 +24957,10 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ tmp[i] = newTemp(Ity_I32); assign(tmp[i], unop(Iop_ReinterpF32asI32, - binop(Iop_I32StoF32, rm, - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - mkexpr(t1), - mkU8(i)))))))); + binop(Iop_RoundF32toInt, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + mkexpr(t1), mkU8(i)))))); } putWReg(wd, @@ -24909,13 +25038,10 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ tmp[i] = newTemp(Ity_I64); assign(tmp[i], unop(Iop_ReinterpF64asI64, - binop(Iop_I64StoF64, rm, - unop(Iop_ReinterpF64asI64, - binop(Iop_RoundF64toInt, rm, - unop(Iop_ReinterpI64asF64, - binop(Iop_GetElem64x2, - mkexpr(t1), - mkU8(i)))))))); + binop(Iop_RoundF64toInt, rm, + unop(Iop_ReinterpI64asF64, + binop(Iop_GetElem64x2, + mkexpr(t1), mkU8(i)))))); } putWReg(wd, @@ -25274,32 +25400,24 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ IRExpr *rm = get_IR_roundingmode_MSA(); assign(t1, binop(Iop_32HLto64, - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - mkexpr(t3), - mkU8(1))))), - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - mkexpr(t3), - mkU8(0))))))); + binop(Iop_F32toI32S, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + mkexpr(t3), mkU8(1)))), + binop(Iop_F32toI32S, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + mkexpr(t3), mkU8(0)))))); assign(t2, binop(Iop_32HLto64, - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - mkexpr(t3), - mkU8(3))))), - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - mkexpr(t3), - mkU8(2))))))); + binop(Iop_F32toI32S, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + mkexpr(t3), mkU8(3)))), + binop(Iop_F32toI32S, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + mkexpr(t3), mkU8(2)))))); putWReg(wd, binop(Iop_64HLtoV128, mkexpr(t2), mkexpr(t1))); @@ -25325,17 +25443,13 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ mkU64(0xC3E0000000000000))))); IRExpr *rm = get_IR_roundingmode_MSA(); assign(t1, - unop(Iop_ReinterpF64asI64, - binop(Iop_RoundF64toInt, rm, - unop(Iop_ReinterpI64asF64, - unop(Iop_V128to64, - mkexpr(t3)))))); + binop(Iop_F64toI64S, rm, + unop(Iop_ReinterpI64asF64, + unop(Iop_V128to64, mkexpr(t3))))); assign(t2, - unop(Iop_ReinterpF64asI64, - binop(Iop_RoundF64toInt, rm, - unop(Iop_ReinterpI64asF64, - unop(Iop_V128HIto64, - mkexpr(t3)))))); + binop(Iop_F64toI64S, rm, + unop(Iop_ReinterpI64asF64, + unop(Iop_V128HIto64, mkexpr(t3))))); putWReg(wd, binop(Iop_64HLtoV128, mkexpr(t2), mkexpr(t1))); @@ -25361,32 +25475,24 @@ static Int msa_2RF(UInt cins, UChar wd, UChar ws) { /* 2RF */ IRExpr *rm = get_IR_roundingmode_MSA(); assign(t1, binop(Iop_32HLto64, - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - getWReg(ws), - mkU8(1))))), - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - getWReg(ws), - mkU8(0))))))); + binop(Iop_F32toI32U, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + getWReg(ws), mkU8(1)))), + binop(Iop_F32toI32U, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + getWReg(ws), mkU8(0)))))); assign(t2, binop(Iop_32HLto64, - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - getWReg(ws), - mkU8(3))))), - unop(Iop_ReinterpF32asI32, - binop(Iop_RoundF32toInt, rm, - unop(Iop_ReinterpI32asF32, - binop(Iop_GetElem32x4, - getWReg(ws), - mkU8(2))))))); + binop(Iop_F32toI32U, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + getWReg(ws), mkU8(3)))), + binop(Iop_F32toI32U, rm, + unop(Iop_ReinterpI32asF32, + binop(Iop_GetElem32x4, + getWReg(ws), mkU8(2)))))); assign(t3, unop(Iop_NotV128, binop(Iop_SarN32x4, @@ -25991,39 +26097,39 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x11: { /* COP1 */ if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */ DIP("mfhc1 r%u, f%u", rt, fs); - if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) { + if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) || + VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { if (fp_mode64) { t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I32); assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs))); assign(t1, unop(Iop_64HIto32, mkexpr(t0))); putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); - break; } else { putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32, getFReg(fs | 1)), True)); - break; } + } else { + ILLEGAL_INSTRUCTON; } - ILLEGAL_INSTRUCTON; break; } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */ DIP("mthc1 r%u, f%u", rt, fs); - if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) { + if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) || + VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { if (fp_mode64) { t0 = newTemp(Ity_I64); assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)), unop(Iop_ReinterpF32asI32, getLoFromF64(Ity_F64, getDReg(fs))))); putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0))); - break; } else { putFReg(fs | 1, unop(Iop_ReinterpI32asF32, mkNarrowTo32(ty, getIReg(rt)))); - break; } + } else { + ILLEGAL_INSTRUCTON; } - ILLEGAL_INSTRUCTON; break; } else if (fmt == 0x8) { /* BC */ /* FcConditionalCode(bc1_cc) */ @@ -26189,7 +26295,437 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, unop(Iop_V128HIto64, mkexpr(t1)))))); dis_branch(False, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0)), imm, &bstmt); + } else if (fmt == 0x09) { /* BC1EQZ */ + if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { + DIP("bc1eqz f%u, %u", ft, imm); + t1 = newTemp(Ity_I1); + if (mode64) { + assign(t1, binop(Iop_CmpEQ64, + binop(Iop_And64, + unop(Iop_ReinterpF64asI64, getDReg(ft)), + mkU64(1)), + mkU64(0))); + } else { + assign(t1, binop(Iop_CmpEQ32, + binop(Iop_And32, + unop(Iop_64to32, + unop(Iop_ReinterpF64asI64, getDReg(ft))), + mkU32(1)), + mkU32(0))); + } + dis_branch(False, mkexpr(t1), imm, &bstmt); + } else { + ILLEGAL_INSTRUCTON; + } + } else if (fmt == 0x0D) { /* BC1NEZ */ + if (VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { + DIP("bc1nez f%u, %u", ft, imm); + t1 = newTemp(Ity_I1); + if (mode64) { + assign(t1, binop(Iop_CmpNE64, + binop(Iop_And64, + unop(Iop_ReinterpF64asI64, getDReg(ft)), + mkU64(1)), + mkU64(0))); + } else { + assign(t1, binop(Iop_CmpNE32, + binop(Iop_And32, + unop(Iop_64to32, + unop(Iop_ReinterpF64asI64, getDReg(ft))), + mkU32(1)), + mkU32(0))); + } + dis_branch(False, mkexpr(t1), imm, &bstmt); + } else { + ILLEGAL_INSTRUCTON; + } } else { + if (fmt == 0x15) { /* CMP.cond.d */ + Bool comparison = True; + UInt signaling = CMPAFD; + DIP("cmp.cond.d f%u, f%u, f%u, cond %u", fd, fs, ft, function); + t0 = newTemp(Ity_I32); + /* Conditions starting with S should signal exception on QNaN inputs. */ + switch (function) { + case 8: /* SAF */ + signaling = CMPSAFD; + case 0: /* AF */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0))); + break; + case 9: /* SUN */ + signaling = CMPSAFD; + case 1: /* UN */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)))); + break; + case 0x19: /* SOR */ + signaling = CMPSAFD; + case 0x11: /* OR */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)))); + break; + case 0xa: /* SEQ */ + signaling = CMPSAFD; + case 2: /* EQ */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)))); + break; + case 0x1A: /* SNEQ */ + signaling = CMPSAFD; + case 0x12: /* NEQ */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)))); + break; + case 0xB: /* SUEQ */ + signaling = CMPSAFD; + case 0x3: /* UEQ */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0), mkU32(0x45)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), + mkU64(0))))); + break; + case 0x1B: /* SNEQ */ + signaling = CMPSAFD; + case 0x13: /* NEQ */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0),mkU32(0x00)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), + mkU64(0))))); + break; + case 0xC: /* SLT */ + signaling = CMPSAFD; + case 0x4: /* LT */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)))); + break; + case 0xD: /* SULT */ + signaling = CMPSAFD; + case 0x5: /* ULT */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0), mkU32(0x45)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), + mkU64(0))))); + break; + case 0xE: /* SLE */ + signaling = CMPSAFD; + case 0x6: /* LE */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0),mkU32(0x40)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), + mkU64(0))))); + break; + case 0xF: /* SULE */ + signaling = CMPSAFD; + case 0x7: /* ULE */ + assign(t0, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); + calculateFCSR(fs, ft, signaling, False, 2); + putDReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)), + binop(Iop_I64StoF64, + get_IR_roundingmode(), mkU64(0)), + unop(Iop_ReinterpI64asF64, + mkU64(0xFFFFFFFFFFFFFFFFULL)))); + break; + default: + comparison = False; + } + if (comparison) { + if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { + ILLEGAL_INSTRUCTON; + } + break; + } + + } else if (fmt == 0x14) { + Bool comparison = True; + UInt signaling = CMPAFS; + DIP("cmp.cond.s f%u, f%u, f%u, cond %u", fd, fs, ft, function); + t0 = newTemp(Ity_I32); + /* Conditions starting with S should signal exception on QNaN inputs. */ + switch (function) { + case 8: /* SAF */ + signaling = CMPSAFS; + case 0: /* AF */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), mkU32(0)))); + break; + case 9: /* SUN */ + signaling = CMPSAFS; + case 1: /* UN */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))))); + break; + case 0x19: /* SOR */ + signaling = CMPSAFS; + case 0x11: /* OR */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x45)), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))))); + break; + case 0xa: /* SEQ */ + signaling = CMPSAFS; + case 2: /* EQ */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))))); + break; + case 0x1A: /* SNEQ */ + signaling = CMPSAFS; + case 0x12: /* NEQ */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))))); + break; + case 0xB: /* SUEQ */ + signaling = CMPSAFS; + case 0x3: /* UEQ */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x40)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0), mkU32(0x45)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0)))))); + break; + case 0x1B: /* SNEQ */ + signaling = CMPSAFS; + case 0x13: /* NEQ */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0),mkU32(0x00)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0)))))); + break; + case 0xC: /* SLT */ + signaling = CMPSAFS; + case 0x4: /* LT */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))))); + break; + case 0xD: /* SULT */ + signaling = CMPSAFS; + case 0x5: /* ULT */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x01)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0), mkU32(0x45)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0)))))); + break; + case 0xE: /* SLE */ + signaling = CMPSAFS; + case 0x6: /* LE */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0),mkU32(0x01)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + IRExpr_ITE(binop(Iop_CmpEQ32, + mkexpr(t0),mkU32(0x40)), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0)))))); + break; + case 0xF: /* SULE */ + signaling = CMPSAFS; + case 0x7: /* ULE */ + assign(t0, binop(Iop_CmpF32, + getLoFromF64(Ity_F64, getFReg(fs)), + getLoFromF64(Ity_F64, getFReg(ft)))); + calculateFCSR(fs, ft, signaling, True, 2); + putFReg(fd, + IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0)), + mkWidenFromF32(tyF, + binop(Iop_I32StoF32, + get_IR_roundingmode(), + mkU32(0))), + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + mkU32(0xFFFFFFFFU))))); + break; + default: + comparison = False; + } + if (comparison) { + if (!VEX_MIPS_CPU_HAS_MIPSR6(archinfo->hwcaps)) { + ILLEGAL_INSTRUCTON; + } + break; + } + } + switch (function) { case 0x4: { /* SQRT.fmt */ switch (fmt) { @@ -26350,8 +26886,10 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("round.l.d f%u, f%u", fd, fs); if (fp_mode64) { calculateFCSR(fs, 0, ROUNDLD, False, 1); - putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0), - getDReg(fs))); + putDReg(fd, unop(Iop_ReinterpI64asF64, + binop(Iop_F64toI64S, + mkU32(0x0), + getDReg(fs)))); } else { ILLEGAL_INSTRUCTON; } @@ -26381,8 +26919,10 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("trunc.l.d f%u, f%u", fd, fs); if (fp_mode64) { calculateFCSR(fs, 0, TRUNCLD, False, 1); - putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3), - getDReg(fs))); + putDReg(fd, unop(Iop_ReinterpI64asF64, + binop(Iop_F64toI64S, + mkU32(0x3), + getDReg(fs)))); } else { ILLEGAL_INSTRUCTON; } @@ -26923,10 +27463,11 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, calculateFCSR(fs, 0, CVTWS, True, 1); putFReg(fd, mkWidenFromF32(tyF, - binop(Iop_RoundF32toInt, - get_IR_roundingmode(), - getLoFromF64(tyF, getFReg(fs)))) - ); + unop(Iop_ReinterpI32asF32, + binop(Iop_F32toI32S, + get_IR_roundingmode(), + getLoFromF64(tyF, + getFReg(fs)))))); break; case 0x11: @@ -26967,8 +27508,10 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("cvt.l.d %u, %u", fd, fs); if (fp_mode64) { calculateFCSR(fs, 0, CVTLD, False, 1); - putDReg(fd, binop(Iop_RoundF64toInt, - get_IR_roundingmode(), getDReg(fs))); + putDReg(fd, unop(Iop_ReinterpI64asF64, + binop(Iop_F64toI64S, + get_IR_roundingmode(), + getDReg(fs)))); } else { ILLEGAL_INSTRUCTON; } @@ -27001,8 +27544,10 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("floor.l.d %u, %u", fd, fs); if (fp_mode64) { calculateFCSR(fs, 0, FLOORLD, False, 1); - putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1), - getDReg(fs))); + putDReg(fd, unop(Iop_ReinterpI64asF64, + binop(Iop_F64toI64S, + mkU32(0x01), + getDReg(fs)))); } else { ILLEGAL_INSTRUCTON; } @@ -27017,25 +27562,13 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x10: /* S */ DIP("round.w.s f%u, f%u", fd, fs); calculateFCSR(fs, 0, ROUNDWS, True, 1); - if (fp_mode64) { - t0 = newTemp(Ity_I64); - t1 = newTemp(Ity_I32); - t3 = newTemp(Ity_F32); - t4 = newTemp(Ity_F32); - /* get lo half of FPR */ - assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); - - assign(t1, unop(Iop_64to32, mkexpr(t0))); - - assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); - - assign(t4, binop(Iop_RoundF32toInt, mkU32(0x0), - mkexpr(t3))); - - putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); - } else - putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0), - getFReg(fs))); + putFReg(fd, + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + binop(Iop_F32toI32S, + mkU32(0x0), + getLoFromF64(tyF, + getFReg(fs)))))); break; case 0x11: /* D */ @@ -27067,25 +27600,13 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x10: /* S */ DIP("floor.w.s f%u, f%u", fd, fs); calculateFCSR(fs, 0, FLOORWS, True, 1); - if (fp_mode64) { - t0 = newTemp(Ity_I64); - t1 = newTemp(Ity_I32); - t3 = newTemp(Ity_F32); - t4 = newTemp(Ity_F32); - /* get lo half of FPR */ - assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); - - assign(t1, unop(Iop_64to32, mkexpr(t0))); - - assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); - - assign(t4, binop(Iop_RoundF32toInt, mkU32(0x1), - mkexpr(t3))); - - putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); - } else - putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1), - getFReg(fs))); + putFReg(fd, + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + binop(Iop_F32toI32S, + mkU32(0x1), + getLoFromF64(tyF, + getFReg(fs)))))); break; case 0x11: /* D */ @@ -27118,25 +27639,13 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x10: /* S */ DIP("trunc.w.s %u, %u", fd, fs); calculateFCSR(fs, 0, TRUNCWS, True, 1); - if (fp_mode64) { - t0 = newTemp(Ity_I64); - t1 = newTemp(Ity_I32); - t3 = newTemp(Ity_F32); - t4 = newTemp(Ity_F32); - /* get lo half of FPR */ - assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); - - assign(t1, unop(Iop_64to32, mkexpr(t0))); - - assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); - - assign(t4, binop(Iop_RoundF32toInt, mkU32(0x3), - mkexpr(t3))); - - putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); - } else - putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3), - getFReg(fs))); + putFReg(fd, + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + binop(Iop_F32toI32S, + mkU32(0x3), + getLoFromF64(tyF, + getFReg(fs)))))); break; case 0x11: /* D */ DIP("trunc.w.d %u, %u", fd, fs); @@ -27169,26 +27678,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x10: /* S */ DIP("ceil.w.s %u, %u", fd, fs); calculateFCSR(fs, 0, CEILWS, True, 1); - if (fp_mode64) { - t0 = newTemp(Ity_I64); - t1 = newTemp(Ity_I32); - t3 = newTemp(Ity_F32); - t4 = newTemp(Ity_F32); - /* get lo half of FPR */ - assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); - - assign(t1, unop(Iop_64to32, mkexpr(t0))); - - assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); - - assign(t4, binop(Iop_RoundF32toInt, mkU32(0x2), - mkexpr(t3))); - - putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); - } else - putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2), - getFReg(fs))); - break; + putFReg(fd, + mkWidenFromF32(tyF, + unop(Iop_ReinterpI32asF32, + binop(Iop_F32toI32S, + mkU32(0x2), + getLoFromF64(tyF, + getFReg(fs)))))); + break; case 0x11: /* D */ DIP("ceil.w.d %u, %u", fd, fs); @@ -27206,6 +27703,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, unop(Iop_ReinterpI32asF32, mkexpr(t0)))); } break; + default: goto decode_failure; @@ -27233,8 +27731,10 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, DIP("ceil.l.d %u, %u", fd, fs); if (fp_mode64) { calculateFCSR(fs, 0, CEILLD, False, 1); - putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2), - getDReg(fs))); + putDReg(fd, unop(Iop_ReinterpI64asF64, + binop(Iop_F64toI64S, + mkU32(0x2), + getDReg(fs)))); } else { ILLEGAL_INSTRUCT... [truncated message content] |