+/*------------------------------------------------------------*/
+/*--- 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;
+}
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
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");
}
}
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;
}
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;
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) {
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;
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);
/* :: 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' */