summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-10-09 14:07:13 -0400
committerGitHub <noreply@github.com>2025-10-09 14:07:13 -0400
commitd8bcd6d82ee2359bf3381770d55e0580afc2b388 (patch)
tree732bca57f23155d3f1caacb94adbeb14eb4f1976 /Source/Core/Common
parentf43b78efb69059866817db7aff6d2bc4f17ac65a (diff)
parentf6e5448b43f74fffab22eca2f96b281ef0f662d3 (diff)
Merge pull request #13996 from SuperSamus/jit64-dynamic-known-jmp-len
Jit64: Dynamic length of regular jump instruction (for known addresses)
Diffstat (limited to 'Source/Core/Common')
-rw-r--r--Source/Core/Common/x64Emitter.cpp32
-rw-r--r--Source/Core/Common/x64Emitter.h4
2 files changed, 21 insertions, 15 deletions
diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp
index 3db669e9b2..46b117a87f 100644
--- a/Source/Core/Common/x64Emitter.cpp
+++ b/Source/Core/Common/x64Emitter.cpp
@@ -412,27 +412,31 @@ void XEmitter::Rex(int w, int r, int x, int b)
Write8(rx);
}
-void XEmitter::JMP(const u8* addr, const Jump jump)
+void XEmitter::JMP(const u8* addr, bool force_near_padding)
{
u64 fn = (u64)addr;
- if (jump == Jump::Short)
- {
- s64 distance = (s64)(fn - ((u64)code + 2));
- ASSERT_MSG(DYNA_REC, distance >= -0x80 && distance < 0x80,
- "Jump::Short target too far away ({}), needs Jump::Near", distance);
- // 8 bits will do
- Write8(0xEB);
- Write8((u8)(s8)distance);
- }
- else
+ s64 distance = (s64)(fn - ((u64)code + SHORT_JMP_LEN));
+ if (distance < -0x80 || distance >= 0x80)
{
- s64 distance = (s64)(fn - ((u64)code + 5));
-
+ distance = (s64)(fn - ((u64)code + NEAR_JMP_LEN));
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
- "Jump::Near target too far away ({}), needs indirect register", distance);
+ "Jump target too far away ({}), needs indirect register", distance);
Write8(0xE9);
Write32((u32)(s32)distance);
}
+ else
+ {
+ Write8(0xEB);
+ Write8((u8)(s8)distance);
+ if (force_near_padding)
+ {
+ for (int i = 0; i < NEAR_JMP_LEN - SHORT_JMP_LEN; i++)
+ {
+ // INT3 is more efficient than NOP if never executed, as it stops CPU speculation.
+ INT3();
+ }
+ }
+ }
}
void XEmitter::JMPptr(const OpArg& arg2)
diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h
index 3c8a411159..71dcea30f9 100644
--- a/Source/Core/Common/x64Emitter.h
+++ b/Source/Core/Common/x64Emitter.h
@@ -444,6 +444,8 @@ public:
Short,
Near,
};
+ static const int SHORT_JMP_LEN = 2;
+ static const int NEAR_JMP_LEN = 5;
// Flow control
void RET();
@@ -451,7 +453,7 @@ public:
void UD2();
[[nodiscard]] FixupBranch J(Jump jump = Jump::Short);
- void JMP(const u8* addr, Jump jump = Jump::Short);
+ void JMP(const u8* addr, bool force_near_padding = false);
void JMPptr(const OpArg& arg);
void JMPself(); // infinite loop!
#ifdef CALL