arm64jit: Update rounding mode on thread switch.
Since fcr31 is per-thread, we must update jit state when it changes. This also fixes the rounding mode on load state and jit/interp switch.
This commit is contained in:
parent
7d3fac2b4b
commit
09e307b097
14 changed files with 39 additions and 6 deletions
|
@ -31,6 +31,7 @@
|
|||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
|
||||
|
@ -1460,6 +1461,10 @@ void __KernelLoadContext(ThreadContext *ctx, bool vfpuEnabled)
|
|||
}
|
||||
|
||||
memcpy(currentMIPS->other, ctx->other, sizeof(ctx->other));
|
||||
if (MIPSComp::jit) {
|
||||
// When thread switching, we must update the rounding mode if cached in the jit.
|
||||
MIPSComp::jit->UpdateFCR31();
|
||||
}
|
||||
|
||||
// Reset the llBit, the other thread may have touched memory.
|
||||
currentMIPS->llBit = 0;
|
||||
|
|
|
@ -106,6 +106,9 @@ void ArmJit::DoState(PointerWrap &p)
|
|||
}
|
||||
}
|
||||
|
||||
void ArmJit::UpdateFCR31() {
|
||||
}
|
||||
|
||||
void ArmJit::FlushAll()
|
||||
{
|
||||
gpr.FlushAll();
|
||||
|
|
|
@ -175,6 +175,7 @@ public:
|
|||
|
||||
void ClearCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
void UpdateFCR31() override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ Arm64Jit::Arm64Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &js, &jo), f
|
|||
AllocCodeSpace(1024 * 1024 * 16); // 32MB is the absolute max because that's what an ARM branch instruction can reach, backwards and forwards.
|
||||
GenerateFixedCode(jo);
|
||||
js.startDefaultPrefix = mips_->HasDefaultPrefix();
|
||||
js.currentRoundingFunc = convertS0ToSCRATCH1[0];
|
||||
js.currentRoundingFunc = convertS0ToSCRATCH1[mips_->fcr31 & 3];
|
||||
}
|
||||
|
||||
Arm64Jit::~Arm64Jit() {
|
||||
|
@ -98,13 +98,14 @@ void Arm64Jit::DoState(PointerWrap &p) {
|
|||
js.hasSetRounding = 1;
|
||||
}
|
||||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ) {
|
||||
js.currentRoundingFunc = convertS0ToSCRATCH1[(mips_->fcr31) & 3];
|
||||
}
|
||||
// Note: we can't update the currentRoundingFunc here because fcr31 wasn't loaded yet.
|
||||
}
|
||||
|
||||
void Arm64Jit::FlushAll()
|
||||
{
|
||||
void Arm64Jit::UpdateFCR31() {
|
||||
js.currentRoundingFunc = convertS0ToSCRATCH1[mips_->fcr31 & 3];
|
||||
}
|
||||
|
||||
void Arm64Jit::FlushAll() {
|
||||
gpr.FlushAll();
|
||||
fpr.FlushAll();
|
||||
FlushPrefixV();
|
||||
|
|
|
@ -176,6 +176,7 @@ public:
|
|||
|
||||
void ClearCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
void UpdateFCR31() override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ void IRJit::DoState(PointerWrap &p) {
|
|||
frontend_.DoState(p);
|
||||
}
|
||||
|
||||
void IRJit::UpdateFCR31() {
|
||||
}
|
||||
|
||||
void IRJit::ClearCache() {
|
||||
ILOG("IRJit: Clearing the cache!");
|
||||
blocks_.Clear();
|
||||
|
|
|
@ -158,6 +158,7 @@ public:
|
|||
|
||||
void ClearCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
void UpdateFCR31() override;
|
||||
|
||||
const u8 *GetDispatcher() const override { return nullptr; }
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ namespace MIPSComp {
|
|||
virtual void Compile(u32 em_address) = 0;
|
||||
virtual void CompileFunction(u32 start_address, u32 length) { }
|
||||
virtual void ClearCache() = 0;
|
||||
virtual void UpdateFCR31() = 0;
|
||||
virtual MIPSOpcode GetOriginalOp(MIPSOpcode op) = 0;
|
||||
|
||||
// No jit operations may be run between these calls.
|
||||
|
|
|
@ -293,6 +293,11 @@ void MIPSState::DoState(PointerWrap &p) {
|
|||
p.Do(inDelaySlot);
|
||||
p.Do(llBit);
|
||||
p.Do(debugCount);
|
||||
|
||||
if (p.mode == p.MODE_READ && MIPSComp::jit) {
|
||||
// Now that we've loaded fcr31, update any jit state associated.
|
||||
MIPSComp::jit->UpdateFCR31();
|
||||
}
|
||||
}
|
||||
|
||||
void MIPSState::SingleStep() {
|
||||
|
|
|
@ -66,6 +66,9 @@ void MipsJit::DoState(PointerWrap &p)
|
|||
}
|
||||
}
|
||||
|
||||
void MipsJit::UpdateFCR31() {
|
||||
}
|
||||
|
||||
void MipsJit::FlushAll()
|
||||
{
|
||||
//gpr.FlushAll();
|
||||
|
|
|
@ -136,6 +136,7 @@ public:
|
|||
|
||||
void ClearCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
void UpdateFCR31() override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
|
|
|
@ -528,6 +528,10 @@ namespace MIPSInt
|
|||
if (fs == 31) {
|
||||
currentMIPS->fcr31 = value & 0x0181FFFF;
|
||||
currentMIPS->fpcond = (value >> 23) & 1;
|
||||
if (MIPSComp::jit) {
|
||||
// In case of DISABLE, we need to tell jit we updated FCR31.
|
||||
MIPSComp::jit->UpdateFCR31();
|
||||
}
|
||||
} else {
|
||||
WARN_LOG_REPORT(CPU, "WriteFCR: Unexpected reg %d (value %08x)", fs, value);
|
||||
}
|
||||
|
|
|
@ -142,6 +142,9 @@ void Jit::DoState(PointerWrap &p) {
|
|||
CBreakPoints::SetSkipFirst(0);
|
||||
}
|
||||
|
||||
void Jit::UpdateFCR31() {
|
||||
}
|
||||
|
||||
void Jit::GetStateAndFlushAll(RegCacheState &state) {
|
||||
gpr.GetState(state.gpr);
|
||||
fpr.GetState(state.fpr);
|
||||
|
|
|
@ -171,6 +171,7 @@ public:
|
|||
blocks.InvalidateICache(em_address, length);
|
||||
}
|
||||
}
|
||||
void UpdateFCR31() override;
|
||||
|
||||
const u8 *GetDispatcher() const override {
|
||||
return dispatcher;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue