Skip to content

Commit

Permalink
PPU LLVM : Match PS3 for the instructions fmadd, fmadds, fmsub, fmsub…
Browse files Browse the repository at this point in the history
…s, fnmadd, fnmadds, fnmsub, fnmsubs

Co-Authored-By: Eladash <18193363+elad335@users.noreply.github.com>
  • Loading branch information
doesthisusername and elad335 committed Mar 27, 2020
1 parent 2aac46e commit fb50f45
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 13 deletions.
5 changes: 5 additions & 0 deletions rpcs3/Emu/Cell/PPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1531,6 +1531,7 @@ extern void ppu_initialize(const ppu_module& info)
enum class ppu_settings : u32
{
non_win32,
accurate_fma,

__bitset_enum_max
};
Expand All @@ -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));
Expand Down
111 changes: 99 additions & 12 deletions rpcs3/Emu/Cell/PPUTranslator.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifdef LLVM_AVAILABLE

#include "Emu/system_config.h"
#include "PPUTranslator.h"
#include "PPUThread.h"
#include "PPUInterpreter.h"
Expand Down Expand Up @@ -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));
Expand All @@ -3896,8 +3907,21 @@ 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));
Expand All @@ -3914,8 +3938,21 @@ 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->CreateFNeg(m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma),
{
a, c, m_ir->CreateFNeg(b)
}));
}
else
{
result = m_ir->CreateFNeg(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));
Expand All @@ -3932,8 +3969,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->CreateFNeg(m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), {a, c, b}));
}
else
{
result = m_ir->CreateFNeg(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)); // TODO ???
//SetFPSCR_FI(Call(GetType<bool>(), m_pure_attr, "__fmadds_get_fi", a, b, c));
Expand Down Expand Up @@ -4182,7 +4229,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 ???
Expand All @@ -4200,7 +4257,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));
Expand All @@ -4218,7 +4285,17 @@ 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));

llvm::Value* result;
if (g_cfg.core.ppu_accurate_fma)
{
result = m_ir->CreateFNeg(m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), { a, c, m_ir->CreateFNeg(b) }));
}
else
{
result = m_ir->CreateFNeg(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 ???
Expand All @@ -4236,7 +4313,17 @@ 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));

llvm::Value* result;
if (g_cfg.core.ppu_accurate_fma)
{
result = m_ir->CreateFNeg(m_ir->CreateCall(get_intrinsic<f64>(llvm::Intrinsic::fma), { a, c, b }));
}
else
{
result = m_ir->CreateFNeg(m_ir->CreateFAdd(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 ???
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/PPUTranslator.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#ifdef LLVM_AVAILABLE

Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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", false };

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 };
Expand Down

0 comments on commit fb50f45

Please sign in to comment.