From: Julian Seward Date: Fri, 8 Aug 2008 08:37:06 +0000 (+0000) Subject: Handle frin, frim, frip, friz, in 64-bit mode only, for now. X-Git-Tag: svn/VALGRIND_3_4_1^2~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a9e6bee6e30d8339c0621f3031dbcdbb01c5b81;p=thirdparty%2Fvalgrind.git Handle frin, frim, frip, friz, in 64-bit mode only, for now. git-svn-id: svn://svn.valgrind.org/vex/trunk@1862 --- diff --git a/VEX/priv/guest-ppc/toIR.c b/VEX/priv/guest-ppc/toIR.c index efe771ef6a..1605a409d6 100644 --- a/VEX/priv/guest-ppc/toIR.c +++ b/VEX/priv/guest-ppc/toIR.c @@ -8845,6 +8845,66 @@ static Bool dis_av_fp_convert ( UInt theInstr ) +/*------------------------------------------------------------*/ +/*--- POWER6 Instruction Translation ---*/ +/*------------------------------------------------------------*/ + +static +Bool dis_P6 ( UInt theInstr, + Bool allow_F, Bool allow_V, Bool allow_FX, Bool allow_GX) +{ + /* This is a hack. We should do P6 capability checking properly. + But anyway, make a guess at whether we should even try to handle + this instruction. All P6 capable CPUs should be able to handle + F, V, FX and GX, so that seems like a good check. */ + if (! (allow_F && allow_V && allow_FX && allow_GX) ) + return False; + if (!mode64) + return False; /* only support P6 in 64-bit mode for now */ + + UInt opc = ifieldOPC(theInstr); /* primary opcode */ + UInt rd = ifieldRegDS(theInstr); /* dst reg */ + UInt ra = ifieldRegA(theInstr); /* first source reg */ + UInt rb = ifieldRegB(theInstr); /* second source reg */ + UInt opc2 = ifieldOPClo10(theInstr); /* secondary opc, 10:1 */ + UInt dot = ifieldBIT0(theInstr); /* Rc field, bit 0 */ + + if (opc == 63 && ra == 0/*presumably*/ && opc2 == 488) { + /* frim (Floating Round to Integer Minus, PPC ISA 2.05 p137) */ + if (dot) return False; + putFReg( rd, unop(Iop_RoundF64toF64_NegINF, getFReg( rb )) ); + DIP("frim%s fr%u,fr%u\n", dot ? "." : "", rd, rb); + return True; + } + + if (opc == 63 && ra == 0/*presumably*/ && opc2 == 456) { + /* frip (Floating Round to Integer Plus, PPC ISA 2.05 p137) */ + if (dot) return False; + putFReg( rd, unop(Iop_RoundF64toF64_PosINF, getFReg( rb )) ); + DIP("frip%s fr%u,fr%u\n", dot ? "." : "", rd, rb); + return True; + } + + if (opc == 63 && ra == 0/*presumably*/ && opc2 == 392) { + /* frin (Floating Round to Integer Nearest, PPC ISA 2.05 p137) */ + if (dot) return False; + putFReg( rd, unop(Iop_RoundF64toF64_NEAREST, getFReg( rb )) ); + DIP("frin%s fr%u,fr%u\n", dot ? "." : "", rd, rb); + return True; + } + + if (opc == 63 && ra == 0/*presumably*/ && opc2 == 424) { + /* frin (Floating Round to Integer Zero, PPC ISA 2.05 p137) */ + if (dot) return False; + putFReg( rd, unop(Iop_RoundF64toF64_ZERO, getFReg( rb )) ); + DIP("friz%s fr%u,fr%u\n", dot ? "." : "", rd, rb); + return True; + } + + if (0) + vex_printf("dis_P6: %u %u %u %u %u %u\n", opc, rd, ra, rb, opc2, dot); + return False; +} @@ -9164,6 +9224,15 @@ DisResult disInstr_PPC_WRK ( case 0x34E: // fcfid if (dis_fp_round(theInstr)) goto decode_success; goto decode_failure; + + /* Power6 rounding stuff */ + case 0x1E8: // frim + case 0x1C8: // frip + case 0x188: // frin + case 0x1A8: // friz + if (dis_P6(theInstr, allow_F, allow_V, allow_FX, allow_GX)) + goto decode_success; + goto decode_failure; /* Floating Point Move Instructions */ case 0x028: // fneg diff --git a/VEX/priv/host-ppc/hdefs.c b/VEX/priv/host-ppc/hdefs.c index cc5d4788fa..1709a139a8 100644 --- a/VEX/priv/host-ppc/hdefs.c +++ b/VEX/priv/host-ppc/hdefs.c @@ -630,6 +630,10 @@ HChar* showPPCFpOp ( PPCFpOp op ) { case Pfp_MOV: return "fmr"; case Pfp_RES: return "fres"; case Pfp_RSQRTE: return "frsqrte"; + case Pfp_FRIM: return "frim"; + case Pfp_FRIN: return "frin"; + case Pfp_FRIP: return "frip"; + case Pfp_FRIZ: return "friz"; default: vpanic("showPPCFpOp"); } } @@ -3165,6 +3169,18 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i, case Pfp_MOV: // fmr, PPC32 p410 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0); break; + case Pfp_FRIM: // frim, PPC ISA 2.05 p137 + p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0); + break; + case Pfp_FRIP: // frip, PPC ISA 2.05 p137 + p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0); + break; + case Pfp_FRIN: // frin, PPC ISA 2.05 p137 + p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0); + break; + case Pfp_FRIZ: // friz, PPC ISA 2.05 p137 + p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0); + break; default: goto bad; } diff --git a/VEX/priv/host-ppc/hdefs.h b/VEX/priv/host-ppc/hdefs.h index 51c3bf1211..c36d42dc45 100644 --- a/VEX/priv/host-ppc/hdefs.h +++ b/VEX/priv/host-ppc/hdefs.h @@ -377,7 +377,8 @@ typedef Pfp_ADDS, Pfp_SUBS, Pfp_MULS, Pfp_DIVS, /* Unary */ - Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE + Pfp_SQRT, Pfp_ABS, Pfp_NEG, Pfp_MOV, Pfp_RES, Pfp_RSQRTE, + Pfp_FRIN, Pfp_FRIM, Pfp_FRIP, Pfp_FRIZ } PPCFpOp; diff --git a/VEX/priv/host-ppc/isel.c b/VEX/priv/host-ppc/isel.c index d33b27784b..c72c769892 100644 --- a/VEX/priv/host-ppc/isel.c +++ b/VEX/priv/host-ppc/isel.c @@ -3242,6 +3242,10 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) case Iop_NegF64: fpop = Pfp_NEG; break; case Iop_AbsF64: fpop = Pfp_ABS; break; case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break; + case Iop_RoundF64toF64_NegINF: fpop = Pfp_FRIM; break; + case Iop_RoundF64toF64_PosINF: fpop = Pfp_FRIP; break; + case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break; + case Iop_RoundF64toF64_ZERO: fpop = Pfp_FRIZ; break; default: break; } if (fpop != Pfp_INVALID) { diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 7539f95bc0..c46e3ed9bb 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -277,6 +277,11 @@ void ppIROp ( IROp op ) case Iop_MSubF64r32: vex_printf("MSubF64r32"); return; case Iop_Est5FRSqrt: vex_printf("Est5FRSqrt"); return; + case Iop_RoundF64toF64_NEAREST: vex_printf("RoundF64toF64_NEAREST"); return; + case Iop_RoundF64toF64_NegINF: vex_printf("RoundF64toF64_NegINF"); return; + case Iop_RoundF64toF64_PosINF: vex_printf("RoundF64toF64_PosINF"); return; + case Iop_RoundF64toF64_ZERO: vex_printf("RoundF64toF64_ZERO"); return; + case Iop_TruncF64asF32: vex_printf("TruncF64asF32"); return; case Iop_CalcFPRF: vex_printf("CalcFPRF"); return; @@ -1709,6 +1714,8 @@ void typeOfPrimop ( IROp op, QUATERNARY(ity_RMode,Ity_F64,Ity_F64,Ity_F64, Ity_F64); case Iop_Est5FRSqrt: + case Iop_RoundF64toF64_NEAREST: case Iop_RoundF64toF64_NegINF: + case Iop_RoundF64toF64_PosINF: case Iop_RoundF64toF64_ZERO: UNARY(Ity_F64, Ity_F64); case Iop_RoundF64toF32: BINARY(ity_RMode,Ity_F64, Ity_F64); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 232f189c97..4fa195df73 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -630,6 +630,10 @@ typedef /* :: F64 -> F64 */ Iop_Est5FRSqrt, /* reciprocal square root estimate, 5 good bits */ + Iop_RoundF64toF64_NEAREST, /* frin */ + Iop_RoundF64toF64_NegINF, /* frim */ + Iop_RoundF64toF64_PosINF, /* frip */ + Iop_RoundF64toF64_ZERO, /* friz */ /* :: F64 -> F32 */ Iop_TruncF64asF32, /* do F64->F32 truncation as per 'fsts' */