From 0df0ea7d85dcaeda8e2aa69a4feee3bc66f39bef Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 18 Nov 2014 00:20:07 -0800 Subject: [PATCH] mips: Add a basic MIPSXCodeBlock. --- Common/MipsEmitter.cpp | 31 ++++++++++++++++++++++++ Common/MipsEmitter.h | 53 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/Common/MipsEmitter.cpp b/Common/MipsEmitter.cpp index a32b36f0c..4e9c5d531 100644 --- a/Common/MipsEmitter.cpp +++ b/Common/MipsEmitter.cpp @@ -242,4 +242,35 @@ void MIPSXEmitter::LUI(MIPSReg rt, MIPSReg rs, s16 imm) { Write32Fields(26, 0x0f, 21, rs, 16, rt, 0, (u16)imm); } +void MIPSXCodeBlock::AllocCodeSpace(int size) { + region_size = size; + region = (u8 *)AllocateExecutableMemory(region_size); + SetCodePtr(region); +} + +// Always clear code space with breakpoints, so that if someone accidentally executes +// uninitialized, it just breaks into the debugger. +void MIPSXCodeBlock::ClearCodeSpace() { + // Set BREAK instructions on all of it. + u32 *region32 = (u32 *)region; + for (u32 i = 0; i < region_size / 4; ++i) { + *region32++ = 0x0000000d; + } + ResetCodePtr(); +} + +void MIPSXCodeBlock::FreeCodeSpace() { + FreeMemoryPages(region, region_size); + region = NULL; + region_size = 0; +} + +void MIPSXCodeBlock::WriteProtect() { + WriteProtectMemory(region, region_size, true); +} + +void MIPSXCodeBlock::UnWriteProtect() { + UnWriteProtectMemory(region, region_size, false); +} + } \ No newline at end of file diff --git a/Common/MipsEmitter.h b/Common/MipsEmitter.h index bdf16e18f..4a4c6ae1d 100644 --- a/Common/MipsEmitter.h +++ b/Common/MipsEmitter.h @@ -184,4 +184,57 @@ private: u8 *lastCacheFlushEnd_; }; +// Everything that needs to generate machine code should inherit from this. +// You get memory management for free, plus, you can use all the LUI etc functions without +// having to prefix them with gen-> or something similar. +class MIPSXCodeBlock : public MIPSXEmitter { +public: + MIPSXCodeBlock() : region(nullptr), region_size(0) { + } + virtual ~MIPSXCodeBlock() { + if (region) { + FreeCodeSpace(); + } + } + + // Call this before you generate any code. + void AllocCodeSpace(int size); + + // Always clear code space with breakpoints, so that if someone accidentally executes + // uninitialized, it just breaks into the debugger. + void ClearCodeSpace(); + + // Call this when shutting down. Don't rely on the destructor, even though it'll do the job. + void FreeCodeSpace(); + + bool IsInSpace(const u8 *ptr) const { + return ptr >= region && ptr < region + region_size; + } + + // Can possibly be undone. Will write protect the entire code region. + // Start over if you need to change the code, though (call FreeCodeSpace(), AllocCodeSpace().) + void WriteProtect(); + void UnWriteProtect(); + + void ResetCodePtr() { + SetCodePtr(region); + } + + size_t GetSpaceLeft() const { + return region_size - (GetCodePtr() - region); + } + + u8 *GetBasePtr() { + return region; + } + + size_t GetOffset(const u8 *ptr) const { + return ptr - region; + } + +protected: + u8 *region; + size_t region_size; +}; + }; \ No newline at end of file