summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2017-02-22 22:26:08 +0100
committerGitHub <noreply@github.com>2017-02-22 22:26:08 +0100
commitfa9b89fdf9718de9c6c82ded9f67feeefaa3775f (patch)
treee49459209da243d93d275f04ff7f3a092d4e1bd0 /Source
parentc81cf111ef97665cf066fafa817aea62d758e288 (diff)
parent674e7430d0c254f3db0dc4b9ac54eb253c95c843 (diff)
Merge pull request #4911 from degasus/ABI
JitArm64: Extract block exit link area generation.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.cpp23
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp74
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h4
3 files changed, 55 insertions, 46 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
index e0b4181120..379e08aff3 100644
--- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
@@ -325,20 +325,10 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
linkData.call = LK;
b->linkData.push_back(linkData);
- MOVI2R(DISPATCHER_PC, destination);
+ blocks.WriteLinkBlock(*this, linkData);
- if (!LK)
- {
- B(dispatcher);
- }
- else
+ if (LK)
{
- BL(dispatcher);
-
- // MOVI2R might only require one instruction. So the const offset of 20 bytes
- // might be wrong. Be sure and just add a NOP here.
- HINT(HINT_NOP);
-
// Write the regular exit node after the return.
linkData.exitAddress = exit_address_after_return;
linkData.exitPtrs = GetWritableCodePtr();
@@ -346,8 +336,7 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
linkData.call = false;
b->linkData.push_back(linkData);
- MOVI2R(DISPATCHER_PC, exit_address_after_return);
- B(dispatcher);
+ blocks.WriteLinkBlock(*this, linkData);
}
}
@@ -387,8 +376,7 @@ void JitArm64::WriteExit(Arm64Gen::ARM64Reg dest, bool LK, u32 exit_address_afte
linkData.call = false;
b->linkData.push_back(linkData);
- MOVI2R(DISPATCHER_PC, exit_address_after_return);
- B(dispatcher);
+ blocks.WriteLinkBlock(*this, linkData);
}
}
@@ -417,8 +405,7 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return)
linkData.call = false;
b->linkData.push_back(linkData);
- MOVI2R(DISPATCHER_PC, exit_address_after_return);
- B(dispatcher);
+ blocks.WriteLinkBlock(*this, linkData);
SetJumpTarget(skip_exit);
}
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
index 7cf4f4aa41..254c5961d5 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
@@ -2,9 +2,9 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/PowerPC/JitArm64/Jit.h"
-#include "Common/CommonTypes.h"
#include "Core/PowerPC/JitArm64/JitArm64Cache.h"
+#include "Common/CommonTypes.h"
+#include "Core/PowerPC/JitArm64/Jit.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitInterface.h"
@@ -12,39 +12,57 @@ JitArm64BlockCache::JitArm64BlockCache(JitBase& jit) : JitBaseBlockCache{jit}
{
}
-void JitArm64BlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
+void JitArm64BlockCache::WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit,
+ const JitBlock::LinkData& source, const JitBlock* dest)
{
- u8* location = source.exitPtrs;
- ARM64XEmitter emit(location);
-
- if (dest)
+ if (!dest)
{
- if (source.call)
- {
- emit.BL(dest->checkedEntry);
- }
- else
- {
- // Are we able to jump directly to the normal entry?
- s64 distance = ((s64)dest->normalEntry - (s64)location) >> 2;
- if (distance >= -0x40000 && distance <= 0x3FFFF)
- {
- emit.B(CC_PL, dest->normalEntry);
- }
-
- // Use the checked entry if either downcount is smaller zero,
- // or if we're not able to inline the downcount check here.
- emit.B(dest->checkedEntry);
- }
- }
- else
- {
- emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
+ // Use a fixed amount of instructions, so we can assume to use 3 instructions on patching.
+ emit.MOVZ(DISPATCHER_PC, source.exitAddress & 0xFFFF, SHIFT_0);
+ emit.MOVK(DISPATCHER_PC, source.exitAddress >> 16, SHIFT_16);
+
if (source.call)
emit.BL(m_jit.GetAsmRoutines()->dispatcher);
else
emit.B(m_jit.GetAsmRoutines()->dispatcher);
+ return;
+ }
+
+ if (source.call)
+ {
+ // The "fast" BL must be the third instruction. So just use the former two to inline the
+ // downcount check here. It's better to do this near jump before the long jump to the other
+ // block.
+ FixupBranch fast_link = emit.B(CC_PL);
+ emit.BL(dest->checkedEntry);
+ emit.SetJumpTarget(fast_link);
+ emit.BL(dest->normalEntry);
+ return;
}
+
+ // Are we able to jump directly to the normal entry?
+ s64 distance = ((s64)dest->normalEntry - (s64)emit.GetCodePtr()) >> 2;
+ if (distance >= -0x40000 && distance <= 0x3FFFF)
+ {
+ emit.B(CC_PL, dest->normalEntry);
+ emit.B(dest->checkedEntry);
+ emit.BRK(101);
+ return;
+ }
+
+ FixupBranch fast_link = emit.B(CC_PL);
+ emit.B(dest->checkedEntry);
+ emit.SetJumpTarget(fast_link);
+ emit.B(dest->normalEntry);
+}
+
+void JitArm64BlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
+{
+ u8* location = source.exitPtrs;
+ ARM64XEmitter emit(location);
+
+ WriteLinkBlock(emit, source, dest);
+
emit.FlushIcache();
}
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h b/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h
index f4b1b3af7f..01d6db5cea 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h
@@ -4,6 +4,7 @@
#pragma once
+#include "Common/Arm64Emitter.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
class JitBase;
@@ -15,6 +16,9 @@ class JitArm64BlockCache : public JitBaseBlockCache
public:
explicit JitArm64BlockCache(JitBase& jit);
+ void WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit, const JitBlock::LinkData& source,
+ const JitBlock* dest = nullptr);
+
private:
void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) override;
void WriteDestroyBlock(const JitBlock& block) override;