JIT optimizations and refactoring (#675)

* CPU/Recompiler: Use rel32 call where possible for no-args

* JitCodeBuffer: Support using preallocated buffer

* CPU/Recompiler/AArch64: Use bl instead of blr for short branches

* CPU/CodeCache: Allocate recompiler buffer in program space

This means we don't need 64-bit moves for every call out of the
recompiler.

* GTE: Don't store as u16 and load as u32

* CPU/Recompiler: Add methods to emit global load/stores

* GTE: Convert class to namespace

* CPU/Recompiler: Call GTE functions directly

* Settings: Turn into a global variable

* GPU: Replace local pointers with global

* InterruptController: Turn into a global pointer

* System: Replace local pointers with global

* Timers: Turn into a global instance

* DMA: Turn into a global instance

* SPU: Turn into a global instance

* CDROM: Turn into a global instance

* MDEC: Turn into a global instance

* Pad: Turn into a global instance

* SIO: Turn into a global instance

* CDROM: Move audio FIFO to the heap

* CPU/Recompiler: Drop ASMFunctions

No longer needed since we have code in the same 4GB window.

* CPUCodeCache: Turn class into namespace

* Bus: Local pointer -> global pointers

* CPU: Turn class into namespace

* Bus: Turn into namespace

* GTE: Store registers in CPU state struct

Allows relative addressing on ARM.

* CPU/Recompiler: Align code storage to page size

* CPU/Recompiler: Fix relative branches on A64

* HostInterface: Local references to global

* System: Turn into a namespace, move events out

* Add guard pages

* Android: Fix build
This commit is contained in:
Connor McLaughlin
2020-07-31 17:09:18 +10:00
committed by GitHub
parent 1f9fc6ab74
commit b6f871d2b9
88 changed files with 4993 additions and 5045 deletions

View File

@ -1,22 +1,13 @@
#pragma once
#include "common/bitfield.h"
#include "common/jit_code_buffer.h"
#include "cpu_types.h"
#include <array>
#include <memory>
#include <unordered_map>
#include <vector>
class JitCodeBuffer;
class Bus;
class System;
namespace CPU {
class Core;
namespace Recompiler {
class ASMFunctions;
}
union CodeBlockKey
{
@ -58,7 +49,7 @@ struct CodeBlockInstruction
struct CodeBlock
{
using HostCodePointer = void (*)(Core*);
using HostCodePointer = void (*)();
CodeBlock(const CodeBlockKey key_) : key(key_) {}
@ -86,67 +77,24 @@ struct CodeBlock
}
};
class CodeCache
{
public:
CodeCache();
~CodeCache();
namespace CodeCache {
void Initialize(System* system, Core* core, Bus* bus, bool use_recompiler);
void Execute();
void Initialize(bool use_recompiler);
void Shutdown();
void Execute();
/// Flushes the code cache, forcing all blocks to be recompiled.
void Flush();
/// Flushes the code cache, forcing all blocks to be recompiled.
void Flush();
/// Changes whether the recompiler is enabled.
void SetUseRecompiler(bool enable);
/// Changes whether the recompiler is enabled.
void SetUseRecompiler(bool enable);
/// Invalidates all blocks which are in the range of the specified code page.
void InvalidateBlocksWithPageIndex(u32 page_index);
/// Invalidates all blocks which are in the range of the specified code page.
void InvalidateBlocksWithPageIndex(u32 page_index);
private:
using BlockMap = std::unordered_map<u32, CodeBlock*>;
void InterpretCachedBlock(const CodeBlock& block);
void InterpretUncachedBlock();
void LogCurrentState();
}; // namespace CodeCache
/// Returns the block key for the current execution state.
CodeBlockKey GetNextBlockKey() const;
/// Looks up the block in the cache if it's already been compiled.
CodeBlock* LookupBlock(CodeBlockKey key);
/// Can the current block execute? This will re-validate the block if necessary.
/// The block can also be flushed if recompilation failed, so ignore the pointer if false is returned.
bool RevalidateBlock(CodeBlock* block);
bool CompileBlock(CodeBlock* block);
void FlushBlock(CodeBlock* block);
void AddBlockToPageMap(CodeBlock* block);
void RemoveBlockFromPageMap(CodeBlock* block);
/// Link block from to to.
void LinkBlock(CodeBlock* from, CodeBlock* to);
/// Unlink all blocks which point to this block, and any that this block links to.
void UnlinkBlock(CodeBlock* block);
void InterpretCachedBlock(const CodeBlock& block);
void InterpretUncachedBlock();
System* m_system = nullptr;
Core* m_core = nullptr;
Bus* m_bus = nullptr;
#ifdef WITH_RECOMPILER
std::unique_ptr<JitCodeBuffer> m_code_buffer;
std::unique_ptr<Recompiler::ASMFunctions> m_asm_functions;
#endif
BlockMap m_blocks;
bool m_use_recompiler = false;
std::array<std::vector<CodeBlock*>, CPU_CODE_CACHE_PAGE_COUNT> m_ram_block_map;
};
} // namespace CPU
} // namespace CPU