Skip to content

Commit

Permalink
Merge pull request #4911 from degasus/ABI
Browse files Browse the repository at this point in the history
JitArm64: Extract block exit link area generation.
  • Loading branch information
degasus committed Feb 22, 2017
2 parents c81cf11 + 674e743 commit fa9b89f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 46 deletions.
23 changes: 5 additions & 18 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Expand Up @@ -325,29 +325,18 @@ 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();
linkData.linkStatus = false;
linkData.call = false;
b->linkData.push_back(linkData);

MOVI2R(DISPATCHER_PC, exit_address_after_return);
B(dispatcher);
blocks.WriteLinkBlock(*this, linkData);
}
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
}
Expand Down
74 changes: 46 additions & 28 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
Expand Up @@ -2,49 +2,67 @@
// 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"

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();
}

Expand Down
4 changes: 4 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include "Common/Arm64Emitter.h"
#include "Core/PowerPC/JitCommon/JitCache.h"

class JitBase;
Expand All @@ -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;
Expand Down

0 comments on commit fa9b89f

Please sign in to comment.