mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 12:32:43 +00:00
PPU LLVM: Add FMA accuracy setting (#7874)
* PPU LLVM : Match PS3 for the instructions fmadd, fmadds, fmsub, fmsubs, fnmadd, fnmadds, fnmsub, fnmsubs Co-authored-by: doesthisusername <yfirestorm@gmail.com>
This commit is contained in:
parent
fc3a134e7d
commit
92f821aeb1
@ -1531,6 +1531,7 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
enum class ppu_settings : u32
|
||||
{
|
||||
non_win32,
|
||||
accurate_fma,
|
||||
|
||||
__bitset_enum_max
|
||||
};
|
||||
@ -1540,6 +1541,10 @@ extern void ppu_initialize(const ppu_module& info)
|
||||
#ifndef _WIN32
|
||||
settings += ppu_settings::non_win32;
|
||||
#endif
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
settings += ppu_settings::accurate_fma;
|
||||
}
|
||||
|
||||
// Write version, hash, CPU, settings
|
||||
fmt::append(obj_name, "v3-tane-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||
|
@ -1,5 +1,6 @@
|
||||
#ifdef LLVM_AVAILABLE
|
||||
|
||||
#include "Emu/system_config.h"
|
||||
#include "PPUTranslator.h"
|
||||
#include "PPUThread.h"
|
||||
#include "PPUInterpreter.h"
|
||||
@ -3878,8 +3879,18 @@ void PPUTranslator::FMADDS(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFPTrunc(m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b), GetType<f32>());
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, b});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFPTrunc(result, GetType<f32>()));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fr", a, b, c));
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fi", a, b, c));
|
||||
@ -3896,8 +3907,18 @@ void PPUTranslator::FMSUBS(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFPTrunc(m_ir->CreateFSub(m_ir->CreateFMul(a, c), b), GetType<f32>());
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, m_ir->CreateFNeg(b)});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFPTrunc(result, GetType<f32>()));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fr", a, b, c)); // TODO ???
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fi", a, b, c));
|
||||
@ -3914,8 +3935,18 @@ void PPUTranslator::FNMSUBS(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFPTrunc(m_ir->CreateFNeg(m_ir->CreateFSub(m_ir->CreateFMul(a, c), b)), GetType<f32>());
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, m_ir->CreateFNeg(b)});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFNeg(m_ir->CreateFPTrunc(result, GetType<f32>())));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fr", a, b, c)); // TODO ???
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fi", a, b, c));
|
||||
@ -3932,8 +3963,18 @@ void PPUTranslator::FNMADDS(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFPTrunc(m_ir->CreateFNeg(m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b)), GetType<f32>());
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, b});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFNeg(m_ir->CreateFPTrunc(result, GetType<f32>())));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fr", a, b, c)); // TODO ???
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fi", a, b, c));
|
||||
@ -4182,7 +4223,17 @@ void PPUTranslator::FMSUB(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, m_ir->CreateFNeg(b)});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fr", a, b, c)); // TODO ???
|
||||
@ -4200,7 +4251,17 @@ void PPUTranslator::FMADD(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), { a, c, b });
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fr", a, b, c));
|
||||
@ -4218,8 +4279,18 @@ void PPUTranslator::FNMSUB(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFNeg(m_ir->CreateFSub(m_ir->CreateFMul(a, c), b));
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, m_ir->CreateFNeg(b)});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFSub(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFNeg(result));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fr", a, b, c)); // TODO ???
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fi", a, b, c));
|
||||
@ -4236,8 +4307,18 @@ void PPUTranslator::FNMADD(ppu_opcode_t op)
|
||||
const auto a = GetFpr(op.fra);
|
||||
const auto b = GetFpr(op.frb);
|
||||
const auto c = GetFpr(op.frc);
|
||||
const auto result = m_ir->CreateFNeg(m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b));
|
||||
SetFpr(op.frd, result);
|
||||
|
||||
llvm::Value* result;
|
||||
if (g_cfg.core.ppu_accurate_fma)
|
||||
{
|
||||
result = m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, b});
|
||||
}
|
||||
else
|
||||
{
|
||||
result = m_ir->CreateFAdd(m_ir->CreateFMul(a, c), b);
|
||||
}
|
||||
|
||||
SetFpr(op.frd, m_ir->CreateFNeg(result));
|
||||
|
||||
//SetFPSCR_FR(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fr", a, b, c)); // TODO ???
|
||||
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadd_get_fi", a, b, c));
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#ifdef LLVM_AVAILABLE
|
||||
|
||||
|
@ -45,6 +45,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_enum<tsx_usage> enable_TSX{ this, "Enable TSX", tsx_usage::enabled }; // Enable TSX. Forcing this on Haswell/Broadwell CPUs should be used carefully
|
||||
cfg::_bool spu_accurate_xfloat{ this, "Accurate xfloat", false };
|
||||
cfg::_bool spu_approx_xfloat{ this, "Approximate xfloat", true };
|
||||
cfg::_bool ppu_accurate_fma{ this, "PPU Accurate FMA", true }; // Enable accurate FMA for CPUs which do not support it natively (can't be disabled for CPUs which do support it)
|
||||
|
||||
cfg::_bool debug_console_mode{ this, "Debug Console Mode", false }; // Debug console emulation, not recommended
|
||||
cfg::_enum<lib_loading_type> lib_loading{ this, "Lib Loader", lib_loading_type::liblv2only };
|
||||
|
Loading…
x
Reference in New Issue
Block a user