unconditional calls and returns (bl, blr). They should also be
emitted for conditional calls and returns, but we don't have a
way to express that right now. Ah well.
+
+ - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
+ ignores the rounding mode, and generates code that assumes
+ round-to-nearest. This means V will compute incorrect results
+ for uses of these IROps when the rounding mode (first) arg is
+ not mkU32(Irrm_NEAREST).
*/
/* "Special" instructions.
switch (opc2) {
case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
- putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) );
+ // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
+ putVSReg( XT, triop(Iop_Add32Fx4, rm,
+ getVSReg( XA ), getVSReg( XB )) );
break;
case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
- putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) );
+ // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
+ putVSReg( XT, triop(Iop_Mul32Fx4, rm,
+ getVSReg( XA ), getVSReg( XB )) );
break;
case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
- putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) );
+ // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
+ putVSReg( XT, triop(Iop_Sub32Fx4, rm,
+ getVSReg( XA ), getVSReg( XB )) );
break;
case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
return False;
}
+ IRTemp rm = newTemp(Ity_I32);
+ assign(rm, get_IR_roundingmode());
+
opc2 = IFIELD( theInstr, 0, 6 );
switch (opc2) {
case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
DIP("vmaddfp v%d,v%d,v%d,v%d\n",
vD_addr, vA_addr, vC_addr, vB_addr);
putVReg( vD_addr,
- binop(Iop_Add32Fx4, mkexpr(vB),
- binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
+ triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
+ mkexpr(vB),
+ triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
+ mkexpr(vA), mkexpr(vC))) );
return True;
case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
vD_addr, vA_addr, vC_addr, vB_addr);
putVReg( vD_addr,
- binop(Iop_Sub32Fx4,
+ triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
mkexpr(vB),
- binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
+ triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
+ mkexpr(vA), mkexpr(vC))) );
return True;
}
switch (opc2) {
case 0x00A: // vaddfp (Add FP, AV p137)
DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
- putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
+ putVReg( vD_addr, triop(Iop_Add32Fx4,
+ mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
return True;
case 0x04A: // vsubfp (Subtract FP, AV p261)
DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
- putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
+ putVReg( vD_addr, triop(Iop_Sub32Fx4,
+ mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
return True;
case 0x40A: // vmaxfp (Maximum FP, AV p178)
binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
assign( lt, unop(Iop_NotV128,
binop(Iop_CmpGE32Fx4, mkexpr(vA),
- binop(Iop_Sub32Fx4, mkexpr(zeros),
- mkexpr(vB)))) );
+ triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
+ mkexpr(zeros),
+ mkexpr(vB)))) );
// finally, just shift gt,lt to correct position
assign( vD, binop(Iop_ShlN32x4,
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);
- putVReg( vD_addr, binop(Iop_Mul32Fx4,
+ putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
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);
- putVReg( vD_addr, binop(Iop_Mul32Fx4,
+ putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
unop(Iop_I32StoFx4, mkexpr(vB)),
mkexpr(vInvScale)) );
return True;
DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
putVReg( vD_addr,
unop(Iop_QFtoI32Ux4_RZ,
- binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
+ triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
+ 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);
putVReg( vD_addr,
unop(Iop_QFtoI32Sx4_RZ,
- binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
+ triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
+ mkexpr(vB), mkexpr(vScale))) );
return True;
default: