Skip to content

Commit

Permalink
PowerPC: Raise alignment exceptions in more situations
Browse files Browse the repository at this point in the history
Intends to improve https://bugs.dolphin-emu.org/issues/12565.

To avoid affecting the performance, the JITs will most of
the time not raise alignment exceptions unless you enable
the new INI-only setting AlignmentExceptions.
  • Loading branch information
JosJuice committed Jul 5, 2021
1 parent deb70fd commit ec3dcf7
Show file tree
Hide file tree
Showing 37 changed files with 669 additions and 501 deletions.
9 changes: 7 additions & 2 deletions Source/Core/Common/Arm64Emitter.cpp
Expand Up @@ -867,11 +867,16 @@ static constexpr u32 MaskImm26(s64 distance)
}

// FixupBranch branching
void ARM64XEmitter::SetJumpTarget(FixupBranch const& branch)
void ARM64XEmitter::SetJumpTarget(const FixupBranch& branch)
{
SetJumpTarget(branch, m_code);
}

void ARM64XEmitter::SetJumpTarget(const FixupBranch& branch, const u8* target)
{
bool Not = false;
u32 inst = 0;
s64 distance = (s64)(m_code - branch.ptr);
s64 distance = static_cast<s64>(target - branch.ptr);
distance >>= 2;

switch (branch.type)
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/Common/Arm64Emitter.h
Expand Up @@ -567,7 +567,8 @@ class ARM64XEmitter
u8* GetWritableCodePtr();

// FixupBranch branching
void SetJumpTarget(FixupBranch const& branch);
void SetJumpTarget(const FixupBranch& branch);
static void SetJumpTarget(const FixupBranch& branch, const u8* target);
FixupBranch CBZ(ARM64Reg Rt);
FixupBranch CBNZ(ARM64Reg Rt);
FixupBranch B(CCFlags cond);
Expand Down
20 changes: 20 additions & 0 deletions Source/Core/Common/x64Emitter.h
Expand Up @@ -1120,6 +1120,15 @@ class XEmitter
ABI_CallFunction(func);
}

// Pass two registers and one constant as parameters.
template <typename FunctionPointer>
void ABI_CallFunctionRRC(FunctionPointer func, X64Reg reg1, X64Reg reg2, u32 param3)
{
MOVTwo(64, ABI_PARAM1, reg1, 0, ABI_PARAM2, reg2);
MOV(32, R(ABI_PARAM3), Imm32(param3));
ABI_CallFunction(func);
}

// Pass a pointer and two registers as parameters.
template <typename FunctionPointer>
void ABI_CallFunctionPRR(FunctionPointer func, const void* ptr, X64Reg reg1, X64Reg reg2)
Expand All @@ -1138,6 +1147,17 @@ class XEmitter
ABI_CallFunction(func);
}

template <typename FunctionPointer>
void ABI_CallFunctionACC(int bits, FunctionPointer func, const Gen::OpArg& arg1, u32 param2,
u32 param3)
{
if (!arg1.IsSimpleReg(ABI_PARAM1))
MOV(bits, R(ABI_PARAM1), arg1);
MOV(32, R(ABI_PARAM2), Imm32(param2));
MOV(32, R(ABI_PARAM3), Imm32(param3));
ABI_CallFunction(func);
}

template <typename FunctionPointer>
void ABI_CallFunctionA(int bits, FunctionPointer func, const Gen::OpArg& arg1)
{
Expand Down
12 changes: 6 additions & 6 deletions Source/Core/Core/Boot/Boot_BS2Emu.cpp
Expand Up @@ -114,9 +114,9 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume)
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(*entry);
const u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
const u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
const u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0, UGeckoInstruction{});
const u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4, UGeckoInstruction{});
const u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8, UGeckoInstruction{});

// iAppLoaderInit
DEBUG_LOG_FMT(MASTER_LOG, "Call iAppLoaderInit");
Expand All @@ -141,9 +141,9 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume)
// iAppLoaderMain returns 0 when there are no more sections to copy.
while (PowerPC::ppcState.gpr[3] != 0x00)
{
const u32 ram_address = PowerPC::Read_U32(0x81300004);
const u32 length = PowerPC::Read_U32(0x81300008);
const u32 dvd_offset = PowerPC::Read_U32(0x8130000c) << (is_wii ? 2 : 0);
const u32 ram_address = PowerPC::Read_U32(0x81300004, UGeckoInstruction{});
const u32 length = PowerPC::Read_U32(0x81300008, UGeckoInstruction{});
const u32 dvd_offset = PowerPC::Read_U32(0x8130000c, UGeckoInstruction{}) << (is_wii ? 2 : 0);

INFO_LOG_FMT(MASTER_LOG, "DVDRead: offset: {:08x} memOffset: {:08x} length: {}", dvd_offset,
ram_address, length);
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/Core/BootManager.cpp
Expand Up @@ -77,6 +77,7 @@ struct ConfigCache
bool bJITFollowBranch;
bool bEnableCheats;
bool bSyncGPUOnSkipIdleHack;
bool bAlignmentExceptions;
bool bFPRF;
bool bAccurateNaNs;
bool bMMU;
Expand Down Expand Up @@ -112,6 +113,7 @@ void ConfigCache::SaveConfig(const SConfig& config)
bJITFollowBranch = config.bJITFollowBranch;
bEnableCheats = config.bEnableCheats;
bSyncGPUOnSkipIdleHack = config.bSyncGPUOnSkipIdleHack;
bAlignmentExceptions = config.bAlignmentExceptions;
bFPRF = config.bFPRF;
bAccurateNaNs = config.bAccurateNaNs;
bDisableICache = config.bDisableICache;
Expand Down Expand Up @@ -158,6 +160,7 @@ void ConfigCache::RestoreConfig(SConfig* config)
config->bJITFollowBranch = bJITFollowBranch;
config->bEnableCheats = bEnableCheats;
config->bSyncGPUOnSkipIdleHack = bSyncGPUOnSkipIdleHack;
config->bAlignmentExceptions = bAlignmentExceptions;
config->bFPRF = bFPRF;
config->bAccurateNaNs = bAccurateNaNs;
config->bDisableICache = bDisableICache;
Expand Down Expand Up @@ -261,6 +264,8 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
core_section->Get("EnableCheats", &StartUp.bEnableCheats, StartUp.bEnableCheats);
core_section->Get("SyncOnSkipIdle", &StartUp.bSyncGPUOnSkipIdleHack,
StartUp.bSyncGPUOnSkipIdleHack);
core_section->Get("AlignmentExceptions", &StartUp.bAlignmentExceptions,
StartUp.bAlignmentExceptions);
core_section->Get("FPRF", &StartUp.bFPRF, StartUp.bFPRF);
core_section->Get("AccurateNaNs", &StartUp.bAccurateNaNs, StartUp.bAccurateNaNs);
core_section->Get("DisableICache", &StartUp.bDisableICache, StartUp.bDisableICache);
Expand Down Expand Up @@ -373,6 +378,7 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
config_cache.bSetEXIDevice[0] = true;
config_cache.bSetEXIDevice[1] = true;
config_cache.bSetEXIDevice[2] = true;
StartUp.bAlignmentExceptions = netplay_settings.m_AlignmentExceptions;
StartUp.bFPRF = netplay_settings.m_FPRF;
StartUp.bAccurateNaNs = netplay_settings.m_AccurateNaNs;
StartUp.bDisableICache = netplay_settings.m_DisableICache;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/Config/MainSettings.cpp
Expand Up @@ -87,6 +87,7 @@ const Info<int> MAIN_SYNC_GPU_MIN_DISTANCE{{System::Main, "Core", "SyncGpuMinDis
const Info<float> MAIN_SYNC_GPU_OVERCLOCK{{System::Main, "Core", "SyncGpuOverclock"}, 1.0f};
const Info<bool> MAIN_FAST_DISC_SPEED{{System::Main, "Core", "FastDiscSpeed"}, false};
const Info<bool> MAIN_LOW_DCBZ_HACK{{System::Main, "Core", "LowDCBZHack"}, false};
const Info<bool> MAIN_ALIGNMENT_EXCEPTIONS{{System::Main, "Core", "AlignmentExceptions"}, false};
const Info<bool> MAIN_FPRF{{System::Main, "Core", "FPRF"}, false};
const Info<bool> MAIN_ACCURATE_NANS{{System::Main, "Core", "AccurateNaNs"}, false};
const Info<bool> MAIN_DISABLE_ICACHE{{System::Main, "Core", "DisableICache"}, false};
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/Config/MainSettings.h
Expand Up @@ -68,6 +68,7 @@ extern const Info<int> MAIN_SYNC_GPU_MIN_DISTANCE;
extern const Info<float> MAIN_SYNC_GPU_OVERCLOCK;
extern const Info<bool> MAIN_FAST_DISC_SPEED;
extern const Info<bool> MAIN_LOW_DCBZ_HACK;
extern const Info<bool> MAIN_ALIGNMENT_EXCEPTIONS;
extern const Info<bool> MAIN_FPRF;
extern const Info<bool> MAIN_ACCURATE_NANS;
extern const Info<bool> MAIN_DISABLE_ICACHE;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
Expand Up @@ -69,6 +69,7 @@ class NetPlayConfigLayerLoader final : public Config::ConfigLayerLoader
layer->Set(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES,
m_settings.m_SafeTextureCacheColorSamples);
layer->Set(Config::GFX_PERF_QUERIES_ENABLE, m_settings.m_PerfQueriesEnable);
layer->Set(Config::MAIN_ALIGNMENT_EXCEPTIONS, m_settings.m_AlignmentExceptions);
layer->Set(Config::MAIN_FPRF, m_settings.m_FPRF);
layer->Set(Config::MAIN_ACCURATE_NANS, m_settings.m_AccurateNaNs);
layer->Set(Config::MAIN_DISABLE_ICACHE, m_settings.m_DisableICache);
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Core/ConfigManager.cpp
Expand Up @@ -214,6 +214,7 @@ void SConfig::SaveCoreSettings(IniFile& ini)
core->Set("SyncGpuMaxDistance", iSyncGpuMaxDistance);
core->Set("SyncGpuMinDistance", iSyncGpuMinDistance);
core->Set("SyncGpuOverclock", fSyncGpuOverclock);
core->Set("AlignmentExceptions", bAlignmentExceptions);
core->Set("FPRF", bFPRF);
core->Set("AccurateNaNs", bAccurateNaNs);
core->Set("EnableCheats", bEnableCheats);
Expand Down Expand Up @@ -512,6 +513,7 @@ void SConfig::LoadCoreSettings(IniFile& ini)
core->Get("SyncGpuOverclock", &fSyncGpuOverclock, 1.0f);
core->Get("FastDiscSpeed", &bFastDiscSpeed, false);
core->Get("LowDCBZHack", &bLowDCBZHack, false);
core->Get("AlignmentExceptions", &bAlignmentExceptions, false);
core->Get("FPRF", &bFPRF, false);
core->Get("AccurateNaNs", &bAccurateNaNs, false);
core->Get("DisableICache", &bDisableICache, false);
Expand Down Expand Up @@ -750,6 +752,7 @@ void SConfig::LoadDefaults()
bRunCompareServer = false;
bDSPHLE = true;
bFastmem = true;
bAlignmentExceptions = false;
bFPRF = false;
bAccurateNaNs = false;
bDisableICache = false;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/ConfigManager.h
Expand Up @@ -109,6 +109,7 @@ struct SConfig
bool bJITRegisterCacheOff = false;

bool bFastmem;
bool bAlignmentExceptions = false;
bool bFPRF = false;
bool bAccurateNaNs = false;
bool bDisableICache = false;
Expand Down
8 changes: 4 additions & 4 deletions Source/Core/Core/FifoPlayer/FifoPlayer.cpp
Expand Up @@ -523,12 +523,12 @@ void FifoPlayer::LoadTextureMemory()

void FifoPlayer::WriteCP(u32 address, u16 value)
{
PowerPC::Write_U16(value, 0xCC000000 | address);
PowerPC::Write_U16(value, 0xCC000000 | address, UGeckoInstruction{});
}

void FifoPlayer::WritePI(u32 address, u32 value)
{
PowerPC::Write_U32(value, 0xCC003000 | address);
PowerPC::Write_U32(value, 0xCC003000 | address, UGeckoInstruction{});
}

void FifoPlayer::FlushWGP()
Expand Down Expand Up @@ -604,13 +604,13 @@ bool FifoPlayer::ShouldLoadXF(u8 reg)
bool FifoPlayer::IsIdleSet()
{
CommandProcessor::UCPStatusReg status =
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER, UGeckoInstruction{});
return status.CommandIdle;
}

bool FifoPlayer::IsHighWatermarkSet()
{
CommandProcessor::UCPStatusReg status =
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER);
PowerPC::Read_U16(0xCC000000 | CommandProcessor::STATUS_REGISTER, UGeckoInstruction{});
return status.OverflowHiWatermark;
}
2 changes: 1 addition & 1 deletion Source/Core/Core/HLE/HLE_OS.cpp
Expand Up @@ -103,7 +103,7 @@ void HLE_write_console()
std::string report_message = GetStringVA(4);
if (PowerPC::HostIsRAMAddress(GPR(5)))
{
const u32 size = PowerPC::Read_U32(GPR(5));
const u32 size = PowerPC::HostRead_U32(GPR(5));
if (size > report_message.size())
WARN_LOG_FMT(OSREPORT_HLE, "__write_console uses an invalid size of {:#010x}", size);
else if (size == 0)
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/NetPlayClient.cpp
Expand Up @@ -696,6 +696,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> m_net_settings.m_EFBEmulateFormatChanges;
packet >> m_net_settings.m_SafeTextureCacheColorSamples;
packet >> m_net_settings.m_PerfQueriesEnable;
packet >> m_net_settings.m_AlignmentExceptions;
packet >> m_net_settings.m_FPRF;
packet >> m_net_settings.m_AccurateNaNs;
packet >> m_net_settings.m_DisableICache;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/NetPlayProto.h
Expand Up @@ -58,6 +58,7 @@ struct NetSettings
bool m_EFBEmulateFormatChanges;
int m_SafeTextureCacheColorSamples;
bool m_PerfQueriesEnable;
bool m_AlignmentExceptions;
bool m_FPRF;
bool m_AccurateNaNs;
bool m_DisableICache;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/NetPlayServer.cpp
Expand Up @@ -1278,6 +1278,7 @@ bool NetPlayServer::SetupNetSettings()
settings.m_SafeTextureCacheColorSamples =
Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
settings.m_PerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
settings.m_AlignmentExceptions = Config::Get(Config::MAIN_ALIGNMENT_EXCEPTIONS);
settings.m_FPRF = Config::Get(Config::MAIN_FPRF);
settings.m_AccurateNaNs = Config::Get(Config::MAIN_ACCURATE_NANS);
settings.m_DisableICache = Config::Get(Config::MAIN_DISABLE_ICACHE);
Expand Down Expand Up @@ -1453,6 +1454,7 @@ bool NetPlayServer::StartGame()
spac << m_settings.m_EFBEmulateFormatChanges;
spac << m_settings.m_SafeTextureCacheColorSamples;
spac << m_settings.m_PerfQueriesEnable;
spac << m_settings.m_AlignmentExceptions;
spac << m_settings.m_FPRF;
spac << m_settings.m_AccurateNaNs;
spac << m_settings.m_DisableICache;
Expand Down
11 changes: 9 additions & 2 deletions Source/Core/Core/PowerPC/Interpreter/ExceptionUtils.h
Expand Up @@ -8,10 +8,17 @@
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PowerPC.h"

inline void GenerateAlignmentException(u32 address)
inline void GenerateAlignmentException(u32 effective_address, UGeckoInstruction inst)
{
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
PowerPC::ppcState.spr[SPR_DAR] = address;
PowerPC::ppcState.spr[SPR_DAR] = effective_address;

// It has not been hardware tested what gets used instead of RD and RA in
// the cases documented as undefined. For now, simply use RD and RA
const bool x = inst.OPCD >= 32;
const u32 op = x ? inst.SUBOP10 : (inst.OPCD >> 1);
const u32 dsisr = ((op >> 8) << 15) | ((op & 0b11111) << 10) | (inst.RD << 5) | (inst.RA);
PowerPC::ppcState.spr[SPR_DSISR] = dsisr;
}

inline void GenerateDSIException(u32 address)
Expand Down

0 comments on commit ec3dcf7

Please sign in to comment.