diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2014-04-09 21:05:57 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2014-04-09 21:05:57 +0200 |
| commit | 4deb8f401152129c4db33ea0d62e32bb29082864 (patch) | |
| tree | 136c038e37087c38d3ba58bc44e774bb5e7f0677 /Source/Core/Common/CodeBlock.h | |
| parent | 7d8604ac1ca9b24cf6b056c1251f46cf3122e888 (diff) | |
| parent | 87d106d65cbabe393b03df6383f573046e663d20 (diff) | |
Merge pull request #253 from Sonicadvance1/CodeBlock-dedup
Remove dumb CodeBlock duplication in the emitters.
Diffstat (limited to 'Source/Core/Common/CodeBlock.h')
| -rw-r--r-- | Source/Core/Common/CodeBlock.h | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/Source/Core/Common/CodeBlock.h b/Source/Core/Common/CodeBlock.h new file mode 100644 index 0000000000..4885a58faf --- /dev/null +++ b/Source/Core/Common/CodeBlock.h @@ -0,0 +1,76 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "Common/Common.h" +#include "Common/MemoryUtil.h" + +// Everything that needs to generate code should inherit from this. +// You get memory management for free, plus, you can use all emitter functions without +// having to prefix them with gen-> or something similar. +// Example implementation: +// class JIT : public CodeBlock<ARMXEmitter> {} +template<class T> class CodeBlock : public T, NonCopyable +{ +private: + // A privately used function to set the executable RAM space to something invalid. + // For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction + virtual void PoisonMemory() = 0; + +protected: + u8 *region; + size_t region_size; + +public: + CodeBlock() : region(nullptr), region_size(0) {} + virtual ~CodeBlock() { if (region) FreeCodeSpace(); } + + // Call this before you generate any code. + void AllocCodeSpace(int size) + { + region_size = size; + region = (u8*)AllocateExecutableMemory(region_size); + T::SetCodePtr(region); + } + + // Always clear code space with breakpoints, so that if someone accidentally executes + // uninitialized, it just breaks into the debugger. + void ClearCodeSpace() + { + PoisonMemory(); + ResetCodePtr(); + } + + // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. + void FreeCodeSpace() + { + FreeMemoryPages(region, region_size); + region = nullptr; + region_size = 0; + } + + bool IsInSpace(u8 *ptr) + { + return (ptr >= region) && (ptr < (region + region_size)); + } + + // Cannot currently be undone. Will write protect the entire code region. + // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()). + void WriteProtect() + { + WriteProtectMemory(region, region_size, true); + } + + void ResetCodePtr() + { + T::SetCodePtr(region); + } + + size_t GetSpaceLeft() const + { + return region_size - (T::GetCodePtr() - region); + } +}; + |
