code_block.h 2.3 KB

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