return True;
case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
- IRTemp zeros = newTemp(Ity_V128);
DIP("vnmsubfp v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vC_addr, vB_addr);
- assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
- putVReg( vD_addr,
- binop(Iop_Sub32Fx4, mkexpr(zeros),
- binop(Iop_Sub32Fx4,
- binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC)),
- mkexpr(vB))) );
+ putVReg( vD_addr, binop(Iop_Sub32Fx4,
+ mkexpr(vB),
+ binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
return True;
}
UChar vB_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */
UInt opc2 = (theInstr >> 0) & 0x7FF; /* theInstr[0:10] */
+ IRTemp vB = newTemp(Ity_V128);
+ IRTemp vScale = newTemp(Ity_V128);
+ IRTemp vInvScale = newTemp(Ity_V128);
+ assign( vB, getVReg(vB_addr));
+
+ /* scale = 2^UIMM, cast to float, reinterpreted as uint */
+ float scale = (float)( (unsigned int) 1<<UIMM_5 );
+ assign( vScale, unop(Iop_Dup32x4, mkU32( *((unsigned int*)(&scale)) )) );
+ float inv_scale = 1/scale;
+ assign( vInvScale, unop(Iop_Dup32x4, mkU32( *((unsigned int*)(&inv_scale)) )) );
+
if (opc1 != 0x4) {
vex_printf("dis_av_fp_convert(PPC32)(instr)\n");
return False;
switch (opc2) {
case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr, binop(Iop_Mul32Fx4,
+ unop(Iop_I32UtoFx4, mkexpr(vB)),
+ mkexpr(vInvScale)) );
+ return True;
case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
- DIP(" => not implemented\n");
- return False;
+
+ putVReg( vD_addr, binop(Iop_Mul32Fx4,
+ unop(Iop_I32StoFx4, mkexpr(vB)),
+ mkexpr(vInvScale)) );
+ return True;
case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr,
+ unop(Iop_QFtoI32Ux4_RZ,
+ binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
+ return True;
case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr,
+ unop(Iop_QFtoI32Sx4_RZ,
+ binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
+ return True;
default:
break; // Fall through...
switch (opc2) {
case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
+ break;
case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
+ break;
case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
+ break;
case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
- DIP(" => not implemented\n");
- return False;
+ putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
+ break;
default:
vex_printf("dis_av_fp_convert(PPC32)(opc2)\n");
/* Floating Point Unary */
case Pavfp_RCPF: return "vrefp";
case Pavfp_RSQRTF: return "vrsqrtefp";
+ case Pavfp_CVTU2F: return "vcfux";
+ case Pavfp_CVTS2F: return "vcfsx";
+ case Pavfp_QCVTF2U: return "vctuxs";
+ case Pavfp_QCVTF2S: return "vctsxs";
+ case Pavfp_ROUNDM: return "vrfim";
+ case Pavfp_ROUNDP: return "vrfip";
+ case Pavfp_ROUNDN: return "vrfin";
+ case Pavfp_ROUNDZ: return "vrfiz";
- default: vpanic("showPPC32AvOp");
+ default: vpanic("showPPC32AvFpOp");
}
}
ppHRegPPC32(i->Pin.AvBin32x4.srcR);
return;
case Pin_AvBin32Fx4:
- vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
+ vex_printf("%s ", showPPC32AvFpOp(i->Pin.AvBin32Fx4.op));
ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
vex_printf(",");
ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
return;
case Pin_AvUn32Fx4:
- vex_printf("%s ", showPPC32AvOp(i->Pin.AvUn32Fx4.op));
+ vex_printf("%s ", showPPC32AvFpOp(i->Pin.AvUn32Fx4.op));
ppHRegPPC32(i->Pin.AvUn32Fx4.dst);
vex_printf(",");
ppHRegPPC32(i->Pin.AvUn32Fx4.src);
UInt vB = 29; // XXX: Using r29 for temp
UInt konst = 0x1F;
- // Better way to load zero_imm?
+ // Better way to load -0.0 (0x80000000) ?
// vspltisw vB,0x1F (0x1F => each word of vB)
p = mkFormVX( p, 4, vB, konst, 0, 908 );
UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
UInt opc2;
switch (i->Pin.AvUn32Fx4.op) {
- case Pavfp_RCPF: opc2 = 266; break; // vrefp
- case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
+ case Pavfp_RCPF: opc2 = 266; break; // vrefp
+ case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
+ case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
+ case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
+ case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
+ case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
+ case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
+ case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
+ case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
+ case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
default:
goto bad;
}