From: Julian Seward Date: Fri, 27 Jan 2006 15:09:35 +0000 (+0000) Subject: Handle ppc32/64 fres, frsqrte. X-Git-Tag: svn/VALGRIND_3_2_3^2~108 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c1d13ecff1aff193115072bc9a542a4bd0a77d29;p=thirdparty%2Fvalgrind.git Handle ppc32/64 fres, frsqrte. git-svn-id: svn://svn.valgrind.org/vex/trunk@1553 --- diff --git a/VEX/priv/guest-ppc/toIR.c b/VEX/priv/guest-ppc/toIR.c index 9d218a919c..f9d53e45b1 100644 --- a/VEX/priv/guest-ppc/toIR.c +++ b/VEX/priv/guest-ppc/toIR.c @@ -5701,16 +5701,15 @@ static Bool dis_fp_arith ( UInt theInstr ) assign( frD, roundToSgl( unop(Iop_SqrtF64, mkexpr(frB)) )); break; -//zz case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) -//zz if (frA_addr != 0 || frC_addr != 0) { -//zz vex_printf("dis_fp_arith(ppc)(instr,fres)\n"); -//zz return False; -//zz } -//zz DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", -//zz frD_addr, frB_addr); -//zz DIP(" => not implemented\n"); -//zz // CAB: Can we use one of the 128 bit SIMD Iop_Recip32F ops? -//zz return False; + case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421) + if (frA_addr != 0 || frC_addr != 0) { + vex_printf("dis_fp_arith(ppc)(instr,fres)\n"); + return False; + } + DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"", + frD_addr, frB_addr); + assign( frD, unop(Iop_Est8FRecip, mkexpr(frB)) ); + break; case 0x19: // fmuls (Floating Multiply Single, PPC32 p414) if (frB_addr != 0) { @@ -5805,16 +5804,15 @@ static Bool dis_fp_arith ( UInt theInstr ) assign( frD, binop( Iop_MulF64, mkexpr(frA), mkexpr(frC) ) ); break; -//zz case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) -//zz if (frA_addr != 0 || frC_addr != 0) { -//zz vex_printf("dis_fp_arith(ppc)(instr,frsqrte)\n"); -//zz return False; -//zz } -//zz DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", -//zz frD_addr, frB_addr); -//zz DIP(" => not implemented\n"); -//zz // CAB: Iop_SqrtF64, then one of the 128 bit SIMD Iop_Recip32F ops? -//zz return False; + case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424) + if (frA_addr != 0 || frC_addr != 0) { + vex_printf("dis_fp_arith(ppc)(instr,frsqrte)\n"); + return False; + } + DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"", + frD_addr, frB_addr); + assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) ); + break; default: vex_printf("dis_fp_arith(ppc)(3F: opc2)\n"); diff --git a/VEX/priv/host-ppc/hdefs.c b/VEX/priv/host-ppc/hdefs.c index 6d027285d2..4058e8a7b3 100644 --- a/VEX/priv/host-ppc/hdefs.c +++ b/VEX/priv/host-ppc/hdefs.c @@ -620,6 +620,8 @@ HChar* showPPCFpOp ( PPCFpOp op ) { case Pfp_ABS: return "fabs"; case Pfp_NEG: return "fneg"; case Pfp_MOV: return "fmr"; + case Pfp_RES: return "fres"; + case Pfp_RSQRTE: return "frsqrte"; default: vpanic("showPPCFpOp"); } } @@ -3124,6 +3126,12 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i, UInt fr_dst = fregNo(i->Pin.FpUnary.dst); UInt fr_src = fregNo(i->Pin.FpUnary.src); switch (i->Pin.FpUnary.op) { + case Pfp_RSQRTE: // frsqrtre, PPC32 p424 + p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 ); + break; + case Pfp_RES: // fres, PPC32 p421 + p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 ); + break; case Pfp_SQRT: // fsqrt, PPC32 p427 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 ); break; diff --git a/VEX/priv/host-ppc/hdefs.h b/VEX/priv/host-ppc/hdefs.h index 622ef48d45..ff2bdaae55 100644 --- a/VEX/priv/host-ppc/hdefs.h +++ b/VEX/priv/host-ppc/hdefs.h @@ -371,7 +371,7 @@ typedef Pfp_ADD, Pfp_SUB, Pfp_MUL, Pfp_DIV, /* Unary */ - Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV + Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE } PPCFpOp; diff --git a/VEX/priv/host-ppc/isel.c b/VEX/priv/host-ppc/isel.c index ac69f48671..7f725a614f 100644 --- a/VEX/priv/host-ppc/isel.c +++ b/VEX/priv/host-ppc/isel.c @@ -2876,9 +2876,11 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) if (e->tag == Iex_Unop) { PPCFpOp fpop = Pfp_INVALID; switch (e->Iex.Unop.op) { - case Iop_NegF64: fpop = Pfp_NEG; break; - case Iop_AbsF64: fpop = Pfp_ABS; break; - case Iop_SqrtF64: fpop = Pfp_SQRT; break; + case Iop_NegF64: fpop = Pfp_NEG; break; + case Iop_AbsF64: fpop = Pfp_ABS; break; + case Iop_SqrtF64: fpop = Pfp_SQRT; break; + case Iop_Est8FRecip: fpop = Pfp_RES; break; + case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break; default: break; } if (fpop != Pfp_INVALID) { diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 264b177f08..ffda4bc8bc 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -263,6 +263,9 @@ void ppIROp ( IROp op ) case Iop_TanF64: vex_printf("TanF64"); return; case Iop_2xm1F64: vex_printf("2xm1F64"); return; + case Iop_Est8FRecip: vex_printf("Est8FRecip"); return; + case Iop_Est5FRSqrt: vex_printf("Est5FRSqrt"); return; + case Iop_CmpF64: vex_printf("CmpF64"); return; case Iop_F64toI16: vex_printf("F64toI16"); return; @@ -1517,6 +1520,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) BINARY(Ity_I32,Ity_F64,Ity_F64); case Iop_NegF64: case Iop_AbsF64: case Iop_SqrtF64: case Iop_SinF64: case Iop_CosF64: case Iop_TanF64: case Iop_2xm1F64: + case Iop_Est8FRecip: case Iop_Est5FRSqrt: UNARY(Ity_F64,Ity_F64); case Iop_ReinterpI64asF64: UNARY(Ity_F64, Ity_I64); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 1e480b59e8..2a5d06e20f 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -331,7 +331,7 @@ typedef Iop_1Sto32, /* :: Ity_Bit -> Ity_I32, signed widen */ Iop_1Sto64, /* :: Ity_Bit -> Ity_I64, signed widen */ - /* ------ Floating point. We try and be IEEE754 compliant. ------ */ + /* ------ Floating point. We try to be IEEE754 compliant. ------ */ /* Binary operations mandated by IEEE754. */ Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, /* Iop_RemF64, */ @@ -359,6 +359,10 @@ typedef Iop_TanF64, /* FTAN */ Iop_2xm1F64, /* (2^arg - 1.0) */ + /* Unary ops supported by PPC but not mandated by 754. */ + Iop_Est8FRecip, /* reciprocal estimate, 8 good bits */ + Iop_Est5FRSqrt, /* reciprocal square root estimate, 5 good bits */ + /* Comparison, yielding GT/LT/EQ/UN(ordered), as per the following: 0x45 Unordered 0x01 LT