summaryrefslogtreecommitdiffstats
path: root/src/common/code_block.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common/code_block.h87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/common/code_block.h b/src/common/code_block.h
new file mode 100644
index 000000000..9ef7296d3
--- /dev/null
+++ b/src/common/code_block.h
@@ -0,0 +1,87 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common_types.h"
+#include "memory_util.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()
+ {
+#ifdef __SYMBIAN32__
+ ResetExecutableMemory(region);
+#else
+ FreeMemoryPages(region, region_size);
+#endif
+ region = nullptr;
+ region_size = 0;
+ }
+
+ bool IsInSpace(const 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);
+ }
+
+ u8 *GetBasePtr() {
+ return region;
+ }
+
+ size_t GetOffset(const u8 *ptr) const {
+ return ptr - region;
+ }
+};