summaryrefslogtreecommitdiff
path: root/src/common/code_block.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/code_block.h')
-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 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common_types.h"
8#include "memory_util.h"
9
10// Everything that needs to generate code should inherit from this.
11// You get memory management for free, plus, you can use all emitter functions without
12// having to prefix them with gen-> or something similar.
13// Example implementation:
14// class JIT : public CodeBlock<ARMXEmitter> {}
15template<class T> class CodeBlock : public T, NonCopyable
16{
17private:
18 // A privately used function to set the executable RAM space to something invalid.
19 // For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction
20 virtual void PoisonMemory() = 0;
21
22protected:
23 u8 *region;
24 size_t region_size;
25
26public:
27 CodeBlock() : region(nullptr), region_size(0) {}
28 virtual ~CodeBlock() { if (region) FreeCodeSpace(); }
29
30 // Call this before you generate any code.
31 void AllocCodeSpace(int size)
32 {
33 region_size = size;
34 region = (u8*)AllocateExecutableMemory(region_size);
35 T::SetCodePtr(region);
36 }
37
38 // Always clear code space with breakpoints, so that if someone accidentally executes
39 // uninitialized, it just breaks into the debugger.
40 void ClearCodeSpace()
41 {
42 PoisonMemory();
43 ResetCodePtr();
44 }
45
46 // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
47 void FreeCodeSpace()
48 {
49#ifdef __SYMBIAN32__
50 ResetExecutableMemory(region);
51#else
52 FreeMemoryPages(region, region_size);
53#endif
54 region = nullptr;
55 region_size = 0;
56 }
57
58 bool IsInSpace(const u8 *ptr)
59 {
60 return (ptr >= region) && (ptr < (region + region_size));
61 }
62
63 // Cannot currently be undone. Will write protect the entire code region.
64 // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
65 void WriteProtect()
66 {
67 WriteProtectMemory(region, region_size, true);
68 }
69
70 void ResetCodePtr()
71 {
72 T::SetCodePtr(region);
73 }
74
75 size_t GetSpaceLeft() const
76 {
77 return region_size - (T::GetCodePtr() - region);
78 }
79
80 u8 *GetBasePtr() {
81 return region;
82 }
83
84 size_t GetOffset(const u8 *ptr) const {
85 return ptr - region;
86 }
87};