code_block.h 2.3 KB

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