mirror of
https://github.com/RPCS3/asmjit.git
synced 2026-07-19 21:33:38 -04:00
- Major documentation reorganization of AsmJit (still far from perfection)
- Documentation - removed verbose @brief and switched to markdown syntax which Doxygen supports. - Added inline documentation to AVX/AVX2 instructions. - Added more documentation notes to utility classes. - Modified documentation groups to be compatible with the new code layout (base/x86). - Renamed VirtualMemoryManager to VMemMgr. - Removed MemoryManager interface (not needed). - Changed JitRuntime to always create a new isolated VMemMgr instance. - Fixed WinRemoteRuntime to work with the new changes. - Added missing insertps instruction to database, assembler and compiler. - Moved global functions in x86cpuinfo to CpuUtil class. - Should notify Issue #10
This commit is contained in:
@@ -234,8 +234,6 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/base
|
||||
lock.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
memorymanager.cpp
|
||||
memorymanager.h
|
||||
podlist.h
|
||||
podvector.cpp
|
||||
podvector.h
|
||||
|
||||
@@ -269,6 +269,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.xor_(intptr_gp0, 0);
|
||||
|
||||
// Fpu.
|
||||
a.nop();
|
||||
|
||||
a.f2xm1();
|
||||
a.fabs();
|
||||
a.fadd(fp0, fpx);
|
||||
@@ -399,6 +401,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.fyl2xp1();
|
||||
|
||||
// MMX/MMX-EXT.
|
||||
a.nop();
|
||||
|
||||
a.movd(ptr_gp0, mm7);
|
||||
a.movd(eax, mm7);
|
||||
a.movd(mm0, ptr_gp0);
|
||||
@@ -501,6 +505,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.emms();
|
||||
|
||||
// 3DNOW!
|
||||
a.nop();
|
||||
|
||||
a.pf2id(mm0, mm7);
|
||||
a.pf2id(mm0, ptr_gp0);
|
||||
a.pf2iw(mm0, mm7);
|
||||
@@ -550,6 +556,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.femms();
|
||||
|
||||
// SSE.
|
||||
a.nop();
|
||||
|
||||
a.addps(xmm0, xmm7);
|
||||
a.addps(xmm0, ptr_gp0);
|
||||
a.addss(xmm0, xmm7);
|
||||
@@ -675,6 +683,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.xorps(xmm0, ptr_gp0);
|
||||
|
||||
// SSE2.
|
||||
a.nop();
|
||||
|
||||
a.addpd(xmm0, xmm7);
|
||||
a.addpd(xmm0, ptr_gp0);
|
||||
a.addsd(xmm0, xmm7);
|
||||
@@ -922,7 +932,9 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.xorpd(xmm0, xmm7);
|
||||
a.xorpd(xmm0, ptr_gp0);
|
||||
|
||||
// SSE3/SSSE3/SSE4.1/SSE4.2.
|
||||
// SSE3.
|
||||
a.nop();
|
||||
|
||||
a.addsubpd(xmm0, xmm7);
|
||||
a.addsubpd(xmm0, ptr_gp0);
|
||||
a.addsubps(xmm0, xmm7);
|
||||
@@ -945,6 +957,10 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.movsldup(xmm0, xmm7);
|
||||
a.movsldup(xmm0, ptr_gp0);
|
||||
a.mwait();
|
||||
|
||||
// SSSE3.
|
||||
a.nop();
|
||||
|
||||
a.psignb(mm0, mm7);
|
||||
a.psignb(mm0, ptr_gp0);
|
||||
a.psignb(xmm0, xmm7);
|
||||
@@ -1009,6 +1025,10 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.palignr(mm0, ptr_gp0, 0);
|
||||
a.palignr(xmm0, xmm0, 0);
|
||||
a.palignr(xmm0, ptr_gp0, 0);
|
||||
|
||||
// SSE4.1.
|
||||
a.nop();
|
||||
|
||||
a.blendpd(xmm0, xmm0, 0);
|
||||
a.blendpd(xmm0, ptr_gp0, 0);
|
||||
a.blendps(xmm0, xmm0, 0);
|
||||
@@ -1023,6 +1043,8 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.dpps(xmm0, ptr_gp0, 0);
|
||||
a.extractps(gp0, xmm0, 0);
|
||||
a.extractps(ptr_gp0, xmm0, 0);
|
||||
a.insertps(xmm0, xmm1, 0);
|
||||
a.insertps(xmm0, ptr_gp0, 0);
|
||||
a.movntdqa(xmm0, ptr_gp0);
|
||||
a.mpsadbw(xmm0, xmm0, 0);
|
||||
a.mpsadbw(xmm0, ptr_gp0, 0);
|
||||
@@ -1104,6 +1126,10 @@ static void opcode(asmjit::host::Assembler& a) {
|
||||
a.roundpd(xmm0, ptr_gp0, 0);
|
||||
a.roundsd(xmm0, xmm0, 0);
|
||||
a.roundsd(xmm0, ptr_gp0, 0);
|
||||
|
||||
// SSE4.2.
|
||||
a.nop();
|
||||
|
||||
a.pcmpestri(xmm0, xmm0, 0);
|
||||
a.pcmpestri(xmm0, ptr_gp0, 0);
|
||||
a.pcmpestrm(xmm0, xmm0, 0);
|
||||
|
||||
+16
-13
@@ -27,8 +27,8 @@ static void gen(void* a, void* b, int i) {
|
||||
static void verify(void* a, void* b) {
|
||||
int ai = *(int*)a;
|
||||
int bi = *(int*)b;
|
||||
if (ai != bi || memcmp(a, b, ai) != 0)
|
||||
{
|
||||
|
||||
if (ai != bi || ::memcmp(a, b, ai) != 0) {
|
||||
printf("Failed to verify %p\n", a);
|
||||
problems++;
|
||||
}
|
||||
@@ -39,9 +39,11 @@ static void die() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void stats(MemoryManager* memmgr) {
|
||||
printf("-- Used: %d\n", (int)memmgr->getUsedBytes());
|
||||
printf("-- Allocated: %d\n", (int)memmgr->getAllocatedBytes());
|
||||
static void stats(VMemMgr& memmgr) {
|
||||
printf("-- Used: %d\n",
|
||||
static_cast<int>(memmgr.getUsedBytes()));
|
||||
printf("-- Allocated: %d\n",
|
||||
static_cast<int>(memmgr.getAllocatedBytes()));
|
||||
}
|
||||
|
||||
static void shuffle(void **a, void **b, size_t count) {
|
||||
@@ -60,12 +62,13 @@ static void shuffle(void **a, void **b, size_t count) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
MemoryManager* memmgr = MemoryManager::getGlobal();
|
||||
VMemMgr memmgr;
|
||||
|
||||
size_t i;
|
||||
size_t count = 200000;
|
||||
|
||||
printf("Memory alloc/free test - %d allocations.\n\n", (int)count);
|
||||
printf("Memory alloc/free test - %d allocations.\n\n",
|
||||
static_cast<int>(count));
|
||||
|
||||
void** a = (void**)::malloc(sizeof(void*) * count);
|
||||
void** b = (void**)::malloc(sizeof(void*) * count);
|
||||
@@ -77,7 +80,7 @@ int main(int argc, char* argv[]) {
|
||||
for (i = 0; i < count; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr->alloc(r);
|
||||
a[i] = memmgr.alloc(r);
|
||||
if (a[i] == NULL) die();
|
||||
|
||||
::memset(a[i], 0, r);
|
||||
@@ -90,7 +93,7 @@ int main(int argc, char* argv[]) {
|
||||
printf("Freeing virtual memory...");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (memmgr->release(a[i]) != kErrorOk) {
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", b[i]);
|
||||
problems++;
|
||||
}
|
||||
@@ -106,7 +109,7 @@ int main(int argc, char* argv[]) {
|
||||
for (i = 0; i < count; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr->alloc(r);
|
||||
a[i] = memmgr.alloc(r);
|
||||
b[i] = ::malloc(r);
|
||||
if (a[i] == NULL || b[i] == NULL) die();
|
||||
|
||||
@@ -124,7 +127,7 @@ int main(int argc, char* argv[]) {
|
||||
printf("Verify and free...");
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
verify(a[i], b[i]);
|
||||
if (memmgr->release(a[i]) != kErrorOk) {
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", a[i]);
|
||||
problems++;
|
||||
}
|
||||
@@ -138,7 +141,7 @@ int main(int argc, char* argv[]) {
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr->alloc(r);
|
||||
a[i] = memmgr.alloc(r);
|
||||
b[i] = ::malloc(r);
|
||||
if (a[i] == NULL || b[i] == NULL) die();
|
||||
|
||||
@@ -151,7 +154,7 @@ int main(int argc, char* argv[]) {
|
||||
printf("Verify and free...");
|
||||
for (i = 0; i < count; i++) {
|
||||
verify(a[i], b[i]);
|
||||
if (memmgr->release(a[i]) != kErrorOk) {
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", a[i]);
|
||||
problems++;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
|
||||
printf(" asmjit::CodeGen : %u\n", static_cast<uint32_t>(sizeof(CodeGen)));
|
||||
printf(" asmjit::BaseAssembler : %u\n", static_cast<uint32_t>(sizeof(BaseAssembler)));
|
||||
printf(" asmjit::BaseCompiler : %u\n", static_cast<uint32_t>(sizeof(BaseCompiler)));
|
||||
printf(" asmjit::BaseRuntime : %u\n", static_cast<uint32_t>(sizeof(BaseRuntime)));
|
||||
printf(" asmjit::Runtime : %u\n", static_cast<uint32_t>(sizeof(Runtime)));
|
||||
printf("\n");
|
||||
printf(" asmjit::Operand : %u\n", static_cast<uint32_t>(sizeof(Operand)));
|
||||
printf(" asmjit::BaseReg : %u\n", static_cast<uint32_t>(sizeof(BaseReg)));
|
||||
|
||||
@@ -22,7 +22,7 @@ using namespace asmjit::host;
|
||||
// [X86Test]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Interface used to test Compiler.
|
||||
//! Interface used to test Compiler.
|
||||
struct X86Test {
|
||||
X86Test(const char* name = NULL) { _name.setString(name); }
|
||||
virtual ~X86Test() {}
|
||||
|
||||
+6
-253
@@ -8,9 +8,13 @@
|
||||
#ifndef _ASMJIT_ASMJIT_H
|
||||
#define _ASMJIT_ASMJIT_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_mainpage]
|
||||
// ============================================================================
|
||||
|
||||
//! @mainpage
|
||||
//!
|
||||
//! @brief AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//!
|
||||
//! AsmJit is a complete JIT and remote assembler for C++ language. It can
|
||||
//! generate native code for x86 and x64 architectures having support for
|
||||
@@ -65,259 +69,8 @@
|
||||
//! @section AsmJit_Main_HomePage AsmJit Homepage
|
||||
//!
|
||||
//! - http://code.google.com/p/asmjit/
|
||||
//!
|
||||
//! @section AsmJit_Main_ResourcesX86 External X86/X64 Assembler Resources
|
||||
//! - http://www.agner.org/optimize/
|
||||
//! - http://www.mark.masmcode.com/ (Assembler Tips)
|
||||
//! - http://avisynth.org/mediawiki/Filter_SDK/Assembler_optimizing (Optimizing)
|
||||
//! - http://www.ragestorm.net/distorm/ (Disassembling)
|
||||
//!
|
||||
//! @section AsmJit_Main_Terminology Terminology
|
||||
//!
|
||||
//! - <b>Non-volatile (preserved) register</b> - Register that can't be changed
|
||||
//! by callee (callee must save and restore it if it want to use it inside).
|
||||
//!
|
||||
//! - <b>Volatile (non-preserved) register</b> - The opossite. Register that can
|
||||
//! be freely used by callee. The caller must free all registers before calling
|
||||
//! other function.
|
||||
|
||||
//! @defgroup asmjit_base Base - base (backend neutral) classes.
|
||||
//!
|
||||
//! Contains all AsmJit classes and helper functions that are neutral or
|
||||
//! abstract. All abstract classes are reimplemented for every supported
|
||||
//! architecture.
|
||||
//!
|
||||
//! - See @c asmjit::Assembler class for low level code generation
|
||||
//! documentation.
|
||||
//! - See @c asmjit::Operand for AsmJit operand's overview.
|
||||
//!
|
||||
//! @section AsmJit_Core_Registers Registers
|
||||
//!
|
||||
//! There are static objects that represents X86 and X64 registers. They can
|
||||
//! be used directly (like @c eax, @c mm, @c xmm, ...) or created through
|
||||
//! these functions:
|
||||
//!
|
||||
//! - @c asmjit::gpb_lo() - Get Gpb-lo register.
|
||||
//! - @c asmjit::gpb_hi() - Get Gpb-hi register.
|
||||
//! - @c asmjit::gpw() - Get Gpw register.
|
||||
//! - @c asmjit::gpd() - Get Gpd register.
|
||||
//! - @c asmjit::gpq() - Get Gpq Gp register.
|
||||
//! - @c asmjit::gpz() - Get Gpd/Gpq register.
|
||||
//! - @c asmjit::fp() - Get Fp register.
|
||||
//! - @c asmjit::mm() - Get Mm register.
|
||||
//! - @c asmjit::xmm() - Get Xmm register.
|
||||
//! - @c asmjit::ymm() - Get Ymm register.
|
||||
//!
|
||||
//! @section AsmJit_Core_Addressing Addressing
|
||||
//!
|
||||
//! X86 and x64 architectures contains several addressing modes and most ones
|
||||
//! are possible with AsmJit library. Memory represents are represented by
|
||||
//! @c asmjit::BaseMem class. These functions are used to make operands that
|
||||
//! represents memory addresses:
|
||||
//!
|
||||
//! - @c asmjit::ptr()
|
||||
//! - @c asmjit::byte_ptr()
|
||||
//! - @c asmjit::word_ptr()
|
||||
//! - @c asmjit::dword_ptr()
|
||||
//! - @c asmjit::qword_ptr()
|
||||
//! - @c asmjit::tword_ptr()
|
||||
//! - @c asmjit::oword_ptr()
|
||||
//! - @c asmjit::yword_ptr()
|
||||
//! - @c asmjit::intptr_ptr()
|
||||
//!
|
||||
//! Most useful function to make pointer should be @c asmjit::ptr(). It creates
|
||||
//! pointer to the target with unspecified size. Unspecified size works in all
|
||||
//! intrinsics where are used registers (this means that size is specified by
|
||||
//! register operand or by instruction itself). For example @c asmjit::ptr()
|
||||
//! can't be used with @c asmjit::Assembler::inc() instruction. In this case
|
||||
//! size must be specified and it's also reason to make difference between
|
||||
//! pointer sizes.
|
||||
//!
|
||||
//! Supported are simple address forms (register + displacement) and complex
|
||||
//! address forms (register + (register << shift) + displacement).
|
||||
//!
|
||||
//! @section AsmJit_Core_Immediates Immediates
|
||||
//!
|
||||
//! Immediate values are constants thats passed directly after instruction
|
||||
//! opcode. To create such value use @c asmjit::imm() or @c asmjit::imm_u()
|
||||
//! methods to create signed or unsigned immediate value.
|
||||
//!
|
||||
//! @sa @c asmjit::BaseCompiler.
|
||||
|
||||
//! @defgroup asmjit_compiler Compiler (high-level code generation).
|
||||
//!
|
||||
//! Contains classes related to @c asmjit::Compiler that can be used
|
||||
//! to generate code using high-level constructs.
|
||||
//!
|
||||
//! - See @c Compiler class for high level code generation
|
||||
//! documentation - calling conventions, function declaration
|
||||
//! and variables management.
|
||||
|
||||
//! @defgroup asmjit_config Configuration.
|
||||
//!
|
||||
//! Contains macros that can be redefined to fit into any project.
|
||||
|
||||
//! @defgroup asmjit_cpuinfo Cpu information.
|
||||
//!
|
||||
//! X86 or x64 cpuid instruction allows to get information about processor
|
||||
//! vendor and it's features. It's always used to detect features like MMX,
|
||||
//! SSE and other newer ones.
|
||||
//!
|
||||
//! AsmJit library supports low level cpuid call implemented internally as
|
||||
//! C++ function using inline assembler or intrinsics and also higher level
|
||||
//! CPU features detection. The low level function (also used by higher level
|
||||
//! one) is @c asmjit::cpuid().
|
||||
//!
|
||||
//! AsmJit library also contains higher level function @c asmjit::getCpu()
|
||||
//! that returns features detected by the library. The detection process is
|
||||
//! done only once and the returned object is always the same. @c BaseCpuInfo
|
||||
//! structure does not contain only information through @c asmjit::cpuid(), but
|
||||
//! there is also small multiplatform code to detect number of processors
|
||||
//! (or cores) through operating system API.
|
||||
//!
|
||||
//! It's recommended to use @c asmjit::cpuInfo to detect and check for
|
||||
//! host processor features.
|
||||
//!
|
||||
//! Example how to use asmjit::cpuid():
|
||||
//!
|
||||
//! @code
|
||||
//! // All functions and structures are in asmjit namesapce.
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Here will be retrieved result of cpuid call.
|
||||
//! CpuId out;
|
||||
//!
|
||||
//! // Use cpuid function to do the job.
|
||||
//! cpuid(0 /* eax */, &out /* eax, ebx, ecx, edx */);
|
||||
//!
|
||||
//! // If eax argument to cpuid is 0, ebx, ecx and edx registers
|
||||
//! // are filled with cpu vendor.
|
||||
//! char vendor[13];
|
||||
//! memcpy(i->vendor, &out.ebx, 4);
|
||||
//! memcpy(i->vendor + 4, &out.edx, 4);
|
||||
//! memcpy(i->vendor + 8, &out.ecx, 4);
|
||||
//! vendor[12] = '\0';
|
||||
//!
|
||||
//! // Print vendor
|
||||
//! puts(vendor);
|
||||
//! @endcode
|
||||
//!
|
||||
//! If the high-level interface of asmjit::BaseCpuInfo is not enough, you can
|
||||
//! use low-level asmjit::cpuid() when running on x86/x64 host, but please read
|
||||
//! processor manuals provided by Intel, AMD or other manufacturer for cpuid
|
||||
//! details.
|
||||
//!
|
||||
//! Example of using @c BaseCpuInfo::getHost():
|
||||
//!
|
||||
//! @code
|
||||
//! // All functions and structures are in asmjit namesapce.
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Call to cpuInfo return BaseCpuInfo structure that shouldn't be modified.
|
||||
//! // Make it const by default.
|
||||
//! const BaseCpuInfo* cpuInfo = BaseCpuInfo::getHost();
|
||||
//!
|
||||
//! // Now you are able to get specific features.
|
||||
//!
|
||||
//! // Processor has SSE2
|
||||
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
|
||||
//! // your code...
|
||||
//! }
|
||||
//! // Processor has MMX
|
||||
//! else if (cpuInfo->hasFeature(kCpuFeature_MMX)) {
|
||||
//! // your code...
|
||||
//! }
|
||||
//! // Processor is old, no SSE2 or MMX support.
|
||||
//! else {
|
||||
//! // your code...
|
||||
//! }
|
||||
//! @endcode
|
||||
//!
|
||||
//! Better example is in app/test/testcpu.cpp file.
|
||||
|
||||
//! @defgroup asmjit_logging Logging and error handling.
|
||||
//!
|
||||
//! Contains classes related to loging. Currently logging is implemented in
|
||||
//! @ref asmjit::BaseLogger class. The function @ref asmjit::BaseLogger::log()
|
||||
//! can be overridden to redirect logging into any user-defined stream.
|
||||
//!
|
||||
//! To log your assembler output to FILE stream use this code:
|
||||
//!
|
||||
//! @code
|
||||
//! // Create assembler
|
||||
//! Assembler a;
|
||||
//!
|
||||
//! // Create and set file based logger
|
||||
//! FileLogger logger(stderr);
|
||||
//! a.setLogger(&logger);
|
||||
//! @endcode
|
||||
//!
|
||||
//! You can see that logging goes through @c Assembler. If you are using
|
||||
//! @c Compiler and you want to log messages in correct assembler order,
|
||||
//! you should look at @ref Compiler::comment() method. It allows you to
|
||||
//! insert text message into items stream so the @c Compiler is able to
|
||||
//! send messages to @ref Assembler in correct order.
|
||||
//!
|
||||
//! @sa @c asmjit::BaseLogger, @c asmjit::FileLogger.
|
||||
|
||||
|
||||
//! @defgroup AsmJit_MemoryManagement Virtual memory management.
|
||||
//!
|
||||
//! Using @c asmjit::Assembler or @c asmjit::Compiler to generate machine
|
||||
//! code is not final step. Each generated code needs to run in memory
|
||||
//! that is not protected against code execution. To alloc this code it's
|
||||
//! needed to use operating system functions provided to enable execution
|
||||
//! code in specified memory block or to allocate memory that is not
|
||||
//! protected. The solution is always to use @c See asmjit::Assembler::make()
|
||||
//! and @c asmjit::Compiler::make() functions that can allocate memory and
|
||||
//! relocate code for you. But AsmJit also contains classes for manual memory
|
||||
//! management thats internally used by AsmJit but can be used by programmers
|
||||
//! too.
|
||||
//!
|
||||
//! Memory management contains low level and high level classes related to
|
||||
//! allocating and freeing virtual memory. Low level class is
|
||||
//! @c asmjit::VMem that can allocate and free full pages of virtual memory
|
||||
//! provided by operating system. Higher level class is @c asmjit::MemoryManager
|
||||
//! that is able to manage complete allocation and free mechanism. It
|
||||
//! internally uses larger chunks of memory to make allocation fast and
|
||||
//! effective.
|
||||
//!
|
||||
//! Using @c asmjit::VMem::alloc() is cross-platform way how to allocate this
|
||||
//! kind of memory without worrying about operating system and it's API. Each
|
||||
//! memory block that is no longer needed should be released by @ref
|
||||
//! asmjit::VMem::release() method. Higher-level interface for virtual memory
|
||||
//! allocation can be found at asmjit::MemoryManager class.
|
||||
//!
|
||||
//! @sa @c asmjit::VMem, @ asmjit::MemoryManager.
|
||||
|
||||
|
||||
//! @addtogroup asmjit_config
|
||||
//! @{
|
||||
|
||||
//! @def ASMJIT_OS_WINDOWS
|
||||
//! @brief Macro that is declared if AsmJit is compiled for Windows.
|
||||
|
||||
//! @def ASMJIT_OS_POSIX
|
||||
//! @brief Macro that is declared if AsmJit is compiled for unix like
|
||||
//! operating system.
|
||||
|
||||
//! @def ASMJIT_API
|
||||
//! @brief Attribute that's added to classes that can be exported if AsmJit
|
||||
//! is compiled as a dll library.
|
||||
|
||||
//! @def ASMJIT_ASSERT
|
||||
//! @brief Assertion macro. Default implementation calls
|
||||
//! @c asmjit::assertionFailed() function.
|
||||
|
||||
//! @}
|
||||
|
||||
|
||||
//! @namespace asmjit
|
||||
//! @brief Main AsmJit library namespace.
|
||||
//!
|
||||
//! There are not other namespaces used in AsmJit library.
|
||||
|
||||
// [Dependencies - Core]
|
||||
// [Dependencies - Base]
|
||||
#include "base.h"
|
||||
|
||||
// [Dependencies - X86/X64]
|
||||
|
||||
+186
-1
@@ -8,7 +8,193 @@
|
||||
#ifndef _ASMJIT_BASE_H
|
||||
#define _ASMJIT_BASE_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base Base
|
||||
//!
|
||||
//! @brief AsmJit Base API.
|
||||
//!
|
||||
//! Contains all `asmjit` classes and helper functions that are architecture
|
||||
//! independent or abstract. Abstract classes are implemented by the backend,
|
||||
//! for example `BaseAssembler` is implemented by `x86x64::X86X64Assembler`.
|
||||
//!
|
||||
//! - See `BaseAssembler` for low level code generation documentation.
|
||||
//! - See `BaseCompiler` for high level code generation documentation.
|
||||
//! - See `Operand` for operand's overview.
|
||||
//!
|
||||
//! @section AsmJit_Core_Registers Registers
|
||||
//!
|
||||
//! There are static objects that represents X86 and X64 registers. They can
|
||||
//! be used directly (like `eax`, `mm`, `xmm`, ...) or created through
|
||||
//! these functions:
|
||||
//!
|
||||
//! - `asmjit::gpb_lo()` - Get Gpb-lo register.
|
||||
//! - `asmjit::gpb_hi()` - Get Gpb-hi register.
|
||||
//! - `asmjit::gpw()` - Get Gpw register.
|
||||
//! - `asmjit::gpd()` - Get Gpd register.
|
||||
//! - `asmjit::gpq()` - Get Gpq Gp register.
|
||||
//! - `asmjit::gpz()` - Get Gpd/Gpq register.
|
||||
//! - `asmjit::fp()` - Get Fp register.
|
||||
//! - `asmjit::mm()` - Get Mm register.
|
||||
//! - `asmjit::xmm()` - Get Xmm register.
|
||||
//! - `asmjit::ymm()` - Get Ymm register.
|
||||
//!
|
||||
//! @section AsmJit_Core_Addressing Addressing
|
||||
//!
|
||||
//! X86 and x64 architectures contains several addressing modes and most ones
|
||||
//! are possible with AsmJit library. Memory represents are represented by
|
||||
//! `BaseMem` class. These functions are used to make operands that represents
|
||||
//! memory addresses:
|
||||
//!
|
||||
//! - `asmjit::ptr()`
|
||||
//! - `asmjit::byte_ptr()`
|
||||
//! - `asmjit::word_ptr()`
|
||||
//! - `asmjit::dword_ptr()`
|
||||
//! - `asmjit::qword_ptr()`
|
||||
//! - `asmjit::tword_ptr()`
|
||||
//! - `asmjit::oword_ptr()`
|
||||
//! - `asmjit::yword_ptr()`
|
||||
//! - `asmjit::intptr_ptr()`
|
||||
//!
|
||||
//! Most useful function to make pointer should be `asmjit::ptr()`. It creates
|
||||
//! pointer to the target with unspecified size. Unspecified size works in all
|
||||
//! intrinsics where are used registers (this means that size is specified by
|
||||
//! register operand or by instruction itself). For example `asmjit::ptr()`
|
||||
//! can't be used with @c asmjit::Assembler::inc() instruction. In this case
|
||||
//! size must be specified and it's also reason to make difference between
|
||||
//! pointer sizes.
|
||||
//!
|
||||
//! Supported are simple address forms (register + displacement) and complex
|
||||
//! address forms (register + (register << shift) + displacement).
|
||||
//!
|
||||
//! @section AsmJit_Core_Immediates Immediates
|
||||
//!
|
||||
//! Immediate values are constants thats passed directly after instruction
|
||||
//! opcode. To create such value use @c asmjit::imm() or @c asmjit::imm_u()
|
||||
//! methods to create signed or unsigned immediate value.
|
||||
//!
|
||||
//! @sa @c asmjit::BaseCompiler.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_globals]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_globals Globals
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief Global definitions, macros and functions.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_codegen]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_codegen Code Generation (Base)
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief Low-level and high-level code generation.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_cpu_info]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_cpu_info CPU Information (Base)
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief CPU Information Interface, platform neutral.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_logging_and_errors]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_logging_and_errors Logging and Error Handling
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief Logging and error handling.
|
||||
//!
|
||||
//! AsmJit contains robust interface that can be used to log the generated code
|
||||
//! and to handle possible errors. Base logging interface is defined in `Logger`
|
||||
//! class that is abstract and can be overridden. AsmJit contains two loggers
|
||||
//! that can be used out-of-the box - `FileLogger` that logs into a `FILE*`
|
||||
//! and `StringLogger` that just concatenates all log messages without sending
|
||||
//! them to a stream.
|
||||
//!
|
||||
//! The following snippet shows how to setup a logger that logs to `stderr`:
|
||||
//!
|
||||
//! ~~~
|
||||
//! // `FileLogger` instance.
|
||||
//! FileLogger logger(stderr);
|
||||
//!
|
||||
//! // `Compiler` or any other `CodeGen` interface.
|
||||
//! host::Compiler c;
|
||||
//!
|
||||
//! // use `setLogger` to replace the `CodeGen` logger.
|
||||
//! c.setLogger(&logger);
|
||||
//! ~~~
|
||||
//!
|
||||
//! @sa @ref `Logger`, @ref `FileLogger`, @ref `StringLogger`.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_util]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_util Utilities
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief Utilities inside AsmJit made public.
|
||||
//!
|
||||
//! AsmJit contains numerous utility classes that are needed by the library
|
||||
//! itself. The most useful ones have been made public and are now exported.
|
||||
//!
|
||||
//! POD-Containers
|
||||
//! --------------
|
||||
//!
|
||||
//! TODO: Documentation
|
||||
//!
|
||||
//! String Builder
|
||||
//! --------------
|
||||
//!
|
||||
//! TODO: Documentation
|
||||
//!
|
||||
//! Integer Utilities
|
||||
//! -----------------
|
||||
//!
|
||||
//! TODO: Documentation
|
||||
//!
|
||||
//! Zone Memory Allocator
|
||||
//! ---------------------
|
||||
//!
|
||||
//! TODO: Documentation
|
||||
//!
|
||||
//! CPU Ticks
|
||||
//! ---------
|
||||
//!
|
||||
//! TODO: Documentation
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_vectypes]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_base_vectypes Vector Types
|
||||
//! @ingroup asmjit_base
|
||||
//!
|
||||
//! @brief Vector types can be used to create a data which is stored in the
|
||||
//! machine code.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::]
|
||||
// ============================================================================
|
||||
|
||||
//! @namespace asmjit
|
||||
//! Main AsmJit library namespace.
|
||||
//!
|
||||
//! There are not other namespaces used in AsmJit library.
|
||||
|
||||
// ============================================================================
|
||||
// [Dependencies - AsmJit]
|
||||
// ============================================================================
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#include "base/assembler.h"
|
||||
@@ -24,7 +210,6 @@
|
||||
#include "base/intutil.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/memorymanager.h"
|
||||
#include "base/podlist.h"
|
||||
#include "base/podvector.h"
|
||||
#include "base/string.h"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/assembler.h"
|
||||
#include "../base/intutil.h"
|
||||
#include "../base/memorymanager.h"
|
||||
#include "../base/vmem.h"
|
||||
|
||||
// [Dependenceis - C]
|
||||
#include <stdarg.h>
|
||||
@@ -24,7 +24,7 @@ namespace asmjit {
|
||||
// [asmjit::BaseAssembler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseAssembler::BaseAssembler(BaseRuntime* runtime) :
|
||||
BaseAssembler::BaseAssembler(Runtime* runtime) :
|
||||
CodeGen(runtime),
|
||||
_buffer(NULL),
|
||||
_end(NULL),
|
||||
|
||||
+96
-89
@@ -23,22 +23,24 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::LabelLink]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Data structure used to link linked-labels.
|
||||
//! @internal
|
||||
//!
|
||||
//! Data structure used to link linked-labels.
|
||||
struct LabelLink {
|
||||
//! @brief Previous link.
|
||||
//! Previous link.
|
||||
LabelLink* prev;
|
||||
//! @brief Offset.
|
||||
//! Offset.
|
||||
intptr_t offset;
|
||||
//! @brief Inlined displacement.
|
||||
//! Inlined displacement.
|
||||
intptr_t displacement;
|
||||
//! @brief RelocId if link must be absolute when relocated.
|
||||
//! RelocId if link must be absolute when relocated.
|
||||
intptr_t relocId;
|
||||
};
|
||||
|
||||
@@ -46,11 +48,13 @@ struct LabelLink {
|
||||
// [asmjit::LabelData]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Label data.
|
||||
//! @internal
|
||||
//!
|
||||
//! Label data.
|
||||
struct LabelData {
|
||||
//! @brief Label offset.
|
||||
//! Label offset.
|
||||
intptr_t offset;
|
||||
//! @brief Label links chain.
|
||||
//! Label links chain.
|
||||
LabelLink* links;
|
||||
};
|
||||
|
||||
@@ -58,7 +62,9 @@ struct LabelData {
|
||||
// [asmjit::RelocData]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Code relocation data (relative vs absolute addresses).
|
||||
//! @internal
|
||||
//!
|
||||
//! Code relocation data (relative vs absolute addresses).
|
||||
//!
|
||||
//! X86/X64:
|
||||
//!
|
||||
@@ -68,16 +74,16 @@ struct LabelData {
|
||||
//! and embedded data. In 32-bit mode we must patch all references to absolute
|
||||
//! address before we can call generated function.
|
||||
struct RelocData {
|
||||
//! @brief Type of relocation.
|
||||
//! Type of relocation.
|
||||
uint32_t type;
|
||||
//! @brief Size of relocation (4 or 8 bytes).
|
||||
//! Size of relocation (4 or 8 bytes).
|
||||
uint32_t size;
|
||||
|
||||
//! @brief Offset from code begin address.
|
||||
//! Offset from code begin address.
|
||||
Ptr from;
|
||||
|
||||
//! @brief Relative displacement from code begin address (not to @c offset)
|
||||
//! or absolute address.
|
||||
//! Relative displacement from code begin address (not to `offset`) or
|
||||
//! absolute address.
|
||||
Ptr data;
|
||||
};
|
||||
|
||||
@@ -85,10 +91,10 @@ struct RelocData {
|
||||
// [asmjit::BaseAssembler]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Base assembler.
|
||||
//! Base assembler.
|
||||
//!
|
||||
//! This class implements core setialization API only. The platform specific
|
||||
//! methods and intrinsics is implemented by derived classes.
|
||||
//! This class implements the base interface to an assembler. The architecture
|
||||
//! specific API is implemented by backends.
|
||||
//!
|
||||
//! @sa BaseCompiler.
|
||||
struct BaseAssembler : public CodeGen {
|
||||
@@ -98,66 +104,66 @@ struct BaseAssembler : public CodeGen {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @ref BaseAssembler instance.
|
||||
ASMJIT_API BaseAssembler(BaseRuntime* runtime);
|
||||
//! @brief Destroy the @ref BaseAssembler instance.
|
||||
//! Create a new `BaseAssembler` instance.
|
||||
ASMJIT_API BaseAssembler(Runtime* runtime);
|
||||
//! Destroy the `BaseAssembler` instance.
|
||||
ASMJIT_API virtual ~BaseAssembler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Clear / Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Clear everything, but not deallocate buffers.
|
||||
//! Clear everything, but not deallocate buffers.
|
||||
ASMJIT_API void clear();
|
||||
//! @brief Reset everything (means also to free all buffers).
|
||||
//! Reset everything (means also to free all buffers).
|
||||
ASMJIT_API void reset();
|
||||
//! @brief Called by clear() and reset() to clear all data related to derived
|
||||
//! class implementation.
|
||||
//! Called by clear() and reset() to clear all data related to derived class
|
||||
//! implementation.
|
||||
ASMJIT_API virtual void _purge();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Buffer]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get capacity of the code buffer.
|
||||
//! Get capacity of the code buffer.
|
||||
ASMJIT_INLINE size_t getCapacity() const {
|
||||
return (size_t)(_end - _buffer);
|
||||
}
|
||||
|
||||
//! @brief Get the number of remaining bytes (space between cursor and the
|
||||
//! end of the buffer).
|
||||
//! Get the number of remaining bytes (space between cursor and the end of
|
||||
//! the buffer).
|
||||
ASMJIT_INLINE size_t getRemainingSpace() const {
|
||||
return (size_t)(_end - _cursor);
|
||||
}
|
||||
|
||||
//! @brief Get buffer.
|
||||
//! Get buffer.
|
||||
ASMJIT_INLINE uint8_t* getBuffer() const {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
//! @brief Get the end of the buffer (points to the first byte that is outside).
|
||||
//! Get the end of the buffer (points to the first byte that is outside).
|
||||
ASMJIT_INLINE uint8_t* getEnd() const {
|
||||
return _end;
|
||||
}
|
||||
|
||||
//! @brief Get the current position in the buffer.
|
||||
//! Get the current position in the buffer.
|
||||
ASMJIT_INLINE uint8_t* getCursor() const {
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
//! @brief Set the current position in the buffer.
|
||||
//! Set the current position in the buffer.
|
||||
ASMJIT_INLINE void setCursor(uint8_t* cursor) {
|
||||
ASMJIT_ASSERT(cursor >= _buffer && cursor <= _end);
|
||||
_cursor = cursor;
|
||||
}
|
||||
|
||||
//! @brief Get the current offset in the buffer (<code>_cursor - _buffer</code>).
|
||||
//! Get the current offset in the buffer.
|
||||
ASMJIT_INLINE size_t getOffset() const {
|
||||
return (size_t)(_cursor - _buffer);
|
||||
}
|
||||
|
||||
//! @brief Set the current offset in the buffer to @a offset and get the
|
||||
//! previous offset value.
|
||||
//! Set the current offset in the buffer to `offset` and get the previous
|
||||
//! offset value.
|
||||
ASMJIT_INLINE size_t setOffset(size_t offset) {
|
||||
ASMJIT_ASSERT(offset < getCapacity());
|
||||
|
||||
@@ -166,84 +172,83 @@ struct BaseAssembler : public CodeGen {
|
||||
return oldOffset;
|
||||
}
|
||||
|
||||
//! @brief Grow the internal buffer.
|
||||
//! Grow the internal buffer.
|
||||
//!
|
||||
//! The internal buffer will grow at least by @a n bytes so @a n bytes
|
||||
//! can be added to it. If @a n is zero or <code>getOffset() + n</code>
|
||||
//! is not greater than the current capacity of the buffer this function
|
||||
//! won't do anything.
|
||||
//! The internal buffer will grow at least by `n` bytes so `n` bytes can be
|
||||
//! added to it. If `n` is zero or `getOffset() + n` is not greater than the
|
||||
//! current capacity of the buffer this function does nothing.
|
||||
ASMJIT_API Error _grow(size_t n);
|
||||
|
||||
//! @brief Reserve the internal buffer to at least @a n bytes.
|
||||
//! Reserve the internal buffer to at least `n` bytes.
|
||||
ASMJIT_API Error _reserve(size_t n);
|
||||
|
||||
//! @brief Set byte at position @a pos.
|
||||
//! Set byte at position `pos`.
|
||||
ASMJIT_INLINE uint8_t getByteAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint8_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set word at position @a pos.
|
||||
//! Set word at position `pos`.
|
||||
ASMJIT_INLINE uint16_t getWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint16_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set dword at position @a pos.
|
||||
//! Set dword at position `pos`.
|
||||
ASMJIT_INLINE uint32_t getDWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set qword at position @a pos.
|
||||
//! Set qword at position `pos`.
|
||||
ASMJIT_INLINE uint64_t getQWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint64_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set int32_t at position @a pos.
|
||||
//! Set int32_t at position `pos`.
|
||||
ASMJIT_INLINE int32_t getInt32At(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const int32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set uint32_t at position @a pos.
|
||||
//! Set uint32_t at position `pos`.
|
||||
ASMJIT_INLINE uint32_t getUInt32At(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! @brief Set byte at position @a pos.
|
||||
//! Set byte at position `pos`.
|
||||
ASMJIT_INLINE void setByteAt(size_t pos, uint8_t x) {
|
||||
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint8_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! @brief Set word at position @a pos.
|
||||
//! Set word at position `pos`.
|
||||
ASMJIT_INLINE void setWordAt(size_t pos, uint16_t x) {
|
||||
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint16_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! @brief Set dword at position @a pos.
|
||||
//! Set dword at position `pos`.
|
||||
ASMJIT_INLINE void setDWordAt(size_t pos, uint32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! @brief Set qword at position @a pos.
|
||||
//! Set qword at position `pos`.
|
||||
ASMJIT_INLINE void setQWordAt(size_t pos, uint64_t x) {
|
||||
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint64_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! @brief Set int32_t at position @a pos.
|
||||
//! Set int32_t at position `pos`.
|
||||
ASMJIT_INLINE void setInt32At(size_t pos, int32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<int32_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! @brief Set uint32_t at position @a pos.
|
||||
//! Set uint32_t at position `pos`.
|
||||
ASMJIT_INLINE void setUInt32At(size_t pos, uint32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
|
||||
@@ -253,7 +258,7 @@ struct BaseAssembler : public CodeGen {
|
||||
// [GetCodeSize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get current offset in buffer (same as <code>getOffset() + getTramplineSize()</code>).
|
||||
//! Get current offset in buffer, same as `getOffset() + getTramplineSize()`.
|
||||
ASMJIT_INLINE size_t getCodeSize() const {
|
||||
return getOffset() + getTrampolineSize();
|
||||
}
|
||||
@@ -262,10 +267,12 @@ struct BaseAssembler : public CodeGen {
|
||||
// [GetTrampolineSize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get size of all possible trampolines needed to successfuly generate
|
||||
//! relative jumps to absolute addresses. This value is only non-zero if jmp
|
||||
//! of call instructions were used with immediate operand (this means jumping
|
||||
//! or calling an absolute address directly).
|
||||
//! Get size of all possible trampolines.
|
||||
//!
|
||||
//! Trampolines are needed to successfuly generate relative jumps to absolute
|
||||
//! addresses. This value is only non-zero if jmp of call instructions were
|
||||
//! used with immediate operand (this means jumping or calling an absolute
|
||||
//! address directly).
|
||||
ASMJIT_INLINE size_t getTrampolineSize() const {
|
||||
return _trampolineSize;
|
||||
}
|
||||
@@ -274,26 +281,26 @@ struct BaseAssembler : public CodeGen {
|
||||
// [Label]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get count of labels created.
|
||||
//! Get count of labels created.
|
||||
ASMJIT_INLINE size_t getLabelsCount() const {
|
||||
return _labels.getLength();
|
||||
}
|
||||
|
||||
//! @brief Get whether @a label is created.
|
||||
//! Get whether `label` is created.
|
||||
ASMJIT_INLINE bool isLabelCreated(const Label& label) const {
|
||||
return static_cast<size_t>(label.getId()) < _labels.getLength();
|
||||
}
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Get @ref LabelData by @a label.
|
||||
//! Get `LabelData` by `label`.
|
||||
ASMJIT_INLINE LabelData* getLabelData(const Label& label) const {
|
||||
return getLabelDataById(label.getId());
|
||||
}
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Get @ref LabelData by @a id.
|
||||
//! Get `LabelData` by `id`.
|
||||
ASMJIT_INLINE LabelData* getLabelDataById(uint32_t id) const {
|
||||
ASMJIT_ASSERT(id != kInvalidValue);
|
||||
ASMJIT_ASSERT(id < _labels.getLength());
|
||||
@@ -303,30 +310,30 @@ struct BaseAssembler : public CodeGen {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Register labels for other code generator (@ref Compiler).
|
||||
//! Register labels for other code generator, i.e. `Compiler`.
|
||||
ASMJIT_API Error _registerIndexedLabels(size_t index);
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Create and initialize a new label.
|
||||
//! Create and initialize a new `Label`.
|
||||
ASMJIT_API Error _newLabel(Label* dst);
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief New LabelLink instance.
|
||||
//! New LabelLink instance.
|
||||
ASMJIT_API LabelLink* _newLabelLink();
|
||||
|
||||
//! @brief Create and return new label.
|
||||
//! Create and return a new `Label`.
|
||||
ASMJIT_INLINE Label newLabel() {
|
||||
Label result(NoInit);
|
||||
_newLabel(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! @brief Bind label to the current offset (virtual).
|
||||
//! Bind label to the current offset.
|
||||
virtual void _bind(const Label& label) = 0;
|
||||
|
||||
//! @brief Bind label to the current offset (virtual).
|
||||
//! Bind label to the current offset.
|
||||
//!
|
||||
//! @note Label can be bound only once!
|
||||
ASMJIT_INLINE void bind(const Label& label) {
|
||||
@@ -337,43 +344,43 @@ struct BaseAssembler : public CodeGen {
|
||||
// [Embed]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Embed data into the code buffer.
|
||||
//! Embed data into the code buffer.
|
||||
ASMJIT_API Error embed(const void* data, uint32_t size);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Align]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Align target buffer to @a m bytes.
|
||||
//! Align target buffer to `m` bytes.
|
||||
//!
|
||||
//! Typical usage of this is to align labels at start of the inner loops.
|
||||
//!
|
||||
//! Inserts @c nop() instructions or CPU optimized NOPs.
|
||||
//! Inserts `nop()` instructions or CPU optimized NOPs.
|
||||
ASMJIT_INLINE Error align(uint32_t m) {
|
||||
return _align(m);
|
||||
}
|
||||
|
||||
//! @brief Align target buffer to @a m bytes (virtual).
|
||||
//! Align target buffer to `m` bytes (virtual).
|
||||
virtual Error _align(uint32_t m) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reloc]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Simplifed version of @c relocCode() method designed for JIT.
|
||||
//! Simplifed version of `relocCode()` method designed for JIT.
|
||||
//!
|
||||
//! @overload
|
||||
ASMJIT_INLINE size_t relocCode(void* dst) const {
|
||||
return _relocCode(dst, static_cast<Ptr>((uintptr_t)dst));
|
||||
}
|
||||
|
||||
//! @brief Relocate code to a given address @a dst.
|
||||
//! Relocate code to a given address `dst`.
|
||||
//!
|
||||
//! @param dst Where the relocated code should me stored. The pointer can be
|
||||
//! address returned by virtual memory allocator or your own address if you
|
||||
//! want only to store the code for later reuse (or load, etc...).
|
||||
//! @param addressBase Base address used for relocation. When using JIT code
|
||||
//! generation, this will be the same as @a dst, only casted to system
|
||||
//! generation, this will be the same as `dst`, only casted to system
|
||||
//! integer type. But when generating code for remote process then the value
|
||||
//! can be different.
|
||||
//!
|
||||
@@ -383,12 +390,12 @@ struct BaseAssembler : public CodeGen {
|
||||
//! for the function.
|
||||
//!
|
||||
//! A given buffer will be overwritten, to get number of bytes required use
|
||||
//! @c getCodeSize().
|
||||
//! `getCodeSize()`.
|
||||
ASMJIT_INLINE size_t relocCode(void* dst, Ptr base) const {
|
||||
return _relocCode(dst, base);
|
||||
}
|
||||
|
||||
//! @brief Reloc code (virtual).
|
||||
//! Reloc code (virtual).
|
||||
virtual size_t _relocCode(void* dst, Ptr base) const = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -401,7 +408,7 @@ struct BaseAssembler : public CodeGen {
|
||||
// [Emit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Emit an instruction.
|
||||
//! Emit an instruction.
|
||||
ASMJIT_API Error emit(uint32_t code);
|
||||
//! @overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0);
|
||||
@@ -414,7 +421,7 @@ struct BaseAssembler : public CodeGen {
|
||||
return _emit(code, o0, o1, o2, o3);
|
||||
}
|
||||
|
||||
//! @brief Emit an instruction with integer immediate operand.
|
||||
//! Emit an instruction with integer immediate operand.
|
||||
ASMJIT_API Error emit(uint32_t code, int o0);
|
||||
//! @overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, int o1);
|
||||
@@ -423,37 +430,37 @@ struct BaseAssembler : public CodeGen {
|
||||
//! @overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3);
|
||||
|
||||
//! @brief Emit an instruction (virtual).
|
||||
//! Emit an instruction (virtual).
|
||||
virtual Error _emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Buffer where the code is emitted (either live or temporary).
|
||||
//! Buffer where the code is emitted (either live or temporary).
|
||||
//!
|
||||
//! This is actually the base pointer of the buffer, to get the current
|
||||
//! position (cursor) look at the @c _cursor member.
|
||||
//! position (cursor) look at the `_cursor` member.
|
||||
uint8_t* _buffer;
|
||||
//! @brief The end of the buffer (points to the first invalid byte).
|
||||
//! The end of the buffer (points to the first invalid byte).
|
||||
//!
|
||||
//! The end of the buffer is calculated as <code>_buffer + size</code>.
|
||||
uint8_t* _end;
|
||||
//! @brief The current position in code @c _buffer.
|
||||
//! The current position in code `_buffer`.
|
||||
uint8_t* _cursor;
|
||||
|
||||
//! @brief Size of possible trampolines.
|
||||
//! Size of possible trampolines.
|
||||
uint32_t _trampolineSize;
|
||||
|
||||
//! @brief Inline comment that will be logged by the next instruction and
|
||||
//! Inline comment that will be logged by the next instruction and
|
||||
//! set to NULL.
|
||||
const char* _comment;
|
||||
//! @brief Linked list of unused links (@c LabelLink* structures)
|
||||
//! Unused `LabelLink` structures pool.
|
||||
LabelLink* _unusedLinks;
|
||||
|
||||
//! @brief Labels data.
|
||||
//! Labels data.
|
||||
PodVector<LabelData> _labels;
|
||||
//! @brief Relocations data.
|
||||
//! Relocations data.
|
||||
PodVector<RelocData> _relocData;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace asmjit {
|
||||
// [asmjit::CodeGen - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
CodeGen::CodeGen(BaseRuntime* runtime) :
|
||||
CodeGen::CodeGen(Runtime* runtime) :
|
||||
_runtime(runtime),
|
||||
_logger(NULL),
|
||||
_errorHandler(NULL),
|
||||
@@ -40,7 +40,7 @@ CodeGen::~CodeGen() {
|
||||
// [asmjit::CodeGen - Logging]
|
||||
// ============================================================================
|
||||
|
||||
Error CodeGen::setLogger(BaseLogger* logger) {
|
||||
Error CodeGen::setLogger(Logger* logger) {
|
||||
_logger = logger;
|
||||
return kErrorOk;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ Error CodeGen::setError(Error error, const char* message) {
|
||||
if (handler != NULL && handler->handleError(error, message))
|
||||
return error;
|
||||
|
||||
BaseLogger* logger = _logger;
|
||||
Logger* logger = _logger;
|
||||
if (logger != NULL) {
|
||||
logger->logFormat(kLoggerStyleComment,
|
||||
"*** ERROR: %s (%u).\n", message, static_cast<unsigned int>(error));
|
||||
|
||||
+53
-51
@@ -20,33 +20,35 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kCodeGen]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief @ref CodeGen features.
|
||||
//! Features of `CodeGen`.
|
||||
ASMJIT_ENUM(kCodeGen) {
|
||||
//! @brief Emit optimized code-alignment sequences.
|
||||
//! Emit optimized code-alignment sequences.
|
||||
//!
|
||||
//! X86/X64:
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! Default align sequence used by X86/X64 architecture is one-byte 0x90
|
||||
//! opcode that is mostly shown by disassemblers as nop. However there are
|
||||
//! more optimized align sequences for 2-11 bytes that may execute faster.
|
||||
//! If this feature is enabled asmjit will generate specialized sequences
|
||||
//! for alignment between 1 to 11 bytes. Also when @ref x86x64::Compiler
|
||||
//! is used, it may add rex prefixes into the code to make some instructions
|
||||
//! larger so no alignment sequences are needed.
|
||||
//! for alignment between 1 to 11 bytes. Also when `x86x64::Compiler` is
|
||||
//! used, it may add rex prefixes into the code to make some instructions
|
||||
//! greater so no alignment sequences are needed.
|
||||
//!
|
||||
//! @default true.
|
||||
//! Default true.
|
||||
kCodeGenOptimizedAlign = 0,
|
||||
|
||||
//! @brief Emit jump-prediction hints.
|
||||
//! Emit jump-prediction hints.
|
||||
//!
|
||||
//! X86/X64:
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! Jump prediction is usually based on the direction of the jump. If the
|
||||
//! jump is backward it is usually predicted as taken; and if the jump is
|
||||
@@ -55,7 +57,7 @@ ASMJIT_ENUM(kCodeGen) {
|
||||
//! However this behavior can be overridden by using instruction prefixes.
|
||||
//! If this option is enabled these hints will be emitted.
|
||||
//!
|
||||
//! @default true.
|
||||
//! Default true.
|
||||
kCodeGenPredictedJumps = 1
|
||||
};
|
||||
|
||||
@@ -63,7 +65,7 @@ ASMJIT_ENUM(kCodeGen) {
|
||||
// [asmjit::CodeGen]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Abstract class inherited by @ref Assembler and @ref Compiler.
|
||||
//! Abstract class inherited by `Assembler` and `Compiler`.
|
||||
struct CodeGen {
|
||||
ASMJIT_NO_COPY(CodeGen)
|
||||
|
||||
@@ -71,76 +73,76 @@ struct CodeGen {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @ref CodeGen instance.
|
||||
ASMJIT_API CodeGen(BaseRuntime* runtime);
|
||||
//! @brief Destroy the @ref CodeGen instance.
|
||||
//! Create a new `CodeGen` instance.
|
||||
ASMJIT_API CodeGen(Runtime* runtime);
|
||||
//! Destroy the `CodeGen` instance.
|
||||
ASMJIT_API virtual ~CodeGen();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Runtime]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get runtime.
|
||||
ASMJIT_INLINE BaseRuntime* getRuntime() const { return _runtime; }
|
||||
//! Get runtime.
|
||||
ASMJIT_INLINE Runtime* getRuntime() const { return _runtime; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logger]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether the code generator has a logger.
|
||||
//! Get whether the code generator has a logger.
|
||||
ASMJIT_INLINE bool hasLogger() const { return _logger != NULL; }
|
||||
//! @brief Get logger.
|
||||
ASMJIT_INLINE BaseLogger* getLogger() const { return _logger; }
|
||||
//! @brief Set logger to @a logger.
|
||||
ASMJIT_API Error setLogger(BaseLogger* logger);
|
||||
//! Get logger.
|
||||
ASMJIT_INLINE Logger* getLogger() const { return _logger; }
|
||||
//! Set logger to `logger`.
|
||||
ASMJIT_API Error setLogger(Logger* logger);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Arch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get target architecture.
|
||||
//! Get target architecture.
|
||||
ASMJIT_INLINE uint32_t getArch() const { return _arch; }
|
||||
|
||||
//! @brief Get default register size (4 or 8 bytes).
|
||||
//! Get default register size (4 or 8 bytes).
|
||||
ASMJIT_INLINE uint32_t getRegSize() const { return _regSize; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Error]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get last error code.
|
||||
//! Get last error code.
|
||||
ASMJIT_INLINE Error getError() const { return _error; }
|
||||
//! @brief Set last error code and propagate it through the error handler.
|
||||
//! Set last error code and propagate it through the error handler.
|
||||
ASMJIT_API Error setError(Error error, const char* message = NULL);
|
||||
//! @brief Clear the last error code.
|
||||
//! Clear the last error code.
|
||||
ASMJIT_INLINE void clearError() { _error = kErrorOk; }
|
||||
|
||||
//! @brief Get error handler.
|
||||
//! Get error handler.
|
||||
ASMJIT_INLINE ErrorHandler* getErrorHandler() const { return _errorHandler; }
|
||||
//! @brief Set error handler.
|
||||
//! Set error handler.
|
||||
ASMJIT_API Error setErrorHandler(ErrorHandler* handler);
|
||||
//! @brief Clear error handler.
|
||||
//! Clear error handler.
|
||||
ASMJIT_INLINE Error clearErrorHandler() { return setErrorHandler(NULL); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Features]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get code-generator @a feature.
|
||||
//! Get code-generator `feature`.
|
||||
ASMJIT_API bool hasFeature(uint32_t feature) const;
|
||||
//! @brief Set code-generator @a feature to @a value.
|
||||
//! Set code-generator `feature` to `value`.
|
||||
ASMJIT_API Error setFeature(uint32_t feature, bool value);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Options]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get options.
|
||||
//! Get options.
|
||||
ASMJIT_INLINE uint32_t getOptions() const { return _options; }
|
||||
//! @brief Set options.
|
||||
//! Set options.
|
||||
ASMJIT_INLINE void setOptions(uint32_t options) { _options = options; }
|
||||
|
||||
//! @brief Get options and clear them.
|
||||
//! Get options and clear them.
|
||||
ASMJIT_INLINE uint32_t getOptionsAndClear() {
|
||||
uint32_t options = _options;
|
||||
_options = 0;
|
||||
@@ -151,7 +153,7 @@ struct CodeGen {
|
||||
// [Purge]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Called by clear() and reset() to clear all data used by the code
|
||||
//! Called by `clear()` and `reset()` to clear all data used by the code
|
||||
//! generator.
|
||||
virtual void _purge() = 0;
|
||||
|
||||
@@ -159,37 +161,37 @@ struct CodeGen {
|
||||
// [Make]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Make is a convenience method to make and relocate the current code
|
||||
//! into the associated runtime.
|
||||
//! Make is a convenience method to make and relocate the current code and
|
||||
//! add it to the associated `Runtime`.
|
||||
//!
|
||||
//! What is needed is only to cast the returned pointer to your function type
|
||||
//! and then use it. If there was an error during make() @c NULL is returned
|
||||
//! and the last error code can be obtained by calling @ref getError().
|
||||
//! and then use it. If there was an error during `make()` `NULL` is returned
|
||||
//! and the last error code can be obtained by calling `getError()`.
|
||||
virtual void* make() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Runtime.
|
||||
BaseRuntime* _runtime;
|
||||
//! @brief Logger.
|
||||
BaseLogger* _logger;
|
||||
//! @brief Error handler, called by @ref setError().
|
||||
//! Runtime.
|
||||
Runtime* _runtime;
|
||||
//! Logger.
|
||||
Logger* _logger;
|
||||
//! Error handler, called by `setError()`.
|
||||
ErrorHandler* _errorHandler;
|
||||
|
||||
//! @brief Target architecture.
|
||||
//! Target architecture.
|
||||
uint8_t _arch;
|
||||
//! @brief Get the default register size of the architecture (4 or 8 bytes).
|
||||
//! Get the default register size of the architecture (4 or 8 bytes).
|
||||
uint8_t _regSize;
|
||||
//! @brief Last error code.
|
||||
//! Last error code.
|
||||
uint8_t _error;
|
||||
//! @brief Target features.
|
||||
//! Target features.
|
||||
uint8_t _features;
|
||||
//! @brief Options for the next generated instruction (only 8-bits used).
|
||||
//! Options for the next generated instruction (only 8-bits used).
|
||||
uint32_t _options;
|
||||
|
||||
//! @brief Base zone.
|
||||
//! Base zone.
|
||||
Zone _baseZone;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ enum { kBaseCompilerDefaultLookAhead = 64 };
|
||||
// [asmjit::BaseCompiler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseCompiler::BaseCompiler(BaseRuntime* runtime) :
|
||||
BaseCompiler::BaseCompiler(Runtime* runtime) :
|
||||
CodeGen(runtime),
|
||||
_nodeFlowId(0),
|
||||
_nodeFlags(0),
|
||||
|
||||
+452
-448
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@ const ConstPoolNode ConstPoolTree::_sentinel = { {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Remove left horizontal links.
|
||||
//! Remove left horizontal links.
|
||||
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node) {
|
||||
if (node->_link[0]->_level == node->_level && node->_level != 0 ) {
|
||||
ConstPoolNode *save = node->_link[0];
|
||||
@@ -45,7 +45,7 @@ static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node)
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Remove consecutive horizontal links.
|
||||
//! Remove consecutive horizontal links.
|
||||
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_splitNode(ConstPoolNode* node) {
|
||||
if (node->_link[1]->_link[1]->_level == node->_level && node->_level != 0) {
|
||||
ConstPoolNode *save = node->_link[1];
|
||||
@@ -159,7 +159,7 @@ void ConstPool::reset() {
|
||||
// [asmjit::ConstPool - Ops]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
|
||||
static ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
|
||||
if (size <= 1)
|
||||
return ConstPool::kIndex1;
|
||||
else if (size <= 3)
|
||||
@@ -172,7 +172,7 @@ ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
|
||||
return ConstPool::kIndex16;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
|
||||
static ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
|
||||
ConstPoolGap* gap = self->_gapPool;
|
||||
if (gap == NULL)
|
||||
return self->_zone->allocT<ConstPoolGap>();
|
||||
@@ -181,7 +181,7 @@ ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
|
||||
return gap;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPoolGap* gap) {
|
||||
static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPoolGap* gap) {
|
||||
gap->_next = self->_gapPool;
|
||||
self->_gapPool = gap;
|
||||
}
|
||||
|
||||
+31
-24
@@ -17,13 +17,16 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPoolNode]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Zone-allocated constant-pool node.
|
||||
//! Zone-allocated constant-pool node.
|
||||
struct ConstPoolNode {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
@@ -37,13 +40,13 @@ struct ConstPoolNode {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Left/Right nodes.
|
||||
//! Left/Right nodes.
|
||||
ConstPoolNode* _link[2];
|
||||
//! @brief Horizontal level for balance.
|
||||
//! Horizontal level for balance.
|
||||
uint32_t _level : 31;
|
||||
//! @brief Whether this constant is shared with another.
|
||||
//! Whether this constant is shared with another.
|
||||
uint32_t _shared : 1;
|
||||
//! @brief Data offset from the beginning of the pool.
|
||||
//! Data offset from the beginning of the pool.
|
||||
uint32_t _offset;
|
||||
};
|
||||
|
||||
@@ -53,10 +56,10 @@ struct ConstPoolNode {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Zone-allocated constant-pool tree.
|
||||
//! Zone-allocated constant-pool tree.
|
||||
struct ConstPoolTree {
|
||||
enum {
|
||||
//! @brief Maximum tree height == log2(1 << 64).
|
||||
//! Maximum tree height == log2(1 << 64).
|
||||
kHeightLimit = 64
|
||||
};
|
||||
|
||||
@@ -169,11 +172,11 @@ struct ConstPoolTree {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Root of the tree
|
||||
//! Root of the tree
|
||||
ConstPoolNode* _root;
|
||||
//! @brief Length of the tree (count of nodes).
|
||||
//! Length of the tree (count of nodes).
|
||||
size_t _length;
|
||||
//! @brief Size of the data.
|
||||
//! Size of the data.
|
||||
size_t _dataSize;
|
||||
};
|
||||
|
||||
@@ -183,13 +186,13 @@ struct ConstPoolTree {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Zone-allocated constant-pool gap.
|
||||
//! Zone-allocated constant-pool gap.
|
||||
struct ConstPoolGap {
|
||||
//! @brief Link to the next gap
|
||||
//! Link to the next gap
|
||||
ConstPoolGap* _next;
|
||||
//! @brief Offset of the gap.
|
||||
//! Offset of the gap.
|
||||
size_t _offset;
|
||||
//! @brief Remaining bytes of the gap (basically a gap size).
|
||||
//! Remaining bytes of the gap (basically a gap size).
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
@@ -197,6 +200,7 @@ struct ConstPoolGap {
|
||||
// [asmjit::ConstPool]
|
||||
// ============================================================================
|
||||
|
||||
//! Constant pool.
|
||||
struct ConstPool {
|
||||
ASMJIT_NO_COPY(ConstPool)
|
||||
|
||||
@@ -227,21 +231,22 @@ struct ConstPool {
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether the constant-pool is empty.
|
||||
//! Get whether the constant-pool is empty.
|
||||
ASMJIT_INLINE bool isEmpty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
//! @brief Get the size of the constant-pool in bytes.
|
||||
//! Get the size of the constant-pool in bytes.
|
||||
ASMJIT_INLINE size_t getSize() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
//! Get minimum alignment.
|
||||
ASMJIT_INLINE size_t getAlignment() const {
|
||||
return _alignment;
|
||||
}
|
||||
|
||||
//! @brief Add a constant to the constant pool.
|
||||
//! Add a constant to the constant pool.
|
||||
//!
|
||||
//! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes.
|
||||
//! The constant is added to the pool only if it doesn't not exist, otherwise
|
||||
@@ -264,28 +269,30 @@ struct ConstPool {
|
||||
// [Fill]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Fill the destination with the constants from the pool.
|
||||
//! Fill the destination with the constants from the pool.
|
||||
ASMJIT_API void fill(void* dst);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Zone allocator.
|
||||
//! Zone allocator.
|
||||
Zone* _zone;
|
||||
//! @brief Tree per size.
|
||||
//! Tree per size.
|
||||
ConstPoolTree _tree[kIndexCount];
|
||||
//! @brief Gaps per size.
|
||||
//! Gaps per size.
|
||||
ConstPoolGap* _gaps[kIndexCount];
|
||||
//! @brief Gaps pool
|
||||
//! Gaps pool
|
||||
ConstPoolGap* _gapPool;
|
||||
|
||||
//! @brief Size of the pool (in bytes).
|
||||
//! Size of the pool (in bytes).
|
||||
size_t _size;
|
||||
//! @brief Alignemnt.
|
||||
//! Alignemnt.
|
||||
size_t _alignment;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
|
||||
@@ -298,7 +298,7 @@ Error BaseContext::removeUnreachableCode() {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Translate the given function @a func.
|
||||
//! Translate the given function `func`.
|
||||
void BaseContext::cleanup() {
|
||||
VarData** array = _contextVd.getData();
|
||||
size_t length = _contextVd.getLength();
|
||||
|
||||
+57
-47
@@ -17,10 +17,17 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseContext]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! Code generation context is the logic behind `BaseCompiler`. The context is
|
||||
//! used to compile the code stored in `BaseCompiler`.
|
||||
struct BaseContext {
|
||||
ASMJIT_NO_COPY(BaseContext)
|
||||
|
||||
@@ -35,41 +42,41 @@ struct BaseContext {
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Reset the whole context.
|
||||
//! Reset the whole context.
|
||||
virtual void reset();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get compiler.
|
||||
//! Get compiler.
|
||||
ASMJIT_INLINE BaseCompiler* getCompiler() const { return _compiler; }
|
||||
|
||||
//! @brief Get function.
|
||||
//! Get function.
|
||||
ASMJIT_INLINE FuncNode* getFunc() const { return _func; }
|
||||
//! @brief Get stop node.
|
||||
//! Get stop node.
|
||||
ASMJIT_INLINE BaseNode* getStop() const { return _stop; }
|
||||
|
||||
//! @brief Get start of the current scope.
|
||||
//! Get start of the current scope.
|
||||
ASMJIT_INLINE BaseNode* getStart() const { return _start; }
|
||||
//! @brief Get end of the current scope.
|
||||
//! Get end of the current scope.
|
||||
ASMJIT_INLINE BaseNode* getEnd() const { return _end; }
|
||||
|
||||
//! @brief Get extra block.
|
||||
//! Get extra block.
|
||||
ASMJIT_INLINE BaseNode* getExtraBlock() const { return _extraBlock; }
|
||||
//! @brief Set extra block.
|
||||
//! Set extra block.
|
||||
ASMJIT_INLINE void setExtraBlock(BaseNode* node) { _extraBlock = node; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Error]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get the last error code.
|
||||
//! Get the last error code.
|
||||
ASMJIT_INLINE Error getError() const {
|
||||
return getCompiler()->getError();
|
||||
}
|
||||
|
||||
//! @brief Set the last error code and propagate it through the error handler.
|
||||
//! Set the last error code and propagate it through the error handler.
|
||||
ASMJIT_INLINE Error setError(Error error, const char* message = NULL) {
|
||||
return getCompiler()->setError(error, message);
|
||||
}
|
||||
@@ -78,19 +85,20 @@ struct BaseContext {
|
||||
// [State]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get current state.
|
||||
ASMJIT_INLINE BaseVarState* getState() const { return _state; }
|
||||
//! Get current state.
|
||||
ASMJIT_INLINE BaseVarState* getState() const {
|
||||
return _state;
|
||||
}
|
||||
|
||||
//! @brief Load current state from @a target state.
|
||||
//! Load current state from `target` state.
|
||||
virtual void loadState(BaseVarState* src) = 0;
|
||||
//! @brief Save current state, returning new @ref BaseVarState instance.
|
||||
//! Save current state, returning new `BaseVarState` instance.
|
||||
virtual BaseVarState* saveState() = 0;
|
||||
|
||||
//! @brief Change the current state to @a target state.
|
||||
//! Change the current state to `target` state.
|
||||
virtual void switchState(BaseVarState* src) = 0;
|
||||
|
||||
//! @brief Change the current state to the intersection of two states @a a
|
||||
//! and @a b.
|
||||
//! Change the current state to the intersection of two states `a` and `b`.
|
||||
virtual void intersectStates(BaseVarState* a, BaseVarState* b) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -140,7 +148,7 @@ struct BaseContext {
|
||||
// [Fetch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Fetch.
|
||||
//! Fetch.
|
||||
//!
|
||||
//! Fetch iterates over all nodes and gathers information about all variables
|
||||
//! used. The process generates information required by register allocator,
|
||||
@@ -151,14 +159,14 @@ struct BaseContext {
|
||||
// [RemoveUnreachableCode]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Remove unreachable code.
|
||||
//! Remove unreachable code.
|
||||
virtual Error removeUnreachableCode();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Analyze]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Preform variable liveness analysis.
|
||||
//! Preform variable liveness analysis.
|
||||
//!
|
||||
//! Analysis phase iterates over nodes in reverse order and generates a bit
|
||||
//! array describing variables that are alive at every node in the function.
|
||||
@@ -180,7 +188,7 @@ struct BaseContext {
|
||||
// [Translate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Translate code by allocating registers and handling state changes.
|
||||
//! Translate code by allocating registers and handling state changes.
|
||||
virtual Error translate() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -205,70 +213,72 @@ struct BaseContext {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Compiler.
|
||||
//! Compiler.
|
||||
BaseCompiler* _compiler;
|
||||
//! @brief Function.
|
||||
//! Function.
|
||||
FuncNode* _func;
|
||||
|
||||
//! @brief Zone allocator.
|
||||
//! Zone allocator.
|
||||
Zone _baseZone;
|
||||
|
||||
//! @brief Start of the current active scope.
|
||||
//! Start of the current active scope.
|
||||
BaseNode* _start;
|
||||
//! @brief End of the current active scope.
|
||||
//! End of the current active scope.
|
||||
BaseNode* _end;
|
||||
|
||||
//! @brief Node that is used to insert extra code after the function body.
|
||||
//! Node that is used to insert extra code after the function body.
|
||||
BaseNode* _extraBlock;
|
||||
//! @brief Stop node.
|
||||
//! Stop node.
|
||||
BaseNode* _stop;
|
||||
|
||||
//! @brief Unreachable nodes.
|
||||
//! Unreachable nodes.
|
||||
PodList<BaseNode*> _unreachableList;
|
||||
//! @brief Jump nodes.
|
||||
//! Jump nodes.
|
||||
PodList<BaseNode*> _jccList;
|
||||
|
||||
//! @brief All variables used by the current function.
|
||||
//! All variables used by the current function.
|
||||
PodVector<VarData*> _contextVd;
|
||||
|
||||
//! @brief Memory used to spill variables.
|
||||
//! Memory used to spill variables.
|
||||
MemCell* _memVarCells;
|
||||
//! @brief Memory used to alloc memory on the stack.
|
||||
//! Memory used to alloc memory on the stack.
|
||||
MemCell* _memStackCells;
|
||||
|
||||
//! @brief Count of 1-byte cells.
|
||||
//! Count of 1-byte cells.
|
||||
uint32_t _mem1ByteVarsUsed;
|
||||
//! @brief Count of 2-byte cells.
|
||||
//! Count of 2-byte cells.
|
||||
uint32_t _mem2ByteVarsUsed;
|
||||
//! @brief Count of 4-byte cells.
|
||||
//! Count of 4-byte cells.
|
||||
uint32_t _mem4ByteVarsUsed;
|
||||
//! @brief Count of 8-byte cells.
|
||||
//! Count of 8-byte cells.
|
||||
uint32_t _mem8ByteVarsUsed;
|
||||
//! @brief Count of 16-byte cells.
|
||||
//! Count of 16-byte cells.
|
||||
uint32_t _mem16ByteVarsUsed;
|
||||
//! @brief Count of 32-byte cells.
|
||||
//! Count of 32-byte cells.
|
||||
uint32_t _mem32ByteVarsUsed;
|
||||
//! @brief Count of 64-byte cells.
|
||||
//! Count of 64-byte cells.
|
||||
uint32_t _mem64ByteVarsUsed;
|
||||
//! @brief Count of stack memory cells.
|
||||
//! Count of stack memory cells.
|
||||
uint32_t _memStackCellsUsed;
|
||||
|
||||
//! @brief Maximum memory alignment used by the function.
|
||||
//! Maximum memory alignment used by the function.
|
||||
uint32_t _memMaxAlign;
|
||||
//! @brief Count of bytes used by variables.
|
||||
//! Count of bytes used by variables.
|
||||
uint32_t _memVarTotal;
|
||||
//! @brief Count of bytes used by stack.
|
||||
//! Count of bytes used by stack.
|
||||
uint32_t _memStackTotal;
|
||||
//! @brief Count of bytes used by variables and stack after alignment.
|
||||
//! Count of bytes used by variables and stack after alignment.
|
||||
uint32_t _memAllTotal;
|
||||
|
||||
//! @brief Default lenght of annotated instruction.
|
||||
//! Default lenght of annotated instruction.
|
||||
uint32_t _annotationLength;
|
||||
|
||||
//! @brief Current state (used by register allocator).
|
||||
//! Current state (used by register allocator).
|
||||
BaseVarState* _state;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
|
||||
@@ -62,7 +62,7 @@ uint32_t BaseCpuInfo::detectNumberOfCores() {
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
struct HostCpuInfo : public x86x64::CpuInfo {
|
||||
ASMJIT_INLINE HostCpuInfo() : CpuInfo() {
|
||||
x86x64::hostCpuDetect(this);
|
||||
x86x64::CpuUtil::detect(this);
|
||||
}
|
||||
};
|
||||
#else
|
||||
|
||||
+33
-30
@@ -16,30 +16,30 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_cpu_info
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kCpuVendor]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Cpu vendor IDs.
|
||||
//! Cpu vendor IDs.
|
||||
//!
|
||||
//! Cpu vendor IDs are specific for AsmJit library. Vendor ID is not directly
|
||||
//! read from cpuid result, instead it's based on CPU vendor string.
|
||||
ASMJIT_ENUM(kCpuVendor) {
|
||||
//! @brief Unknown CPU vendor.
|
||||
//! Unknown CPU vendor.
|
||||
kCpuVendorUnknown = 0,
|
||||
|
||||
//! @brief Intel CPU vendor.
|
||||
//! Intel CPU vendor.
|
||||
kCpuVendorIntel = 1,
|
||||
//! @brief AMD CPU vendor.
|
||||
//! AMD CPU vendor.
|
||||
kCpuVendorAmd = 2,
|
||||
//! @brief National Semiconductor CPU vendor (applies also to Cyrix processors).
|
||||
//! National Semiconductor CPU vendor (applies also to Cyrix processors).
|
||||
kCpuVendorNSM = 3,
|
||||
//! @brief Transmeta CPU vendor.
|
||||
//! Transmeta CPU vendor.
|
||||
kCpuVendorTransmeta = 4,
|
||||
//! @brief VIA CPU vendor.
|
||||
//! VIA CPU vendor.
|
||||
kCpuVendorVia = 5
|
||||
};
|
||||
|
||||
@@ -47,11 +47,14 @@ ASMJIT_ENUM(kCpuVendor) {
|
||||
// [asmjit::BaseCpuInfo]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Base cpu information.
|
||||
//! Base cpu information.
|
||||
struct BaseCpuInfo {
|
||||
ASMJIT_NO_COPY(BaseCpuInfo)
|
||||
|
||||
enum { kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8 };
|
||||
//! @internal
|
||||
enum {
|
||||
kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
@@ -63,23 +66,23 @@ struct BaseCpuInfo {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get CPU vendor string.
|
||||
//! Get CPU vendor string.
|
||||
ASMJIT_INLINE const char* getVendorString() const { return _vendorString; }
|
||||
//! @brief Get CPU brand string.
|
||||
//! Get CPU brand string.
|
||||
ASMJIT_INLINE const char* getBrandString() const { return _brandString; }
|
||||
|
||||
//! @brief Get CPU vendor ID.
|
||||
//! Get CPU vendor ID.
|
||||
ASMJIT_INLINE uint32_t getVendorId() const { return _vendorId; }
|
||||
//! @brief Get CPU family ID.
|
||||
//! Get CPU family ID.
|
||||
ASMJIT_INLINE uint32_t getFamily() const { return _family; }
|
||||
//! @brief Get CPU model ID.
|
||||
//! Get CPU model ID.
|
||||
ASMJIT_INLINE uint32_t getModel() const { return _model; }
|
||||
//! @brief Get CPU stepping.
|
||||
//! Get CPU stepping.
|
||||
ASMJIT_INLINE uint32_t getStepping() const { return _stepping; }
|
||||
//! @brief Get CPU cores count (or sum of all cores of all procesors).
|
||||
//! Get CPU cores count (or sum of all cores of all procesors).
|
||||
ASMJIT_INLINE uint32_t getCoresCount() const { return _coresCount; }
|
||||
|
||||
//! @brief Get whether CPU has a @a feature.
|
||||
//! Get whether CPU has a `feature`.
|
||||
ASMJIT_INLINE bool hasFeature(uint32_t feature) const {
|
||||
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
|
||||
|
||||
@@ -87,7 +90,7 @@ struct BaseCpuInfo {
|
||||
(_features[feature / kFeaturesPerUInt32] >> (feature % kFeaturesPerUInt32)) & 0x1);
|
||||
}
|
||||
|
||||
//! @brief Add CPU @a feature.
|
||||
//! Add a CPU `feature`.
|
||||
ASMJIT_INLINE BaseCpuInfo& addFeature(uint32_t feature) {
|
||||
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
|
||||
|
||||
@@ -99,36 +102,36 @@ struct BaseCpuInfo {
|
||||
// [Statics]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Detect number of cores (or sum of all cores of all processors).
|
||||
//! Detect number of cores (or sum of all cores of all processors).
|
||||
static ASMJIT_API uint32_t detectNumberOfCores();
|
||||
|
||||
//! @brief Get host cpu.
|
||||
//! Get host cpu.
|
||||
static ASMJIT_API const BaseCpuInfo* getHost();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Size of the structure in bytes.
|
||||
//! Size of the structure in bytes.
|
||||
uint32_t _size;
|
||||
|
||||
//! @brief Cpu short vendor string.
|
||||
//! Cpu short vendor string.
|
||||
char _vendorString[16];
|
||||
//! @brief Cpu long vendor string (brand).
|
||||
//! Cpu long vendor string (brand).
|
||||
char _brandString[64];
|
||||
|
||||
//! @brief Cpu vendor id (see @c asmjit::kCpuVendor enum).
|
||||
//! Cpu vendor id, see `asmjit::kCpuVendor`.
|
||||
uint32_t _vendorId;
|
||||
//! @brief Cpu family ID.
|
||||
//! Cpu family ID.
|
||||
uint32_t _family;
|
||||
//! @brief Cpu model ID.
|
||||
//! Cpu model ID.
|
||||
uint32_t _model;
|
||||
//! @brief Cpu stepping.
|
||||
//! Cpu stepping.
|
||||
uint32_t _stepping;
|
||||
//! @brief Cpu cores count (or sum of all CPU cores of all processors).
|
||||
//! Cpu cores count (or sum of all CPU cores of all processors).
|
||||
uint32_t _coresCount;
|
||||
|
||||
//! @brief Cpu features bitfield.
|
||||
//! Cpu features bitfield.
|
||||
uint32_t _features[4];
|
||||
};
|
||||
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuTicks]
|
||||
// ============================================================================
|
||||
|
||||
//! CPU ticks utilities.
|
||||
struct CpuTicks {
|
||||
//! Get the current CPU ticks for benchmarking (1ms resolution).
|
||||
static ASMJIT_API uint32_t now();
|
||||
};
|
||||
|
||||
|
||||
+249
-241
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,10 @@ ErrorHandler::~ErrorHandler() {}
|
||||
// [asmjit::ErrorHandler - Interface]
|
||||
// ============================================================================
|
||||
|
||||
ErrorHandler* ErrorHandler::addRef() const { return const_cast<ErrorHandler*>(this); }
|
||||
ErrorHandler* ErrorHandler::addRef() const {
|
||||
return const_cast<ErrorHandler*>(this);
|
||||
}
|
||||
|
||||
void ErrorHandler::release() {}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
+61
-49
@@ -13,80 +13,82 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_logging_and_errors
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kError]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief AsmJit error codes.
|
||||
//! AsmJit error codes.
|
||||
ASMJIT_ENUM(kError) {
|
||||
//! @brief No error (success).
|
||||
//! No error (success).
|
||||
//!
|
||||
//! This is default state and state you want.
|
||||
kErrorOk = 0,
|
||||
|
||||
//! @brief Heap memory allocation failed.
|
||||
//! Heap memory allocation failed.
|
||||
kErrorNoHeapMemory = 1,
|
||||
//! @brief Virtual memory allocation failed.
|
||||
//! Virtual memory allocation failed.
|
||||
kErrorNoVirtualMemory = 2,
|
||||
|
||||
//! @brief Invalid argument.
|
||||
//! Invalid argument.
|
||||
kErrorInvalidArgument = 3,
|
||||
//! @brief Invalid state.
|
||||
//! Invalid state.
|
||||
kErrorInvalidState = 4,
|
||||
|
||||
//! @brief Unknown instruction. This happens only if instruction code is
|
||||
//! Unknown instruction. This happens only if instruction code is
|
||||
//! out of bounds. Shouldn't happen.
|
||||
kErrorAssemblerUnknownInst = 5,
|
||||
//! @brief Illegal instruction, usually generated by asmjit::Assembler
|
||||
//! Illegal instruction, usually generated by asmjit::Assembler
|
||||
//! class when emitting instruction opcode. If this error is generated the
|
||||
//! target buffer is not affected by this invalid instruction.
|
||||
//!
|
||||
//! You can also get this status code if you are under x64 (64-bit x86) and
|
||||
//! you tried to decode instruction using AH, BH, CH or DH register with REX
|
||||
//! prefix. These registers can't be accessed if REX prefix is used and AsmJit
|
||||
//! didn't check for this situation in intrinsics (@c Compiler takes care of
|
||||
//! didn't check for this situation in intrinsics (`BaseCompiler` takes care of
|
||||
//! this and rearrange registers if needed).
|
||||
//!
|
||||
//! Examples that will raise @c kErrorAssemblerIllegalInst error (a is
|
||||
//! @c Assembler instance):
|
||||
//! Example of raising `kErrorAssemblerIllegalInst` error.
|
||||
//!
|
||||
//! @code
|
||||
//! a.mov(dword_ptr(eax), al); // Invalid address size.
|
||||
//! a.mov(byte_ptr(r10), ah); // Undecodable instruction (AH used with r10
|
||||
//! // that can be encoded by using REX prefix only)
|
||||
//! @endcode
|
||||
//! ~~~
|
||||
//! // Invalid address size.
|
||||
//! a.mov(dword_ptr(eax), al);
|
||||
//!
|
||||
//! // Undecodable instruction - AH used with r10 that can be encoded by using
|
||||
//! // REX prefix only.
|
||||
//! a.mov(byte_ptr(r10), ah);
|
||||
//! ~~~
|
||||
//!
|
||||
//! @note In debug mode you get assertion failure instead of setting error
|
||||
//! code.
|
||||
kErrorAssemblerIllegalInst = 6,
|
||||
//! @brief Illegal addressing used (unencodable).
|
||||
//! Illegal addressing used (unencodable).
|
||||
kErrorAssemblerIllegalAddr = 7,
|
||||
//! @brief Short jump instruction used, but displacement is out of bounds.
|
||||
//! Short jump instruction used, but displacement is out of bounds.
|
||||
kErrorAssemblerIllegalShortJump = 8,
|
||||
|
||||
//! @brief No function defined.
|
||||
//! No function defined.
|
||||
kErrorCompilerNoFunc = 9,
|
||||
//! @brief Function generation is not finished by using @c Compiler::endFunc()
|
||||
//! Function generation is not finished by using `BaseCompiler::endFunc()`
|
||||
//! or something bad happened during generation related to function. This can
|
||||
//! be missing compiler node, etc...
|
||||
kErrorCompilerIncompleteFunc = 10,
|
||||
//! @brief Tried to generate a function with overlapped arguments.
|
||||
//! Tried to generate a function with overlapped arguments.
|
||||
kErrorCompilerOverlappedArgs = 11,
|
||||
|
||||
//! @brief Compiler can't allocate registers.
|
||||
//! Compiler can't allocate registers.
|
||||
kErrorCompilerNoRegs = 12,
|
||||
//! @brief Compiler can't allocate registers, because they overlap.
|
||||
//! Compiler can't allocate registers, because they overlap.
|
||||
kErrorCompilerOverlappedRegs = 13,
|
||||
|
||||
//! @brief Tried to call function with an incompatible argument.
|
||||
//! Tried to call function with an incompatible argument.
|
||||
kErrorCompilerIncompatibleArg = 14,
|
||||
//! @brief Incompatible return value.
|
||||
//! Incompatible return value.
|
||||
kErrorCompilerIncompatibleRet = 15,
|
||||
|
||||
//! @brief Count of AsmJit status codes. Can grow in future.
|
||||
//! Count of AsmJit status codes. Can grow in future.
|
||||
kErrorCount = 16
|
||||
};
|
||||
|
||||
@@ -100,42 +102,48 @@ typedef uint32_t Error;
|
||||
// [asmjit::ErrorHandler]
|
||||
// ============================================================================
|
||||
|
||||
//! Error handler.
|
||||
//!
|
||||
//! Error handler can be used to override the default behavior of `CodeGen`
|
||||
//! error handling and propagation. See `handleError` on how to override it.
|
||||
//!
|
||||
//! Please note that `addRef` and `release` functions are used, but there is
|
||||
//! no reference counting implemented by default, reimplement to change the
|
||||
//! default behavior.
|
||||
struct ErrorHandler {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @ref ErrorHandler.
|
||||
//! Create a new `ErrorHandler`.
|
||||
ASMJIT_API ErrorHandler();
|
||||
//! @brief Destroy the @ref ErrorHandler.
|
||||
//! Destroy the `ErrorHandler`.
|
||||
ASMJIT_API virtual ~ErrorHandler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Reference this error handler.
|
||||
//! Reference this error handler.
|
||||
//!
|
||||
//! @note This member function is provided for convenience. The default
|
||||
//! implementation does nothing. If you are working in environment where
|
||||
//! multiple @ref ErrorHandler instances are used in different @ref Assembler
|
||||
//! and @ref Compiler instances (or in multithreaded environment) you might
|
||||
//! want to provide your own functionality for reference counting. In that
|
||||
//! case override @ref addRef() and @ref release() functions to inc/dec your
|
||||
//! reference count value.
|
||||
//! multiple `ErrorHandler` instances are used by a different code generators
|
||||
//! you may provide your own functionality for reference counting. In that
|
||||
//! case `addRef()` and `release()` functions should be overridden.
|
||||
ASMJIT_API virtual ErrorHandler* addRef() const;
|
||||
|
||||
//! @brief Release this error handler.
|
||||
//! Release this error handler.
|
||||
//!
|
||||
//! @note This member function is provided for convenience. See @ref addRef()
|
||||
//! @note This member function is provided for convenience. See `addRef()`
|
||||
//! for more detailed information related to reference counting.
|
||||
ASMJIT_API virtual void release();
|
||||
|
||||
//! @brief Error handler (pure).
|
||||
//! Error handler (pure).
|
||||
//!
|
||||
//! Error handler is called when an error happened. An error can happen in
|
||||
//! many places, but error handler is mostly used by @ref Assembler and
|
||||
//! @ref Compiler classes to report anything that may prevent correct code
|
||||
//! many places, but error handler is mostly used by `BaseAssembler` and
|
||||
//! `BaseCompiler` classes to report anything that may prevent correct code
|
||||
//! generation. There are multiple ways how the error handler can be used
|
||||
//! and each has it's pros/cons.
|
||||
//!
|
||||
@@ -144,22 +152,22 @@ struct ErrorHandler {
|
||||
//! exceptions it is exception-safe and handleError() can report an incoming
|
||||
//! error by throwing an exception of any type. It's guaranteed that the
|
||||
//! exception won't be catched by AsmJit and will be propagated to the code
|
||||
//! calling AsmJit @ref Assembler or @ref Compiler. Alternative to throwing
|
||||
//! calling AsmJit `BaseAssembler` or `BaseCompiler`. Alternative to throwing
|
||||
//! exception is using setjmp() / longjmp() pair from the standard C library.
|
||||
//!
|
||||
//! If the exception or setjmp() / longjmp() mechanism is used, the state of
|
||||
//! the @ref Assember or @ref Compiler is unchanged and if it's possible the
|
||||
//! the `BaseAssember` or `BaseCompiler` is unchanged and if it's possible the
|
||||
//! execution (instruction serialization) can continue. However if the error
|
||||
//! happened during any phase that translates or modifies the stored code
|
||||
//! (for example relocation done by @ref Assembler or analysis/translation
|
||||
//! done by @ref Compiler) the execution can't continue and the error will
|
||||
//! be also stored in @ref Assembler or @ref Compiler.
|
||||
//! (for example relocation done by `BaseAssembler` or analysis/translation
|
||||
//! done by `BaseCompiler`) the execution can't continue and the error will
|
||||
//! be also stored in `BaseAssembler` or `BaseCompiler`.
|
||||
//!
|
||||
//! Finally, if exceptions nor setjmp() / longjmp() mechanisms were used,
|
||||
//! you can still implement a compatible design by returning from your error
|
||||
//! handler. Returning @c true means that error was reported and AsmJit
|
||||
//! should continue execution. When @c false is returned, AsmJit sets the
|
||||
//! error immediately to the @ref Assembler or @ref Compiler and execution
|
||||
//! handler. Returning `true` means that error was reported and AsmJit
|
||||
//! should continue execution. When `false` is returned, AsmJit sets the
|
||||
//! error immediately to the `BaseAssembler` or `BaseCompiler` and execution
|
||||
//! shouldn't continue (this is the default behavior in case no error handler
|
||||
//! is used).
|
||||
virtual bool handleError(Error code, const char* message) = 0;
|
||||
@@ -169,8 +177,9 @@ struct ErrorHandler {
|
||||
// [asmjit::ErrorUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Error utilities.
|
||||
struct ErrorUtil {
|
||||
//! @brief Get printable version of AsmJit @ref kError code.
|
||||
//! Get printable version of AsmJit `kError` code.
|
||||
static ASMJIT_API const char* asString(Error code);
|
||||
};
|
||||
|
||||
@@ -178,6 +187,9 @@ struct ErrorUtil {
|
||||
// [ASMJIT_PROPAGATE_ERROR]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! Used by AsmJit to return the `_Exp_` result if it's an error.
|
||||
#define ASMJIT_PROPAGATE_ERROR(_Exp_) \
|
||||
do { \
|
||||
::asmjit::Error errval_ = (_Exp_); \
|
||||
|
||||
+131
-108
@@ -17,6 +17,9 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
@@ -28,8 +31,12 @@ struct FnTypeId;
|
||||
// [asmjit::kFuncConv]
|
||||
// ============================================================================
|
||||
|
||||
//! Function calling convention.
|
||||
//!
|
||||
//! For a platform specific calling conventions, see:
|
||||
//! - `x86x64::kFuncConv` - X86/X64 calling conventions.
|
||||
ASMJIT_ENUM(kFuncConv) {
|
||||
//! @brief Calling convention is invalid (can't be used).
|
||||
//! Calling convention is invalid (can't be used).
|
||||
kFuncConvNone = 0
|
||||
};
|
||||
|
||||
@@ -37,43 +44,54 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
// [asmjit::kFuncHint]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function hints.
|
||||
//! Function hints.
|
||||
//!
|
||||
//! For a platform specific calling conventions, see:
|
||||
//! - `x86x64::kFuncHint` - X86/X64 function hints.
|
||||
ASMJIT_ENUM(kFuncHint) {
|
||||
//! @brief Make a naked function (default true).
|
||||
//! Make a naked function (default true).
|
||||
//!
|
||||
//! Naked function is function without using standard prolog/epilog sequence).
|
||||
//!
|
||||
//! @section X86/X64
|
||||
//! X86/X64 Specific
|
||||
//! ----------------
|
||||
//!
|
||||
//! Standard prolog sequence is:
|
||||
//!
|
||||
//! "push zbp"
|
||||
//! "mov zsp, zbp"
|
||||
//! "sub zsp, StackAdjustment"
|
||||
//! ~~~
|
||||
//! push zbp
|
||||
//! mov zsp, zbp
|
||||
//! sub zsp, StackAdjustment
|
||||
//! ~~~
|
||||
//!
|
||||
//! which is equal to:
|
||||
//! which is an equivalent to:
|
||||
//!
|
||||
//! "enter StackAdjustment, 0"
|
||||
//! ~~~
|
||||
//! enter StackAdjustment, 0
|
||||
//! ~~~
|
||||
//!
|
||||
//! Standard epilog sequence is:
|
||||
//!
|
||||
//! "mov zsp, zbp"
|
||||
//! "pop zbp"
|
||||
//! "ret"
|
||||
//! ~~~
|
||||
//! mov zsp, zbp
|
||||
//! pop zbp
|
||||
//! ~~~
|
||||
//!
|
||||
//! which is equal to:
|
||||
//! which is an equavalent to:
|
||||
//!
|
||||
//! "leave"
|
||||
//! "ret"
|
||||
//! ~~~
|
||||
//! leave
|
||||
//! ~~~
|
||||
//!
|
||||
//! Naked functions can omit the prolog/epilog sequence. The advantage of
|
||||
//! doing such modification is that EBP/RBP register can be used by the
|
||||
//! register allocator which can result in less spills/allocs.
|
||||
kFuncHintNaked = 0,
|
||||
|
||||
//! @brief Generate compact function prolog/epilog if possible.
|
||||
//! Generate compact function prolog/epilog if possible.
|
||||
//!
|
||||
//! @section X86/X64
|
||||
//! X86/X64 Specific
|
||||
//! ----------------
|
||||
//!
|
||||
//! Use shorter, but possible slower prolog/epilog sequence to save/restore
|
||||
//! registers.
|
||||
@@ -84,22 +102,26 @@ ASMJIT_ENUM(kFuncHint) {
|
||||
// [asmjit::kFuncFlags]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function flags.
|
||||
//! Function flags.
|
||||
//!
|
||||
//! For a platform specific calling conventions, see:
|
||||
//! - `x86x64::kFuncFlags` - X86/X64 function flags.
|
||||
ASMJIT_ENUM(kFuncFlags) {
|
||||
//! @brief Whether the function is using naked (minimal) prolog / epilog.
|
||||
//! Whether the function is using naked (minimal) prolog / epilog.
|
||||
kFuncFlagIsNaked = 0x00000001,
|
||||
|
||||
//! @brief Whether an another function is called from this function.
|
||||
//! Whether an another function is called from this function.
|
||||
kFuncFlagIsCaller = 0x00000002,
|
||||
|
||||
//! @brief Whether the stack is not aligned to the required stack alignment,
|
||||
//! Whether the stack is not aligned to the required stack alignment,
|
||||
//! thus it has to be aligned manually.
|
||||
kFuncFlagIsStackMisaligned = 0x00000004,
|
||||
|
||||
//! @brief Whether the stack pointer is adjusted by the stack size needed
|
||||
//! Whether the stack pointer is adjusted by the stack size needed
|
||||
//! to save registers and function variables.
|
||||
//!
|
||||
//! @section X86/X64
|
||||
//! X86/X64 Specific
|
||||
//! ----------------
|
||||
//!
|
||||
//! Stack pointer (ESP/RSP) is adjusted by 'sub' instruction in prolog and by
|
||||
//! 'add' instruction in epilog (only if function is not naked). If function
|
||||
@@ -107,7 +129,7 @@ ASMJIT_ENUM(kFuncFlags) {
|
||||
//! adjust the stack (like "and zsp, -Alignment").
|
||||
kFuncFlagIsStackAdjusted = 0x00000008,
|
||||
|
||||
//! @brief Whether the function is finished using @c Compiler::endFunc().
|
||||
//! Whether the function is finished using `BaseCompiler::endFunc()`.
|
||||
kFuncFlagIsFinished = 0x80000000
|
||||
};
|
||||
|
||||
@@ -115,14 +137,14 @@ ASMJIT_ENUM(kFuncFlags) {
|
||||
// [asmjit::kFuncDir]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function arguments direction.
|
||||
//! Function arguments direction.
|
||||
ASMJIT_ENUM(kFuncDir) {
|
||||
//! @brief Arguments are passed left to right.
|
||||
//! Arguments are passed left to right.
|
||||
//!
|
||||
//! This arguments direction is unusual to C programming, it's used by pascal
|
||||
//! compilers and in some calling conventions by Borland compiler).
|
||||
kFuncDirLtr = 0,
|
||||
//! @brief Arguments are passed right ro left
|
||||
//! Arguments are passed right ro left
|
||||
//!
|
||||
//! This is default argument direction in C programming.
|
||||
kFuncDirRtl = 1
|
||||
@@ -133,7 +155,7 @@ ASMJIT_ENUM(kFuncDir) {
|
||||
// ============================================================================
|
||||
|
||||
enum {
|
||||
//! @brief Invalid stack offset in function or function parameter.
|
||||
//! Invalid stack offset in function or function parameter.
|
||||
kFuncStackInvalid = -1
|
||||
};
|
||||
|
||||
@@ -141,19 +163,19 @@ enum {
|
||||
// [asmjit::kFuncArg]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function argument (lo/hi) specification.
|
||||
//! Function argument (lo/hi) specification.
|
||||
ASMJIT_ENUM(kFuncArg) {
|
||||
//! @brief Maxumum number of function arguments supported by AsmJit.
|
||||
//! Maxumum number of function arguments supported by AsmJit.
|
||||
kFuncArgCount = 16,
|
||||
//! @brief Extended maximum number of arguments (used internally).
|
||||
//! Extended maximum number of arguments (used internally).
|
||||
kFuncArgCountLoHi = kFuncArgCount * 2,
|
||||
|
||||
//! @brief Index to the LO part of function argument (default).
|
||||
//! Index to the LO part of function argument (default).
|
||||
//!
|
||||
//! This value is typically omitted and added only if there is HI argument
|
||||
//! accessed.
|
||||
kFuncArgLo = 0,
|
||||
//! @brief Index to the HI part of function argument.
|
||||
//! Index to the HI part of function argument.
|
||||
//!
|
||||
//! HI part of function argument depends on target architecture. On x86 it's
|
||||
//! typically used to transfer 64-bit integers (they form a pair of 32-bit
|
||||
@@ -165,11 +187,11 @@ ASMJIT_ENUM(kFuncArg) {
|
||||
// [asmjit::kFuncRet]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function return value (lo/hi) specification.
|
||||
//! Function return value (lo/hi) specification.
|
||||
ASMJIT_ENUM(kFuncRet) {
|
||||
//! @brief Index to the LO part of function return value.
|
||||
//! Index to the LO part of function return value.
|
||||
kFuncRetLo = 0,
|
||||
//! @brief Index to the HI part of function return value.
|
||||
//! Index to the HI part of function return value.
|
||||
kFuncRetHi = 1
|
||||
};
|
||||
|
||||
@@ -187,44 +209,45 @@ ASMJIT_ENUM(kFuncRet) {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Declare C/C++ type-id mapped to @c asmjit::kVarType.
|
||||
//! Declare C/C++ type-id mapped to `kVarType`.
|
||||
#define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \
|
||||
template<> \
|
||||
struct TypeId<_T_> { enum { kId = _Id_ }; }
|
||||
|
||||
//! @brief Function builder 'void' type.
|
||||
//! Function builder 'void' type.
|
||||
struct FnVoid {};
|
||||
|
||||
//! @brief Function builder 'int8_t' type.
|
||||
//! Function builder 'int8_t' type.
|
||||
struct FnInt8 {};
|
||||
//! @brief Function builder 'uint8_t' type.
|
||||
//! Function builder 'uint8_t' type.
|
||||
struct FnUInt8 {};
|
||||
|
||||
//! @brief Function builder 'int16_t' type.
|
||||
//! Function builder 'int16_t' type.
|
||||
struct FnInt16 {};
|
||||
//! @brief Function builder 'uint16_t' type.
|
||||
//! Function builder 'uint16_t' type.
|
||||
struct FnUInt16 {};
|
||||
|
||||
//! @brief Function builder 'int32_t' type.
|
||||
//! Function builder 'int32_t' type.
|
||||
struct FnInt32 {};
|
||||
//! @brief Function builder 'uint32_t' type.
|
||||
//! Function builder 'uint32_t' type.
|
||||
struct FnUInt32 {};
|
||||
|
||||
//! @brief Function builder 'int64_t' type.
|
||||
//! Function builder 'int64_t' type.
|
||||
struct FnInt64 {};
|
||||
//! @brief Function builder 'uint64_t' type.
|
||||
//! Function builder 'uint64_t' type.
|
||||
struct FnUInt64 {};
|
||||
|
||||
//! @brief Function builder 'intptr_t' type.
|
||||
//! Function builder 'intptr_t' type.
|
||||
struct FnIntPtr {};
|
||||
//! @brief Function builder 'uintptr_t' type.
|
||||
//! Function builder 'uintptr_t' type.
|
||||
struct FnUIntPtr {};
|
||||
|
||||
//! @brief Function builder 'float' type.
|
||||
//! Function builder 'float' type.
|
||||
struct FnFloat {};
|
||||
//! @brief Function builder 'double' type.
|
||||
//! Function builder 'double' type.
|
||||
struct FnDouble {};
|
||||
|
||||
#if !defined(ASMJIT_DOCGEN)
|
||||
ASMJIT_DECLARE_TYPE_CORE(kVarTypeIntPtr);
|
||||
|
||||
ASMJIT_DECLARE_TYPE_ID(void, kVarTypeInvalid);
|
||||
@@ -259,15 +282,13 @@ ASMJIT_DECLARE_TYPE_ID(FnFloat, kVarTypeFp32);
|
||||
|
||||
ASMJIT_DECLARE_TYPE_ID(double, kVarTypeFp64);
|
||||
ASMJIT_DECLARE_TYPE_ID(FnDouble, kVarTypeFp64);
|
||||
#endif // !ASMJIT_DOCGEN
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FuncInOut]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function in/out (argument or a return value).
|
||||
//!
|
||||
//! This class contains function argument or return value translated from the
|
||||
//! @ref FuncPrototype.
|
||||
//! Function in/out - argument or return value translated from `FuncPrototype`.
|
||||
struct FuncInOut {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
@@ -281,7 +302,7 @@ struct FuncInOut {
|
||||
ASMJIT_INLINE bool hasStackOffset() const { return _stackOffset != kFuncStackInvalid; }
|
||||
ASMJIT_INLINE int32_t getStackOffset() const { return static_cast<int32_t>(_stackOffset); }
|
||||
|
||||
//! @brief Get whether the argument / return value is assigned.
|
||||
//! Get whether the argument / return value is assigned.
|
||||
ASMJIT_INLINE bool isSet() const {
|
||||
return (_regIndex != kInvalidReg) | (_stackOffset != kFuncStackInvalid);
|
||||
}
|
||||
@@ -290,7 +311,7 @@ struct FuncInOut {
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Reset the function argument to "unassigned state".
|
||||
//! Reset the function argument to "unassigned state".
|
||||
ASMJIT_INLINE void reset() { _packed = 0xFFFFFFFF; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -299,15 +320,15 @@ struct FuncInOut {
|
||||
|
||||
union {
|
||||
struct {
|
||||
//! @brief Variable type, see @c kVarType.
|
||||
//! Variable type, see `kVarType`.
|
||||
uint8_t _varType;
|
||||
//! @brief Register index if argument / return value is a register.
|
||||
//! Register index if argument / return value is a register.
|
||||
uint8_t _regIndex;
|
||||
//! @brief Stack offset if argument / return value is on the stack.
|
||||
//! Stack offset if argument / return value is on the stack.
|
||||
int16_t _stackOffset;
|
||||
};
|
||||
|
||||
//! @brief All members packed into single 32-bit integer.
|
||||
//! All members packed into single 32-bit integer.
|
||||
uint32_t _packed;
|
||||
};
|
||||
};
|
||||
@@ -316,32 +337,32 @@ struct FuncInOut {
|
||||
// [asmjit::FuncPrototype]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function prototype.
|
||||
//! Function prototype.
|
||||
//!
|
||||
//! Function prototype contains information about function return type, count
|
||||
//! of arguments and their types. Function prototype is a low level structure
|
||||
//! which doesn't contain platform specific or calling convention specific
|
||||
//! information. Function prototype is used to create a @ref FuncDecl.
|
||||
//! information. Function prototype is used to create a `FuncDecl`.
|
||||
struct FuncPrototype {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get function return value.
|
||||
//! Get function return value.
|
||||
ASMJIT_INLINE uint32_t getRet() const { return _ret; }
|
||||
|
||||
//! @brief Get function arguments' IDs.
|
||||
//! Get function arguments' IDs.
|
||||
ASMJIT_INLINE const uint32_t* getArgList() const { return _argList; }
|
||||
//! @brief Get count of function arguments.
|
||||
//! Get count of function arguments.
|
||||
ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; }
|
||||
|
||||
//! @brief Get argument at index @a id.
|
||||
//! Get argument at index `id`.
|
||||
ASMJIT_INLINE uint32_t getArg(uint32_t id) const {
|
||||
ASMJIT_ASSERT(id < _argCount);
|
||||
return _argList[id];
|
||||
}
|
||||
|
||||
//! @brief Set function definition - return type and arguments.
|
||||
//! Set function definition - return type and arguments.
|
||||
ASMJIT_INLINE void _setPrototype(uint32_t ret, const uint32_t* argList, uint32_t argCount) {
|
||||
_ret = ret;
|
||||
_argList = argList;
|
||||
@@ -361,62 +382,62 @@ struct FuncPrototype {
|
||||
// [asmjit::FuncDecl]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Function declaration.
|
||||
//! Function declaration.
|
||||
struct FuncDecl {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors - Calling Convention]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get function calling convention, see @c kFuncConv.
|
||||
//! Get function calling convention, see `kFuncConv`.
|
||||
ASMJIT_INLINE uint32_t getConvention() const { return _convention; }
|
||||
|
||||
//! @brief Get whether the callee pops the stack.
|
||||
//! Get whether the callee pops the stack.
|
||||
ASMJIT_INLINE uint32_t getCalleePopsStack() const { return _calleePopsStack; }
|
||||
|
||||
//! @brief Get direction of arguments passed on the stack.
|
||||
//! Get direction of arguments passed on the stack.
|
||||
//!
|
||||
//! Direction should be always @c kFuncDirRtl.
|
||||
//! Direction should be always `kFuncDirRtl`.
|
||||
//!
|
||||
//! @note This is related to used calling convention, it's not affected by
|
||||
//! number of function arguments or their types.
|
||||
ASMJIT_INLINE uint32_t getDirection() const { return _direction; }
|
||||
|
||||
//! @brief Get stack size needed for function arguments passed on the stack.
|
||||
//! Get stack size needed for function arguments passed on the stack.
|
||||
ASMJIT_INLINE uint32_t getArgStackSize() const { return _argStackSize; }
|
||||
//! @brief Get size of "Red Zone".
|
||||
//! Get size of "Red Zone".
|
||||
ASMJIT_INLINE uint32_t getRedZoneSize() const { return _redZoneSize; }
|
||||
//! @brief Get size of "Spill Zone".
|
||||
//! Get size of "Spill Zone".
|
||||
ASMJIT_INLINE uint32_t getSpillZoneSize() const { return _spillZoneSize; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors - Arguments and Return]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether the function has a return value.
|
||||
//! Get whether the function has a return value.
|
||||
ASMJIT_INLINE bool hasRet() const { return _retCount != 0; }
|
||||
//! @brief Get count of function return values.
|
||||
//! Get count of function return values.
|
||||
ASMJIT_INLINE uint32_t getRetCount() const { return _retCount; }
|
||||
|
||||
//! @brief Get function return value.
|
||||
//! Get function return value.
|
||||
ASMJIT_INLINE FuncInOut& getRet(uint32_t index = kFuncRetLo) { return _retList[index]; }
|
||||
//! @brief Get function return value.
|
||||
//! Get function return value.
|
||||
ASMJIT_INLINE const FuncInOut& getRet(uint32_t index = kFuncRetLo) const { return _retList[index]; }
|
||||
|
||||
//! @brief Get count of function arguments.
|
||||
//! Get count of function arguments.
|
||||
ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; }
|
||||
|
||||
//! @brief Get function arguments array.
|
||||
//! Get function arguments array.
|
||||
ASMJIT_INLINE FuncInOut* getArgList() { return _argList; }
|
||||
//! @brief Get function arguments array (const).
|
||||
//! Get function arguments array (const).
|
||||
ASMJIT_INLINE const FuncInOut* getArgList() const { return _argList; }
|
||||
|
||||
//! @brief Get function argument at index @a index.
|
||||
//! Get function argument at index `index`.
|
||||
ASMJIT_INLINE FuncInOut& getArg(size_t index) {
|
||||
ASMJIT_ASSERT(index < kFuncArgCountLoHi);
|
||||
return _argList[index];
|
||||
}
|
||||
|
||||
//! @brief Get function argument at index @a index.
|
||||
//! Get function argument at index `index`.
|
||||
ASMJIT_INLINE const FuncInOut& getArg(size_t index) const {
|
||||
ASMJIT_ASSERT(index < kFuncArgCountLoHi);
|
||||
return _argList[index];
|
||||
@@ -431,38 +452,38 @@ struct FuncDecl {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Calling convention.
|
||||
//! Calling convention.
|
||||
uint8_t _convention;
|
||||
//! @brief Whether a callee pops stack.
|
||||
//! Whether a callee pops stack.
|
||||
uint8_t _calleePopsStack : 1;
|
||||
//! @brief Direction for arguments passed on the stack, see @c kFuncDir.
|
||||
//! Direction for arguments passed on the stack, see `kFuncDir`.
|
||||
uint8_t _direction : 1;
|
||||
//! @brief Reserved #0 (alignment).
|
||||
//! Reserved #0 (alignment).
|
||||
uint8_t _reserved0 : 6;
|
||||
|
||||
//! @brief Count of arguments (in @c _argList).
|
||||
//! Count of arguments in `_argList`.
|
||||
uint8_t _argCount;
|
||||
//! @brief Count of return value(s).
|
||||
//! Count of return value(s).
|
||||
uint8_t _retCount;
|
||||
|
||||
//! @brief Count of bytes consumed by arguments on the stack (aligned).
|
||||
//! Count of bytes consumed by arguments on the stack (aligned).
|
||||
uint32_t _argStackSize;
|
||||
|
||||
//! @brief Size of "Red Zone".
|
||||
//! Size of "Red Zone".
|
||||
//!
|
||||
//! @note Used by AMD64-ABI (128 bytes).
|
||||
uint16_t _redZoneSize;
|
||||
|
||||
//! @brief Size of "Spill Zone".
|
||||
//! Size of "Spill Zone".
|
||||
//!
|
||||
//! @note Used by WIN64-ABI (32 bytes).
|
||||
uint16_t _spillZoneSize;
|
||||
|
||||
//! @brief Function arguments (including HI arguments) mapped to physical
|
||||
//! Function arguments (including HI arguments) mapped to physical
|
||||
//! registers and stack offset.
|
||||
FuncInOut _argList[kFuncArgCountLoHi];
|
||||
|
||||
//! @brief Function return value(s).
|
||||
//! Function return value(s).
|
||||
FuncInOut _retList[2];
|
||||
};
|
||||
|
||||
@@ -470,7 +491,7 @@ struct FuncDecl {
|
||||
// [asmjit::FuncBuilderX]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Custom function builder for up to 32 function arguments.
|
||||
//! Custom function builder for up to 32 function arguments.
|
||||
struct FuncBuilderX : public FuncPrototype {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
@@ -484,7 +505,7 @@ struct FuncBuilderX : public FuncPrototype {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Set return type to @a retType.
|
||||
//! Set return type to `retType`.
|
||||
ASMJIT_INLINE void setRet(uint32_t retType) {
|
||||
_ret = retType;
|
||||
}
|
||||
@@ -523,7 +544,7 @@ struct FuncBuilderX : public FuncPrototype {
|
||||
|
||||
#define _TID(_T_) TypeId<_T_>::kId
|
||||
|
||||
//! @brief Function builder (no args).
|
||||
//! Function builder (no args).
|
||||
template<typename RET>
|
||||
struct FuncBuilder0 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder0() {
|
||||
@@ -531,7 +552,7 @@ struct FuncBuilder0 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (1 argument).
|
||||
//! Function builder (1 argument).
|
||||
template<typename RET, typename P0>
|
||||
struct FuncBuilder1 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder1() {
|
||||
@@ -540,7 +561,7 @@ struct FuncBuilder1 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (2 arguments).
|
||||
//! Function builder (2 arguments).
|
||||
template<typename RET, typename P0, typename P1>
|
||||
struct FuncBuilder2 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder2() {
|
||||
@@ -549,7 +570,7 @@ struct FuncBuilder2 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (3 arguments).
|
||||
//! Function builder (3 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2>
|
||||
struct FuncBuilder3 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder3() {
|
||||
@@ -558,7 +579,7 @@ struct FuncBuilder3 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (4 arguments).
|
||||
//! Function builder (4 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3>
|
||||
struct FuncBuilder4 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder4() {
|
||||
@@ -567,7 +588,7 @@ struct FuncBuilder4 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (5 arguments).
|
||||
//! Function builder (5 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4>
|
||||
struct FuncBuilder5 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder5() {
|
||||
@@ -576,7 +597,7 @@ struct FuncBuilder5 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (6 arguments).
|
||||
//! Function builder (6 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
|
||||
struct FuncBuilder6 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder6() {
|
||||
@@ -585,7 +606,7 @@ struct FuncBuilder6 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (7 arguments).
|
||||
//! Function builder (7 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
|
||||
struct FuncBuilder7 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder7() {
|
||||
@@ -594,7 +615,7 @@ struct FuncBuilder7 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (8 arguments).
|
||||
//! Function builder (8 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
|
||||
struct FuncBuilder8 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder8() {
|
||||
@@ -603,7 +624,7 @@ struct FuncBuilder8 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (9 arguments).
|
||||
//! Function builder (9 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
|
||||
struct FuncBuilder9 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder9() {
|
||||
@@ -612,7 +633,7 @@ struct FuncBuilder9 : public FuncPrototype {
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Function builder (10 arguments).
|
||||
//! Function builder (10 arguments).
|
||||
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
|
||||
struct FuncBuilder10 : public FuncPrototype {
|
||||
ASMJIT_INLINE FuncBuilder10() {
|
||||
@@ -623,6 +644,8 @@ struct FuncBuilder10 : public FuncPrototype {
|
||||
|
||||
#undef _TID
|
||||
|
||||
//! @}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
|
||||
+30
-18
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_globals
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
@@ -26,25 +26,25 @@ namespace asmjit {
|
||||
static const size_t kInvalidIndex = ~static_cast<size_t>(0);
|
||||
|
||||
ASMJIT_ENUM(kGlobals) {
|
||||
//! @brief Invalid value or operand id.
|
||||
//! Invalid value or operand id.
|
||||
kInvalidValue = 0xFFFFFFFF,
|
||||
|
||||
//! @brief Invalid register index.
|
||||
//! Invalid register index.
|
||||
kInvalidReg = 0xFF,
|
||||
|
||||
//! @brief Minimum reserved bytes in @ref Buffer.
|
||||
//! Minimum reserved bytes in `Buffer`.
|
||||
kBufferGrow = 32U,
|
||||
|
||||
//! @brief Minimum size of assembler/compiler code buffer.
|
||||
//! Minimum size of assembler/compiler code buffer.
|
||||
kMemAllocMinimum = 4096,
|
||||
|
||||
//! @brief Memory grow threshold.
|
||||
//! Memory grow threshold.
|
||||
//!
|
||||
//! After the grow threshold is reached the capacity won't be doubled
|
||||
//! anymore.
|
||||
kMemAllocGrowMax = 8192 * 1024,
|
||||
|
||||
//! @brief Host memory allocator overhead.
|
||||
//! Host memory allocator overhead.
|
||||
//!
|
||||
//! We decrement the overhead from our pools so the host operating system
|
||||
//! doesn't need allocate an extra virtual page to put the data it needs
|
||||
@@ -58,17 +58,17 @@ ASMJIT_ENUM(kGlobals) {
|
||||
// [asmjit::kArch]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Architecture.
|
||||
//! Architecture.
|
||||
ASMJIT_ENUM(kArch) {
|
||||
//! @brief No/Unknown architecture.
|
||||
//! No/Unknown architecture.
|
||||
kArchNone = 0,
|
||||
|
||||
//! @brief X86 architecture.
|
||||
//! X86 architecture.
|
||||
kArchX86 = 1,
|
||||
//! @brief X64 architecture, also called AMD64.
|
||||
//! X64 architecture, also called AMD64.
|
||||
kArchX64 = 2,
|
||||
|
||||
//! @brief Arm architecture.
|
||||
//! Arm architecture.
|
||||
kArchArm = 4,
|
||||
|
||||
#if defined(ASMJIT_HOST_X86)
|
||||
@@ -83,25 +83,32 @@ ASMJIT_ENUM(kArch) {
|
||||
kArchHost = kArchArm,
|
||||
#endif // ASMJIT_HOST_ARM
|
||||
|
||||
//! @brief Whether the host is 64-bit.
|
||||
//! Whether the host is 64-bit.
|
||||
kArchHost64Bit = sizeof(intptr_t) >= 8
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Init / NoInit]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_DOCGEN)
|
||||
struct _Init {};
|
||||
static const _Init Init = {};
|
||||
|
||||
struct _NoInit {};
|
||||
static const _NoInit NoInit = {};
|
||||
#endif // !ASMJIT_DOCGEN
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Assert]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Called in debug build on assertion failure.
|
||||
//! @addtogroup asmjit_base_logging_and_errors
|
||||
//! @{
|
||||
|
||||
//! Called in debug build on assertion failure.
|
||||
//!
|
||||
//! @param exp Expression that failed.
|
||||
//! @param file Source file name where it happened.
|
||||
@@ -128,16 +135,21 @@ ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
|
||||
// [asmjit_cast<>]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Cast used to cast pointer to function. It's like reinterpret_cast<>,
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
//! Cast used to cast pointer to function. It's like reinterpret_cast<>,
|
||||
//! but uses internally C style cast to work with MinGW.
|
||||
//!
|
||||
//! If you are using single compiler and @c reinterpret_cast<> works for you,
|
||||
//! there is no reason to use @c asmjit_cast<>. If you are writing
|
||||
//! If you are using single compiler and `reinterpret_cast<>` works for you,
|
||||
//! there is no reason to use `asmjit_cast<>`. If you are writing
|
||||
//! cross-platform software with various compiler support, consider using
|
||||
//! @c asmjit_cast<> instead of @c reinterpret_cast<>.
|
||||
//! `asmjit_cast<>` instead of `reinterpret_cast<>`.
|
||||
template<typename T, typename Z>
|
||||
static ASMJIT_INLINE T asmjit_cast(Z* p) { return (T)p; }
|
||||
|
||||
//! @}
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
|
||||
+43
-16
@@ -20,13 +20,14 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::IntTraits]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
template<typename T>
|
||||
struct IntTraits {
|
||||
enum {
|
||||
@@ -46,31 +47,40 @@ struct IntTraits {
|
||||
// [asmjit::IntUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Integer utilities.
|
||||
struct IntUtil {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Float <-> Int]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @internal
|
||||
union Float {
|
||||
int32_t i;
|
||||
float f;
|
||||
};
|
||||
|
||||
//! @internal
|
||||
union Double {
|
||||
int64_t i;
|
||||
double d;
|
||||
};
|
||||
|
||||
//! Bit-cast `float` to 32-bit integer.
|
||||
static ASMJIT_INLINE int32_t floatAsInt(float f) { Float m; m.f = f; return m.i; }
|
||||
//! Bit-cast 32-bit integer to `float`.
|
||||
static ASMJIT_INLINE float intAsFloat(int32_t i) { Float m; m.i = i; return m.f; }
|
||||
|
||||
//! Bit-cast `double` to 64-bit integer.
|
||||
static ASMJIT_INLINE int64_t doubleAsInt(double d) { Double m; m.d = d; return m.i; }
|
||||
//! Bit-cast 64-bit integer to `double`.
|
||||
static ASMJIT_INLINE double intAsDouble(int64_t i) { Double m; m.i = i; return m.d; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Pack / Unpack]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Pack two 8-bit integer and one 16-bit integer into a 32-bit integer as it
|
||||
//! is an array of `{u0,u1,w2}`.
|
||||
static ASMJIT_INLINE uint32_t pack32_2x8_1x16(uint32_t u0, uint32_t u1, uint32_t w2) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return u0 + (u1 << 8) + (w2 << 16);
|
||||
@@ -79,6 +89,7 @@ struct IntUtil {
|
||||
#endif // ASMJIT_HOST
|
||||
}
|
||||
|
||||
//! Pack four 8-bit integer into a 32-bit integer as it is an array of `{u0,u1,u2,u3}`.
|
||||
static ASMJIT_INLINE uint32_t pack32_4x8(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return u0 + (u1 << 8) + (u2 << 16) + (u3 << 24);
|
||||
@@ -87,6 +98,7 @@ struct IntUtil {
|
||||
#endif // ASMJIT_HOST
|
||||
}
|
||||
|
||||
//! Pack two 32-bit integer into a 64-bit integer as it is an array of `{u0,u1}`.
|
||||
static ASMJIT_INLINE uint64_t pack64_2x32(uint32_t u0, uint32_t u1) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return (static_cast<uint64_t>(u1) << 32) + u0;
|
||||
@@ -102,9 +114,11 @@ struct IntUtil {
|
||||
// NOTE: Because some environments declare min() and max() as macros, it has
|
||||
// been decided to use different name so we never collide with them.
|
||||
|
||||
//! Get minimum value of `a` and `b`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T iMin(const T& a, const T& b) { return a < b ? a : b; }
|
||||
|
||||
//! Get maximum value of `a` and `b`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T iMax(const T& a, const T& b) { return a > b ? a : b; }
|
||||
|
||||
@@ -112,6 +126,7 @@ struct IntUtil {
|
||||
// [AsmJit - MaxUInt]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get maximum unsigned value of `T`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T maxUInt() { return ~T(0); }
|
||||
|
||||
@@ -119,6 +134,7 @@ struct IntUtil {
|
||||
// [AsmJit - InInterval]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether `x` is greater or equal than `start` and less or equal than `end`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool inInterval(const T& x, const T& start, const T& end) {
|
||||
return x >= start && x <= end;
|
||||
@@ -128,8 +144,7 @@ struct IntUtil {
|
||||
// [AsmJit - IsInt/IsUInt]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to a signed 8-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to a signed 8-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt8(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -138,8 +153,7 @@ struct IntUtil {
|
||||
return x <= T(127);
|
||||
}
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to an unsigned 8-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to an unsigned 8-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt8(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -148,8 +162,7 @@ struct IntUtil {
|
||||
return sizeof(T) <= sizeof(uint8_t) ? true : x <= T(255);
|
||||
}
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to a signed 16-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to a signed 16-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt16(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -158,8 +171,7 @@ struct IntUtil {
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(int16_t) ? true : x <= T(32767));
|
||||
}
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to an unsigned 16-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to an unsigned 16-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt16(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -168,8 +180,7 @@ struct IntUtil {
|
||||
return sizeof(T) <= sizeof(uint16_t) ? true : x <= T(65535);
|
||||
}
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to a signed 32-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to a signed 32-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt32(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -178,8 +189,7 @@ struct IntUtil {
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(int32_t) ? true : x <= T(2147483647));
|
||||
}
|
||||
|
||||
//! @brief Get whether the given integer @a x can be casted to an unsigned 32-bit
|
||||
//! integer.
|
||||
//! Get whether the given integer `x` can be casted to an unsigned 32-bit integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt32(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
@@ -192,6 +202,7 @@ struct IntUtil {
|
||||
// [AsmJit - IsPowerOf2]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the `n` value is a power of two (only one bit is set).
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isPowerOf2(T n) {
|
||||
return n != 0 && (n & (n - 1)) == 0;
|
||||
@@ -201,49 +212,59 @@ struct IntUtil {
|
||||
// [AsmJit - Mask]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Generate a bit-mask that has `x` bit set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x) {
|
||||
ASMJIT_ASSERT(x < 32);
|
||||
return (1U << x);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0` and `x1` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1) {
|
||||
return mask(x0) | mask(x1);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1` and `x2` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2) {
|
||||
return mask(x0) | mask(x1) | mask(x2);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2` and `x3` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3` and `x4` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4` and `x5` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5` and `x6` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6` and `x7` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7` and `x8` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
|
||||
mask(x8) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7`, `x8` and `x9` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8, uint32_t x9) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
|
||||
@@ -254,6 +275,7 @@ struct IntUtil {
|
||||
// [AsmJit - Bits]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Generate a bit-mask that has `x` most significant bits set.
|
||||
static ASMJIT_INLINE uint32_t bits(uint32_t x) {
|
||||
// Shifting more bits that the type has has undefined behavior. Everything
|
||||
// we need is that application shouldn't crash because of that, but the
|
||||
@@ -271,6 +293,7 @@ struct IntUtil {
|
||||
// [AsmJit - HasBit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether `x` has bit `n` set.
|
||||
static ASMJIT_INLINE bool hasBit(uint32_t x, uint32_t n) {
|
||||
return static_cast<bool>((x >> n) & 0x1);
|
||||
}
|
||||
@@ -279,7 +302,9 @@ struct IntUtil {
|
||||
// [AsmJit - BitCount]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// From http://graphics.stanford.edu/~seander/bithacks.html .
|
||||
//! Get count of bits in `x`.
|
||||
//!
|
||||
//! Taken from http://graphics.stanford.edu/~seander/bithacks.html .
|
||||
static ASMJIT_INLINE uint32_t bitCount(uint32_t x) {
|
||||
x = x - ((x >> 1) & 0x55555555U);
|
||||
x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
|
||||
@@ -290,6 +315,7 @@ struct IntUtil {
|
||||
// [AsmJit - FindFirstBit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @internal
|
||||
static ASMJIT_INLINE uint32_t findFirstBitSlow(uint32_t mask) {
|
||||
// This is a reference (slow) implementation of findFirstBit(), used when
|
||||
// we don't have compiler support for this task. The implementation speed
|
||||
@@ -308,6 +334,7 @@ struct IntUtil {
|
||||
return 0xFFFFFFFFU;
|
||||
}
|
||||
|
||||
//! Find a first bit in `mask`.
|
||||
static ASMJIT_INLINE uint32_t findFirstBit(uint32_t mask) {
|
||||
#if defined(_MSC_VER)
|
||||
DWORD i;
|
||||
@@ -369,13 +396,13 @@ struct IntUtil {
|
||||
return (base % alignment) == 0;
|
||||
}
|
||||
|
||||
//! @brief Align @a base to @a alignment.
|
||||
//! Align `base` to `alignment`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T alignTo(T base, T alignment) {
|
||||
return (base + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
//! @brief Get delta required to align @a base to @a alignment.
|
||||
//! Get delta required to align `base` to `alignment`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T deltaTo(T base, T alignment) {
|
||||
return alignTo(base, alignment) - base;
|
||||
|
||||
+16
-16
@@ -26,14 +26,14 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Lock]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Lock - used in thread-safe code for locking.
|
||||
//! Lock - used in thread-safe code for locking.
|
||||
struct Lock {
|
||||
ASMJIT_NO_COPY(Lock)
|
||||
|
||||
@@ -44,14 +44,14 @@ struct Lock {
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
typedef CRITICAL_SECTION Handle;
|
||||
|
||||
//! @brief Create a new @ref Lock instance.
|
||||
//! Create a new `Lock` instance.
|
||||
ASMJIT_INLINE Lock() { InitializeCriticalSection(&_handle); }
|
||||
//! @brief Destroy the @ref Lock instance.
|
||||
//! Destroy the `Lock` instance.
|
||||
ASMJIT_INLINE ~Lock() { DeleteCriticalSection(&_handle); }
|
||||
|
||||
//! @brief Lock.
|
||||
//! Lock.
|
||||
ASMJIT_INLINE void lock() { EnterCriticalSection(&_handle); }
|
||||
//! @brief Unlock.
|
||||
//! Unlock.
|
||||
ASMJIT_INLINE void unlock() { LeaveCriticalSection(&_handle); }
|
||||
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
@@ -63,14 +63,14 @@ struct Lock {
|
||||
#if defined(ASMJIT_OS_POSIX)
|
||||
typedef pthread_mutex_t Handle;
|
||||
|
||||
//! @brief Create a new @ref Lock instance.
|
||||
//! Create a new `Lock` instance.
|
||||
ASMJIT_INLINE Lock() { pthread_mutex_init(&_handle, NULL); }
|
||||
//! @brief Destroy the @ref Lock instance.
|
||||
//! Destroy the `Lock` instance.
|
||||
ASMJIT_INLINE ~Lock() { pthread_mutex_destroy(&_handle); }
|
||||
|
||||
//! @brief Lock.
|
||||
//! Lock.
|
||||
ASMJIT_INLINE void lock() { pthread_mutex_lock(&_handle); }
|
||||
//! @brief Unlock.
|
||||
//! Unlock.
|
||||
ASMJIT_INLINE void unlock() { pthread_mutex_unlock(&_handle); }
|
||||
#endif // ASMJIT_OS_POSIX
|
||||
|
||||
@@ -78,7 +78,7 @@ struct Lock {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get handle.
|
||||
//! Get handle.
|
||||
ASMJIT_INLINE Handle& getHandle() { return _handle; }
|
||||
//! @overload
|
||||
ASMJIT_INLINE const Handle& getHandle() const { return _handle; }
|
||||
@@ -87,7 +87,7 @@ struct Lock {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Handle.
|
||||
//! Handle.
|
||||
Handle _handle;
|
||||
};
|
||||
|
||||
@@ -95,7 +95,7 @@ struct Lock {
|
||||
// [asmjit::AutoLock]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Scope auto locker.
|
||||
//! Scope auto locker.
|
||||
struct AutoLock {
|
||||
ASMJIT_NO_COPY(AutoLock)
|
||||
|
||||
@@ -103,12 +103,12 @@ struct AutoLock {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Locks @a target.
|
||||
//! Autolock `target`, scoped.
|
||||
ASMJIT_INLINE AutoLock(Lock& target) : _target(target) {
|
||||
_target.lock();
|
||||
}
|
||||
|
||||
//! @brief Unlocks target.
|
||||
//! Autounlock `target`.
|
||||
ASMJIT_INLINE ~AutoLock() {
|
||||
_target.unlock();
|
||||
}
|
||||
@@ -117,7 +117,7 @@ struct AutoLock {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Pointer to target (lock).
|
||||
//! Pointer to target (lock).
|
||||
Lock& _target;
|
||||
};
|
||||
|
||||
|
||||
+11
-11
@@ -21,21 +21,21 @@
|
||||
namespace asmjit {
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseLogger - Construction / Destruction]
|
||||
// [asmjit::Logger - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseLogger::BaseLogger() {
|
||||
Logger::Logger() {
|
||||
_options = 0;
|
||||
::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
|
||||
}
|
||||
|
||||
BaseLogger::~BaseLogger() {}
|
||||
Logger::~Logger() {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseLogger - Logging]
|
||||
// [asmjit::Logger - Logging]
|
||||
// ============================================================================
|
||||
|
||||
void BaseLogger::logFormat(uint32_t style, const char* fmt, ...) {
|
||||
void Logger::logFormat(uint32_t style, const char* fmt, ...) {
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
|
||||
@@ -47,7 +47,7 @@ void BaseLogger::logFormat(uint32_t style, const char* fmt, ...) {
|
||||
logString(style, buf, len);
|
||||
}
|
||||
|
||||
void BaseLogger::logBinary(uint32_t style, const void* data, size_t size) {
|
||||
void Logger::logBinary(uint32_t style, const void* data, size_t size) {
|
||||
static const char prefix[] = ".data ";
|
||||
static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
@@ -78,10 +78,10 @@ void BaseLogger::logBinary(uint32_t style, const void* data, size_t size) {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseLogger - LogBinary]
|
||||
// [asmjit::Logger - LogBinary]
|
||||
// ============================================================================
|
||||
|
||||
void BaseLogger::setOption(uint32_t id, bool value) {
|
||||
void Logger::setOption(uint32_t id, bool value) {
|
||||
if (id >= kLoggerOptionCount)
|
||||
return;
|
||||
|
||||
@@ -94,10 +94,10 @@ void BaseLogger::setOption(uint32_t id, bool value) {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseLogger - Indentation]
|
||||
// [asmjit::Logger - Indentation]
|
||||
// ============================================================================
|
||||
|
||||
void BaseLogger::setIndentation(const char* indentation) {
|
||||
void Logger::setIndentation(const char* indentation) {
|
||||
::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
|
||||
if (!indentation)
|
||||
return;
|
||||
@@ -120,7 +120,7 @@ FileLogger::~FileLogger() {}
|
||||
// [asmjit::FileLogger - Accessors]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Set file stream.
|
||||
//! Set file stream.
|
||||
void FileLogger::setStream(FILE* stream) {
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
+49
-52
@@ -20,24 +20,24 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_logging
|
||||
//! @addtogroup asmjit_base_logging_and_errors
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kLoggerOption]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Logger options.
|
||||
//! Logger options.
|
||||
ASMJIT_ENUM(kLoggerOption) {
|
||||
//! @brief Whether to output instructions also in binary form.
|
||||
//! Whether to output instructions also in binary form.
|
||||
kLoggerOptionBinaryForm = 0,
|
||||
|
||||
//! @brief Whether to output immediates as hexadecimal numbers.
|
||||
//! Whether to output immediates as hexadecimal numbers.
|
||||
kLoggerOptionHexImmediate = 1,
|
||||
//! @brief Whether to output displacements as hexadecimal numbers.
|
||||
//! Whether to output displacements as hexadecimal numbers.
|
||||
kLoggerOptionHexDisplacement = 2,
|
||||
|
||||
//! @brief Count of logger options.
|
||||
//! Count of logger options.
|
||||
kLoggerOptionCount = 3
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ ASMJIT_ENUM(kLoggerOption) {
|
||||
// [asmjit::kLoggerStyle]
|
||||
// ============================================================================
|
||||
|
||||
//! Logger style.
|
||||
ASMJIT_ENUM(kLoggerStyle) {
|
||||
kLoggerStyleDefault = 0,
|
||||
kLoggerStyleDirective = 1,
|
||||
@@ -59,77 +60,75 @@ ASMJIT_ENUM(kLoggerStyle) {
|
||||
// [asmjit::Logger]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Abstract logging class.
|
||||
//! Abstract logging class.
|
||||
//!
|
||||
//! This class can be inherited and reimplemented to fit into your logging
|
||||
//! subsystem. When reimplementing use @c asmjit::Logger::log() method to
|
||||
//! log into your stream.
|
||||
//! subsystem. When reimplementing use `Logger::log()` method to log into
|
||||
//! a custom stream.
|
||||
//!
|
||||
//! This class also contain @c _enabled member that can be used to enable
|
||||
//! This class also contain `_enabled` member that can be used to enable
|
||||
//! or disable logging.
|
||||
struct BaseLogger {
|
||||
ASMJIT_NO_COPY(BaseLogger)
|
||||
struct Logger {
|
||||
ASMJIT_NO_COPY(Logger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a @ref BaseLogger instance.
|
||||
ASMJIT_API BaseLogger();
|
||||
//! @brief Destroy the @ref BaseLogger instance.
|
||||
ASMJIT_API virtual ~BaseLogger();
|
||||
//! Create a `Logger` instance.
|
||||
ASMJIT_API Logger();
|
||||
//! Destroy the `Logger` instance.
|
||||
ASMJIT_API virtual ~Logger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logging]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Abstract method to log output.
|
||||
//!
|
||||
//! Default implementation that is in @c asmjit::Logger is to do nothing.
|
||||
//! It's virtual to fit to your logging system.
|
||||
//! Log output.
|
||||
virtual void logString(uint32_t style, const char* buf, size_t len = kInvalidIndex) = 0;
|
||||
|
||||
//! @brief Log formatter message (like sprintf) sending output to @c logString() method.
|
||||
//! Log formatter message (like sprintf) sending output to `logString()` method.
|
||||
ASMJIT_API void logFormat(uint32_t style, const char* fmt, ...);
|
||||
//! @brief Log binary data.
|
||||
//! Log binary data.
|
||||
ASMJIT_API void logBinary(uint32_t style, const void* data, size_t size);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Options]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get all logger options as a single integer.
|
||||
ASMJIT_INLINE uint32_t getOptions() const
|
||||
{ return _options; }
|
||||
//! Get all logger options as a single integer.
|
||||
ASMJIT_INLINE uint32_t getOptions() const {
|
||||
return _options;
|
||||
}
|
||||
|
||||
//! @brief Get the given logger option.
|
||||
//! Get the given logger option.
|
||||
ASMJIT_INLINE bool getOption(uint32_t id) const {
|
||||
ASMJIT_ASSERT(id < kLoggerOptionCount);
|
||||
return static_cast<bool>((_options >> id) & 0x1);
|
||||
}
|
||||
|
||||
//! @brief Set the given logger option.
|
||||
//! Set the given logger option.
|
||||
ASMJIT_API void setOption(uint32_t id, bool value);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Indentation]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get indentation.
|
||||
//! Get indentation.
|
||||
ASMJIT_INLINE const char* getIndentation() const { return _indentation; }
|
||||
//! @brief Set indentation.
|
||||
//! Set indentation.
|
||||
ASMJIT_API void setIndentation(const char* indentation);
|
||||
//! @brief Reset indentation.
|
||||
//! Reset indentation.
|
||||
ASMJIT_INLINE void resetIndentation() { setIndentation(NULL); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Options, see @ref kLoggerOption.
|
||||
//! Options, see `kLoggerOption`.
|
||||
uint32_t _options;
|
||||
|
||||
//! @brief Indentation.
|
||||
//! Indentation.
|
||||
char _indentation[12];
|
||||
};
|
||||
|
||||
@@ -137,35 +136,33 @@ struct BaseLogger {
|
||||
// [asmjit::FileLogger]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Logger that can log to standard C @c FILE* stream.
|
||||
struct FileLogger : public BaseLogger {
|
||||
//! Logger that can log to standard C `FILE*` stream.
|
||||
struct FileLogger : public Logger {
|
||||
ASMJIT_NO_COPY(FileLogger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @c FileLogger.
|
||||
//! @param stream FILE stream where logging will be sent (can be @c NULL
|
||||
//! to disable logging).
|
||||
//! Create a new `FileLogger` that logs to a `FILE` stream.
|
||||
ASMJIT_API FileLogger(FILE* stream = NULL);
|
||||
|
||||
//! @brief Destroy the @ref FileLogger.
|
||||
//! Destroy the `FileLogger`.
|
||||
ASMJIT_API virtual ~FileLogger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get @c FILE* stream.
|
||||
//! Get `FILE*` stream.
|
||||
//!
|
||||
//! @note Return value can be @c NULL.
|
||||
//! @note Return value can be `NULL`.
|
||||
ASMJIT_INLINE FILE* getStream() const { return _stream; }
|
||||
|
||||
//! @brief Set @c FILE* stream.
|
||||
//! Set `FILE*` stream.
|
||||
//!
|
||||
//! @param stream @c FILE stream where to log output (can be @c NULL to
|
||||
//! disable logging).
|
||||
//! @param stream `FILE` stream where to log output, can be set to `NULL` to
|
||||
//! disable logging.
|
||||
ASMJIT_API void setStream(FILE* stream);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -178,7 +175,7 @@ struct FileLogger : public BaseLogger {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief C file stream.
|
||||
//! C file stream.
|
||||
FILE* _stream;
|
||||
};
|
||||
|
||||
@@ -186,31 +183,31 @@ struct FileLogger : public BaseLogger {
|
||||
// [asmjit::StringLogger]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief String logger.
|
||||
struct StringLogger : public BaseLogger {
|
||||
//! String logger.
|
||||
struct StringLogger : public Logger {
|
||||
ASMJIT_NO_COPY(StringLogger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create new @ref StringLogger.
|
||||
//! Create new `StringLogger`.
|
||||
ASMJIT_API StringLogger();
|
||||
|
||||
//! @brief Destroy the @ref StringLogger.
|
||||
//! Destroy the `StringLogger`.
|
||||
ASMJIT_API virtual ~StringLogger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get <code>char*</code> pointer which represents the resulting
|
||||
//! Get <code>char*</code> pointer which represents the resulting
|
||||
//! string.
|
||||
//!
|
||||
//! The pointer is owned by @ref StringLogger, it can't be modified or freed.
|
||||
//! The pointer is owned by `StringLogger`, it can't be modified or freed.
|
||||
ASMJIT_INLINE const char* getString() const { return _stringBuilder.getData(); }
|
||||
|
||||
//! @brief Clear the resulting string.
|
||||
//! Clear the resulting string.
|
||||
ASMJIT_INLINE void clearString() { _stringBuilder.clear(); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -223,7 +220,7 @@ struct StringLogger : public BaseLogger {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Output.
|
||||
//! Output.
|
||||
StringBuilder _stringBuilder;
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,169 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_MEMORYMANAGER_H
|
||||
#define _ASMJIT_BASE_MEMORYMANAGER_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/defs.h"
|
||||
#include "../base/error.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup AsmJit_MemoryManagement
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kVirtualAlloc]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Type of virtual memory allocation, see @ref MemoryManager::alloc().
|
||||
ASMJIT_ENUM(kVirtualAlloc) {
|
||||
//! @brief Normal memory allocation, has to be freed by @ref MemoryManager::release().
|
||||
kVirtualAllocFreeable = 0,
|
||||
//! @brief Allocate permanent memory, can't be freed.
|
||||
kVirtualAllocPermanent = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::MemoryManager]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Virtual memory manager interface.
|
||||
//!
|
||||
//! This class is pure virtual. You can get default virtual memory manager using
|
||||
//! @c getGlobal() method. If you want to create more memory managers with same
|
||||
//! functionality as global memory manager use @c VirtualMemoryManager class.
|
||||
struct MemoryManager {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create memory manager instance.
|
||||
ASMJIT_API MemoryManager();
|
||||
//! @brief Destroy memory manager instance, this means also to free all memory
|
||||
//! blocks.
|
||||
ASMJIT_API virtual ~MemoryManager();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Free all allocated memory.
|
||||
virtual void reset() = 0;
|
||||
|
||||
//! @brief Allocate a @a size bytes of virtual memory.
|
||||
//!
|
||||
//! Note that if you are implementing your own virtual memory manager then you
|
||||
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
|
||||
//! manager that allocated memory will be never freed.
|
||||
virtual void* alloc(size_t size, uint32_t type = kVirtualAllocFreeable) = 0;
|
||||
//! @brief Free previously allocated memory at a given @a address.
|
||||
virtual Error release(void* address) = 0;
|
||||
//! @brief Free some tail memory.
|
||||
virtual Error shrink(void* address, size_t used) = 0;
|
||||
|
||||
//! @brief Get how many bytes are currently used.
|
||||
virtual size_t getUsedBytes() = 0;
|
||||
//! @brief Get how many bytes are currently allocated.
|
||||
virtual size_t getAllocatedBytes() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Statics]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get global memory manager instance.
|
||||
//!
|
||||
//! Global instance is instance of @c VirtualMemoryManager class. Global memory
|
||||
//! manager is used by default by @ref Assembler::make() and @ref Compiler::make()
|
||||
//! methods.
|
||||
static ASMJIT_API MemoryManager* getGlobal();
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VirtualMemoryManager]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Reference implementation of memory manager that uses @ref asmjit::VMem
|
||||
//! class to allocate chunks of virtual memory and bit arrays to manage it.
|
||||
struct VirtualMemoryManager : public MemoryManager {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a @c VirtualMemoryManager instance.
|
||||
ASMJIT_API VirtualMemoryManager();
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! @brief Create a @c VirtualMemoryManager instance for process @a hProcess.
|
||||
//!
|
||||
//! This is specialized version of constructor available only for windows and
|
||||
//! usable to alloc/free memory of different process.
|
||||
explicit ASMJIT_API VirtualMemoryManager(HANDLE hProcess);
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! @brief Destroy the @c VirtualMemoryManager instance, this means also to
|
||||
//! free all blocks.
|
||||
ASMJIT_API virtual ~VirtualMemoryManager();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual void reset();
|
||||
|
||||
ASMJIT_API virtual void* alloc(size_t size, uint32_t type = kVirtualAllocFreeable);
|
||||
ASMJIT_API virtual Error release(void* address);
|
||||
ASMJIT_API virtual Error shrink(void* address, size_t used);
|
||||
|
||||
ASMJIT_API virtual size_t getUsedBytes();
|
||||
ASMJIT_API virtual size_t getAllocatedBytes();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Virtual Memory Manager Specific]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether to keep allocated memory after memory manager is
|
||||
//! destroyed.
|
||||
//!
|
||||
//! @sa @c setKeepVirtualMemory().
|
||||
ASMJIT_API bool getKeepVirtualMemory() const;
|
||||
|
||||
//! @brief Set whether to keep allocated memory after memory manager is
|
||||
//! destroyed.
|
||||
//!
|
||||
//! This method is usable when patching code of remote process. You need to
|
||||
//! allocate process memory, store generated assembler into it and patch the
|
||||
//! method you want to redirect (into your code). This method affects only
|
||||
//! VirtualMemoryManager destructor. After destruction all internal
|
||||
//! structures are freed, only the process virtual memory remains.
|
||||
//!
|
||||
//! @note Memory allocated with kVirtualAllocPermanent is always kept.
|
||||
//!
|
||||
//! @sa @c getKeepVirtualMemory().
|
||||
ASMJIT_API void setKeepVirtualMemory(bool keepVirtualMemory);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Pointer to private data hidden out of the public API.
|
||||
void* _d;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_MEMORYMANAGER_H
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodList<T>]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
template <typename T>
|
||||
struct PodList {
|
||||
ASMJIT_NO_COPY(PodList<T>)
|
||||
@@ -37,12 +38,12 @@ struct PodList {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get next node.
|
||||
//! Get next node.
|
||||
ASMJIT_INLINE Link* getNext() const { return _next; }
|
||||
|
||||
//! @brief Get value.
|
||||
//! Get value.
|
||||
ASMJIT_INLINE T getValue() const { return _value; }
|
||||
//! @brief Set value to @a value.
|
||||
//! Set value to `value`.
|
||||
ASMJIT_INLINE void setValue(const T& value) { _value = value; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
+55
-36
@@ -18,20 +18,23 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodVectorData]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
struct PodVectorData {
|
||||
//! @brief Get data.
|
||||
ASMJIT_INLINE void* getData() const { return (void*)(this + 1); }
|
||||
//! Get data.
|
||||
ASMJIT_INLINE void* getData() const {
|
||||
return (void*)(this + 1);
|
||||
}
|
||||
|
||||
//! @brief Capacity of the vector.
|
||||
//! Capacity of the vector.
|
||||
size_t capacity;
|
||||
//! @brief Length of the vector.
|
||||
//! Length of the vector.
|
||||
size_t length;
|
||||
};
|
||||
|
||||
@@ -39,6 +42,7 @@ struct PodVectorData {
|
||||
// [asmjit::PodVectorBase]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
struct PodVectorBase {
|
||||
static ASMJIT_API const PodVectorData _nullData;
|
||||
|
||||
@@ -46,11 +50,11 @@ struct PodVectorBase {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new instance of @ref PodVectorBase.
|
||||
//! Create a new instance of `PodVectorBase`.
|
||||
ASMJIT_INLINE PodVectorBase() :
|
||||
_d(const_cast<PodVectorData*>(&_nullData)) {}
|
||||
|
||||
//! @brief Destroy the @ref PodVectorBase and data.
|
||||
//! Destroy the `PodVectorBase` and data.
|
||||
ASMJIT_INLINE ~PodVectorBase() {
|
||||
if (_d != &_nullData)
|
||||
::free(_d);
|
||||
@@ -76,7 +80,7 @@ public:
|
||||
// [asmjit::PodVector<T>]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Template used to store and manage array of POD data.
|
||||
//! Template used to store and manage array of POD data.
|
||||
//!
|
||||
//! This template has these adventages over other vector<> templates:
|
||||
//! - Non-copyable (designed to be non-copyable, we want it)
|
||||
@@ -91,38 +95,51 @@ struct PodVector : PodVectorBase {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create new instance of @ref PodVector<>.
|
||||
//! Create a new instance of `PodVector<T>`.
|
||||
ASMJIT_INLINE PodVector() {}
|
||||
//! @brief Destroy the @ref PodVector<> and data.
|
||||
//! Destroy the `PodVector<>` and data.
|
||||
ASMJIT_INLINE ~PodVector() {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Data]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get whether the vector is empty.
|
||||
ASMJIT_INLINE bool isEmpty() const { return _d->length == 0; }
|
||||
//! @brief Get length.
|
||||
ASMJIT_INLINE size_t getLength() const { return _d->length; }
|
||||
//! @brief Get capacity.
|
||||
ASMJIT_INLINE size_t getCapacity() const { return _d->capacity; }
|
||||
//! Get whether the vector is empty.
|
||||
ASMJIT_INLINE bool isEmpty() const {
|
||||
return _d->length == 0;
|
||||
}
|
||||
|
||||
//! Get length.
|
||||
ASMJIT_INLINE size_t getLength() const {
|
||||
return _d->length;
|
||||
}
|
||||
|
||||
//! Get capacity.
|
||||
ASMJIT_INLINE size_t getCapacity() const {
|
||||
return _d->capacity;
|
||||
}
|
||||
|
||||
//! Get data.
|
||||
ASMJIT_INLINE T* getData() {
|
||||
return static_cast<T*>(_d->getData());
|
||||
}
|
||||
|
||||
//! @brief Get data.
|
||||
ASMJIT_INLINE T* getData() { return static_cast<T*>(_d->getData()); }
|
||||
//! @overload
|
||||
ASMJIT_INLINE const T* getData() const { return static_cast<const T*>(_d->getData()); }
|
||||
ASMJIT_INLINE const T* getData() const {
|
||||
return static_cast<const T*>(_d->getData());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Clear / Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Clear vector data, but don't free an internal buffer.
|
||||
//! Clear vector data, but don't free an internal buffer.
|
||||
ASMJIT_INLINE void clear() {
|
||||
if (_d != &_nullData)
|
||||
_d->length = 0;
|
||||
}
|
||||
|
||||
//! @brief Clear vector data and free internal buffer.
|
||||
//! Clear vector data and free internal buffer.
|
||||
ASMJIT_INLINE void reset() {
|
||||
if (_d != &_nullData) {
|
||||
::free(_d);
|
||||
@@ -134,19 +151,21 @@ struct PodVector : PodVectorBase {
|
||||
// [Grow / Reserve]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Called to grow the buffer to fit at least @a n elements more.
|
||||
ASMJIT_INLINE Error _grow(size_t n)
|
||||
{ return PodVectorBase::_grow(n, sizeof(T)); }
|
||||
//! Called to grow the buffer to fit at least `n` elements more.
|
||||
ASMJIT_INLINE Error _grow(size_t n) {
|
||||
return PodVectorBase::_grow(n, sizeof(T));
|
||||
}
|
||||
|
||||
//! @brief Realloc internal array to fit at least @a to items.
|
||||
ASMJIT_INLINE Error _reserve(size_t n)
|
||||
{ return PodVectorBase::_reserve(n, sizeof(T)); }
|
||||
//! Realloc internal array to fit at least `n` items.
|
||||
ASMJIT_INLINE Error _reserve(size_t n) {
|
||||
return PodVectorBase::_reserve(n, sizeof(T));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Prepend @a item to vector.
|
||||
//! Prepend `item` to vector.
|
||||
Error prepend(const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
@@ -162,7 +181,7 @@ struct PodVector : PodVectorBase {
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! @brief Insert an @a item at the @a index.
|
||||
//! Insert an `item` at the `index`.
|
||||
Error insert(size_t index, const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
ASMJIT_ASSERT(index <= d->length);
|
||||
@@ -180,7 +199,7 @@ struct PodVector : PodVectorBase {
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! @brief Append @a item to vector.
|
||||
//! Append `item` to vector.
|
||||
Error append(const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
@@ -195,7 +214,7 @@ struct PodVector : PodVectorBase {
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! @brief Get index of @a val or kInvalidIndex if not found.
|
||||
//! Get index of `val` or `kInvalidIndex` if not found.
|
||||
size_t indexOf(const T& val) const {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
@@ -209,7 +228,7 @@ struct PodVector : PodVectorBase {
|
||||
return kInvalidIndex;
|
||||
}
|
||||
|
||||
//! @brief Remove item at index @a i.
|
||||
//! Remove item at index `i`.
|
||||
void removeAt(size_t i) {
|
||||
PodVectorData* d = _d;
|
||||
ASMJIT_ASSERT(i < d->length);
|
||||
@@ -219,26 +238,26 @@ struct PodVector : PodVectorBase {
|
||||
::memmove(data, data + 1, d->length - i);
|
||||
}
|
||||
|
||||
//! @brief Swap this pod-vector with @a other.
|
||||
//! Swap this pod-vector with `other`.
|
||||
void swap(PodVector<T>& other) {
|
||||
T* otherData = other._d;
|
||||
other._d = _d;
|
||||
_d = otherData;
|
||||
}
|
||||
|
||||
//! @brief Get item at index @a i.
|
||||
//! Get item at index `i`.
|
||||
ASMJIT_INLINE T& operator[](size_t i) {
|
||||
ASMJIT_ASSERT(i < getLength());
|
||||
return getData()[i];
|
||||
}
|
||||
|
||||
//! @brief Get item at index @a i.
|
||||
//! Get item at index `i`.
|
||||
ASMJIT_INLINE const T& operator[](size_t i) const {
|
||||
ASMJIT_ASSERT(i < getLength());
|
||||
return getData()[i];
|
||||
}
|
||||
|
||||
//! @brief Allocate and append a new item and return its address.
|
||||
//! Allocate and append a new item and return its address.
|
||||
T* newElement() {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "../base/cpuinfo.h"
|
||||
#include "../base/defs.h"
|
||||
#include "../base/error.h"
|
||||
#include "../base/memorymanager.h"
|
||||
#include "../base/runtime.h"
|
||||
|
||||
// [Api-Begin]
|
||||
@@ -21,19 +20,18 @@
|
||||
namespace asmjit {
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseRuntime - Construction / Destruction]
|
||||
// [asmjit::Runtime - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
BaseRuntime::BaseRuntime() {}
|
||||
BaseRuntime::~BaseRuntime() {}
|
||||
Runtime::Runtime() {}
|
||||
Runtime::~Runtime() {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::JitRuntime - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
JitRuntime::JitRuntime(MemoryManager* memmgr) :
|
||||
_memoryManager(memmgr ? memmgr : MemoryManager::getGlobal()),
|
||||
_allocType(kVirtualAllocFreeable) {}
|
||||
JitRuntime::JitRuntime() :
|
||||
_allocType(kVMemAllocFreeable) {}
|
||||
|
||||
JitRuntime::~JitRuntime() {}
|
||||
|
||||
@@ -82,8 +80,7 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
|
||||
return kErrorCompilerNoFunc;
|
||||
}
|
||||
|
||||
MemoryManager* memmgr = getMemoryManager();
|
||||
void* p = memmgr->alloc(codeSize, getAllocType());
|
||||
void* p = _memMgr.alloc(codeSize, getAllocType());
|
||||
|
||||
if (p == NULL) {
|
||||
*dst = NULL;
|
||||
@@ -93,9 +90,9 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
|
||||
// Relocate the code.
|
||||
size_t relocSize = assembler->relocCode(p);
|
||||
|
||||
// Return unused memory to MemoryManager.
|
||||
// Return unused memory to `VMemMgr`.
|
||||
if (relocSize < codeSize)
|
||||
memmgr->shrink(p, relocSize);
|
||||
_memMgr.shrink(p, relocSize);
|
||||
|
||||
// Return the code.
|
||||
*dst = p;
|
||||
@@ -103,8 +100,7 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
|
||||
}
|
||||
|
||||
Error JitRuntime::release(void* p) {
|
||||
MemoryManager* memmgr = getMemoryManager();
|
||||
return memmgr->release(p);
|
||||
return _memMgr.release(p);
|
||||
}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
+42
-39
@@ -10,63 +10,57 @@
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/error.h"
|
||||
#include "../base/vmem.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
struct BaseAssembler;
|
||||
struct BaseCpuInfo;
|
||||
struct MemoryManager;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::BaseRuntime]
|
||||
// [asmjit::Runtime]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Base runtime.
|
||||
struct BaseRuntime {
|
||||
ASMJIT_NO_COPY(BaseRuntime)
|
||||
//! Base runtime.
|
||||
struct Runtime {
|
||||
ASMJIT_NO_COPY(Runtime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a @ref BaseRuntime instance.
|
||||
ASMJIT_API BaseRuntime();
|
||||
//! @brief Destroy the @ref BaseRuntime instance.
|
||||
ASMJIT_API virtual ~BaseRuntime();
|
||||
//! Create a `Runtime` instance.
|
||||
ASMJIT_API Runtime();
|
||||
//! Destroy the `Runtime` instance.
|
||||
ASMJIT_API virtual ~Runtime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get stack alignment of target runtime.
|
||||
//! Get stack alignment of target runtime.
|
||||
virtual uint32_t getStackAlignment() = 0;
|
||||
|
||||
//! @brief Get CPU information.
|
||||
//! Get CPU information.
|
||||
virtual const BaseCpuInfo* getCpuInfo() = 0;
|
||||
|
||||
//! @brief Allocate memory for code generated in @a assembler and reloc it
|
||||
//! to the target location.
|
||||
//! Allocate a memory needed for a code generated by `BaseAssembler` and
|
||||
//! relocate it to the target location.
|
||||
//!
|
||||
//! This method is universal allowing any preprocessing / postprocessing
|
||||
//! with code generated by @ref BaseAssembler or @ref BaseCompiler. Because
|
||||
//! @ref BaseCompiler always uses @ref BaseAssembler it's allowed to access
|
||||
//! only the @ref BaseAssembler instance.
|
||||
//!
|
||||
//! This method is always last step when using code generation. You can use
|
||||
//! it to allocate memory for JIT code, saving code to remote process or a
|
||||
//! file.
|
||||
//!
|
||||
//! @retrurn Status code, see @ref kError.
|
||||
//! Returns Status code as `kError`.
|
||||
virtual Error add(void** dst, BaseAssembler* assembler) = 0;
|
||||
|
||||
//! @brief Release memory allocated by add.
|
||||
//! Release memory allocated by `add`.
|
||||
virtual Error release(void* p) = 0;
|
||||
};
|
||||
|
||||
@@ -74,21 +68,21 @@ struct BaseRuntime {
|
||||
// [asmjit::JitRuntime]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief JIT runtime.
|
||||
struct JitRuntime : public BaseRuntime {
|
||||
//! JIT runtime.
|
||||
struct JitRuntime : public Runtime {
|
||||
ASMJIT_NO_COPY(JitRuntime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a @c JitRuntime instance.
|
||||
ASMJIT_API JitRuntime(MemoryManager* memmgr = NULL);
|
||||
//! @brief Destroy the @c JitRuntime instance.
|
||||
//! Create a `JitRuntime` instance.
|
||||
ASMJIT_API JitRuntime();
|
||||
//! Destroy the `JitRuntime` instance.
|
||||
ASMJIT_API virtual ~JitRuntime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Memory Manager and Alloc Type]
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Note: These members can be ignored by all derived classes. They are here
|
||||
@@ -96,13 +90,20 @@ struct JitRuntime : public BaseRuntime {
|
||||
// code patching or making dynamic loadable libraries/executables) ignore
|
||||
// members accessed by these accessors.
|
||||
|
||||
//! @brief Get the @c MemoryManager instance.
|
||||
ASMJIT_INLINE MemoryManager* getMemoryManager() const { return _memoryManager; }
|
||||
//! Get the `VMemMgr` instance.
|
||||
ASMJIT_INLINE VMemMgr* getMemMgr() const {
|
||||
return const_cast<VMemMgr*>(&_memMgr);
|
||||
}
|
||||
|
||||
//! @brief Get the type of allocation.
|
||||
ASMJIT_INLINE uint32_t getAllocType() const { return _allocType; }
|
||||
//! @brief Set the type of allocation.
|
||||
ASMJIT_INLINE void setAllocType(uint32_t allocType) { _allocType = allocType; }
|
||||
//! Get the type of allocation.
|
||||
ASMJIT_INLINE uint32_t getAllocType() const {
|
||||
return _allocType;
|
||||
}
|
||||
|
||||
//! Set the type of allocation.
|
||||
ASMJIT_INLINE void setAllocType(uint32_t allocType) {
|
||||
_allocType = allocType;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
@@ -118,12 +119,14 @@ struct JitRuntime : public BaseRuntime {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Memory manager.
|
||||
MemoryManager* _memoryManager;
|
||||
//! @brief Type of allocation.
|
||||
//! Virtual memory manager.
|
||||
VMemMgr _memMgr;
|
||||
//! Type of allocation.
|
||||
uint32_t _allocType;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
|
||||
+96
-70
@@ -20,18 +20,20 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kStringOp]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief String operation.
|
||||
//! @internal
|
||||
//!
|
||||
//! String operation.
|
||||
ASMJIT_ENUM(kStringOp) {
|
||||
//! @brief Replace the current string by a given content.
|
||||
//! Replace the current string by a given content.
|
||||
kStringOpSet = 0,
|
||||
//! @brief Append a given content to the current string.
|
||||
//! Append a given content to the current string.
|
||||
kStringOpAppend = 1
|
||||
};
|
||||
|
||||
@@ -39,7 +41,9 @@ ASMJIT_ENUM(kStringOp) {
|
||||
// [asmjit::kStringFormat]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief String format flags.
|
||||
//! @internal
|
||||
//!
|
||||
//! String format flags.
|
||||
ASMJIT_ENUM(kStringFormat) {
|
||||
kStringFormatShowSign = 0x00000001,
|
||||
kStringFormatShowSpace = 0x00000002,
|
||||
@@ -51,7 +55,9 @@ ASMJIT_ENUM(kStringFormat) {
|
||||
// [asmjit::StringUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief String utilities.
|
||||
//! @internal
|
||||
//!
|
||||
//! String utilities.
|
||||
struct StringUtil {
|
||||
static ASMJIT_INLINE size_t nlen(const char* s, size_t maxlen) {
|
||||
size_t i;
|
||||
@@ -66,7 +72,9 @@ struct StringUtil {
|
||||
// [asmjit::StringBuilder]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief String builder.
|
||||
//! @internal
|
||||
//!
|
||||
//! String builder.
|
||||
//!
|
||||
//! String builder was designed to be able to build a string using append like
|
||||
//! operation to append numbers, other strings, or signle characters. It can
|
||||
@@ -90,31 +98,31 @@ struct StringBuilder {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get string builder capacity.
|
||||
//! Get string builder capacity.
|
||||
ASMJIT_INLINE size_t getCapacity() const { return _capacity; }
|
||||
//! @brief Get length.
|
||||
//! Get length.
|
||||
ASMJIT_INLINE size_t getLength() const { return _length; }
|
||||
|
||||
//! @brief Get null-terminated string data.
|
||||
//! Get null-terminated string data.
|
||||
ASMJIT_INLINE char* getData() { return _data; }
|
||||
//! @brief Get null-terminated string data (const).
|
||||
//! Get null-terminated string data (const).
|
||||
ASMJIT_INLINE const char* getData() const { return _data; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Prepare / Reserve]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Prepare to set/append.
|
||||
//! Prepare to set/append.
|
||||
ASMJIT_API char* prepare(uint32_t op, size_t len);
|
||||
|
||||
//! @brief Reserve @a to bytes in string builder.
|
||||
//! Reserve `to` bytes in string builder.
|
||||
ASMJIT_API bool reserve(size_t to);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Clear]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Clear the content in String builder.
|
||||
//! Clear the content in String builder.
|
||||
ASMJIT_API void clear();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -132,77 +140,91 @@ struct StringBuilder {
|
||||
// [Set]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Replace the current content by @a str of @a len.
|
||||
ASMJIT_INLINE bool setString(const char* str, size_t len = kInvalidIndex)
|
||||
{ return _opString(kStringOpSet, str, len); }
|
||||
//! Replace the current content by `str` of `len`.
|
||||
ASMJIT_INLINE bool setString(const char* str, size_t len = kInvalidIndex) {
|
||||
return _opString(kStringOpSet, str, len);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by formatted string @a fmt.
|
||||
ASMJIT_INLINE bool setVFormat(const char* fmt, va_list ap)
|
||||
{ return _opVFormat(kStringOpSet, fmt, ap); }
|
||||
//! Replace the current content by formatted string `fmt`.
|
||||
ASMJIT_INLINE bool setVFormat(const char* fmt, va_list ap) {
|
||||
return _opVFormat(kStringOpSet, fmt, ap);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by formatted string @a fmt.
|
||||
//! Replace the current content by formatted string `fmt`.
|
||||
ASMJIT_API bool setFormat(const char* fmt, ...);
|
||||
|
||||
//! @brief Replace the current content by @a c character.
|
||||
ASMJIT_INLINE bool setChar(char c)
|
||||
{ return _opChar(kStringOpSet, c); }
|
||||
//! Replace the current content by `c` character.
|
||||
ASMJIT_INLINE bool setChar(char c) {
|
||||
return _opChar(kStringOpSet, c);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by @a c of @a len.
|
||||
ASMJIT_INLINE bool setChars(char c, size_t len)
|
||||
{ return _opChars(kStringOpSet, c, len); }
|
||||
//! Replace the current content by `c` of `len`.
|
||||
ASMJIT_INLINE bool setChars(char c, size_t len) {
|
||||
return _opChars(kStringOpSet, c, len);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by @a i..
|
||||
ASMJIT_INLINE bool setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
|
||||
{ return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned); }
|
||||
//! Replace the current content by formatted integer `i`.
|
||||
ASMJIT_INLINE bool setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by @a i..
|
||||
ASMJIT_INLINE bool setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
|
||||
{ return _opNumber(kStringOpSet, i, base, width, flags); }
|
||||
//! Replace the current content by formatted integer `i`.
|
||||
ASMJIT_INLINE bool setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpSet, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! @brief Replace the current content by the given @a data converted to a HEX string.
|
||||
ASMJIT_INLINE bool setHex(const void* data, size_t len)
|
||||
{ return _opHex(kStringOpSet, data, len); }
|
||||
//! Replace the current content by the given `data` converted to a HEX string.
|
||||
ASMJIT_INLINE bool setHex(const void* data, size_t len) {
|
||||
return _opHex(kStringOpSet, data, len);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Append]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Append @a str of @a len.
|
||||
ASMJIT_INLINE bool appendString(const char* str, size_t len = kInvalidIndex)
|
||||
{ return _opString(kStringOpAppend, str, len); }
|
||||
//! Append `str` of `len`.
|
||||
ASMJIT_INLINE bool appendString(const char* str, size_t len = kInvalidIndex) {
|
||||
return _opString(kStringOpAppend, str, len);
|
||||
}
|
||||
|
||||
//! @brief Append a formatted string @a fmt to the current content.
|
||||
ASMJIT_INLINE bool appendVFormat(const char* fmt, va_list ap)
|
||||
{ return _opVFormat(kStringOpAppend, fmt, ap); }
|
||||
//! Append a formatted string `fmt` to the current content.
|
||||
ASMJIT_INLINE bool appendVFormat(const char* fmt, va_list ap) {
|
||||
return _opVFormat(kStringOpAppend, fmt, ap);
|
||||
}
|
||||
|
||||
//! @brief Append a formatted string @a fmt to the current content.
|
||||
//! Append a formatted string `fmt` to the current content.
|
||||
ASMJIT_API bool appendFormat(const char* fmt, ...);
|
||||
|
||||
//! @brief Append @a c character.
|
||||
ASMJIT_INLINE bool appendChar(char c)
|
||||
{ return _opChar(kStringOpAppend, c); }
|
||||
//! Append `c` character.
|
||||
ASMJIT_INLINE bool appendChar(char c) {
|
||||
return _opChar(kStringOpAppend, c);
|
||||
}
|
||||
|
||||
//! @brief Append @a c of @a len.
|
||||
ASMJIT_INLINE bool appendChars(char c, size_t len)
|
||||
{ return _opChars(kStringOpAppend, c, len); }
|
||||
//! Append `c` of `len`.
|
||||
ASMJIT_INLINE bool appendChars(char c, size_t len) {
|
||||
return _opChars(kStringOpAppend, c, len);
|
||||
}
|
||||
|
||||
//! @brief Append @a i.
|
||||
ASMJIT_INLINE bool appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
|
||||
{ return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned); }
|
||||
//! Append `i`.
|
||||
ASMJIT_INLINE bool appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned);
|
||||
}
|
||||
|
||||
//! @brief Append @a i.
|
||||
ASMJIT_INLINE bool appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
|
||||
{ return _opNumber(kStringOpAppend, i, base, width, flags); }
|
||||
//! Append `i`.
|
||||
ASMJIT_INLINE bool appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpAppend, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! @brief Append the given @a data converted to a HEX string.
|
||||
ASMJIT_INLINE bool appendHex(const void* data, size_t len)
|
||||
{ return _opHex(kStringOpAppend, data, len); }
|
||||
//! Append the given `data` converted to a HEX string.
|
||||
ASMJIT_INLINE bool appendHex(const void* data, size_t len) {
|
||||
return _opHex(kStringOpAppend, data, len);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [_Append]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Append @a str of @a len (inlined, without buffer overflow check).
|
||||
//! Append `str` of `len`, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendString(const char* str, size_t len = kInvalidIndex) {
|
||||
// len should be a constant if we are inlining.
|
||||
if (len == kInvalidIndex) {
|
||||
@@ -230,7 +252,7 @@ struct StringBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Append @a c character (inlined, without buffer overflow check).
|
||||
//! Append `c` character, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendChar(char c) {
|
||||
ASMJIT_ASSERT(_capacity - _length >= 1);
|
||||
|
||||
@@ -239,7 +261,7 @@ struct StringBuilder {
|
||||
_data[_length] = '\0';
|
||||
}
|
||||
|
||||
//! @brief Append @a c of @a len (inlined, without buffer overflow check).
|
||||
//! Append `c` of `len`, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendChars(char c, size_t len) {
|
||||
ASMJIT_ASSERT(_capacity - _length >= len);
|
||||
|
||||
@@ -282,10 +304,12 @@ struct StringBuilder {
|
||||
// [Eq]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Check for equality with other @a str.
|
||||
//! Check for equality with other `str` of `len`.
|
||||
ASMJIT_API bool eq(const char* str, size_t len = kInvalidIndex) const;
|
||||
//! @brief Check for equality with StringBuilder @a other.
|
||||
ASMJIT_INLINE bool eq(const StringBuilder& other) const { return eq(other._data); }
|
||||
//! Check for equality with `other`.
|
||||
ASMJIT_INLINE bool eq(const StringBuilder& other) const {
|
||||
return eq(other._data);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Operator Overload]
|
||||
@@ -301,13 +325,13 @@ struct StringBuilder {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief String data.
|
||||
//! String data.
|
||||
char* _data;
|
||||
//! @brief Length.
|
||||
//! Length.
|
||||
size_t _length;
|
||||
//! @brief Capacity.
|
||||
//! Capacity.
|
||||
size_t _capacity;
|
||||
//! @brief Whether the string can be freed.
|
||||
//! Whether the string can be freed.
|
||||
size_t _canFree;
|
||||
};
|
||||
|
||||
@@ -315,6 +339,7 @@ struct StringBuilder {
|
||||
// [asmjit::StringBuilderT]
|
||||
// ============================================================================
|
||||
|
||||
//! @internal
|
||||
template<size_t N>
|
||||
struct StringBuilderT : public StringBuilder {
|
||||
ASMJIT_NO_COPY(StringBuilderT<N>)
|
||||
@@ -336,8 +361,9 @@ struct StringBuilderT : public StringBuilder {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Embedded data.
|
||||
char _embeddedData[static_cast<size_t>(N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
|
||||
//! Embedded data.
|
||||
char _embeddedData[static_cast<size_t>(
|
||||
N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
+150
-147
File diff suppressed because it is too large
Load Diff
+1106
-46
File diff suppressed because it is too large
Load Diff
+133
-24
@@ -8,61 +8,170 @@
|
||||
#ifndef _ASMJIT_BASE_VMEM_H
|
||||
#define _ASMJIT_BASE_VMEM_H
|
||||
|
||||
// [Dependencies]
|
||||
#include "../base/defs.h"
|
||||
#include "../base/error.h"
|
||||
|
||||
// [Dependencies - Windows]
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
# include <windows.h>
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMem]
|
||||
// [asmjit::kVMemAlloc]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Class that helps with allocating memory for executing code
|
||||
//! generated by JIT compiler.
|
||||
//! Type of virtual memory allocation, see `VMemMgr::alloc()`.
|
||||
ASMJIT_ENUM(kVMemAlloc) {
|
||||
//! Normal memory allocation, has to be freed by `VMemMgr::release()`.
|
||||
kVMemAllocFreeable = 0,
|
||||
//! Allocate permanent memory, can't be freed.
|
||||
kVMemAllocPermanent = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMemUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Virtual memory utilities.
|
||||
//!
|
||||
//! There are defined functions that provides facility to allocate and free
|
||||
//! memory where can be executed code. If processor and operating system
|
||||
//! supports execution protection then you can't run code from normally
|
||||
//! malloc()'ed memory.
|
||||
//! Defines functions that provide facility to allocate and free memory that is
|
||||
//! executable in a platform independent manner. If both the processor and host
|
||||
//! operating system support data-execution-prevention then the only way how to
|
||||
//! run machine code is to allocate it to a memory that has marked as executable.
|
||||
//! VMemUtil is just unified interface to platform dependent APIs.
|
||||
//!
|
||||
//! Functions are internally implemented by operating system dependent way.
|
||||
//! VirtualAlloc() function is used for Windows operating system and mmap()
|
||||
//! for posix ones. If you want to study or create your own functions, look
|
||||
//! at VirtualAlloc() or mmap() documentation (depends on you target OS).
|
||||
//!
|
||||
//! Under posix operating systems is also useable mprotect() function, that
|
||||
//! can enable execution protection to malloc()'ed memory block.
|
||||
struct VMem {
|
||||
//! @brief Allocate virtual memory.
|
||||
//! `VirtualAlloc()` function is used on Windows operating system and `mmap()`
|
||||
//! on POSIX. `VirtualAlloc()` and `mmap()` documentation provide a detailed
|
||||
//! overview on how to use a platform specific APIs.
|
||||
struct VMemUtil {
|
||||
//! Get the alignment guaranteed by alloc().
|
||||
static ASMJIT_API size_t getAlignment();
|
||||
|
||||
//! Get size of the single page.
|
||||
static ASMJIT_API size_t getPageSize();
|
||||
|
||||
//! Allocate virtual memory.
|
||||
//!
|
||||
//! Pages are readable/writeable, but they are not guaranteed to be
|
||||
//! executable unless 'canExecute' is true. Returns the address of
|
||||
//! allocated memory, or NULL on failure.
|
||||
static ASMJIT_API void* alloc(size_t length, size_t* allocated, bool canExecute);
|
||||
|
||||
//! @brief Free memory allocated by @c alloc()
|
||||
//! Free memory allocated by `alloc()`.
|
||||
static ASMJIT_API void release(void* addr, size_t length);
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! @brief Allocate virtual memory of @a hProcess.
|
||||
//! Allocate virtual memory of `hProcess`.
|
||||
//!
|
||||
//! @note This function is Windows specific.
|
||||
static ASMJIT_API void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute);
|
||||
|
||||
//! @brief Free virtual memory of @a hProcess.
|
||||
//! Free virtual memory of `hProcess`.
|
||||
//!
|
||||
//! @note This function is Windows specific.
|
||||
static ASMJIT_API void releaseProcessMemory(HANDLE hProcess, void* addr, size_t length);
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
};
|
||||
|
||||
//! @brief Get the alignment guaranteed by alloc().
|
||||
static ASMJIT_API size_t getAlignment();
|
||||
// ============================================================================
|
||||
// [asmjit::VMemMgr]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Get size of the single page.
|
||||
static ASMJIT_API size_t getPageSize();
|
||||
//! Reference implementation of memory manager that uses `VMemUtil` to allocate
|
||||
//! chunks of virtual memory and bit arrays to manage it.
|
||||
struct VMemMgr {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `VMemMgr` instance.
|
||||
ASMJIT_API VMemMgr();
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Create a `VMemMgr` instance for `hProcess`.
|
||||
//!
|
||||
//! This is a specialized version of constructor available only for windows
|
||||
//! and usable to alloc/free memory of a different process.
|
||||
explicit ASMJIT_API VMemMgr(HANDLE hProcess);
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Destroy the `VMemMgr` instance and free all blocks.
|
||||
ASMJIT_API ~VMemMgr();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Free all allocated memory.
|
||||
ASMJIT_API void reset();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Get the handle of the process memory manager is bound to.
|
||||
ASMJIT_API HANDLE getProcessHandle() const;
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Get how many bytes are currently used.
|
||||
ASMJIT_API size_t getUsedBytes() const;
|
||||
//! Get how many bytes are currently allocated.
|
||||
ASMJIT_API size_t getAllocatedBytes() const;
|
||||
|
||||
//! Get whether to keep allocated memory after the `VMemMgr` is destroyed.
|
||||
//!
|
||||
//! @sa `setKeepVirtualMemory()`.
|
||||
ASMJIT_API bool getKeepVirtualMemory() const;
|
||||
|
||||
//! Set whether to keep allocated memory after memory manager is
|
||||
//! destroyed.
|
||||
//!
|
||||
//! This method is usable when patching code of remote process. You need to
|
||||
//! allocate process memory, store generated assembler into it and patch the
|
||||
//! method you want to redirect (into your code). This method affects only
|
||||
//! VMemMgr destructor. After destruction all internal
|
||||
//! structures are freed, only the process virtual memory remains.
|
||||
//!
|
||||
//! @note Memory allocated with kVMemAllocPermanent is always kept.
|
||||
//!
|
||||
//! @sa `getKeepVirtualMemory()`.
|
||||
ASMJIT_API void setKeepVirtualMemory(bool keepVirtualMemory);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Alloc / Release]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Allocate a `size` bytes of virtual memory.
|
||||
//!
|
||||
//! Note that if you are implementing your own virtual memory manager then you
|
||||
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
|
||||
//! manager that allocated memory will be never freed.
|
||||
ASMJIT_API void* alloc(size_t size, uint32_t type = kVMemAllocFreeable);
|
||||
|
||||
//! Free previously allocated memory at a given `address`.
|
||||
ASMJIT_API Error release(void* address);
|
||||
|
||||
//! Free some tail memory.
|
||||
ASMJIT_API Error shrink(void* address, size_t used);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! Pointer to private data hidden out of the public API.
|
||||
void* _d;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @brief Zero width chunk used when Zone doesn't have any memory allocated.
|
||||
//! Zero width chunk used when Zone doesn't have any memory allocated.
|
||||
static const Zone::Chunk Zone_zeroChunk = {
|
||||
NULL, 0, 0, { 0 }
|
||||
};
|
||||
|
||||
+29
-31
@@ -16,17 +16,17 @@
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! @addtogroup asmjit_base
|
||||
//! @addtogroup asmjit_base_util
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Zone]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Fast incremental memory allocator.
|
||||
//! Fast incremental memory allocator.
|
||||
//!
|
||||
//! Memory allocator designed to allocate small objects that will be invalidated
|
||||
//! (free) all at once.
|
||||
//! (freed) all at once.
|
||||
struct Zone {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Chunk]
|
||||
@@ -34,19 +34,19 @@ struct Zone {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief One allocated chunk of memory.
|
||||
//! One allocated chunk of memory.
|
||||
struct Chunk {
|
||||
//! @brief Get count of remaining (unused) bytes in chunk.
|
||||
//! Get count of remaining (unused) bytes in chunk.
|
||||
ASMJIT_INLINE size_t getRemainingSize() const { return size - pos; }
|
||||
|
||||
//! @brief Link to previous chunk.
|
||||
//! Link to previous chunk.
|
||||
Chunk* prev;
|
||||
//! @brief Position in this chunk.
|
||||
//! Position in this chunk.
|
||||
size_t pos;
|
||||
//! @brief Size of this chunk (in bytes).
|
||||
//! Size of this chunk (in bytes).
|
||||
size_t size;
|
||||
|
||||
//! @brief Data.
|
||||
//! Data.
|
||||
uint8_t data[sizeof(void*)];
|
||||
};
|
||||
|
||||
@@ -54,25 +54,25 @@ struct Zone {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new instance of @c Zone allocator.
|
||||
//! Create a new instance of `Zone` allocator.
|
||||
//!
|
||||
//! @param chunkSize Default size of the first chunk.
|
||||
ASMJIT_API Zone(size_t chunkSize);
|
||||
|
||||
//! @brief Destroy @ref Zone instance.
|
||||
//! Destroy `Zone` instance.
|
||||
ASMJIT_API ~Zone();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Clear / Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Free all allocated memory except first block that remains for reuse.
|
||||
//! Free all allocated memory except first block that remains for reuse.
|
||||
//!
|
||||
//! Note that this method will invalidate all instances using this memory
|
||||
//! allocated by this zone instance.
|
||||
ASMJIT_API void clear();
|
||||
|
||||
//! @brief Free all allocated memory at once.
|
||||
//! Free all allocated memory at once.
|
||||
//!
|
||||
//! Note that this method will invalidate all instances using this memory
|
||||
//! allocated by this zone instance.
|
||||
@@ -82,32 +82,30 @@ struct Zone {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get (default) chunk size.
|
||||
//! Get (default) chunk size.
|
||||
ASMJIT_INLINE size_t getChunkSize() const { return _chunkSize; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Alloc]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Allocate @c size bytes of memory.
|
||||
//! Allocate `size` bytes of memory.
|
||||
//!
|
||||
//! Pointer allocated by this way will be valid until @c Zone object is
|
||||
//! destroyed. To create class by this way use placement @c new and @c delete
|
||||
//! Pointer allocated by this way will be valid until `Zone` object is
|
||||
//! destroyed. To create class by this way use placement `new` and `delete`
|
||||
//! operators:
|
||||
//!
|
||||
//! @code
|
||||
//! ~~~
|
||||
//! // Example of simple class allocation.
|
||||
//! using namespace asmjit
|
||||
//!
|
||||
//! // Your class.
|
||||
//! class Object
|
||||
//! {
|
||||
//! class Object {
|
||||
//! // members...
|
||||
//! };
|
||||
//!
|
||||
//! // Your function
|
||||
//! void f()
|
||||
//! {
|
||||
//! void f() {
|
||||
//! // Create zone object with chunk size of 65536 bytes.
|
||||
//! Zone zone(65536);
|
||||
//!
|
||||
@@ -120,9 +118,9 @@ struct Zone {
|
||||
//! obj->~Object();
|
||||
//!
|
||||
//! // Zone destructor will free all memory allocated through it, you can
|
||||
//! // call @c zone.reset() if you wan't to reuse current @ref Zone.
|
||||
//! // call `zone.reset()` if you wan't to reuse current `Zone`.
|
||||
//! }
|
||||
//! @endcode
|
||||
//! ~~~
|
||||
ASMJIT_INLINE void* alloc(size_t size) {
|
||||
Chunk* cur = _chunks;
|
||||
|
||||
@@ -136,7 +134,7 @@ struct Zone {
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
//! @brief Like @ref alloc(), but returns <code>T*</code>.
|
||||
//! Like `alloc()`, but the return is casted to `T*`.
|
||||
template<typename T>
|
||||
ASMJIT_INLINE T* allocT(size_t size = sizeof(T)) {
|
||||
return static_cast<T*>(alloc(size));
|
||||
@@ -145,7 +143,7 @@ struct Zone {
|
||||
//! @internal
|
||||
ASMJIT_API void* _alloc(size_t size);
|
||||
|
||||
//! @brief Allocate @c size bytes of zeroed memory.
|
||||
//! Allocate `size` bytes of zeroed memory.
|
||||
ASMJIT_INLINE void* calloc(size_t size) {
|
||||
Chunk* cur = _chunks;
|
||||
|
||||
@@ -163,22 +161,22 @@ struct Zone {
|
||||
//! @internal
|
||||
ASMJIT_API void* _calloc(size_t size);
|
||||
|
||||
//! @brief Helper to duplicate data.
|
||||
//! Helper to duplicate data.
|
||||
ASMJIT_API void* dup(const void* data, size_t size);
|
||||
|
||||
//! @brief Helper to duplicate string.
|
||||
//! Helper to duplicate string.
|
||||
ASMJIT_API char* sdup(const char* str);
|
||||
|
||||
//! @brief Helper to duplicate formatted string, maximum length is 256 bytes.
|
||||
//! Helper to duplicate formatted string, maximum length is 256 bytes.
|
||||
ASMJIT_API char* sformat(const char* str, ...);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Last allocated chunk of memory.
|
||||
//! Last allocated chunk of memory.
|
||||
Chunk* _chunks;
|
||||
//! @brief Default chunk size.
|
||||
//! Default chunk size.
|
||||
size_t _chunkSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,16 @@
|
||||
// [Dependencies - C++]
|
||||
#include <new>
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Documentation]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_DOCGEN)
|
||||
# define ASMJIT_BUILD_X86
|
||||
# define ASMJIT_BUILD_X64
|
||||
# define ASMJIT_API
|
||||
#endif // ASMJIT_DOCGEN
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - OS]
|
||||
// ============================================================================
|
||||
|
||||
@@ -22,11 +22,10 @@ namespace contrib {
|
||||
// ============================================================================
|
||||
|
||||
WinRemoteRuntime::WinRemoteRuntime(HANDLE hProcess) :
|
||||
_hProcess(hProcess),
|
||||
_memoryManager(hProcess) {
|
||||
_memMgr(hProcess) {
|
||||
|
||||
// We are patching another process so enable keep-virtual-memory option.
|
||||
_memoryManager.setKeepVirtualMemory(true);
|
||||
_memMgr.setKeepVirtualMemory(true);
|
||||
}
|
||||
|
||||
WinRemoteRuntime::~WinRemoteRuntime() {}
|
||||
@@ -53,7 +52,7 @@ uint32_t WinRemoteRuntime::add(void** dest, BaseAssembler* assembler) {
|
||||
}
|
||||
|
||||
// Allocate a pernament remote process memory.
|
||||
void* processMemPtr = _memoryManager.alloc(codeSize, kVirtualAllocPermanent);
|
||||
void* processMemPtr = _memMgr.alloc(codeSize, kVMemAllocPermanent);
|
||||
|
||||
if (processMemPtr == NULL) {
|
||||
::free(codeData);
|
||||
@@ -64,7 +63,7 @@ uint32_t WinRemoteRuntime::add(void** dest, BaseAssembler* assembler) {
|
||||
// Relocate and write the code to the process memory.
|
||||
assembler->relocCode(codeData, (uintptr_t)processMemPtr);
|
||||
|
||||
::WriteProcessMemory(_hProcess, processMemPtr, codeData, codeSize, NULL);
|
||||
::WriteProcessMemory(getProcessHandle(), processMemPtr, codeData, codeSize, NULL);
|
||||
::free(codeData);
|
||||
|
||||
*dest = processMemPtr;
|
||||
|
||||
@@ -21,28 +21,33 @@ namespace contrib {
|
||||
// [asmjit::contrib::WinRemoteRuntime]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief WinRemoteRuntime can be used to inject code to a remote process.
|
||||
struct WinRemoteRuntime : public BaseRuntime {
|
||||
//! WinRemoteRuntime can be used to inject code to a remote process.
|
||||
struct WinRemoteRuntime : public Runtime {
|
||||
ASMJIT_NO_COPY(WinRemoteRuntime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
//! @brief Create a @c WinRemoteRuntime instance for a given @a hProcess.
|
||||
|
||||
//! Create a `WinRemoteRuntime` instance for a given `hProcess`.
|
||||
ASMJIT_API WinRemoteRuntime(HANDLE hProcess);
|
||||
|
||||
//! @brief Destroy the @c WinRemoteRuntime instance.
|
||||
//! Destroy the `WinRemoteRuntime` instance.
|
||||
ASMJIT_API virtual ~WinRemoteRuntime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get the remote process handle.
|
||||
ASMJIT_INLINE HANDLE getProcess() const { return _hProcess; }
|
||||
//! Get the remote process handle.
|
||||
ASMJIT_INLINE HANDLE getProcessHandle() const {
|
||||
return _memMgr.getProcessHandle();
|
||||
}
|
||||
|
||||
//! @brief Get the virtual memory manager.
|
||||
ASMJIT_INLINE VirtualMemoryManager* getMemoryManager() { return &_memoryManager; }
|
||||
//! Get the remote memory manager.
|
||||
ASMJIT_INLINE VMemMgr* getMemMgr() const {
|
||||
return const_cast<VMemMgr*>(&_memMgr);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
@@ -54,11 +59,8 @@ struct WinRemoteRuntime : public BaseRuntime {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Process.
|
||||
HANDLE _hProcess;
|
||||
|
||||
//! @brief Virtual memory manager.
|
||||
VirtualMemoryManager _memoryManager;
|
||||
//! Remove memory manager.
|
||||
VMemMgr _memMgr;
|
||||
};
|
||||
|
||||
} // contrib namespace
|
||||
|
||||
@@ -8,7 +8,114 @@
|
||||
#ifndef _ASMJIT_X86_H
|
||||
#define _ASMJIT_X86_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86x64]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_x86x64 X86/X64
|
||||
//!
|
||||
//! @brief X86/X64 API
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86x64_codegen]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_x86x64_codegen Code Generation (X86/X64)
|
||||
//! @ingroup asmjit_x86x64
|
||||
//!
|
||||
//! @brief Low-level and high-level code generation.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86x64_cpu_info]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_x86x64_cpu_info CPU Information (X86/X64)
|
||||
//! @ingroup asmjit_x86x64
|
||||
//!
|
||||
//! @brief CPU information specific to X86/X64 architecture.
|
||||
//!
|
||||
//! The CPUID instruction can be used to get an exhaustive information related
|
||||
//! to the host X86/X64 processor. AsmJit contains utilities that can get the
|
||||
//! most important information related to the features supported by the CPU
|
||||
//! and the host operating system, in addition to host processor name and number
|
||||
//! of cores. Class `CpuInfo` extends `BaseCpuInfo` and provides functionality
|
||||
//! specific to X86 and X64.
|
||||
//!
|
||||
//! By default AsmJit queries the CPU information after the library is loaded
|
||||
//! and the queried information is reused by all instances of `JitRuntime`.
|
||||
//! The global instance of `CpuInfo` can't be changed, because it will affect
|
||||
//! the code generation of all `Runtime`s. If there is a need to have a
|
||||
//! specific CPU information which contains modified features or processor
|
||||
//! vendor it's possible by creating a new instance of `CpuInfo` and setting
|
||||
//! up its members. `CpuUtil::detect` can be used to detect CPU features into
|
||||
//! an existing `CpuInfo` instance - it may become handly if only one property
|
||||
//! has to be turned on/off.
|
||||
//!
|
||||
//! If the high-level interface `CpuInfo` offers is not enough there is also
|
||||
//! `CpuUtil::callCpuId` helper that can be used to call CPUID instruction with
|
||||
//! a given parameters and to consume the output.
|
||||
//!
|
||||
//! Cpu detection is important when generating a JIT code that may or may not
|
||||
//! use certain CPU features. For example there used to be a SSE/SSE2 detection
|
||||
//! in the past and today there is often AVX/AVX2 detection.
|
||||
//!
|
||||
//! The example below shows how to detect SSE2:
|
||||
//!
|
||||
//! ~~~
|
||||
//! using namespace asmjit;
|
||||
//! using namespace asmjit::host;
|
||||
//!
|
||||
//! // Get `CpuInfo` global instance.
|
||||
//! const CpuInfo* cpuInfo = CpuInfo::getHost();
|
||||
//!
|
||||
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
|
||||
//! // Processor has SSE2.
|
||||
//! }
|
||||
//! else if (cpuInfo->hasFeature(kCpuFeatureMmx)) {
|
||||
//! // Processor doesn't have SSE2, but has MMX.
|
||||
//! }
|
||||
//! else {
|
||||
//! // An archaic processor, it's a wonder AsmJit works here!
|
||||
//! }
|
||||
//! ~~~
|
||||
//!
|
||||
//! The next example shows how to call CPUID directly:
|
||||
//!
|
||||
//! ~~~
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // The result of CPUID call.
|
||||
//! CpuId out;
|
||||
//!
|
||||
//! // Call CPUID, first two arguments are passed in EAX/ECX.
|
||||
//! CpuUtil::callCpuId(0, 0, &out);
|
||||
//!
|
||||
//! // If EAX argument is 0, EBX, ECX and EDX registers are filled with a cpu vendor.
|
||||
//! char cpuVendor[13];
|
||||
//! memcpy(cpuVendor, &out.ebx, 4);
|
||||
//! memcpy(cpuVendor + 4, &out.edx, 4);
|
||||
//! memcpy(cpuVendor + 8, &out.ecx, 4);
|
||||
//! vendor[12] = '\0';
|
||||
//!
|
||||
//! // Print a CPU vendor retrieved from CPUID.
|
||||
//! ::printf("%s", cpuVendor);
|
||||
//! ~~~
|
||||
//!
|
||||
//! @sa @ref asmjit_base_cpu_info
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86x64_constants]
|
||||
// ============================================================================
|
||||
|
||||
//! @defgroup asmjit_x86x64_constants Constants (X86/X64)
|
||||
//! @ingroup asmjit_x86x64
|
||||
//!
|
||||
//! @brief Constants and definitions specific to X86/X64 architecture.
|
||||
|
||||
// ============================================================================
|
||||
// [Dependencies - AsmJit]
|
||||
// ============================================================================
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#include "x86/x86assembler.h"
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/intutil.h"
|
||||
#include "../base/logger.h"
|
||||
#include "../base/memorymanager.h"
|
||||
#include "../base/runtime.h"
|
||||
#include "../base/string.h"
|
||||
#include "../base/vmem.h"
|
||||
#include "../x86/x86assembler.h"
|
||||
#include "../x86/x86cpuinfo.h"
|
||||
#include "../x86/x86defs.h"
|
||||
@@ -60,7 +60,7 @@ enum kVexVVVV {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Instruction 2-byte/3-byte opcode prefix definition.
|
||||
//! Instruction 2-byte/3-byte opcode prefix definition.
|
||||
struct OpCodeMM {
|
||||
uint8_t len;
|
||||
uint8_t data[3];
|
||||
@@ -68,7 +68,7 @@ struct OpCodeMM {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit
|
||||
//! Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit
|
||||
//! extensions
|
||||
static const uint8_t x86OpCodePP[8] = {
|
||||
0x00,
|
||||
@@ -83,7 +83,7 @@ static const uint8_t x86OpCodePP[8] = {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Instruction 2-byte/3-byte opcode prefix data.
|
||||
//! Instruction 2-byte/3-byte opcode prefix data.
|
||||
static const OpCodeMM x86OpCodeMM[] = {
|
||||
{ 0, { 0x00, 0x00, 0 } },
|
||||
{ 1, { 0x0F, 0x00, 0 } },
|
||||
@@ -111,7 +111,9 @@ static const uint8_t x86OpCodePopSeg[8] = { 0x00, 0x07, 0x00, 0x17, 0x1F, 0xA1,
|
||||
// [asmjit::X64TrampolineWriter]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Trampoline writer.
|
||||
//! @internal
|
||||
//!
|
||||
//! Trampoline writer.
|
||||
struct X64TrampolineWriter {
|
||||
// Size of trampoline
|
||||
enum {
|
||||
@@ -120,9 +122,8 @@ struct X64TrampolineWriter {
|
||||
kSizeTotal = kSizeJmp + kSizeAddr
|
||||
};
|
||||
|
||||
// Write trampoline into code at address @a code that will jump to @a target.
|
||||
static void writeTrampoline(uint8_t* code, uint64_t target)
|
||||
{
|
||||
// Write trampoline into code at address `code` that will jump to `target`.
|
||||
static void writeTrampoline(uint8_t* code, uint64_t target) {
|
||||
code[0] = 0xFF; // Jmp OpCode.
|
||||
code[1] = 0x25; // ModM (RIP addressing).
|
||||
((uint32_t*)(code + 2))[0] = 0; // Offset (zero).
|
||||
@@ -221,7 +222,7 @@ struct X64TrampolineWriter {
|
||||
// [asmjit::x86x64::Assembler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
X86X64Assembler::X86X64Assembler(BaseRuntime* runtime) : BaseAssembler(runtime) {}
|
||||
X86X64Assembler::X86X64Assembler(Runtime* runtime) : BaseAssembler(runtime) {}
|
||||
X86X64Assembler::~X86X64Assembler() {}
|
||||
|
||||
// ============================================================================
|
||||
@@ -887,12 +888,12 @@ static bool X86Assembler_dumpComment(StringBuilder& sb, size_t len, const uint8_
|
||||
// [asmjit::x86x64::Assembler - Emit]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Encode MODR/M.
|
||||
//! Encode MODR/M.
|
||||
static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) {
|
||||
return (m << 6) + (o << 3) + rm;
|
||||
}
|
||||
|
||||
//! @brief Encode SIB.
|
||||
//! Encode SIB.
|
||||
static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) {
|
||||
return (s << 6) + (i << 3) + b;
|
||||
}
|
||||
@@ -928,7 +929,7 @@ static ASMJIT_INLINE Error X86X64Assembler_emit(X86X64Assembler* self, uint32_t
|
||||
//
|
||||
// AVX:
|
||||
// 0x0008 - AVX.W.
|
||||
// 0xF000 - VVVV, zeros by default, see @ref kVexVVVV.
|
||||
// 0xF000 - VVVV, zeros by default, see `kVexVVVV`.
|
||||
//
|
||||
uint32_t opX;
|
||||
|
||||
@@ -3969,8 +3970,8 @@ _EmitXopM:
|
||||
// [Emit - Jump/Call to an Immediate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Emit relative relocation to absolute pointer @a target. It's needed
|
||||
// to add what instruction is emitting this, because in x64 mode the relative
|
||||
// Emit relative relocation to absolute pointer `target`. It's needed to add
|
||||
// what instruction is emitting this, because in x64 mode the relative
|
||||
// displacement can be impossible to calculate and in this case the trampoline
|
||||
// is used.
|
||||
_EmitJmpOrCallImm:
|
||||
@@ -4087,7 +4088,7 @@ _GrowBuffer:
|
||||
namespace asmjit {
|
||||
namespace x86 {
|
||||
|
||||
Assembler::Assembler(BaseRuntime* runtime) : X86X64Assembler(runtime) {
|
||||
Assembler::Assembler(Runtime* runtime) : X86X64Assembler(runtime) {
|
||||
_arch = kArchX86;
|
||||
_regSize = 4;
|
||||
}
|
||||
@@ -4116,7 +4117,7 @@ Error Assembler::_emit(uint32_t code, const Operand& o0, const Operand& o1, cons
|
||||
namespace asmjit {
|
||||
namespace x64 {
|
||||
|
||||
Assembler::Assembler(BaseRuntime* runtime) : X86X64Assembler(runtime) {
|
||||
Assembler::Assembler(Runtime* runtime) : X86X64Assembler(runtime) {
|
||||
_arch = kArchX64;
|
||||
_regSize = 8;
|
||||
}
|
||||
|
||||
+1905
-955
File diff suppressed because it is too large
Load Diff
@@ -96,14 +96,14 @@ static Error X86X64Compiler_emitConstPool(X86X64Compiler* self,
|
||||
// [asmjit::x86x64::X86X64Compiler - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
X86X64Compiler::X86X64Compiler(BaseRuntime* runtime) : BaseCompiler(runtime) {}
|
||||
X86X64Compiler::X86X64Compiler(Runtime* runtime) : BaseCompiler(runtime) {}
|
||||
X86X64Compiler::~X86X64Compiler() {}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::X86X64Compiler - Inst]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief Get compiler instruction item size without operands assigned.
|
||||
//! Get compiler instruction item size without operands assigned.
|
||||
static ASMJIT_INLINE size_t X86X64Compiler_getInstSize(uint32_t code) {
|
||||
return (IntUtil::inInterval<uint32_t>(code, _kInstJbegin, _kInstJend)) ? sizeof(JumpNode) : sizeof(InstNode);
|
||||
}
|
||||
@@ -600,7 +600,7 @@ _OnError:
|
||||
template<typename Assembler>
|
||||
static ASMJIT_INLINE void* X86X64Compiler_make(X86X64Compiler* self) {
|
||||
Assembler assembler(self->_runtime);
|
||||
BaseLogger* logger = self->_logger;
|
||||
Logger* logger = self->_logger;
|
||||
|
||||
if (logger) {
|
||||
assembler.setLogger(logger);
|
||||
@@ -699,7 +699,7 @@ _Error:
|
||||
namespace asmjit {
|
||||
namespace x86 {
|
||||
|
||||
Compiler::Compiler(BaseRuntime* runtime) : X86X64Compiler(runtime) {
|
||||
Compiler::Compiler(Runtime* runtime) : X86X64Compiler(runtime) {
|
||||
_arch = kArchX86;
|
||||
_regSize = 4;
|
||||
_targetVarMapping = _varMapping;
|
||||
@@ -721,7 +721,7 @@ Compiler::~Compiler() {}
|
||||
namespace asmjit {
|
||||
namespace x64 {
|
||||
|
||||
Compiler::Compiler(BaseRuntime* runtime) : X86X64Compiler(runtime) {
|
||||
Compiler::Compiler(Runtime* runtime) : X86X64Compiler(runtime) {
|
||||
_arch = kArchX64;
|
||||
_regSize = 8;
|
||||
_targetVarMapping = _varMapping;
|
||||
|
||||
+815
-831
File diff suppressed because it is too large
Load Diff
@@ -1557,7 +1557,7 @@ static void X86X64Context_prepareSingleVarInst(uint32_t code, VarAttr* va) {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Add unreachable-flow data to the unreachable flow list.
|
||||
//! Add unreachable-flow data to the unreachable flow list.
|
||||
static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self, BaseNode* node) {
|
||||
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
|
||||
if (link == NULL)
|
||||
@@ -1571,7 +1571,7 @@ static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self,
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Add jump-flow data to the jcc flow list.
|
||||
//! Add jump-flow data to the jcc flow list.
|
||||
static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNode* node) {
|
||||
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
|
||||
|
||||
@@ -1586,7 +1586,7 @@ static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNod
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Get mask of all registers actually used to pass function arguments.
|
||||
//! Get mask of all registers actually used to pass function arguments.
|
||||
static ASMJIT_INLINE RegMask X86X64Context_getUsedArgs(X86X64Context* self, X86X64CallNode* node, X86X64FuncDecl* decl) {
|
||||
RegMask regs;
|
||||
regs.reset();
|
||||
@@ -1815,7 +1815,7 @@ static ASMJIT_INLINE Error X86X64Context_insertSArgNode(
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Prepare the given function @a func.
|
||||
//! Prepare the given function `func`.
|
||||
//!
|
||||
//! For each node:
|
||||
//! - Create and assign groupId and flowId.
|
||||
@@ -2608,12 +2608,12 @@ _NoMemory:
|
||||
|
||||
//! @internal
|
||||
struct LivenessTarget {
|
||||
//! @brief Previous target.
|
||||
//! Previous target.
|
||||
LivenessTarget* prev;
|
||||
|
||||
//! @brief Target node.
|
||||
//! Target node.
|
||||
TargetNode* node;
|
||||
//! @brief Jumped from.
|
||||
//! Jumped from.
|
||||
JumpNode* from;
|
||||
};
|
||||
|
||||
@@ -2952,33 +2952,33 @@ struct X86X64BaseAlloc {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get the context.
|
||||
//! Get the context.
|
||||
ASMJIT_INLINE X86X64Context* getContext() const { return _context; }
|
||||
//! @brief Get the current state (always the same instance as X86X64Context::_x86State).
|
||||
//! Get the current state (always the same instance as X86X64Context::_x86State).
|
||||
ASMJIT_INLINE VarState* getState() const { return _context->getState(); }
|
||||
|
||||
//! @brief Get the node.
|
||||
//! Get the node.
|
||||
ASMJIT_INLINE BaseNode* getNode() const { return _node; }
|
||||
|
||||
//! @brief Get VarAttr list (all).
|
||||
//! Get VarAttr list (all).
|
||||
ASMJIT_INLINE VarAttr* getVaList() const { return _vaList[0]; }
|
||||
//! @brief Get VarAttr list (per class).
|
||||
//! Get VarAttr list (per class).
|
||||
ASMJIT_INLINE VarAttr* getVaListByClass(uint32_t c) const { return _vaList[c]; }
|
||||
|
||||
//! @brief Get VarAttr count (all).
|
||||
//! Get VarAttr count (all).
|
||||
ASMJIT_INLINE uint32_t getVaCount() const { return _vaCount; }
|
||||
//! @brief Get VarAttr count (per class).
|
||||
//! Get VarAttr count (per class).
|
||||
ASMJIT_INLINE uint32_t getVaCountByClass(uint32_t c) const { return _count.get(c); }
|
||||
|
||||
//! @brief Get whether all variables of class @a c are done.
|
||||
//! Get whether all variables of class `c` are done.
|
||||
ASMJIT_INLINE bool isVaDone(uint32_t c) const { return _done.get(c) == _count.get(c); }
|
||||
|
||||
//! @brief Get how many variables have been allocated.
|
||||
//! Get how many variables have been allocated.
|
||||
ASMJIT_INLINE uint32_t getVaDone(uint32_t c) const { return _done.get(c); }
|
||||
|
||||
ASMJIT_INLINE void addVaDone(uint32_t c, uint32_t n = 1) { _done.add(c, n); }
|
||||
|
||||
//! @brief Get number of allocable registers per class.
|
||||
//! Get number of allocable registers per class.
|
||||
ASMJIT_INLINE uint32_t getGaRegs(uint32_t c) const {
|
||||
return _context->_gaRegs[c];
|
||||
}
|
||||
@@ -3007,25 +3007,25 @@ protected:
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Context.
|
||||
//! Context.
|
||||
X86X64Context* _context;
|
||||
//! @brief Compiler.
|
||||
//! Compiler.
|
||||
X86X64Compiler* _compiler;
|
||||
|
||||
//! @brief Node.
|
||||
//! Node.
|
||||
BaseNode* _node;
|
||||
|
||||
//! @brief Variable instructions.
|
||||
//! Variable instructions.
|
||||
VarInst* _vi;
|
||||
//! @brief VarAttr list (per register class).
|
||||
//! VarAttr list (per register class).
|
||||
VarAttr* _vaList[4];
|
||||
|
||||
//! @brief Count of all VarAttr's.
|
||||
//! Count of all VarAttr's.
|
||||
uint32_t _vaCount;
|
||||
|
||||
//! @brief VarAttr's total counter.
|
||||
//! VarAttr's total counter.
|
||||
RegCount _count;
|
||||
//! @brief VarAttr's done counter.
|
||||
//! VarAttr's done counter.
|
||||
RegCount _done;
|
||||
};
|
||||
|
||||
@@ -3120,7 +3120,7 @@ ASMJIT_INLINE void X86X64BaseAlloc::unuseAfter() {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Register allocator context (asm instructions).
|
||||
//! Register allocator context (asm instructions).
|
||||
struct X86X64VarAlloc : public X86X64BaseAlloc {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
@@ -3162,7 +3162,7 @@ protected:
|
||||
// [GuessAlloc / GuessSpill]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Guess which register is the best candidate for 'vd' from
|
||||
//! Guess which register is the best candidate for 'vd' from
|
||||
//! 'allocableRegs'.
|
||||
//!
|
||||
//! The guess is based on looking ahead and inspecting register allocator
|
||||
@@ -3173,7 +3173,7 @@ protected:
|
||||
template<int C>
|
||||
ASMJIT_INLINE uint32_t guessAlloc(VarData* vd, uint32_t allocableRegs);
|
||||
|
||||
//! @brief Guess whether to move the given 'vd' instead of spill.
|
||||
//! Guess whether to move the given 'vd' instead of spill.
|
||||
template<int C>
|
||||
ASMJIT_INLINE uint32_t guessSpill(VarData* vd, uint32_t allocableRegs);
|
||||
|
||||
@@ -3188,9 +3188,9 @@ protected:
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Will alloc to these registers.
|
||||
//! Will alloc to these registers.
|
||||
RegMask _willAlloc;
|
||||
//! @brief Will spill these registers.
|
||||
//! Will spill these registers.
|
||||
RegMask _willSpill;
|
||||
};
|
||||
|
||||
@@ -3745,7 +3745,7 @@ ASMJIT_INLINE void X86X64VarAlloc::modified() {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Register allocator context (function call).
|
||||
//! Register allocator context (function call).
|
||||
struct X86X64CallAlloc : public X86X64BaseAlloc {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
@@ -3758,7 +3758,7 @@ struct X86X64CallAlloc : public X86X64BaseAlloc {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get the node.
|
||||
//! Get the node.
|
||||
ASMJIT_INLINE X86X64CallNode* getNode() const { return static_cast<X86X64CallNode*>(_node); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -3837,9 +3837,9 @@ protected:
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Will alloc to these registers.
|
||||
//! Will alloc to these registers.
|
||||
RegMask _willAlloc;
|
||||
//! @brief Will spill these registers.
|
||||
//! Will spill these registers.
|
||||
RegMask _willSpill;
|
||||
};
|
||||
|
||||
@@ -5298,7 +5298,7 @@ static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64As
|
||||
BaseNode* node_ = start;
|
||||
StringBuilder& sb = self->_stringBuilder;
|
||||
|
||||
BaseLogger* logger;
|
||||
Logger* logger;
|
||||
uint32_t vdCount;
|
||||
uint32_t annotationLength;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
namespace asmjit {
|
||||
namespace x86x64 {
|
||||
|
||||
//! @addtogroup asmjit_x86x64
|
||||
//! @addtogroup asmjit_x86x64_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
@@ -31,7 +31,7 @@ namespace x86x64 {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Compiler context is used by @ref X86X64Compiler.
|
||||
//! Compiler context is used by `X86X64Compiler`.
|
||||
//!
|
||||
//! Compiler context is used during compilation and normally developer doesn't
|
||||
//! need access to it. The context is user per function (it's reset after each
|
||||
@@ -43,9 +43,9 @@ struct X86X64Context : public BaseContext {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @ref Context instance.
|
||||
//! Create a new `X86X64Context` instance.
|
||||
X86X64Context(X86X64Compiler* compiler);
|
||||
//! @brief Destroy the @ref Context instance.
|
||||
//! Destroy the `X86X64Context` instance.
|
||||
virtual ~X86X64Context();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -58,12 +58,12 @@ struct X86X64Context : public BaseContext {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get compiler as @ref X86X64Compiler.
|
||||
//! Get compiler as `X86X64Compiler`.
|
||||
ASMJIT_INLINE X86X64Compiler* getCompiler() const {
|
||||
return static_cast<X86X64Compiler*>(_compiler);
|
||||
}
|
||||
|
||||
//! @brief Get function as @ref X86X64FuncNode.
|
||||
//! Get function as `X86X64FuncNode`.
|
||||
ASMJIT_INLINE X86X64FuncNode* getFunc() const {
|
||||
return reinterpret_cast<X86X64FuncNode*>(_func);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ struct X86X64Context : public BaseContext {
|
||||
return _baseRegsCount == 16;
|
||||
}
|
||||
|
||||
//! @brief Get clobbered registers (global).
|
||||
//! Get clobbered registers (global).
|
||||
ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t c) {
|
||||
return _clobberedRegs.get(c);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Attach / Detach]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Attach.
|
||||
//! Attach.
|
||||
//!
|
||||
//! Attach a register to the 'VarData', changing 'VarData' members to show
|
||||
//! that the variable is currently alive and linking variable with the
|
||||
@@ -157,7 +157,7 @@ struct X86X64Context : public BaseContext {
|
||||
ASMJIT_CONTEXT_CHECK_STATE
|
||||
}
|
||||
|
||||
//! @brief Detach.
|
||||
//! Detach.
|
||||
//!
|
||||
//! The opposite of 'Attach'. Detach resets the members in 'VarData'
|
||||
//! (regIndex, state and changed flags) and unlinks the variable with the
|
||||
@@ -185,7 +185,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Rebase]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Rebase.
|
||||
//! Rebase.
|
||||
//!
|
||||
//! Change the register of the 'VarData' changing also the current 'VarState'.
|
||||
//! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't
|
||||
@@ -213,7 +213,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Load / Save]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Load.
|
||||
//! Load.
|
||||
//!
|
||||
//! Load variable from its memory slot to a register, emitting 'Load'
|
||||
//! instruction and changing the variable state to allocated.
|
||||
@@ -230,7 +230,7 @@ struct X86X64Context : public BaseContext {
|
||||
ASMJIT_CONTEXT_CHECK_STATE
|
||||
}
|
||||
|
||||
//! @brief Save.
|
||||
//! Save.
|
||||
//!
|
||||
//! Save the variable into its home location, but keep it as allocated.
|
||||
template<int C>
|
||||
@@ -254,7 +254,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Move / Swap]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Move a register.
|
||||
//! Move a register.
|
||||
//!
|
||||
//! Move register from one index to another, emitting 'Move' if needed. This
|
||||
//! function does nothing if register is already at the given index.
|
||||
@@ -273,7 +273,7 @@ struct X86X64Context : public BaseContext {
|
||||
ASMJIT_CONTEXT_CHECK_STATE
|
||||
}
|
||||
|
||||
//! @brief Swap two registers
|
||||
//! Swap two registers
|
||||
//!
|
||||
//! It's only possible to swap Gp registers.
|
||||
ASMJIT_INLINE void swapGp(VarData* aVd, VarData* bVd) {
|
||||
@@ -308,7 +308,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Alloc / Spill]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Alloc
|
||||
//! Alloc
|
||||
template<int C>
|
||||
ASMJIT_INLINE void alloc(VarData* vd, uint32_t regIndex) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
@@ -346,7 +346,7 @@ struct X86X64Context : public BaseContext {
|
||||
ASMJIT_CONTEXT_CHECK_STATE
|
||||
}
|
||||
|
||||
//! @brief Spill.
|
||||
//! Spill.
|
||||
//!
|
||||
//! Spill variable/register, saves the content to the memory-home if modified.
|
||||
template<int C>
|
||||
@@ -391,7 +391,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [Unuse]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Unuse.
|
||||
//! Unuse.
|
||||
//!
|
||||
//! Unuse variable, it will be detached it if it's allocated then its state
|
||||
//! will be changed to kVarStateUnused.
|
||||
@@ -413,7 +413,7 @@ struct X86X64Context : public BaseContext {
|
||||
// [State]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get state as @ref VarState.
|
||||
//! Get state as `VarState`.
|
||||
ASMJIT_INLINE VarState* getState() const {
|
||||
return const_cast<VarState*>(&_x86State);
|
||||
}
|
||||
@@ -465,45 +465,45 @@ struct X86X64Context : public BaseContext {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief X86/X64 stack-pointer (esp or rsp).
|
||||
//! X86/X64 stack-pointer (esp or rsp).
|
||||
GpReg _zsp;
|
||||
//! @brief X86/X64 frame-pointer (ebp or rbp).
|
||||
//! X86/X64 frame-pointer (ebp or rbp).
|
||||
GpReg _zbp;
|
||||
//! @brief Temporary memory operand.
|
||||
//! Temporary memory operand.
|
||||
Mem _memSlot;
|
||||
|
||||
//! @brief X86/X64 specific compiler state (linked with @ref _state).
|
||||
//! X86/X64 specific compiler state, linked to `_state`.
|
||||
VarState _x86State;
|
||||
//! @brief Clobbered registers (for the whole function).
|
||||
//! Clobbered registers (for the whole function).
|
||||
RegMask _clobberedRegs;
|
||||
|
||||
//! @brief Memory cell where is stored address used to restore manually
|
||||
//! Memory cell where is stored address used to restore manually
|
||||
//! aligned stack.
|
||||
MemCell* _stackFrameCell;
|
||||
|
||||
//! @brief Global allocable registers mask.
|
||||
//! Global allocable registers mask.
|
||||
uint32_t _gaRegs[kRegClassCount];
|
||||
|
||||
//! @brief X86/X64 number of Gp/Xmm registers.
|
||||
//! X86/X64 number of Gp/Xmm registers.
|
||||
uint8_t _baseRegsCount;
|
||||
//! @brief Function arguments base pointer (register).
|
||||
//! Function arguments base pointer (register).
|
||||
uint8_t _argBaseReg;
|
||||
//! @brief Function variables base pointer (register).
|
||||
//! Function variables base pointer (register).
|
||||
uint8_t _varBaseReg;
|
||||
//! @brief Whether to emit comments.
|
||||
//! Whether to emit comments.
|
||||
uint8_t _emitComments;
|
||||
|
||||
//! @brief Function arguments base offset.
|
||||
//! Function arguments base offset.
|
||||
int32_t _argBaseOffset;
|
||||
//! @brief Function variables base offset.
|
||||
//! Function variables base offset.
|
||||
int32_t _varBaseOffset;
|
||||
|
||||
//! @brief Function arguments displacement.
|
||||
//! Function arguments displacement.
|
||||
int32_t _argActualDisp;
|
||||
//! @brief Function variables displacement.
|
||||
//! Function variables displacement.
|
||||
int32_t _varActualDisp;
|
||||
|
||||
//! @brief Temporary string builder used for logging.
|
||||
//! Temporary string builder used for logging.
|
||||
StringBuilderT<256> _stringBuilder;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,65 +28,34 @@ namespace asmjit {
|
||||
namespace x86x64 {
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::hostCpuId]
|
||||
// [asmjit::x86x64::CpuVendor]
|
||||
// ============================================================================
|
||||
|
||||
// This is messy, I know. Cpuid is implemented as intrinsic in VS2005, but
|
||||
// we should support other compilers as well. Main problem is that MS compilers
|
||||
// in 64-bit mode not allows to use inline assembler, so we need intrinsic and
|
||||
// we need also asm version.
|
||||
struct CpuVendor {
|
||||
uint32_t id;
|
||||
char text[12];
|
||||
};
|
||||
|
||||
// hostCpuId() and detectCpuInfo() for x86 and x64 platforms begins here.
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
void hostCpuId(uint32_t inEax, uint32_t inEcx, CpuId* result) {
|
||||
static const CpuVendor cpuVendorTable[] = {
|
||||
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
|
||||
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
|
||||
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } },
|
||||
{ kCpuVendorNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
|
||||
{ kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
|
||||
{ kCpuVendorTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
|
||||
{ kCpuVendorNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
|
||||
{ kCpuVendorTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
|
||||
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler.
|
||||
// ASMJIT_HOST_X64 is here only for readibility, only VS2005 can compile 64-bit code.
|
||||
# if _MSC_VER >= 1400 || defined(ASMJIT_HOST_X64)
|
||||
// Done by intrinsics.
|
||||
__cpuidex(reinterpret_cast<int*>(result->i), inEax, inEcx);
|
||||
# else // _MSC_VER < 1400
|
||||
uint32_t cpuid_eax = inEax;
|
||||
uint32_t cpuid_ecx = inCax;
|
||||
uint32_t* cpuid_out = result->i;
|
||||
static ASMJIT_INLINE bool cpuVendorEq(const CpuVendor& info, const char* vendorString) {
|
||||
const uint32_t* a = reinterpret_cast<const uint32_t*>(info.text);
|
||||
const uint32_t* b = reinterpret_cast<const uint32_t*>(vendorString);
|
||||
|
||||
__asm {
|
||||
mov eax, cpuid_eax
|
||||
mov ecx, cpuid_ecx
|
||||
mov edi, cpuid_out
|
||||
cpuid
|
||||
mov dword ptr[edi + 0], eax
|
||||
mov dword ptr[edi + 4], ebx
|
||||
mov dword ptr[edi + 8], ecx
|
||||
mov dword ptr[edi + 12], edx
|
||||
}
|
||||
# endif // _MSC_VER < 1400
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
// Note, patched to preserve ebx/rbx register which is used by GCC.
|
||||
# if defined(ASMJIT_HOST_X86)
|
||||
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
|
||||
asm ("mov %%ebx, %%edi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%edi, %%ebx\n" \
|
||||
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
|
||||
# else
|
||||
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
|
||||
asm ("mov %%rbx, %%rdi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%rdi, %%rbx\n" \
|
||||
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
|
||||
# endif
|
||||
__myCpuId(inEax, inEcx, result->eax, result->ebx, result->ecx, result->edx);
|
||||
#endif // Compiler #ifdef.
|
||||
return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::cpuSimplifyBrandString]
|
||||
// ============================================================================
|
||||
|
||||
static ASMJIT_INLINE void cpuSimplifyBrandString(char* s) {
|
||||
static ASMJIT_INLINE void simplifyBrandString(char* s) {
|
||||
// Always clear the current character in the buffer. It ensures that there
|
||||
// is no garbage after the string NULL terminator.
|
||||
char* d = s;
|
||||
@@ -117,38 +86,61 @@ _Skip:
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::CpuVendor]
|
||||
// [asmjit::x86x64::CpuUtil]
|
||||
// ============================================================================
|
||||
|
||||
struct CpuVendor {
|
||||
uint32_t id;
|
||||
char text[12];
|
||||
};
|
||||
// This is messy, I know. Cpuid is implemented as intrinsic in VS2005, but
|
||||
// we should support other compilers as well. Main problem is that MS compilers
|
||||
// in 64-bit mode not allows to use inline assembler, so we need intrinsic and
|
||||
// we need also asm version.
|
||||
|
||||
static const CpuVendor cpuVendorTable[] = {
|
||||
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
|
||||
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
|
||||
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } },
|
||||
{ kCpuVendorNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
|
||||
{ kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
|
||||
{ kCpuVendorTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
|
||||
{ kCpuVendorNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
|
||||
{ kCpuVendorTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
|
||||
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }
|
||||
};
|
||||
// callCpuId() and detectCpuInfo() for x86 and x64 platforms begins here.
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
void CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, CpuId* outResult) {
|
||||
|
||||
static ASMJIT_INLINE bool cpuVendorEq(const CpuVendor& info, const char* vendorString) {
|
||||
const uint32_t* a = reinterpret_cast<const uint32_t*>(info.text);
|
||||
const uint32_t* b = reinterpret_cast<const uint32_t*>(vendorString);
|
||||
#if defined(_MSC_VER)
|
||||
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler.
|
||||
// ASMJIT_HOST_X64 is here only for readibility, only VS2005 can compile 64-bit code.
|
||||
# if _MSC_VER >= 1400 || defined(ASMJIT_HOST_X64)
|
||||
// Done by intrinsics.
|
||||
__cpuidex(reinterpret_cast<int*>(outResult->i), inEax, inEcx);
|
||||
# else // _MSC_VER < 1400
|
||||
uint32_t cpuid_eax = inEax;
|
||||
uint32_t cpuid_ecx = inCax;
|
||||
uint32_t* cpuid_out = outResult->i;
|
||||
|
||||
return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]);
|
||||
__asm {
|
||||
mov eax, cpuid_eax
|
||||
mov ecx, cpuid_ecx
|
||||
mov edi, cpuid_out
|
||||
cpuid
|
||||
mov dword ptr[edi + 0], eax
|
||||
mov dword ptr[edi + 4], ebx
|
||||
mov dword ptr[edi + 8], ecx
|
||||
mov dword ptr[edi + 12], edx
|
||||
}
|
||||
# endif // _MSC_VER < 1400
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
// Note, patched to preserve ebx/rbx register which is used by GCC.
|
||||
# if defined(ASMJIT_HOST_X86)
|
||||
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
|
||||
asm ("mov %%ebx, %%edi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%edi, %%ebx\n" \
|
||||
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
|
||||
# else
|
||||
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
|
||||
asm ("mov %%rbx, %%rdi\n" \
|
||||
"cpuid\n" \
|
||||
"xchg %%rdi, %%rbx\n" \
|
||||
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
|
||||
# endif
|
||||
__myCpuId(inEax, inEcx, outResult->eax, outResult->ebx, outResult->ecx, outResult->edx);
|
||||
#endif // COMPILER
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::hostCpuDetect]
|
||||
// ============================================================================
|
||||
|
||||
void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
void CpuUtil::detect(CpuInfo* cpuInfo) {
|
||||
CpuId regs;
|
||||
|
||||
uint32_t i;
|
||||
@@ -163,7 +155,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
cpuInfo->_coresCount = BaseCpuInfo::detectNumberOfCores();
|
||||
|
||||
// Get vendor string/id.
|
||||
hostCpuId(0, 0, ®s);
|
||||
callCpuId(0, 0, ®s);
|
||||
|
||||
maxId = regs.eax;
|
||||
::memcpy(cpuInfo->_vendorString, ®s.ebx, 4);
|
||||
@@ -178,7 +170,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
}
|
||||
|
||||
// Get feature flags in ecx/edx and family/model in eax.
|
||||
hostCpuId(1, 0, ®s);
|
||||
callCpuId(1, 0, ®s);
|
||||
|
||||
// Fill family and model fields.
|
||||
cpuInfo->_family = (regs.eax >> 8) & 0x0F;
|
||||
@@ -235,7 +227,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
|
||||
// Detect new features if the processor supports CPUID-07.
|
||||
if (maxId >= 7) {
|
||||
hostCpuId(7, 0, ®s);
|
||||
callCpuId(7, 0, ®s);
|
||||
|
||||
if (regs.ebx & 0x00000001) cpuInfo->addFeature(kCpuFeatureFsGsBase);
|
||||
if (regs.ebx & 0x00000008) cpuInfo->addFeature(kCpuFeatureBmi);
|
||||
@@ -252,13 +244,13 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
|
||||
// Calling cpuid with 0x80000000 as the in argument gets the number of valid
|
||||
// extended IDs.
|
||||
hostCpuId(0x80000000, 0, ®s);
|
||||
callCpuId(0x80000000, 0, ®s);
|
||||
|
||||
uint32_t maxExtId = IntUtil::iMin<uint32_t>(regs.eax, 0x80000004);
|
||||
uint32_t* brand = reinterpret_cast<uint32_t*>(cpuInfo->_brandString);
|
||||
|
||||
for (i = 0x80000001; i <= maxExtId; i++) {
|
||||
hostCpuId(i, 0, ®s);
|
||||
callCpuId(i, 0, ®s);
|
||||
|
||||
switch (i) {
|
||||
case 0x80000001:
|
||||
@@ -292,7 +284,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
|
||||
}
|
||||
|
||||
// Simplify the brand string (remove unnecessary spaces to make printing nicer).
|
||||
cpuSimplifyBrandString(cpuInfo->_brandString);
|
||||
simplifyBrandString(cpuInfo->_brandString);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+82
-72
@@ -18,103 +18,109 @@
|
||||
namespace asmjit {
|
||||
namespace x86x64 {
|
||||
|
||||
//! @addtogroup asmjit_x86x64
|
||||
//! @addtogroup asmjit_x86x64_cpu_info
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
struct CpuInfo;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::kCpuFeature]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86 CPU features.
|
||||
//! X86 CPU features.
|
||||
ASMJIT_ENUM(kCpuFeature) {
|
||||
//! @brief Cpu has multithreading.
|
||||
//! Cpu has multithreading.
|
||||
kCpuFeatureMultithreading = 1,
|
||||
//! @brief Cpu has execute disable bit.
|
||||
//! Cpu has execute disable bit.
|
||||
kCpuFeatureExecuteDisableBit,
|
||||
//! @brief Cpu has RDTSC.
|
||||
//! Cpu has RDTSC.
|
||||
kCpuFeatureRdtsc,
|
||||
//! @brief Cpu has RDTSCP.
|
||||
//! Cpu has RDTSCP.
|
||||
kCpuFeatureRdtscp,
|
||||
//! @brief Cpu has CMOV.
|
||||
//! Cpu has CMOV.
|
||||
kCpuFeatureCmov,
|
||||
//! @brief Cpu has CMPXCHG8B.
|
||||
//! Cpu has CMPXCHG8B.
|
||||
kCpuFeatureCmpXchg8B,
|
||||
//! @brief Cpu has CMPXCHG16B (x64).
|
||||
//! Cpu has CMPXCHG16B (x64).
|
||||
kCpuFeatureCmpXchg16B,
|
||||
//! @brief Cpu has CLFUSH.
|
||||
//! Cpu has CLFUSH.
|
||||
kCpuFeatureClflush,
|
||||
//! @brief Cpu has PREFETCH.
|
||||
//! Cpu has PREFETCH.
|
||||
kCpuFeaturePrefetch,
|
||||
//! @brief Cpu has LAHF/SAHF.
|
||||
//! Cpu has LAHF/SAHF.
|
||||
kCpuFeatureLahfSahf,
|
||||
//! @brief Cpu has FXSAVE/FXRSTOR.
|
||||
//! Cpu has FXSAVE/FXRSTOR.
|
||||
kCpuFeatureFxsr,
|
||||
//! @brief Cpu has FXSAVE/FXRSTOR optimizations.
|
||||
//! Cpu has FXSAVE/FXRSTOR optimizations.
|
||||
kCpuFeatureFfxsr,
|
||||
//! @brief Cpu has MMX.
|
||||
//! Cpu has MMX.
|
||||
kCpuFeatureMmx,
|
||||
//! @brief Cpu has extended MMX.
|
||||
//! Cpu has extended MMX.
|
||||
kCpuFeatureMmxExt,
|
||||
//! @brief Cpu has 3dNow!
|
||||
//! Cpu has 3dNow!
|
||||
kCpuFeature3dNow,
|
||||
//! @brief Cpu has enchanced 3dNow!
|
||||
//! Cpu has enchanced 3dNow!
|
||||
kCpuFeature3dNowExt,
|
||||
//! @brief Cpu has SSE.
|
||||
//! Cpu has SSE.
|
||||
kCpuFeatureSse,
|
||||
//! @brief Cpu has SSE2.
|
||||
//! Cpu has SSE2.
|
||||
kCpuFeatureSse2,
|
||||
//! @brief Cpu has SSE3.
|
||||
//! Cpu has SSE3.
|
||||
kCpuFeatureSse3,
|
||||
//! @brief Cpu has Supplemental SSE3 (SSSE3).
|
||||
//! Cpu has Supplemental SSE3 (SSSE3).
|
||||
kCpuFeatureSsse3,
|
||||
//! @brief Cpu has SSE4.A.
|
||||
//! Cpu has SSE4.A.
|
||||
kCpuFeatureSse4A,
|
||||
//! @brief Cpu has SSE4.1.
|
||||
//! Cpu has SSE4.1.
|
||||
kCpuFeatureSse41,
|
||||
//! @brief Cpu has SSE4.2.
|
||||
//! Cpu has SSE4.2.
|
||||
kCpuFeatureSse42,
|
||||
//! @brief Cpu has Misaligned SSE (MSSE).
|
||||
//! Cpu has Misaligned SSE (MSSE).
|
||||
kCpuFeatureMsse,
|
||||
//! @brief Cpu has MONITOR and MWAIT.
|
||||
//! Cpu has MONITOR and MWAIT.
|
||||
kCpuFeatureMonitorMWait,
|
||||
//! @brief Cpu has MOVBE.
|
||||
//! Cpu has MOVBE.
|
||||
kCpuFeatureMovbe,
|
||||
//! @brief Cpu has POPCNT.
|
||||
//! Cpu has POPCNT.
|
||||
kCpuFeaturePopcnt,
|
||||
//! @brief Cpu has LZCNT.
|
||||
//! Cpu has LZCNT.
|
||||
kCpuFeatureLzcnt,
|
||||
//! @brief Cpu has AESNI.
|
||||
//! Cpu has AESNI.
|
||||
kCpuFeatureAesni,
|
||||
//! @brief Cpu has PCLMULQDQ.
|
||||
//! Cpu has PCLMULQDQ.
|
||||
kCpuFeaturePclmulqdq,
|
||||
//! @brief Cpu has RDRAND.
|
||||
//! Cpu has RDRAND.
|
||||
kCpuFeatureRdrand,
|
||||
//! @brief Cpu has AVX.
|
||||
//! Cpu has AVX.
|
||||
kCpuFeatureAvx,
|
||||
//! @brief Cpu has AVX2.
|
||||
//! Cpu has AVX2.
|
||||
kCpuFeatureAvx2,
|
||||
//! @brief Cpu has F16C.
|
||||
//! Cpu has F16C.
|
||||
kCpuFeatureF16C,
|
||||
//! @brief Cpu has FMA3.
|
||||
//! Cpu has FMA3.
|
||||
kCpuFeatureFma3,
|
||||
//! @brief Cpu has FMA4.
|
||||
//! Cpu has FMA4.
|
||||
kCpuFeatureFma4,
|
||||
//! @brief Cpu has XOP.
|
||||
//! Cpu has XOP.
|
||||
kCpuFeatureXop,
|
||||
//! @brief Cpu has BMI.
|
||||
//! Cpu has BMI.
|
||||
kCpuFeatureBmi,
|
||||
//! @brief Cpu has BMI2.
|
||||
//! Cpu has BMI2.
|
||||
kCpuFeatureBmi2,
|
||||
//! @brief Cpu has HLE.
|
||||
//! Cpu has HLE.
|
||||
kCpuFeatureHle,
|
||||
//! @brief Cpu has RTM.
|
||||
//! Cpu has RTM.
|
||||
kCpuFeatureRtm,
|
||||
//! @brief Cpu has FSGSBASE.
|
||||
//! Cpu has FSGSBASE.
|
||||
kCpuFeatureFsGsBase,
|
||||
//! @brief Cpu has enhanced REP MOVSB/STOSB.
|
||||
//! Cpu has enhanced REP MOVSB/STOSB.
|
||||
kCpuFeatureRepMovsbStosbExt,
|
||||
|
||||
//! @brief Count of X86/X64 Cpu features.
|
||||
//! Count of X86/X64 Cpu features.
|
||||
kCpuFeatureCount
|
||||
};
|
||||
|
||||
@@ -122,23 +128,38 @@ ASMJIT_ENUM(kCpuFeature) {
|
||||
// [asmjit::x86x64::CpuId]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86/X64 cpuid output.
|
||||
//! X86/X64 CPUID output.
|
||||
union CpuId {
|
||||
//! @brief EAX/EBX/ECX/EDX output.
|
||||
//! EAX/EBX/ECX/EDX output.
|
||||
uint32_t i[4];
|
||||
|
||||
struct {
|
||||
//! @brief EAX output.
|
||||
//! EAX output.
|
||||
uint32_t eax;
|
||||
//! @brief EBX output.
|
||||
//! EBX output.
|
||||
uint32_t ebx;
|
||||
//! @brief ECX output.
|
||||
//! ECX output.
|
||||
uint32_t ecx;
|
||||
//! @brief EDX output.
|
||||
//! EDX output.
|
||||
uint32_t edx;
|
||||
};
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::CpuUtil]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
//! CPU utilities available only if the host processor is X86/X64.
|
||||
struct CpuUtil {
|
||||
//! Get the result of calling CPUID instruction to `out`.
|
||||
ASMJIT_API static void callCpuId(uint32_t inEax, uint32_t inEcx, CpuId* out);
|
||||
|
||||
//! Detect the Host CPU.
|
||||
ASMJIT_API static void detect(CpuInfo* cpuInfo);
|
||||
};
|
||||
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::CpuInfo]
|
||||
// ============================================================================
|
||||
@@ -157,22 +178,22 @@ struct CpuInfo : public BaseCpuInfo {
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get processor type.
|
||||
//! Get processor type.
|
||||
ASMJIT_INLINE uint32_t getProcessorType() const {
|
||||
return _processorType;
|
||||
}
|
||||
|
||||
//! @brief Get brand index.
|
||||
//! Get brand index.
|
||||
ASMJIT_INLINE uint32_t getBrandIndex() const {
|
||||
return _brandIndex;
|
||||
}
|
||||
|
||||
//! @brief Get flush cache line size.
|
||||
//! Get flush cache line size.
|
||||
ASMJIT_INLINE uint32_t getFlushCacheLineSize() const {
|
||||
return _flushCacheLineSize;
|
||||
}
|
||||
|
||||
//! @brief Get maximum logical processors count.
|
||||
//! Get maximum logical processors count.
|
||||
ASMJIT_INLINE uint32_t getMaxLogicalProcessors() const {
|
||||
return _maxLogicalProcessors;
|
||||
}
|
||||
@@ -181,7 +202,7 @@ struct CpuInfo : public BaseCpuInfo {
|
||||
// [Statics]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get global instance of @ref X86CpuInfo.
|
||||
//! Get global instance of `x86x64::CpuInfo`.
|
||||
static ASMJIT_INLINE const CpuInfo* getHost() {
|
||||
return static_cast<const CpuInfo*>(BaseCpuInfo::getHost());
|
||||
}
|
||||
@@ -190,27 +211,16 @@ struct CpuInfo : public BaseCpuInfo {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Processor type.
|
||||
//! Processor type.
|
||||
uint32_t _processorType;
|
||||
//! @brief Brand index.
|
||||
//! Brand index.
|
||||
uint32_t _brandIndex;
|
||||
//! @brief Flush cache line size in bytes.
|
||||
//! Flush cache line size in bytes.
|
||||
uint32_t _flushCacheLineSize;
|
||||
//! @brief Maximum number of addressable IDs for logical processors.
|
||||
//! Maximum number of addressable IDs for logical processors.
|
||||
uint32_t _maxLogicalProcessors;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::hostCpuId / hostCpuDetect]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
//! @brief Get the result of calling CPUID instruction.
|
||||
ASMJIT_API void hostCpuId(uint32_t inEax, uint32_t inEcx, CpuId* result);
|
||||
//! @brief Detect host CPU.
|
||||
ASMJIT_API void hostCpuDetect(CpuInfo* cpuInfo);
|
||||
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
|
||||
|
||||
//! @}
|
||||
|
||||
} // x86x64 namespace
|
||||
|
||||
+803
-800
File diff suppressed because it is too large
Load Diff
+821
-802
File diff suppressed because it is too large
Load Diff
+24
-26
@@ -52,8 +52,6 @@ static ASMJIT_INLINE uint32_t x86ArgTypeToXmmType(uint32_t aType) {
|
||||
|
||||
#define R(_Index_) kRegIndex##_Index_
|
||||
static uint32_t X86X64FuncDecl_initConv(X86X64FuncDecl* self, uint32_t arch, uint32_t conv) {
|
||||
uint32_t i;
|
||||
|
||||
// Setup defaults.
|
||||
self->_argStackSize = 0;
|
||||
self->_redZoneSize = 0;
|
||||
@@ -66,13 +64,8 @@ static uint32_t X86X64FuncDecl_initConv(X86X64FuncDecl* self, uint32_t arch, uin
|
||||
self->_passed.reset();
|
||||
self->_preserved.reset();
|
||||
|
||||
for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_passedOrderGp); i++) {
|
||||
self->_passedOrderGp[i] = kInvalidReg;
|
||||
}
|
||||
|
||||
for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm); i++) {
|
||||
self->_passedOrderXmm[i] = kInvalidReg;
|
||||
}
|
||||
::memset(self->_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderGp));
|
||||
::memset(self->_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderXmm));
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [X86 Support]
|
||||
@@ -328,10 +321,14 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
|
||||
FuncInOut& arg = self->getArg(i);
|
||||
uint32_t varType = varMapping[arg.getVarType()];
|
||||
|
||||
if (x86ArgIsInt(varType) && gpPos < 16 && self->_passedOrderGp[gpPos] != kInvalidReg) {
|
||||
arg._regIndex = self->_passedOrderGp[gpPos++];
|
||||
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
|
||||
}
|
||||
if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp))
|
||||
continue;
|
||||
|
||||
if (self->_passedOrderGp[gpPos] == kInvalidReg)
|
||||
continue;
|
||||
|
||||
arg._regIndex = self->_passedOrderGp[gpPos++];
|
||||
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
|
||||
}
|
||||
|
||||
// Stack arguments.
|
||||
@@ -375,11 +372,13 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
|
||||
FuncInOut& arg = self->getArg(i);
|
||||
uint32_t varType = varMapping[arg.getVarType()];
|
||||
|
||||
if (x86ArgIsInt(varType)) {
|
||||
if (x86ArgIsInt(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderGp)) {
|
||||
arg._regIndex = self->_passedOrderGp[i];
|
||||
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
|
||||
continue;
|
||||
}
|
||||
else if (x86ArgIsFp(varType)) {
|
||||
|
||||
if (x86ArgIsFp(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm)) {
|
||||
arg._varType = static_cast<uint8_t>(x86ArgTypeToXmmType(varType));
|
||||
arg._regIndex = self->_passedOrderXmm[i];
|
||||
self->_used.add(kRegClassXy, IntUtil::mask(arg.getRegIndex()));
|
||||
@@ -413,10 +412,14 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
|
||||
FuncInOut& arg = self->getArg(i);
|
||||
uint32_t varType = varMapping[arg.getVarType()];
|
||||
|
||||
if (x86ArgIsInt(varType) && gpPos < 32 && self->_passedOrderGp[gpPos] != kInvalidReg) {
|
||||
arg._regIndex = self->_passedOrderGp[gpPos++];
|
||||
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
|
||||
}
|
||||
if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp))
|
||||
continue;
|
||||
|
||||
if (self->_passedOrderGp[gpPos] == kInvalidReg)
|
||||
continue;
|
||||
|
||||
arg._regIndex = self->_passedOrderGp[gpPos++];
|
||||
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
|
||||
}
|
||||
|
||||
// Register arguments (Xmm), always left-to-right.
|
||||
@@ -523,13 +526,8 @@ void X86X64FuncDecl::reset() {
|
||||
_passed.reset();
|
||||
_preserved.reset();
|
||||
|
||||
for (i = 0; i < ASMJIT_ARRAY_SIZE(_passedOrderGp); i++) {
|
||||
_passedOrderGp[i] = kInvalidReg;
|
||||
}
|
||||
|
||||
for (i = 0; i < ASMJIT_ARRAY_SIZE(_passedOrderXmm); i++) {
|
||||
_passedOrderXmm[i] = kInvalidReg;
|
||||
}
|
||||
::memset(_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderGp));
|
||||
::memset(_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderXmm));
|
||||
}
|
||||
|
||||
} // x86x64 namespace
|
||||
|
||||
+89
-78
@@ -19,14 +19,14 @@
|
||||
namespace asmjit {
|
||||
namespace x86x64 {
|
||||
|
||||
//! @addtogroup asmjit_x86x64
|
||||
//! @addtogroup asmjit_x86x64_codegen
|
||||
//! @{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::kFuncConv]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86 function calling conventions.
|
||||
//! X86 function calling conventions.
|
||||
//!
|
||||
//! Calling convention is scheme how function arguments are passed into
|
||||
//! function and how functions returns values. In assembler programming
|
||||
@@ -34,33 +34,32 @@ namespace x86x64 {
|
||||
//! even small inconsistency can cause undefined behavior or crash.
|
||||
//!
|
||||
//! List of calling conventions for 32-bit x86 mode:
|
||||
//! - @c kFuncConvCDecl - Calling convention for C runtime.
|
||||
//! - @c kFuncConvStdCall - Calling convention for WinAPI functions.
|
||||
//! - @c kFuncConvMsThisCall - Calling convention for C++ members under
|
||||
//! Windows (produced by MSVC and all MSVC compatible compilers).
|
||||
//! - @c kFuncConvMsFastCall - Fastest calling convention that can be used
|
||||
//! by MSVC compiler.
|
||||
//! - @c kFuncConv_BORNANDFASTCALL - Borland fastcall convention.
|
||||
//! - @c kFuncConvGccFastCall - GCC fastcall convention (2 register arguments).
|
||||
//! - @c kFuncConvGccRegParm1 - GCC regparm(1) convention.
|
||||
//! - @c kFuncConvGccRegParm2 - GCC regparm(2) convention.
|
||||
//! - @c kFuncConvGccRegParm3 - GCC regparm(3) convention.
|
||||
//! - `kFuncConvCDecl` - Calling convention for C runtime.
|
||||
//! - `kFuncConvStdCall` - Calling convention for WinAPI functions.
|
||||
//! - `kFuncConvMsThisCall` - Calling convention for C++ members under
|
||||
//! Windows (produced by MSVC and all MSVC compatible compilers).
|
||||
//! - `kFuncConvMsFastCall` - Fastest calling convention that can be used
|
||||
//! by MSVC compiler.
|
||||
//! - `kFuncConvBorlandFastCall` - Borland fastcall convention.
|
||||
//! - `kFuncConvGccFastCall` - GCC fastcall convention (2 register arguments).
|
||||
//! - `kFuncConvGccRegParm1` - GCC regparm(1) convention.
|
||||
//! - `kFuncConvGccRegParm2` - GCC regparm(2) convention.
|
||||
//! - `kFuncConvGccRegParm3` - GCC regparm(3) convention.
|
||||
//!
|
||||
//! List of calling conventions for 64-bit x86 mode (x64):
|
||||
//! - @c kFuncConvX64W - Windows 64-bit calling convention (WIN64 ABI).
|
||||
//! - @c kFuncConvX64U - Unix 64-bit calling convention (AMD64 ABI).
|
||||
//! - `kFuncConvX64W` - Windows 64-bit calling convention (WIN64 ABI).
|
||||
//! - `kFuncConvX64U` - Unix 64-bit calling convention (AMD64 ABI).
|
||||
//!
|
||||
//! There is also @c kFuncConvHost that is defined to fit best to your
|
||||
//! compiler.
|
||||
//! There is also `kFuncConvHost` that is defined to fit the host calling
|
||||
//! convention.
|
||||
//!
|
||||
//! These types are used together with @c asmjit::Compiler::addFunc()
|
||||
//! method.
|
||||
//! These types are used together with `BaseCompiler::addFunc()` method.
|
||||
ASMJIT_ENUM(kFuncConv) {
|
||||
// --------------------------------------------------------------------------
|
||||
// [X64]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief X64 calling convention for Windows platform (WIN64 ABI).
|
||||
//! X64 calling convention for Windows platform (WIN64 ABI).
|
||||
//!
|
||||
//! For first four arguments are used these registers:
|
||||
//! - 1. 32/64-bit integer or floating point argument - rcx/xmm0
|
||||
@@ -93,7 +92,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! http://msdn.microsoft.com/en-us/library/9b372w95.aspx .
|
||||
kFuncConvX64W = 1,
|
||||
|
||||
//! @brief X64 calling convention for Unix platforms (AMD64 ABI).
|
||||
//! X64 calling convention for Unix platforms (AMD64 ABI).
|
||||
//!
|
||||
//! First six 32 or 64-bit integer arguments are passed in rdi, rsi, rdx,
|
||||
//! rcx, r8, r9 registers. First eight floating point or Xmm arguments
|
||||
@@ -120,7 +119,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
// [X86]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Cdecl calling convention (used by C runtime).
|
||||
//! Cdecl calling convention (used by C runtime).
|
||||
//!
|
||||
//! Compatible across MSVC and GCC.
|
||||
//!
|
||||
@@ -131,7 +130,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! - Caller.
|
||||
kFuncConvCDecl = 3,
|
||||
|
||||
//! @brief Stdcall calling convention (used by WinAPI).
|
||||
//! Stdcall calling convention (used by WinAPI).
|
||||
//!
|
||||
//! Compatible across MSVC and GCC.
|
||||
//!
|
||||
@@ -146,7 +145,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! - Floating points - fp0 register.
|
||||
kFuncConvStdCall = 4,
|
||||
|
||||
//! @brief MSVC specific calling convention used by MSVC/Intel compilers
|
||||
//! MSVC specific calling convention used by MSVC/Intel compilers
|
||||
//! for struct/class methods.
|
||||
//!
|
||||
//! This is MSVC (and Intel) only calling convention used in Windows
|
||||
@@ -170,7 +169,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! it's implicit and there is no way how to override it.
|
||||
kFuncConvMsThisCall = 5,
|
||||
|
||||
//! @brief MSVC specific fastcall.
|
||||
//! MSVC specific fastcall.
|
||||
//!
|
||||
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
|
||||
//! registers, all others on the stack in right-to-left order.
|
||||
@@ -189,7 +188,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! mechanism.
|
||||
kFuncConvMsFastCall = 6,
|
||||
|
||||
//! @brief Borland specific fastcall with 2 parameters in registers.
|
||||
//! Borland specific fastcall with 2 parameters in registers.
|
||||
//!
|
||||
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
|
||||
//! registers, all others on the stack in left-to-right order.
|
||||
@@ -208,7 +207,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! to other fastcall conventions used in different compilers.
|
||||
kFuncConvBorlandFastCall = 7,
|
||||
|
||||
//! @brief GCC specific fastcall convention.
|
||||
//! GCC specific fastcall convention.
|
||||
//!
|
||||
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
|
||||
//! registers, all others on the stack in right-to-left order.
|
||||
@@ -223,11 +222,10 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! - Integer types - EAX:EDX registers.
|
||||
//! - Floating points - fp0 register.
|
||||
//!
|
||||
//! @note This calling convention should be compatible with
|
||||
//! @c kFuncConvMsFastCall.
|
||||
//! @note This calling convention should be compatible with `kFuncConvMsFastCall`.
|
||||
kFuncConvGccFastCall = 8,
|
||||
|
||||
//! @brief GCC specific regparm(1) convention.
|
||||
//! GCC specific regparm(1) convention.
|
||||
//!
|
||||
//! The first parameter (evaluated from left-to-right) is in EAX register,
|
||||
//! all others on the stack in right-to-left order.
|
||||
@@ -243,7 +241,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! - Floating points - fp0 register.
|
||||
kFuncConvGccRegParm1 = 9,
|
||||
|
||||
//! @brief GCC specific regparm(2) convention.
|
||||
//! GCC specific regparm(2) convention.
|
||||
//!
|
||||
//! Two first parameters (evaluated from left-to-right) are in EAX:EDX
|
||||
//! registers, all others on the stack in right-to-left order.
|
||||
@@ -259,7 +257,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
//! - Floating points - fp0 register.
|
||||
kFuncConvGccRegParm2 = 10,
|
||||
|
||||
//! @brief GCC specific fastcall with 3 parameters in registers.
|
||||
//! GCC specific fastcall with 3 parameters in registers.
|
||||
//!
|
||||
//! Three first parameters (evaluated from left-to-right) are in
|
||||
//! EAX:EDX:ECX registers, all others on the stack in right-to-left order.
|
||||
@@ -277,7 +275,7 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
|
||||
//! @internal
|
||||
//!
|
||||
//! @brief Count of function calling conventions.
|
||||
//! Count of function calling conventions.
|
||||
_kFuncConvCount = 12,
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -285,24 +283,24 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @def kFuncConvHost
|
||||
//! @brief Default calling convention for current platform / operating system.
|
||||
//! Default calling convention for current platform / operating system.
|
||||
|
||||
//! @def kFuncConvHostCDecl
|
||||
//! @brief Default C calling convention based on current compiler's settings.
|
||||
//! Default C calling convention based on current compiler's settings.
|
||||
|
||||
//! @def kFuncConvHostStdCall
|
||||
//! @brief Compatibility for __stdcall calling convention.
|
||||
//! Compatibility for `__stdcall` calling convention.
|
||||
//!
|
||||
//! @note This enumeration is always set to a value which is compatible with
|
||||
//! current compilers __stdcall calling convention. In 64-bit mode the value
|
||||
//! is compatible with @ref kFuncConvX64W or @ref kFuncConvX64U.
|
||||
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
|
||||
|
||||
//! @def kFuncConvHostFastCall
|
||||
//! @brief Compatibility for __fastcall calling convention.
|
||||
//! Compatibility for `__fastcall` calling convention.
|
||||
//!
|
||||
//! @note This enumeration is always set to a value which is compatible with
|
||||
//! current compilers __fastcall calling convention. In 64-bit mode the value
|
||||
//! is compatible with @ref kFuncConvX64W or @ref kFuncConvX64U.
|
||||
//! current compilers `__fastcall` calling convention. In 64-bit mode the value
|
||||
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
|
||||
|
||||
#if defined(ASMJIT_HOST_X86)
|
||||
|
||||
@@ -339,16 +337,16 @@ ASMJIT_ENUM(kFuncConv) {
|
||||
// [asmjit::x86x64::kFuncHint]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86 function hints.
|
||||
//! X86 function hints.
|
||||
ASMJIT_ENUM(kFuncHint) {
|
||||
//! @brief Use push/pop sequences instead of mov sequences in function prolog
|
||||
//! Use push/pop sequences instead of mov sequences in function prolog
|
||||
//! and epilog.
|
||||
kFuncHintPushPop = 16,
|
||||
//! @brief Add emms instruction to the function epilog.
|
||||
//! Add emms instruction to the function epilog.
|
||||
kFuncHintEmms = 17,
|
||||
//! @brief Add sfence instruction to the function epilog.
|
||||
//! Add sfence instruction to the function epilog.
|
||||
kFuncHintSFence = 18,
|
||||
//! @brief Add lfence instruction to the function epilog.
|
||||
//! Add lfence instruction to the function epilog.
|
||||
kFuncHintLFence = 19
|
||||
};
|
||||
|
||||
@@ -356,36 +354,34 @@ ASMJIT_ENUM(kFuncHint) {
|
||||
// [asmjit::x86x64::kFuncFlags]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86 function flags.
|
||||
//! X86 function flags.
|
||||
ASMJIT_ENUM(kFuncFlags) {
|
||||
//! @brief Whether to emit register load/save sequence using push/pop pairs.
|
||||
//! Whether to emit register load/save sequence using push/pop pairs.
|
||||
kFuncFlagPushPop = 0x00010000,
|
||||
|
||||
//! @brief Whether to emit "enter" instead of three instructions in case
|
||||
//! Whether to emit `enter` instead of three instructions in case
|
||||
//! that the function is not naked or misaligned.
|
||||
kFuncFlagEnter = 0x00020000,
|
||||
|
||||
//! @brief Whether to emit "leave" instead of two instructions in case
|
||||
//! Whether to emit `leave` instead of two instructions in case
|
||||
//! that the function is not naked or misaligned.
|
||||
kFuncFlagLeave = 0x00040000,
|
||||
|
||||
//! @brief Whether it's required to move arguments to a new stack location,
|
||||
//! Whether it's required to move arguments to a new stack location,
|
||||
//! because of manual aligning.
|
||||
kFuncFlagMoveArgs = 0x00080000,
|
||||
|
||||
//! @brief Whether to emit EMMS instruction in epilog (auto-detected).
|
||||
//! Whether to emit `emms` instruction in epilog (auto-detected).
|
||||
kFuncFlagEmms = 0x01000000,
|
||||
|
||||
//! @brief Whether to emit SFence instruction in epilog (auto-detected).
|
||||
//! Whether to emit `sfence` instruction in epilog (auto-detected).
|
||||
//!
|
||||
//! @note @ref kFuncFlagSFence and @ref kFuncFlagLFence
|
||||
//! combination will result in emitting mfence.
|
||||
//! `kFuncFlagSFence` with `kFuncFlagLFence` results in emitting `mfence`.
|
||||
kFuncFlagSFence = 0x02000000,
|
||||
|
||||
//! @brief Whether to emit LFence instruction in epilog (auto-detected).
|
||||
//! Whether to emit `lfence` instruction in epilog (auto-detected).
|
||||
//!
|
||||
//! @note @ref kFuncFlagSFence and @ref kFuncFlagLFence
|
||||
//! combination will result in emitting mfence.
|
||||
//! `kFuncFlagSFence` with `kFuncFlagLFence` results in emitting `mfence`.
|
||||
kFuncFlagLFence = 0x04000000
|
||||
};
|
||||
|
||||
@@ -393,6 +389,9 @@ ASMJIT_ENUM(kFuncFlags) {
|
||||
// [asmjit::x86x64::x86GetArchFromCConv]
|
||||
// ============================================================================
|
||||
|
||||
//! Get architecture by a calling convention.
|
||||
//!
|
||||
//! Returns `kArchX86` or `kArchX64` depending on `conv`.
|
||||
static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
|
||||
return IntUtil::inInterval<uint32_t>(conv, kFuncConvX64W, kFuncConvX64U) ? kArchX64 : kArchX86;
|
||||
}
|
||||
@@ -401,56 +400,68 @@ static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
|
||||
// [asmjit::x86x64::X86X64FuncDecl]
|
||||
// ============================================================================
|
||||
|
||||
//! @brief X86 function, including calling convention, arguments and their
|
||||
//! X86 function, including calling convention, arguments and their
|
||||
//! register indices or stack positions.
|
||||
struct X86X64FuncDecl : public FuncDecl {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Create a new @ref X86X64FuncDecl instance.
|
||||
ASMJIT_INLINE X86X64FuncDecl() { reset(); }
|
||||
//! Create a new `X86X64FuncDecl` instance.
|
||||
ASMJIT_INLINE X86X64FuncDecl() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors - X86]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Get used registers (mask).
|
||||
//! Get used registers (mask).
|
||||
//!
|
||||
//! @note The result depends on the function calling convention AND the
|
||||
//! function prototype. Returned mask contains only registers actually used
|
||||
//! to pass function arguments.
|
||||
ASMJIT_INLINE uint32_t getUsed(uint32_t c) const { return _used.get(c); }
|
||||
ASMJIT_INLINE uint32_t getUsed(uint32_t c) const {
|
||||
return _used.get(c);
|
||||
}
|
||||
|
||||
//! @brief Get passed registers (mask).
|
||||
//! Get passed registers (mask).
|
||||
//!
|
||||
//! @note The result depends on the function calling convention used; the
|
||||
//! prototype of the function doesn't affect the mask returned.
|
||||
ASMJIT_INLINE uint32_t getPassed(uint32_t c) const { return _passed.get(c); }
|
||||
ASMJIT_INLINE uint32_t getPassed(uint32_t c) const {
|
||||
return _passed.get(c);
|
||||
}
|
||||
|
||||
//! @brief Get preserved registers (mask).
|
||||
//! Get preserved registers (mask).
|
||||
//!
|
||||
//! @note The result depends on the function calling convention used; the
|
||||
//! prototype of the function doesn't affect the mask returned.
|
||||
ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const { return _preserved.get(c); }
|
||||
ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const {
|
||||
return _preserved.get(c);
|
||||
}
|
||||
|
||||
//! @brief Get ther order of passed registers (Gp).
|
||||
//! Get ther order of passed registers (Gp).
|
||||
//!
|
||||
//! @note The result depends on the function calling convention used; the
|
||||
//! prototype of the function doesn't affect the mask returned.
|
||||
ASMJIT_INLINE const uint8_t* getPassedOrderGp() const { return _passedOrderGp; }
|
||||
ASMJIT_INLINE const uint8_t* getPassedOrderGp() const {
|
||||
return _passedOrderGp;
|
||||
}
|
||||
|
||||
//! @brief Get ther order of passed registers (Xmm).
|
||||
//! Get ther order of passed registers (Xmm).
|
||||
//!
|
||||
//! @note The result depends on the function calling convention used; the
|
||||
//! prototype of the function doesn't affect the mask returned.
|
||||
ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const { return _passedOrderXmm; }
|
||||
ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const {
|
||||
return _passedOrderXmm;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [SetPrototype]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Set function prototype.
|
||||
//! Set function prototype.
|
||||
//!
|
||||
//! This will set function calling convention and setup arguments variables.
|
||||
//!
|
||||
@@ -467,18 +478,18 @@ struct X86X64FuncDecl : public FuncDecl {
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! @brief Used registers .
|
||||
//! Used registers.
|
||||
RegMask _used;
|
||||
|
||||
//! @brief Passed registers (defined by the calling convention).
|
||||
//! Passed registers (defined by the calling convention).
|
||||
RegMask _passed;
|
||||
//! @brief Preserved registers (defined by the calling convention).
|
||||
//! Preserved registers (defined by the calling convention).
|
||||
RegMask _preserved;
|
||||
|
||||
//! @brief Order of registers defined to pass function arguments (Gp).
|
||||
uint8_t _passedOrderGp[kFuncArgCount];
|
||||
//! @brief Order of registers defined to pass function arguments (Xmm).
|
||||
uint8_t _passedOrderXmm[kFuncArgCount];
|
||||
//! Order of registers defined to pass function arguments (Gp).
|
||||
uint8_t _passedOrderGp[8];
|
||||
//! Order of registers defined to pass function arguments (Xmm).
|
||||
uint8_t _passedOrderXmm[8];
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
# Doxyfile 1.8.7
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
|
||||
PROJECT_NAME = "AsmJit"
|
||||
PROJECT_NUMBER = "1.1"
|
||||
PROJECT_BRIEF = "Complete Remote and JIT Assembler for x86/x64"
|
||||
|
||||
OUTPUT_DIRECTORY = .
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
|
||||
# descriptions after the members that are listed in the file and class
|
||||
# documentation (similar to Javadoc). Set to NO to disable this.
|
||||
# The default value is: YES.
|
||||
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
|
||||
# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
|
||||
# description of a member or function before the detailed description
|
||||
#
|
||||
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||
# brief descriptions will be completely suppressed.
|
||||
# The default value is: YES.
|
||||
|
||||
REPEAT_BRIEF = YES
|
||||
|
||||
# This tag implements a quasi-intelligent brief description abbreviator that is
|
||||
# used to form the text in various listings. Each string in this list, if found
|
||||
# as the leading text of the brief description, will be stripped from the text
|
||||
# and the result, after processing the whole list, is used as the annotated
|
||||
# text. Otherwise, the brief description is used as-is. If left blank, the
|
||||
# following values are used ($name is automatically replaced with the name of
|
||||
# the entity):The $name class, The $name widget, The $name file, is, provides,
|
||||
# specifies, contains, represents, a, an and the.
|
||||
|
||||
ABBREVIATE_BRIEF =
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# doxygen will generate a detailed section even if there is only a brief
|
||||
# description.
|
||||
# The default value is: NO.
|
||||
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
|
||||
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
|
||||
# inherited members of a class in the documentation of that class as if those
|
||||
# members were ordinary class members. Constructors, destructors and assignment
|
||||
# operators of the base classes will not be shown.
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
|
||||
# before files name in the file list and in the header files. If set to NO the
|
||||
# shortest path that makes the file name unique will be used
|
||||
# The default value is: YES.
|
||||
|
||||
FULL_PATH_NAMES = YES
|
||||
|
||||
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
|
||||
# Stripping is only done if one of the specified strings matches the left-hand
|
||||
# part of the path. The tag can be used to show relative paths in the file list.
|
||||
# If left blank the directory from which doxygen is run is used as the path to
|
||||
# strip.
|
||||
#
|
||||
# Note that you can specify absolute paths here, but also relative paths, which
|
||||
# will be relative from the directory where doxygen is started.
|
||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
||||
# path mentioned in the documentation of a class, which tells the reader which
|
||||
# header file to include in order to use a class. If left blank only the name of
|
||||
# the header file containing the class definition is used. Otherwise one should
|
||||
# specify the list of include paths that are normally passed to the compiler
|
||||
# using the -I flag.
|
||||
|
||||
STRIP_FROM_INC_PATH =
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
||||
# less readable) file names. This can be useful is your file systems doesn't
|
||||
# support long names like on DOS, Mac, or CD-ROM.
|
||||
# The default value is: NO.
|
||||
|
||||
SHORT_NAMES = NO
|
||||
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
|
||||
# first line (until the first dot) of a Javadoc-style comment as the brief
|
||||
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
|
||||
# style comments (thus requiring an explicit @brief command for a brief
|
||||
# description.)
|
||||
# The default value is: NO.
|
||||
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
|
||||
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
|
||||
# line (until the first dot) of a Qt-style comment as the brief description. If
|
||||
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
|
||||
# requiring an explicit \brief command for a brief description.)
|
||||
# The default value is: NO.
|
||||
|
||||
QT_AUTOBRIEF = NO
|
||||
|
||||
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
|
||||
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
|
||||
# a brief description. This used to be the default behavior. The new default is
|
||||
# to treat a multi-line C++ comment block as a detailed description. Set this
|
||||
# tag to YES if you prefer the old behavior instead.
|
||||
#
|
||||
# Note that setting this tag to YES also means that rational rose comments are
|
||||
# not recognized any more.
|
||||
# The default value is: NO.
|
||||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||
# documentation from any documented member that it re-implements.
|
||||
# The default value is: YES.
|
||||
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
|
||||
# new page for each member. If set to NO, the documentation of a member will be
|
||||
# part of the file/class/namespace that contains it.
|
||||
# The default value is: NO.
|
||||
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 2
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = NO
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
# The default value is: NO.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
||||
# (for instance a group of public functions) to be put as a subgroup of that
|
||||
# type (e.g. under the Public Functions section). Set it to NO to prevent
|
||||
# subgrouping. Alternatively, this can be done per class using the
|
||||
# \nosubgrouping command.
|
||||
# The default value is: YES.
|
||||
|
||||
SUBGROUPING = YES
|
||||
|
||||
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
|
||||
# are shown inside the group in which they are included (e.g. using \ingroup)
|
||||
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
|
||||
# and RTF).
|
||||
#
|
||||
# Note that this feature does not work in combination with
|
||||
# SEPARATE_MEMBER_PAGES.
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
|
||||
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
|
||||
# with only public data fields or simple typedef fields will be shown inline in
|
||||
# the documentation of the scope in which they are defined (i.e. file,
|
||||
# namespace, or group documentation), provided this scope is documented. If set
|
||||
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
|
||||
# Man pages) or section (for LaTeX and RTF).
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = NO
|
||||
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
HIDE_IN_BODY_DOCS = YES
|
||||
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
||||
# their full class and namespace scopes in the documentation. If set to YES the
|
||||
# scope will be hidden.
|
||||
# The default value is: NO.
|
||||
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = NO
|
||||
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TESTLIST = NO
|
||||
GENERATE_BUGLIST = NO
|
||||
GENERATE_DEPRECATEDLIST= NO
|
||||
|
||||
MAX_INITIALIZER_LINES = 0
|
||||
SHOW_USED_FILES = NO
|
||||
SHOW_FILES = NO
|
||||
SHOW_NAMESPACES = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
INPUT = ../src/asmjit
|
||||
INPUT_ENCODING = UTF-8
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
USE_MDFILE_AS_MAINPAGE = ../README.md
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
ALPHABETICAL_INDEX = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
GENERATE_HTML = YES
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_RTF = NO
|
||||
GENERATE_MAN = NO
|
||||
|
||||
HTML_OUTPUT = doc
|
||||
HTML_FILE_EXTENSION = .html
|
||||
|
||||
LAYOUT_FILE = doc-layout.xml
|
||||
HTML_HEADER = doc-header.html
|
||||
HTML_FOOTER = doc-footer.html
|
||||
HTML_STYLESHEET = doc-style.css
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = NO
|
||||
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 0
|
||||
SEARCHENGINE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the CHM output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
||||
# Windows.
|
||||
#
|
||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||
# files are now used as the Windows 98 help format, and will replace the old
|
||||
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
|
||||
# HTML files also contain an index, a table of contents, and you can search for
|
||||
# words in the documentation. The HTML workshop also contains a viewer for
|
||||
# compressed HTML files.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_HTMLHELP = NO
|
||||
|
||||
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
|
||||
# file. You can add a path in front of the file if the result should not be
|
||||
# written to the html output directory.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
CHM_FILE =
|
||||
|
||||
# The HHC_LOCATION tag can be used to specify the location (absolute path
|
||||
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
|
||||
# doxygen will try to run the HTML help compiler on the generated index.hhp.
|
||||
# The file has to be specified with full path.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
HHC_LOCATION =
|
||||
|
||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
||||
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
|
||||
# enables the Previous and Next buttons.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
BINARY_TOC = NO
|
||||
|
||||
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
|
||||
# the table of contents of the HTML help documentation and to the tree view.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||
|
||||
TOC_EXPAND = NO
|
||||
|
||||
# If you want full control over the layout of the generated HTML pages it might
|
||||
# be necessary to disable the index and replace it with your own. The
|
||||
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
|
||||
# of each HTML page. A value of NO enables the index and the value YES disables
|
||||
# it. Since the tabs in the index contain the same information as the navigation
|
||||
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
DISABLE_INDEX = NO
|
||||
|
||||
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
|
||||
# structure should be generated to display hierarchical information. If the tag
|
||||
# value is set to YES, a side panel will be generated containing a tree-like
|
||||
# index structure (just like the one that is generated for HTML Help). For this
|
||||
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
|
||||
# (i.e. any modern browser). Windows users are probably better off using the
|
||||
# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
|
||||
# further fine-tune the look of the index. As an example, the default style
|
||||
# sheet generated by doxygen has an example that shows how to put an image at
|
||||
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
|
||||
# the same information as the tab index, you could consider setting
|
||||
# DISABLE_INDEX to YES when enabling this option.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
#
|
||||
# Note that a value of 0 will completely suppress the enum values from appearing
|
||||
# in the overview section.
|
||||
# Minimum value: 0, maximum value: 20, default value: 4.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
ENUM_VALUES_PER_LINE = 0
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
|
||||
# to set the initial width (in pixels) of the frame in which the tree is shown.
|
||||
# Minimum value: 0, maximum value: 1500, default value: 250.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
TREEVIEW_WIDTH = 250
|
||||
|
||||
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
|
||||
# external symbols imported via tag files in a separate window.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
PREDEFINED = ASMJIT_DOCGEN=1
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
CLASS_DIAGRAMS = NO
|
||||
CLASS_GRAPH = NO
|
||||
@@ -0,0 +1,21 @@
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<title>$projectname: $title</title>
|
||||
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div id="top">
|
||||
|
||||
<!--BEGIN TITLEAREA-->
|
||||
<div id="titlearea">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr style="height: 56px;">
|
||||
<!--BEGIN PROJECT_LOGO-->
|
||||
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||
<!--END PROJECT_LOGO-->
|
||||
|
||||
<td style="padding-left: 0.5em;">
|
||||
<div id="projectname">$projectname <span id="projectnumber">$projectnumber</span> API</div>
|
||||
<div id="projectbrief">$projectbrief</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--END TITLEAREA-->
|
||||
@@ -0,0 +1,112 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title=""/>
|
||||
<tab type="pages" visible="yes" title=""/>
|
||||
<tab type="modules" visible="yes" title=""/>
|
||||
<tab type="namespaces" visible="no" title=""/>
|
||||
<tab type="classes" visible="no" title=""/>
|
||||
<tab type="files" visible="no" title=""/>
|
||||
<tab type="examples" visible="no" title=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription title=""/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
</doxygenlayout>
|
||||
+1399
File diff suppressed because it is too large
Load Diff
-1634
File diff suppressed because it is too large
Load Diff
@@ -1,405 +0,0 @@
|
||||
body, table, div, p, dl {
|
||||
font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* @group Heading Levels */
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
caption {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.qindex, div.navtab{
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
div.qindex, div.navpath {
|
||||
width: 100%;
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
div.navtab {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
/* @group Link Styling */
|
||||
|
||||
a {
|
||||
color: #153788;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contents a:visited {
|
||||
color: #1b77c5;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.qindex {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.qindexHL {
|
||||
font-weight: bold;
|
||||
background-color: #6666cc;
|
||||
color: #ffffff;
|
||||
border: 1px double #9295C2;
|
||||
}
|
||||
|
||||
.contents a.qindexHL:visited {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.el {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.elRef {
|
||||
}
|
||||
|
||||
a.code {
|
||||
}
|
||||
|
||||
a.codeRef {
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
dl.el {
|
||||
margin-left: -1cm;
|
||||
}
|
||||
|
||||
.fragment {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 105%;
|
||||
}
|
||||
|
||||
pre.fragment {
|
||||
border: 1px dotted #CCCCFF;
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
}
|
||||
|
||||
div.ah {
|
||||
background-color: black;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 3px;
|
||||
margin-top: 3px
|
||||
}
|
||||
|
||||
div.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.groupText {
|
||||
margin-left: 16px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
td.indexkey {
|
||||
background-color: #e8eef2;
|
||||
font-weight: bold;
|
||||
border: 1px solid #CCCCCC;
|
||||
margin: 2px 0px 2px 0;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
td.indexvalue {
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #CCCCCC;
|
||||
padding: 2px 10px;
|
||||
margin: 2px 0px;
|
||||
}
|
||||
|
||||
tr.memlist {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
p.formulaDsp {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.formulaDsp {
|
||||
|
||||
}
|
||||
|
||||
img.formulaInl {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* @group Code Colorization */
|
||||
|
||||
span.keyword {
|
||||
color: #008000
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #604020
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #e08000
|
||||
}
|
||||
|
||||
span.comment {
|
||||
color: #800000
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #806020
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color: #002080
|
||||
}
|
||||
|
||||
span.charliteral {
|
||||
color: #008080
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
td.tiny {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
.dirtab {
|
||||
padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #84b0c7;
|
||||
}
|
||||
|
||||
th.dirtab {
|
||||
background: #e8eef2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #666;
|
||||
}
|
||||
|
||||
/* @group Member Descriptions */
|
||||
|
||||
.mdescLeft, .mdescRight,
|
||||
.memItemLeft, .memItemRight,
|
||||
.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
|
||||
background-color: #FFFFFF;
|
||||
border: none;
|
||||
margin: 4px;
|
||||
padding: 1px 0 0 8px;
|
||||
}
|
||||
|
||||
.mdescLeft, .mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.memItemLeft, .memItemRight {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
border-top: 1px solid #CCCCFF;
|
||||
}
|
||||
|
||||
.mdescLeft, .mdescRight {
|
||||
}
|
||||
|
||||
.memTemplParams {
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Member Details */
|
||||
|
||||
/* Styles for detailed member documentation */
|
||||
|
||||
.memtemplate {
|
||||
margin-left: 3px;
|
||||
font-weight: normal;
|
||||
font-size: 80%;
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
.memnav {
|
||||
background-color: #e8eef2;
|
||||
border: 1px solid #84b0c7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.memitem {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.memname {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.memproto, .memdoc {
|
||||
}
|
||||
|
||||
.memproto {
|
||||
padding: 0;
|
||||
background-color: #EEEEFF;
|
||||
border: 1px solid #CCCCFF;
|
||||
}
|
||||
|
||||
.memdoc {
|
||||
padding: 2px 5px;
|
||||
border-left: 1px solid #CCCCFF;
|
||||
border-right: 1px solid #CCCCFF;
|
||||
border-bottom: 1px solid #CCCCFF;
|
||||
}
|
||||
|
||||
.paramkey {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.paramtype {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.paramname {
|
||||
color: #606060;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.paramname em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Directory (tree) */
|
||||
|
||||
/* for the tree view */
|
||||
|
||||
.ftvtree {
|
||||
font-family: sans-serif;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
/* these are for tree view when used as main index */
|
||||
|
||||
.directory {
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.directory h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
/*
|
||||
The following two styles can be used to replace the root node title
|
||||
with an image of your choice. Simply uncomment the next two styles,
|
||||
specify the name of your image and be sure to set 'height' to the
|
||||
proper pixel height of your image.
|
||||
*/
|
||||
|
||||
/*
|
||||
.directory h3.swap {
|
||||
height: 61px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("yourimage.gif");
|
||||
}
|
||||
.directory h3.swap span {
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.directory > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.directory p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.directory div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.directory img {
|
||||
vertical-align: -30%;
|
||||
}
|
||||
|
||||
/* these are for tree view when not used as main index */
|
||||
|
||||
.directory-alt {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.directory-alt h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.directory-alt > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.directory-alt p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.directory-alt div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.directory-alt img {
|
||||
vertical-align: -30%;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
address {
|
||||
font-style: normal;
|
||||
color: #333;
|
||||
}
|
||||
Reference in New Issue
Block a user