mirror of
https://github.com/RPCS3/asmjit.git
synced 2026-07-19 13:27:34 -04:00
176 lines
4.9 KiB
C++
176 lines
4.9 KiB
C++
// [AsmJit]
|
|
// Complete x86/x64 JIT and Remote Assembler for C++.
|
|
//
|
|
// [License]
|
|
// Zlib - See LICENSE.md file in the package.
|
|
|
|
// [Export]
|
|
#define ASMJIT_EXPORTS
|
|
|
|
// [Dependencies - AsmJit]
|
|
#include "../base/assembler.h"
|
|
#include "../base/cpuinfo.h"
|
|
#include "../base/runtime.h"
|
|
|
|
// [Api-Begin]
|
|
#include "../apibegin.h"
|
|
|
|
namespace asmjit {
|
|
|
|
// ============================================================================
|
|
// [asmjit::Runtime - Construction / Destruction]
|
|
// ============================================================================
|
|
|
|
Runtime::Runtime() {
|
|
_sizeLimit = 0;
|
|
_baseAddress = kNoBaseAddress;
|
|
|
|
_runtimeType = kRuntimeTypeNone;
|
|
_allocType = kVMemAllocFreeable;
|
|
::memset(_reserved, 0, sizeof(_reserved));
|
|
}
|
|
Runtime::~Runtime() {}
|
|
|
|
// ============================================================================
|
|
// [asmjit::HostRuntime - Construction / Destruction]
|
|
// ============================================================================
|
|
|
|
HostRuntime::HostRuntime() { _runtimeType = kRuntimeTypeJit; }
|
|
HostRuntime::~HostRuntime() {}
|
|
|
|
// ============================================================================
|
|
// [asmjit::HostRuntime - Interface]
|
|
// ============================================================================
|
|
|
|
const CpuInfo* HostRuntime::getCpuInfo() {
|
|
return CpuInfo::getHost();
|
|
}
|
|
|
|
uint32_t HostRuntime::getStackAlignment() {
|
|
uint32_t alignment = sizeof(intptr_t);
|
|
|
|
// Modern Linux, APPLE and UNIX guarantees 16-byte stack alignment, but I'm
|
|
// not sure about all other UNIX operating systems, because 16-byte alignment
|
|
// is addition to an older specification.
|
|
#if (ASMJIT_ARCH_X64) || \
|
|
(ASMJIT_ARCH_X86 && (ASMJIT_OS_LINUX || ASMJIT_OS_BSD || ASMJIT_OS_MAC || ASMJIT_OS_ANDROID))
|
|
alignment = 16;
|
|
#endif
|
|
|
|
return alignment;
|
|
}
|
|
|
|
void HostRuntime::flush(void* p, size_t size) {
|
|
// Only useful on non-x86 architectures.
|
|
#if !ASMJIT_ARCH_X86 && !ASMJIT_ARCH_X64
|
|
# if ASMJIT_OS_WINDOWS
|
|
// Windows has built-in support in kernel32.dll.
|
|
::FlushInstructionCache(_memMgr.getProcessHandle(), p, size);
|
|
# endif // ASMJIT_OS_WINDOWS
|
|
#else
|
|
ASMJIT_UNUSED(p);
|
|
ASMJIT_UNUSED(size);
|
|
#endif // !ASMJIT_ARCH_X86 && !ASMJIT_ARCH_X64
|
|
}
|
|
|
|
// ============================================================================
|
|
// [asmjit::StaticRuntime - Construction / Destruction]
|
|
// ============================================================================
|
|
|
|
StaticRuntime::StaticRuntime(void* baseAddress, size_t sizeLimit) {
|
|
_sizeLimit = sizeLimit;
|
|
_baseAddress = static_cast<Ptr>((uintptr_t)baseAddress);
|
|
}
|
|
StaticRuntime::~StaticRuntime() {}
|
|
|
|
// ============================================================================
|
|
// [asmjit::StaticRuntime - Interface]
|
|
// ============================================================================
|
|
|
|
Error StaticRuntime::add(void** dst, Assembler* assembler) {
|
|
size_t codeSize = assembler->getCodeSize();
|
|
size_t sizeLimit = _sizeLimit;
|
|
|
|
if (codeSize == 0) {
|
|
*dst = nullptr;
|
|
return kErrorNoCodeGenerated;
|
|
}
|
|
|
|
if (sizeLimit != 0 && sizeLimit < codeSize) {
|
|
*dst = nullptr;
|
|
return kErrorCodeTooLarge;
|
|
}
|
|
|
|
Ptr baseAddress = _baseAddress;
|
|
uint8_t* p = static_cast<uint8_t*>((void*)static_cast<uintptr_t>(baseAddress));
|
|
|
|
// Since the base address is known the `relocSize` returned should be equal
|
|
// to `codeSize`. It's better to fail if they don't match instead of passsing
|
|
// silently.
|
|
size_t relocSize = assembler->relocCode(p, baseAddress);
|
|
if (relocSize == 0 || codeSize != relocSize) {
|
|
*dst = nullptr;
|
|
return kErrorInvalidState;
|
|
}
|
|
|
|
_baseAddress += codeSize;
|
|
if (sizeLimit)
|
|
sizeLimit -= codeSize;
|
|
|
|
flush(p, codeSize);
|
|
*dst = p;
|
|
|
|
return kErrorOk;
|
|
}
|
|
|
|
Error StaticRuntime::release(void* p) {
|
|
// There is nothing to release as `StaticRuntime` doesn't manage any memory.
|
|
ASMJIT_UNUSED(p);
|
|
return kErrorOk;
|
|
}
|
|
|
|
// ============================================================================
|
|
// [asmjit::JitRuntime - Construction / Destruction]
|
|
// ============================================================================
|
|
|
|
JitRuntime::JitRuntime() {}
|
|
JitRuntime::~JitRuntime() {}
|
|
|
|
// ============================================================================
|
|
// [asmjit::JitRuntime - Interface]
|
|
// ============================================================================
|
|
|
|
Error JitRuntime::add(void** dst, Assembler* assembler) {
|
|
size_t codeSize = assembler->getCodeSize();
|
|
if (codeSize == 0) {
|
|
*dst = nullptr;
|
|
return kErrorNoCodeGenerated;
|
|
}
|
|
|
|
void* p = _memMgr.alloc(codeSize, getAllocType());
|
|
if (p == nullptr) {
|
|
*dst = nullptr;
|
|
return kErrorNoVirtualMemory;
|
|
}
|
|
|
|
// Relocate the code and release the unused memory back to `VMemMgr`.
|
|
size_t relocSize = assembler->relocCode(p);
|
|
if (relocSize < codeSize) {
|
|
_memMgr.shrink(p, relocSize);
|
|
}
|
|
|
|
flush(p, relocSize);
|
|
*dst = p;
|
|
|
|
return kErrorOk;
|
|
}
|
|
|
|
Error JitRuntime::release(void* p) {
|
|
return _memMgr.release(p);
|
|
}
|
|
|
|
} // asmjit namespace
|
|
|
|
// [Api-End]
|
|
#include "../apiend.h"
|