mirror of
https://github.com/RPCS3/rpcs3
synced 2024-11-02 11:45:30 +00:00
PPU: Implement PPU Traps Stubbing option
This commit is contained in:
parent
8e9d2fa70e
commit
f0cdd8ace6
4 changed files with 34 additions and 9 deletions
|
@ -65,6 +65,13 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
|||
const char* start = &value.front();
|
||||
const char* end = &value.back() + 1;
|
||||
int base = 10;
|
||||
int sign = +1;
|
||||
|
||||
if (start[0] == '-')
|
||||
{
|
||||
sign = -1;
|
||||
start += 1;
|
||||
}
|
||||
|
||||
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X'))
|
||||
{
|
||||
|
@ -75,12 +82,14 @@ bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
|||
|
||||
const auto ret = std::from_chars(start, end, result, base);
|
||||
|
||||
if (ret.ec != std::errc() || ret.ptr != end)
|
||||
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): invalid integer", value);
|
||||
return false;
|
||||
}
|
||||
|
||||
result *= sign;
|
||||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int('%s'): out of bounds (%d..%d)", value, min, max);
|
||||
|
|
|
@ -336,7 +336,7 @@ extern u32 ppu_lwarx(ppu_thread& ppu, u32 addr);
|
|||
extern u64 ppu_ldarx(ppu_thread& ppu, u32 addr);
|
||||
extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value);
|
||||
extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value);
|
||||
|
||||
extern void ppu_trap(ppu_thread& ppu, u64 addr);
|
||||
|
||||
|
||||
class ppu_scale_table_t
|
||||
|
@ -2903,7 +2903,8 @@ bool ppu_interpreter::TDI(ppu_thread& ppu, ppu_opcode_t op)
|
|||
((op.bo & 0x2) && a_ < b_) ||
|
||||
((op.bo & 0x1) && a_ > b_))
|
||||
{
|
||||
fmt::throw_exception("Trap!" HERE);
|
||||
ppu_trap(ppu, ppu.cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2920,7 +2921,8 @@ bool ppu_interpreter::TWI(ppu_thread& ppu, ppu_opcode_t op)
|
|||
((op.bo & 0x2) && a_ < b_) ||
|
||||
((op.bo & 0x1) && a_ > b_))
|
||||
{
|
||||
fmt::throw_exception("Trap!" HERE);
|
||||
ppu_trap(ppu, ppu.cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3261,7 +3263,8 @@ bool ppu_interpreter::TW(ppu_thread& ppu, ppu_opcode_t op)
|
|||
(static_cast<u32>(a) < static_cast<u32>(b) && (op.bo & 0x2)) ||
|
||||
(static_cast<u32>(a) > static_cast<u32>(b) && (op.bo & 0x1)))
|
||||
{
|
||||
fmt::throw_exception("Trap!" HERE);
|
||||
ppu_trap(ppu, ppu.cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3474,7 +3477,8 @@ bool ppu_interpreter::TD(ppu_thread& ppu, ppu_opcode_t op)
|
|||
((op.bo & 0x2) && a_ < b_) ||
|
||||
((op.bo & 0x1) && a_ > b_))
|
||||
{
|
||||
fmt::throw_exception("Trap!" HERE);
|
||||
ppu_trap(ppu, ppu.cia);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -998,10 +998,21 @@ extern __m128i sse_cellbe_lvrx_v0(u64 addr);
|
|||
extern void sse_cellbe_stvlx_v0(u64 addr, __m128i a);
|
||||
extern void sse_cellbe_stvrx_v0(u64 addr, __m128i a);
|
||||
|
||||
[[noreturn]] static void ppu_trap(ppu_thread& ppu, u64 addr)
|
||||
void ppu_trap(ppu_thread& ppu, u64 addr)
|
||||
{
|
||||
ppu.cia = ::narrow<u32>(addr);
|
||||
fmt::throw_exception("Trap! (0x%llx)", addr);
|
||||
verify(HERE), (addr & (~u64{UINT32_MAX} | 0x3)) == 0;
|
||||
ppu.cia = static_cast<u32>(addr);
|
||||
|
||||
u32 add = static_cast<u32>(g_cfg.core.stub_ppu_traps) * 4;
|
||||
|
||||
// If stubbing is enabled, check current instruction and the following
|
||||
if (!add || !vm::check_addr(ppu.cia, 4, vm::page_executable) || !vm::check_addr(ppu.cia + add, 4, vm::page_executable))
|
||||
{
|
||||
fmt::throw_exception("PPU Trap!" HERE);
|
||||
}
|
||||
|
||||
ppu_log.error("PPU Trap: Stubbing %d instructions %s.", std::abs(static_cast<s32>(add) / 4), add >> 31 ? "backwards" : "forwards");
|
||||
ppu.cia += add; // Skip instructions, hope for valid code (interprter may be invoked temporarily)
|
||||
}
|
||||
|
||||
[[noreturn]] static void ppu_error(ppu_thread& ppu, u64 addr, u32 op)
|
||||
|
|
|
@ -52,6 +52,7 @@ struct cfg_root : cfg::node
|
|||
cfg::_bool spu_approx_xfloat{ this, "Approximate xfloat", true };
|
||||
cfg::_bool llvm_accurate_dfma{ this, "LLVM Accurate DFMA", true }; // Enable accurate double-precision FMA for CPUs which do not support it natively
|
||||
cfg::_bool llvm_ppu_accurate_vector_nan{ this, "PPU LLVM Accurate Vector NaN values", false };
|
||||
cfg::_int<-64, 64> stub_ppu_traps{ this, "Stub PPU Traps", 0, true }; // Hack, skip PPU traps for rare cases where the trap is continueable (specify relative instructions to skip)
|
||||
|
||||
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…
Reference in a new issue