|
From: <sv...@va...> - 2008-08-08 08:37:01
|
Author: sewardj
Date: 2008-08-08 09:37:06 +0100 (Fri, 08 Aug 2008)
New Revision: 1862
Log:
Handle frin, frim, frip, friz, in 64-bit mode only, for now.
Modified:
trunk/priv/guest-ppc/toIR.c
trunk/priv/host-ppc/hdefs.c
trunk/priv/host-ppc/hdefs.h
trunk/priv/host-ppc/isel.c
trunk/priv/ir/irdefs.c
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest-ppc/toIR.c
===================================================================
--- trunk/priv/guest-ppc/toIR.c 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/priv/guest-ppc/toIR.c 2008-08-08 08:37:06 UTC (rev 1862)
@@ -8845,9 +8845,69 @@
+/*------------------------------------------------------------*/
+/*--- 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;
+}
+
+
+
/*------------------------------------------------------------*/
/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
@@ -9164,6 +9224,15 @@
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
Modified: trunk/priv/host-ppc/hdefs.c
===================================================================
--- trunk/priv/host-ppc/hdefs.c 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/priv/host-ppc/hdefs.c 2008-08-08 08:37:06 UTC (rev 1862)
@@ -630,6 +630,10 @@
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 @@
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;
}
Modified: trunk/priv/host-ppc/hdefs.h
===================================================================
--- trunk/priv/host-ppc/hdefs.h 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/priv/host-ppc/hdefs.h 2008-08-08 08:37:06 UTC (rev 1862)
@@ -377,7 +377,8 @@
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;
Modified: trunk/priv/host-ppc/isel.c
===================================================================
--- trunk/priv/host-ppc/isel.c 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/priv/host-ppc/isel.c 2008-08-08 08:37:06 UTC (rev 1862)
@@ -3242,6 +3242,10 @@
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) {
Modified: trunk/priv/ir/irdefs.c
===================================================================
--- trunk/priv/ir/irdefs.c 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/priv/ir/irdefs.c 2008-08-08 08:37:06 UTC (rev 1862)
@@ -277,6 +277,11 @@
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 @@
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);
Modified: trunk/pub/libvex_ir.h
===================================================================
--- trunk/pub/libvex_ir.h 2008-08-06 19:13:42 UTC (rev 1861)
+++ trunk/pub/libvex_ir.h 2008-08-08 08:37:06 UTC (rev 1862)
@@ -630,6 +630,10 @@
/* :: 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' */
|