mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Merge pull request #9727 from hrydgard/arm64-jitcache-fix
ARM64: Don't rewrite the dispatcher when clearing the code cache
This commit is contained in:
commit
4b46bb4ecf
@ -302,7 +302,7 @@ const u8* ARM64XEmitter::AlignCode16()
|
||||
{
|
||||
int c = int((u64)m_code & 15);
|
||||
if (c)
|
||||
ReserveCodeSpace(16-c);
|
||||
ReserveCodeSpace(16 - c);
|
||||
return m_code;
|
||||
}
|
||||
|
||||
@ -509,7 +509,7 @@ void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const voi
|
||||
|
||||
distance >>= 2;
|
||||
|
||||
_assert_msg_(DYNA_REC, distance >= -0x3FFF && distance < 0x3FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
|
||||
_assert_msg_(DYNA_REC, distance >= -0x1FFF && distance < 0x1FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
|
||||
|
||||
Rt = DecodeReg(Rt);
|
||||
Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | \
|
||||
@ -3896,4 +3896,15 @@ void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||
}
|
||||
}
|
||||
|
||||
void ARM64CodeBlock::PoisonMemory(int offset) {
|
||||
u32* ptr = (u32*)(region + offset);
|
||||
u32* maxptr = (u32*)(region + region_size - offset);
|
||||
// If our memory isn't a multiple of u32 then this won't write the last remaining bytes with anything
|
||||
// Less than optimal, but there would be nothing we could do but throw a runtime warning anyway.
|
||||
// AArch64: 0xD4200000 = BRK 0
|
||||
while (ptr < maxptr)
|
||||
*ptr++ = 0xD4200000;
|
||||
FlushIcacheSection((u8 *)ptr, (u8 *)maxptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -985,15 +985,6 @@ private:
|
||||
class ARM64CodeBlock : public CodeBlock<ARM64XEmitter>
|
||||
{
|
||||
private:
|
||||
void PoisonMemory() override
|
||||
{
|
||||
u32* ptr = (u32*)region;
|
||||
u32* maxptr = (u32*)(region + region_size);
|
||||
// If our memory isn't a multiple of u32 then this won't write the last remaining bytes with anything
|
||||
// Less than optimal, but there would be nothing we could do but throw a runtime warning anyway.
|
||||
// AArch64: 0xD4200000 = BRK 0
|
||||
while (ptr < maxptr)
|
||||
*ptr++ = 0xD4200000;
|
||||
}
|
||||
void PoisonMemory(int offset) override;
|
||||
};
|
||||
}
|
||||
|
@ -3211,10 +3211,10 @@ void ARMXEmitter::VCVTF16F32(ARMReg Dest, ARMReg Src) {
|
||||
|
||||
// Always clear code space with breakpoints, so that if someone accidentally executes
|
||||
// uninitialized, it just breaks into the debugger.
|
||||
void ARMXCodeBlock::PoisonMemory() {
|
||||
void ARMXCodeBlock::PoisonMemory(int offset) {
|
||||
// TODO: this isn't right for ARM!
|
||||
memset(region, 0xCC, region_size);
|
||||
ResetCodePtr();
|
||||
memset(region + offset, 0xCC, region_size - offset);
|
||||
ResetCodePtr(offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -895,7 +895,7 @@ public:
|
||||
|
||||
class ARMXCodeBlock : public CodeBlock<ARMXEmitter> {
|
||||
public:
|
||||
void PoisonMemory() override;
|
||||
void PoisonMemory(int offset) override;
|
||||
};
|
||||
|
||||
// VFP Specific
|
||||
|
@ -42,7 +42,7 @@ template<class T> class CodeBlock : public CodeBlockCommon, public T, NonCopyabl
|
||||
private:
|
||||
// A privately used function to set the executable RAM space to something invalid.
|
||||
// For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction
|
||||
virtual void PoisonMemory() = 0;
|
||||
virtual void PoisonMemory(int offset) = 0;
|
||||
|
||||
public:
|
||||
CodeBlock() : writeStart_(nullptr) {}
|
||||
@ -58,14 +58,13 @@ public:
|
||||
|
||||
// Always clear code space with breakpoints, so that if someone accidentally executes
|
||||
// uninitialized, it just breaks into the debugger.
|
||||
void ClearCodeSpace() {
|
||||
void ClearCodeSpace(int offset) {
|
||||
if (PlatformIsWXExclusive()) {
|
||||
ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
} else {
|
||||
ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE | MEM_PROT_EXEC);
|
||||
}
|
||||
PoisonMemory();
|
||||
ResetCodePtr();
|
||||
// If not WX Exclusive, no need to call ProtectMemoryPages because we never change the protection from RWX.
|
||||
PoisonMemory(offset);
|
||||
ResetCodePtr(offset);
|
||||
}
|
||||
|
||||
// BeginWrite/EndWrite assume that we keep appending.
|
||||
@ -109,8 +108,8 @@ public:
|
||||
return T::GetCodePointer();
|
||||
}
|
||||
|
||||
void ResetCodePtr() {
|
||||
T::SetCodePointer(region);
|
||||
void ResetCodePtr(int offset) {
|
||||
T::SetCodePointer(region + offset);
|
||||
}
|
||||
|
||||
size_t GetSpaceLeft() const {
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "StringUtils.h"
|
||||
|
@ -53,7 +53,11 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||
va_start(args, format);
|
||||
CharArrayFromFormatV(buffer, sizeof(buffer)-1, format, args);
|
||||
va_end(args);
|
||||
|
||||
// Safe android logging
|
||||
#ifdef PPSSPP_PLATFORM(ANDROID)
|
||||
ELOG("%s: %s", caption, buffer);
|
||||
#endif
|
||||
// Normal logging
|
||||
ERROR_LOG(SYSTEM, "%s: %s", caption, buffer);
|
||||
|
||||
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
|
||||
|
@ -101,7 +101,7 @@ void ThunkManager::Init()
|
||||
void ThunkManager::Reset()
|
||||
{
|
||||
thunks.clear();
|
||||
ResetCodePtr();
|
||||
ResetCodePtr(0);
|
||||
}
|
||||
|
||||
void ThunkManager::Shutdown()
|
||||
|
@ -1980,9 +1980,9 @@ void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); }
|
||||
|
||||
void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); }
|
||||
|
||||
void XCodeBlock::PoisonMemory() {
|
||||
void XCodeBlock::PoisonMemory(int offset) {
|
||||
// x86/64: 0xCC = breakpoint
|
||||
memset(region, 0xCC, region_size);
|
||||
memset(region + offset, 0xCC, region_size - offset);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1061,7 +1061,7 @@ public:
|
||||
|
||||
class XCodeBlock : public CodeBlock<XEmitter> {
|
||||
public:
|
||||
void PoisonMemory() override;
|
||||
void PoisonMemory(int offset) override;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -152,7 +152,7 @@ void ArmJit::FlushPrefixV()
|
||||
void ArmJit::ClearCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
ClearCodeSpace();
|
||||
ClearCodeSpace(0);
|
||||
GenerateFixedCode();
|
||||
}
|
||||
|
||||
|
@ -318,10 +318,11 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
|
||||
}
|
||||
}
|
||||
|
||||
// Don't forget to zap the instruction cache! This must stay at the end of this function.
|
||||
FlushIcache();
|
||||
// Let's spare the pre-generated code from unprotect-reprotect.
|
||||
AlignCodePage();
|
||||
jitStartOffset = (int)(GetCodePtr() - start);
|
||||
// Don't forget to zap the instruction cache! This must stay at the end of this function.
|
||||
FlushIcache();
|
||||
EndWrite();
|
||||
}
|
||||
|
||||
|
@ -142,8 +142,7 @@ void Arm64Jit::FlushPrefixV() {
|
||||
void Arm64Jit::ClearCache() {
|
||||
ILOG("ARM64Jit: Clearing the cache!");
|
||||
blocks.Clear();
|
||||
ClearCodeSpace();
|
||||
GenerateFixedCode(jo);
|
||||
ClearCodeSpace(jitStartOffset);
|
||||
}
|
||||
|
||||
void Arm64Jit::InvalidateCacheAt(u32 em_address, int length) {
|
||||
|
@ -280,6 +280,8 @@ public:
|
||||
const u8 *applyRoundingMode;
|
||||
const u8 *updateRoundingMode;
|
||||
|
||||
int jitStartOffset;
|
||||
|
||||
// Indexed by FPCR FZ:RN bits for convenience. Uses SCRATCH2.
|
||||
const u8 *convertS0ToSCRATCH1[8];
|
||||
};
|
||||
|
@ -219,7 +219,7 @@ void Jit::UpdateRoundingMode() {
|
||||
void Jit::ClearCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
ClearCodeSpace();
|
||||
ClearCodeSpace(0);
|
||||
GenerateFixedCode(jo);
|
||||
}
|
||||
|
||||
|
@ -448,7 +448,7 @@ void JitSafeMemFuncs::Init(ThunkManager *thunks) {
|
||||
}
|
||||
|
||||
void JitSafeMemFuncs::Shutdown() {
|
||||
ResetCodePtr();
|
||||
ResetCodePtr(0);
|
||||
FreeCodeSpace();
|
||||
}
|
||||
|
||||
|
@ -1281,5 +1281,5 @@ VertexDecoderJitCache::VertexDecoderJitCache()
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Clear() {
|
||||
ClearCodeSpace();
|
||||
ClearCodeSpace(0);
|
||||
}
|
||||
|
@ -359,6 +359,9 @@ void SystemInfoScreen::CreateViews() {
|
||||
deviceSpecs->Add(new ItemHeader("System Information"));
|
||||
deviceSpecs->Add(new InfoItem("Name", System_GetProperty(SYSPROP_NAME)));
|
||||
deviceSpecs->Add(new InfoItem("Lang/Region", System_GetProperty(SYSPROP_LANGREGION)));
|
||||
std::string board = System_GetProperty(SYSPROP_BOARDNAME);
|
||||
if (!board.empty())
|
||||
deviceSpecs->Add(new InfoItem("Board", board));
|
||||
deviceSpecs->Add(new InfoItem("ABI", GetCompilerABI()));
|
||||
#ifdef _WIN32
|
||||
if (IsDebuggerPresent()) {
|
||||
|
@ -330,6 +330,7 @@ static std::queue<FrameCommand> frameCommands;
|
||||
std::string systemName;
|
||||
std::string langRegion;
|
||||
std::string mogaVersion;
|
||||
std::string boardName;
|
||||
|
||||
static float left_joystick_x_async;
|
||||
static float left_joystick_y_async;
|
||||
@ -419,6 +420,8 @@ std::string System_GetProperty(SystemProperty prop) {
|
||||
return langRegion;
|
||||
case SYSPROP_MOGA_VERSION:
|
||||
return mogaVersion;
|
||||
case SYSPROP_BOARDNAME:
|
||||
return boardName;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@ -548,7 +551,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||
std::string shortcut_param = GetJavaString(env, jshortcutParam);
|
||||
std::string cacheDir = GetJavaString(env, jcacheDir);
|
||||
std::string buildBoard = GetJavaString(env, jboard);
|
||||
|
||||
boardName = buildBoard;
|
||||
ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str());
|
||||
ILOG("NativeApp.init(): Launch shortcut parameter: %s", shortcut_param.c_str());
|
||||
|
||||
|
@ -155,6 +155,7 @@ enum SystemProperty {
|
||||
SYSPROP_NAME,
|
||||
SYSPROP_LANGREGION,
|
||||
SYSPROP_CPUINFO,
|
||||
SYSPROP_BOARDNAME,
|
||||
SYSPROP_CLIPBOARD_TEXT,
|
||||
SYSPROP_GPUDRIVER_VERSION,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user