From ddbeebb887cff61b087a48738650832bc62c9e83 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 21 Jul 2015 20:08:49 -0400
Subject: Common: Ported over boilerplate x86 JIT code from Dolphin/PPSSPP.

---
 src/common/code_block.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 src/common/code_block.h

(limited to 'src/common/code_block.h')

diff --git a/src/common/code_block.h b/src/common/code_block.h
new file mode 100644
index 0000000000..9ef7296d38
--- /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;
+    }
+};
-- 
cgit v1.2.3-70-g09d2