diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 04fad178c6..01879d4d3a 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -4192,9 +4192,7 @@ private: } } - (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; - + (u64&)CPU.FPR[frd] = r; if(rc) UNK("fctiw."); } void FCTIWZ(u32 frd, u32 frb, bool rc) @@ -4232,10 +4230,7 @@ private: value = (u32)i; } - (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | value; - if (value == 0 && ( (u64&)b & DOUBLE_SIGN )) - (u64&)CPU.FPR[frd] |= 0x100000000ull; - + (u64&)CPU.FPR[frd] = (u64)value; if(rc) UNK("fctiwz."); } void FDIV(u32 frd, u32 fra, u32 frb, bool rc) @@ -4333,7 +4328,7 @@ private: { CPU.SetFPSCRException(FPSCR_ZX); } - CPU.FPR[frd] = static_cast(1.0 / sqrt(CPU.FPR[frb])); + CPU.FPR[frd] = 1.0 / sqrt(CPU.FPR[frb]); if(rc) UNK("frsqrte.");//CPU.UpdateCR1(CPU.FPR[frd]); } void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) @@ -4458,9 +4453,7 @@ private: } } - (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; - + (u64&)CPU.FPR[frd] = r; if(rc) UNK("fctid."); } void FCTIDZ(u32 frd, u32 frb, bool rc) @@ -4498,9 +4491,7 @@ private: r = (u64)i; } - (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; - + (u64&)CPU.FPR[frd] = r; if(rc) UNK("fctidz."); } void FCFID(u32 frd, u32 frb, bool rc) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 79f189fe03..91d97036f1 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -3991,8 +3991,7 @@ void Compiler::FDIVS(u32 frd, u32 fra, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); auto res_f64 = m_ir_builder->CreateFDiv(ra_f64, rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4007,8 +4006,7 @@ void Compiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); auto res_f64 = m_ir_builder->CreateFSub(ra_f64, rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4023,8 +4021,7 @@ void Compiler::FADDS(u32 frd, u32 fra, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4038,8 +4035,7 @@ void Compiler::FSQRTS(u32 frd, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); auto res_f64 = (Value *)m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::sqrt, m_ir_builder->getDoubleTy()), rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4052,7 +4048,8 @@ void Compiler::FSQRTS(u32 frd, u32 frb, bool rc) { void Compiler::FRES(u32 frd, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); auto res_f64 = m_ir_builder->CreateFDiv(ConstantFP::get(m_ir_builder->getDoubleTy(), 1.0), rb_f64); - SetFpr(frd, res_f64); + auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4067,8 +4064,7 @@ void Compiler::FMULS(u32 frd, u32 fra, u32 frc, bool rc) { auto rc_f64 = GetFpr(frc); auto res_f64 = m_ir_builder->CreateFMul(ra_f64, rc_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4084,8 +4080,7 @@ void Compiler::FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { auto rc_f64 = GetFpr(frc); auto res_f64 = (Value *)m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fmuladd, m_ir_builder->getDoubleTy()), ra_f64, rc_f64, rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4102,8 +4097,7 @@ void Compiler::FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { rb_f64 = m_ir_builder->CreateFNeg(rb_f64); auto res_f64 = (Value *)m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fmuladd, m_ir_builder->getDoubleTy()), ra_f64, rc_f64, rb_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4121,8 +4115,7 @@ void Compiler::FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { auto res_f64 = (Value *)m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fmuladd, m_ir_builder->getDoubleTy()), ra_f64, rc_f64, rb_f64); res_f64 = m_ir_builder->CreateFNeg(res_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4139,8 +4132,7 @@ void Compiler::FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { auto res_f64 = (Value *)m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fmuladd, m_ir_builder->getDoubleTy()), ra_f64, rc_f64, rb_f64); res_f64 = m_ir_builder->CreateFNeg(res_f64); auto res_f32 = m_ir_builder->CreateFPTrunc(res_f64, m_ir_builder->getFloatTy()); - res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); - SetFpr(frd, res_f64); + SetFpr(frd, res_f32); if (rc) { // TODO: Implement this @@ -4194,27 +4186,68 @@ void Compiler::MTFSF(u32 flm, u32 frb, bool rc) { } void Compiler::FCMPU(u32 crfd, u32 fra, u32 frb) { - InterpreterCall("FCMPU", &PPUInterpreter::FCMPU, crfd, fra, frb); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto lt_i1 = m_ir_builder->CreateFCmpOLT(ra_f64, rb_f64); + auto gt_i1 = m_ir_builder->CreateFCmpOGT(ra_f64, rb_f64); + auto eq_i1 = m_ir_builder->CreateFCmpOEQ(ra_f64, rb_f64); + auto cr_i32 = GetCr(); + cr_i32 = SetNibble(cr_i32, crfd, lt_i1, gt_i1, eq_i1, m_ir_builder->getInt1(false)); + SetCr(cr_i32); + + // TODO: Set flags / Handle NaN } void Compiler::FRSP(u32 frd, u32 frb, bool rc) { - InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc); + auto rb_f64 = GetFpr(frb); + auto res_f32 = m_ir_builder->CreateFPTrunc(rb_f64, m_ir_builder->getFloatTy()); + auto res_f64 = m_ir_builder->CreateFPExt(res_f32, m_ir_builder->getDoubleTy()); + SetFpr(frd, res_f64); + + if (rc) { + // TODO: Implement this + CompilationError("FRSP."); + } + + // TODO: Revisit this + // TODO: Set flags } void Compiler::FCTIW(u32 frd, u32 frb, bool rc) { - auto rb_f64 = GetFpr(frb); + auto rb_f64 = GetFpr(frb); + auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFF)); + auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648)); auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty()); - SetFpr(frd, res_i32); + auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty()); + res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64); + res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x80000000), res_i64); + SetFpr(frd, res_i64); if (rc) { // TODO: Implement this CompilationError("FCTIW."); } - // TODO: Set flags / Handle NaN / Implement Saturation + // TODO: Set flags / Implement rounding modes + //InterpreterCall("FCTIW", &PPUInterpreter::FCTIWZ, frd, frb, rc); } void Compiler::FCTIWZ(u32 frd, u32 frb, bool rc) { + //auto rb_f64 = GetFpr(frb); + //auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFF)); + //auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -2147483648)); + //auto res_i32 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt32Ty()); + //auto res_i64 = m_ir_builder->CreateZExt(res_i32, m_ir_builder->getInt64Ty()); + //res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFF), res_i64); + //res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x80000000), res_i64); + //SetFpr(frd, res_i64); + + //if (rc) { + // // TODO: Implement this + // CompilationError("FCTIWZ."); + //} + + // TODO: Set flags InterpreterCall("FCTIWZ", &PPUInterpreter::FCTIWZ, frd, frb, rc); } @@ -4274,7 +4307,19 @@ void Compiler::FSQRT(u32 frd, u32 frb, bool rc) { } void Compiler::FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { - InterpreterCall("FSEL", &PPUInterpreter::FSEL, frd, fra, frc, frb, rc); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto rc_f64 = GetFpr(frc); + auto cmp_i1 = m_ir_builder->CreateFCmpOGE(ra_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0.0)); + auto res_f64 = m_ir_builder->CreateSelect(cmp_i1, rc_f64, rb_f64); + SetFpr(frd, res_f64); + + if (rc) { + // TODO: Implement this + CompilationError("FSEL."); + } + + // TODO: Set flags } void Compiler::FMUL(u32 frd, u32 fra, u32 frc, bool rc) { @@ -4368,7 +4413,16 @@ void Compiler::FNMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { } void Compiler::FCMPO(u32 crfd, u32 fra, u32 frb) { - InterpreterCall("FCMPO", &PPUInterpreter::FCMPO, crfd, fra, frb); + auto ra_f64 = GetFpr(fra); + auto rb_f64 = GetFpr(frb); + auto lt_i1 = m_ir_builder->CreateFCmpOLT(ra_f64, rb_f64); + auto gt_i1 = m_ir_builder->CreateFCmpOGT(ra_f64, rb_f64); + auto eq_i1 = m_ir_builder->CreateFCmpOEQ(ra_f64, rb_f64); + auto cr_i32 = GetCr(); + cr_i32 = SetNibble(cr_i32, crfd, lt_i1, gt_i1, eq_i1, m_ir_builder->getInt1(false)); + SetCr(cr_i32); + + // TODO: Set flags / Handle NaN } void Compiler::FNEG(u32 frd, u32 frb, bool rc) { @@ -4424,7 +4478,11 @@ void Compiler::FABS(u32 frd, u32 frb, bool rc) { void Compiler::FCTID(u32 frd, u32 frb, bool rc) { auto rb_f64 = GetFpr(frb); + auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFFFFFFFFFFll)); + auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808ll)); auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty()); + res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64); + res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64); SetFpr(frd, res_i64); if (rc) { @@ -4432,10 +4490,25 @@ void Compiler::FCTID(u32 frd, u32 frb, bool rc) { CompilationError("FCTID."); } - // TODO: Set flags / Handle NaN / Implement Saturation + // TODO: Set flags / Implement rounding modes + //InterpreterCall("FCTIDZ", &PPUInterpreter::FCTID, frd, frb, rc); } void Compiler::FCTIDZ(u32 frd, u32 frb, bool rc) { + //auto rb_f64 = GetFpr(frb); + //auto max_i1 = m_ir_builder->CreateFCmpOGT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), 0x7FFFFFFFFFFFFFFFll)); + //auto min_i1 = m_ir_builder->CreateFCmpULT(rb_f64, ConstantFP::get(m_ir_builder->getDoubleTy(), -9223372036854775808ll)); + //auto res_i64 = m_ir_builder->CreateFPToSI(rb_f64, m_ir_builder->getInt64Ty()); + //res_i64 = m_ir_builder->CreateSelect(max_i1, m_ir_builder->getInt64(0x7FFFFFFFFFFFFFFF), res_i64); + //res_i64 = m_ir_builder->CreateSelect(min_i1, m_ir_builder->getInt64(0x8000000000000000), res_i64); + //SetFpr(frd, res_i64); + + //if (rc) { + // // TODO: Implement this + // CompilationError("FCTIDZ."); + //} + + // TODO: Set flags InterpreterCall("FCTIDZ", &PPUInterpreter::FCTIDZ, frd, frb, rc); } diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index 9acb6ddfc4..855c18e287 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -164,7 +164,7 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp std::string ret; for (int i = 0; i < 32; i++) { - ret += fmt::Format("GPR[%02d] = 0x%016llx FPR[%02d] = %16g VPR[%02d] = 0x%s [%s]\n", i, GPR[i], i, FPR[i]._double, i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str()); + ret += fmt::Format("GPR[%02d] = 0x%016llx FPR[%02d] = %16g (0x%016llx) VPR[%02d] = 0x%s [%s]\n", i, GPR[i], i, FPR[i]._double, FPR[i]._u64, i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str()); } for (int i = 0; i < 8; i++) { @@ -663,17 +663,22 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMSUBS, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMSUBS, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMADDS, 0, 5, 0, 1, 2, 3, false); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCMPU, 0, 5, 5, 0, 1); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FRSP, 0, 5, 0, 1, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIW, 0, 5, 0, 1, false); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIWZ, 0, 5, 0, 1, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FDIV, 0, 5, 0, 1, 2, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSUB, 0, 5, 0, 1, 2, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FADD, 0, 5, 0, 1, 2, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRT, 0, 5, 0, 1, false); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSEL, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMUL, 0, 5, 0, 1, 2, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FRSQRTE, 0, 5, 0, 1, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMSUB, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMADD, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMSUB, 0, 5, 0, 1, 2, 3, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMADD, 0, 5, 0, 1, 2, 3, false); + VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCMPO, 0, 5, 3, 0, 1); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNEG, 0, 5, 0, 1, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMR, 0, 5, 0, 1, false); VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNABS, 0, 5, 0, 1, false);