diff options
| author | JMC47 <JMC4789@gmail.com> | 2025-10-09 14:07:13 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-09 14:07:13 -0400 |
| commit | d8bcd6d82ee2359bf3381770d55e0580afc2b388 (patch) | |
| tree | 732bca57f23155d3f1caacb94adbeb14eb4f1976 /Source/Core/Common | |
| parent | f43b78efb69059866817db7aff6d2bc4f17ac65a (diff) | |
| parent | f6e5448b43f74fffab22eca2f96b281ef0f662d3 (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.cpp | 32 | ||||
| -rw-r--r-- | Source/Core/Common/x64Emitter.h | 4 |
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 |
