mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
Added minimalist unit testing (and removed some apps that did some tests).
This commit is contained in:
@@ -14,6 +14,12 @@ CMake_Minimum_Required(VERSION 2.8.12)
|
||||
# Whether to build static library (default FALSE).
|
||||
# Set(ASMJIT_STATIC FALSE)
|
||||
|
||||
# Whether to build contribution together with AsmJit (default FALSE)
|
||||
# Set(ASMJIT_BUILD_CONTRIB)
|
||||
|
||||
# Whether to build tests (default FALSE).
|
||||
# Set(ASMJIT_BUILD_TEST FALSE)
|
||||
|
||||
# Whether to build samples (default FALSE).
|
||||
# Set(ASMJIT_BUILD_SAMPLES FALSE)
|
||||
|
||||
@@ -73,9 +79,13 @@ Set(ASMJIT_CFLAGS)
|
||||
Set(ASMJIT_CFLAGS_DBG)
|
||||
Set(ASMJIT_CFLAGS_REL)
|
||||
|
||||
Set(ASMJIT_DEFINE "-D")
|
||||
|
||||
# MSVC.
|
||||
If(MSVC)
|
||||
Message("-- Using MSVC")
|
||||
|
||||
Set(ASMJIT_DEFINE "/D")
|
||||
Set(ASMJIT_LFLAGS "/OPT:REF /OPT:ICF")
|
||||
Set(ASMJIT_CFLAGS /GF)
|
||||
Set(ASMJIT_CFLAGS_DBG /DASMJIT_DEBUG /GS /GR-)
|
||||
@@ -86,10 +96,6 @@ If(MSVC)
|
||||
List(APPEND ASMJIT_CFLAGS /D_UNICODE)
|
||||
EndIf()
|
||||
|
||||
If(ASMJIT_STATIC)
|
||||
List(APPEND ASMJIT_CFLAGS /DASMJIT_STATIC)
|
||||
EndIf()
|
||||
|
||||
# Enable multi-process compilation.
|
||||
If(NOT MSVC60 AND NOT MSVC70 AND NOT MSVC71)
|
||||
List(APPEND ASMJIT_CFLAGS /MP)
|
||||
@@ -99,6 +105,7 @@ EndIf()
|
||||
# GCC.
|
||||
If(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
Message("-- Using GCC")
|
||||
|
||||
Set(ASMJIT_CFLAGS
|
||||
-fno-exceptions)
|
||||
Set(ASMJIT_CFLAGS_DBG -DASMJIT_DEBUG -O0
|
||||
@@ -113,10 +120,11 @@ If(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
If(WIN32)
|
||||
List(APPEND ASMJIT_CFLAGS -D_UNICODE)
|
||||
EndIf()
|
||||
EndIf()
|
||||
|
||||
If(ASMJIT_STATIC)
|
||||
List(APPEND ASMJIT_CFLAGS -DASMJIT_STATIC)
|
||||
EndIf()
|
||||
# Static library.
|
||||
If(ASMJIT_STATIC)
|
||||
List(APPEND ASMJIT_CFLAGS "${ASMJIT_DEFINE}ASMJIT_STATIC")
|
||||
EndIf()
|
||||
|
||||
# Dependencies - Base.
|
||||
@@ -171,8 +179,7 @@ Macro(AsmJit_AddLibrary in_name in_src in_deps in_cflags in_cflags_dbg in_cflags
|
||||
Set_Target_Properties(${in_name} PROPERTIES COMPILE_FLAGS ${in_cflags} ${in_cflags_rel})
|
||||
EndIf()
|
||||
Else()
|
||||
Target_Compile_Options(${in_name} PUBLIC
|
||||
${in_cflags}
|
||||
Target_Compile_Options(${in_name} PUBLIC ${in_cflags}
|
||||
$<$<CONFIG:Debug>:${in_cflags_dbg}>
|
||||
$<$<NOT:$<CONFIG:Debug>>:${in_cflags_rel}>)
|
||||
EndIf()
|
||||
@@ -228,6 +235,7 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/base
|
||||
func.h
|
||||
globals.cpp
|
||||
globals.h
|
||||
intutil.cpp
|
||||
intutil.h
|
||||
lock.h
|
||||
logger.cpp
|
||||
@@ -269,10 +277,12 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/x86
|
||||
x86util.h
|
||||
)
|
||||
|
||||
If(ASMJIT_BUILD_CONTRIB)
|
||||
AsmJit_AddSource(ASMJIT_SRC asmjit/contrib
|
||||
winremoteruntime.cpp
|
||||
winremoteruntime.h
|
||||
)
|
||||
EndIf()
|
||||
|
||||
# =============================================================================
|
||||
# [AsmJit - Headers]
|
||||
@@ -305,6 +315,41 @@ If(NOT ASMJIT_EMBED)
|
||||
)
|
||||
EndIf()
|
||||
|
||||
# =============================================================================
|
||||
# [Asmjit - Testing]
|
||||
# =============================================================================
|
||||
|
||||
# AsmJit library is always embedded into the tests executable. This way it's
|
||||
# much easier to test private functions compared to just linking to AsmJit.
|
||||
If(ASMJIT_BUILD_TEST)
|
||||
AsmJit_AddSource(ASMJIT_TEST_SRC asmjit/test
|
||||
main.cpp
|
||||
test.cpp
|
||||
test.h)
|
||||
|
||||
Set(ASMJIT_TEST_CFLAGS
|
||||
${ASMJIT_CFLAGS}
|
||||
${ASMJIT_DEFINE}ASMJIT_STATIC
|
||||
${ASMJIT_DEFINE}ASMJIT_TEST)
|
||||
|
||||
Add_Executable(asmjit_test ${ASMJIT_SRC} ${ASMJIT_TEST_SRC})
|
||||
Target_Link_Libraries(asmjit_test ${ASMJIT_DEPS})
|
||||
|
||||
If(${CMAKE_BUILD_TYPE})
|
||||
If(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
Set_Target_Properties(asmjit_test PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_DBG})
|
||||
Else()
|
||||
Set_Target_Properties(asmjit_test PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_REL})
|
||||
EndIf()
|
||||
Else()
|
||||
Target_Compile_Options(asmjit_test PUBLIC ${ASMJIT_TEST_CFLAGS}
|
||||
$<$<CONFIG:Debug>:${ASMJIT_CFLAGS_DBG}>
|
||||
$<$<NOT:$<CONFIG:Debug>>:${ASMJIT_CFLAGS_REL}>)
|
||||
EndIf()
|
||||
|
||||
Set_Target_Properties(asmjit_test PROPERTIES LINK_FLAGS "${ASMJIT_LFLAGS}")
|
||||
EndIf()
|
||||
|
||||
# =============================================================================
|
||||
# [Asmjit - Samples]
|
||||
# =============================================================================
|
||||
@@ -312,12 +357,7 @@ EndIf()
|
||||
If(ASMJIT_BUILD_SAMPLES)
|
||||
Set(ASMJIT_SRC_SAMPLES
|
||||
benchx86
|
||||
testcpu
|
||||
testdummy
|
||||
testmem
|
||||
testopcode
|
||||
testpool
|
||||
testsizeof
|
||||
testx86
|
||||
)
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include <asmjit/asmjit.h>
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
struct CpuFeature {
|
||||
uint32_t feature;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
static const CpuFeature x86x64Features[] = {
|
||||
{ x86x64::kCpuFeatureMultithreading , "Multithreading" },
|
||||
{ x86x64::kCpuFeatureExecuteDisableBit , "Execute-Disable Bit" },
|
||||
{ x86x64::kCpuFeatureRdtsc , "Rdtsc" },
|
||||
{ x86x64::kCpuFeatureRdtscp , "Rdtscp" },
|
||||
{ x86x64::kCpuFeatureCmov , "Cmov" },
|
||||
{ x86x64::kCpuFeatureCmpXchg8B , "Cmpxchg8b" },
|
||||
{ x86x64::kCpuFeatureCmpXchg16B , "Cmpxchg16b" },
|
||||
{ x86x64::kCpuFeatureClflush , "Clflush" },
|
||||
{ x86x64::kCpuFeaturePrefetch , "Prefetch" },
|
||||
{ x86x64::kCpuFeatureLahfSahf , "Lahf/Sahf" },
|
||||
{ x86x64::kCpuFeatureFxsr , "Fxsave/Fxrstor" },
|
||||
{ x86x64::kCpuFeatureFfxsr , "Fxsave/Fxrstor Opt." },
|
||||
{ x86x64::kCpuFeatureMmx , "Mmx" },
|
||||
{ x86x64::kCpuFeatureMmxExt , "MmxExt" },
|
||||
{ x86x64::kCpuFeature3dNow , "3dnow" },
|
||||
{ x86x64::kCpuFeature3dNowExt , "3dnowExt" },
|
||||
{ x86x64::kCpuFeatureSse , "Sse" },
|
||||
{ x86x64::kCpuFeatureSse2 , "Sse2" },
|
||||
{ x86x64::kCpuFeatureSse3 , "Sse3" },
|
||||
{ x86x64::kCpuFeatureSsse3 , "Ssse3" },
|
||||
{ x86x64::kCpuFeatureSse4A , "Sse4a" },
|
||||
{ x86x64::kCpuFeatureSse41 , "Sse4.1" },
|
||||
{ x86x64::kCpuFeatureSse42 , "Sse4.2" },
|
||||
{ x86x64::kCpuFeatureMsse , "Misaligned SSE" },
|
||||
{ x86x64::kCpuFeatureMonitorMWait , "Monitor/MWait" },
|
||||
{ x86x64::kCpuFeatureMovbe , "Movbe" },
|
||||
{ x86x64::kCpuFeaturePopcnt , "Popcnt" },
|
||||
{ x86x64::kCpuFeatureLzcnt , "Lzcnt" },
|
||||
{ x86x64::kCpuFeatureAesni , "AesNI" },
|
||||
{ x86x64::kCpuFeaturePclmulqdq , "Pclmulqdq" },
|
||||
{ x86x64::kCpuFeatureRdrand , "Rdrand" },
|
||||
{ x86x64::kCpuFeatureAvx , "Avx" },
|
||||
{ x86x64::kCpuFeatureAvx2 , "Avx2" },
|
||||
{ x86x64::kCpuFeatureF16C , "F16C" },
|
||||
{ x86x64::kCpuFeatureFma3 , "Fma3" },
|
||||
{ x86x64::kCpuFeatureFma4 , "Fma4" },
|
||||
{ x86x64::kCpuFeatureXop , "Xop" },
|
||||
{ x86x64::kCpuFeatureBmi , "Bmi" },
|
||||
{ x86x64::kCpuFeatureBmi2 , "Bmi2" },
|
||||
{ x86x64::kCpuFeatureHle , "Hle" },
|
||||
{ x86x64::kCpuFeatureRtm , "Rtm" },
|
||||
{ x86x64::kCpuFeatureFsGsBase , "FsGsBase" },
|
||||
{ x86x64::kCpuFeatureRepMovsbStosbExt , "RepMovsbStosbExt" }
|
||||
};
|
||||
#endif // ASMJIT_HOST || ASMJIT_HOST_X64
|
||||
|
||||
static void printFeatures(const char* prefix, const BaseCpuInfo* cpuInfo, const CpuFeature* data) {
|
||||
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(x86x64Features); i++) {
|
||||
if (cpuInfo->hasFeature(data[i].feature)) {
|
||||
printf("%s%s\n", prefix, data[i].description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
const BaseCpuInfo* cpuInfo_ = BaseCpuInfo::getHost();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Core Features]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
printf("Host CPU\n");
|
||||
printf("========\n");
|
||||
|
||||
printf("\nBasic info\n");
|
||||
printf(" Vendor string : %s\n", cpuInfo_->getVendorString());
|
||||
printf(" Brand string : %s\n", cpuInfo_->getBrandString());
|
||||
printf(" Family : %u\n", cpuInfo_->getFamily());
|
||||
printf(" Model : %u\n", cpuInfo_->getModel());
|
||||
printf(" Stepping : %u\n", cpuInfo_->getStepping());
|
||||
printf(" Cores Count : %u\n", cpuInfo_->getCoresCount());
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [X86 Features]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
const x86x64::CpuInfo* cpuInfo = static_cast<const x86x64::CpuInfo*>(cpuInfo_);
|
||||
|
||||
printf("\nX86/X64 Extended Info:\n");
|
||||
printf(" Processor Type : %u\n", cpuInfo->getProcessorType());
|
||||
printf(" Brand Index : %u\n", cpuInfo->getBrandIndex());
|
||||
printf(" CL Flush Cache Line : %u\n", cpuInfo->getFlushCacheLineSize());
|
||||
printf(" Max logical Processors: %u\n", cpuInfo->getMaxLogicalProcessors());
|
||||
|
||||
printf("\nX86/X64 Features:\n");
|
||||
printFeatures(" ", cpuInfo, x86x64Features);
|
||||
#endif // ASMJIT_HOST || ASMJIT_HOST_X64
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// This file is used as a dummy test. It's changed during development.
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include <asmjit/asmjit.h>
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef int (*MyFunc)(void);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
using namespace asmjit;
|
||||
using namespace asmjit::host;
|
||||
|
||||
JitRuntime runtime;
|
||||
FileLogger logger(stderr);
|
||||
logger.setOption(kLoggerOptionBinaryForm, true);
|
||||
|
||||
Compiler c(&runtime);
|
||||
c.setLogger(&logger);
|
||||
|
||||
c.addFunc(kFuncConvHost, FuncBuilder0<int>());
|
||||
c.endFunc();
|
||||
|
||||
MyFunc func = asmjit_cast<MyFunc>(c.make());
|
||||
func();
|
||||
|
||||
runtime.release((void*)func);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include <asmjit/asmjit.h>
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
static int problems = 0;
|
||||
|
||||
static void gen(void* a, void* b, int i) {
|
||||
int pattern = rand() % 256;
|
||||
*(int *)a = i;
|
||||
*(int *)b = i;
|
||||
::memset((char*)a + sizeof(int), pattern, i - sizeof(int));
|
||||
::memset((char*)b + sizeof(int), pattern, i - sizeof(int));
|
||||
}
|
||||
|
||||
static void verify(void* a, void* b) {
|
||||
int ai = *(int*)a;
|
||||
int bi = *(int*)b;
|
||||
|
||||
if (ai != bi || ::memcmp(a, b, ai) != 0) {
|
||||
printf("Failed to verify %p\n", a);
|
||||
problems++;
|
||||
}
|
||||
}
|
||||
|
||||
static void die() {
|
||||
printf("Couldn't allocate virtual memory, this test needs at least 100MB of free virtual memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
size_t si = (size_t)rand() % count;
|
||||
|
||||
void *ta = a[i];
|
||||
void *tb = b[i];
|
||||
|
||||
a[i] = a[si];
|
||||
b[i] = b[si];
|
||||
|
||||
a[si] = ta;
|
||||
b[si] = tb;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
VMemMgr memmgr;
|
||||
|
||||
size_t i;
|
||||
size_t count = 200000;
|
||||
|
||||
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);
|
||||
if (!a || !b) die();
|
||||
|
||||
srand(100);
|
||||
printf("Allocating virtual memory...");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
if (a[i] == NULL) die();
|
||||
|
||||
::memset(a[i], 0, r);
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
printf("Freeing virtual memory...");
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", b[i]);
|
||||
problems++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
printf("Verified alloc/free test - %d allocations.\n\n", (int)count);
|
||||
|
||||
printf("Alloc...");
|
||||
for (i = 0; i < count; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
b[i] = ::malloc(r);
|
||||
if (a[i] == NULL || b[i] == NULL) die();
|
||||
|
||||
gen(a[i], b[i], r);
|
||||
}
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
printf("Shuffling...");
|
||||
shuffle(a, b, count);
|
||||
printf("Done.\n");
|
||||
|
||||
printf("\n");
|
||||
printf("Verify and free...");
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
verify(a[i], b[i]);
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", a[i]);
|
||||
problems++;
|
||||
}
|
||||
::free(b[i]);
|
||||
}
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
printf("Alloc...");
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
b[i] = ::malloc(r);
|
||||
if (a[i] == NULL || b[i] == NULL) die();
|
||||
|
||||
gen(a[i], b[i], r);
|
||||
}
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
printf("Verify and free...");
|
||||
for (i = 0; i < count; i++) {
|
||||
verify(a[i], b[i]);
|
||||
if (memmgr.release(a[i]) != kErrorOk) {
|
||||
printf("Failed to free %p.\n", a[i]);
|
||||
problems++;
|
||||
}
|
||||
::free(b[i]);
|
||||
}
|
||||
printf("Done.\n");
|
||||
stats(memmgr);
|
||||
|
||||
printf("\n");
|
||||
if (problems)
|
||||
printf("Status: Failure: %d problems found\n", problems);
|
||||
else
|
||||
printf("Status: Success\n");
|
||||
|
||||
::free(a);
|
||||
::free(b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include <asmjit/asmjit.h>
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
// ============================================================================
|
||||
// [EXPECT]
|
||||
// ============================================================================
|
||||
|
||||
static void expectFailed(const char* msg) {
|
||||
printf("Failure: %s\n", msg);
|
||||
abort();
|
||||
}
|
||||
|
||||
#define EXPECT(_Exp_, _Msg_) \
|
||||
do { \
|
||||
if (!(_Exp_)) { \
|
||||
expectFailed(_Msg_); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
// ============================================================================
|
||||
// [Main]
|
||||
// ============================================================================
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
Zone zone(16192);
|
||||
ConstPool pool(&zone);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t kCount = 1000000;
|
||||
|
||||
printf("Adding %u constants to the pool.\n", kCount);
|
||||
{
|
||||
size_t prevOffset;
|
||||
size_t curOffset;
|
||||
uint64_t c = ASMJIT_UINT64_C(0x0101010101010101);
|
||||
|
||||
EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(prevOffset == 0,
|
||||
"pool.add() - First constant should have zero offset.");
|
||||
|
||||
for (i = 1; i < kCount; i++) {
|
||||
c++;
|
||||
EXPECT(pool.add(&c, 8, curOffset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(prevOffset + 8 == curOffset,
|
||||
"pool.add() - Returned incorrect curOffset.");
|
||||
EXPECT(pool.getSize() == (i + 1) * 8,
|
||||
"pool.getSize() - Reports incorrect size.");
|
||||
prevOffset = curOffset;
|
||||
}
|
||||
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Retrieving %u constants from the pool.\n", kCount);
|
||||
{
|
||||
uint64_t c = ASMJIT_UINT64_C(0x0101010101010101);
|
||||
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == i * 8,
|
||||
"pool.add() - Should have reused constant.");
|
||||
c++;
|
||||
}
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Checking if the constants were split into 4-byte patterns.\n");
|
||||
{
|
||||
uint32_t c = 0x01010101;
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 4, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == i * 8,
|
||||
"pool.add() - Should reuse existing constant.");
|
||||
c++;
|
||||
}
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Adding 2 byte constant to misalign the current offset.\n");
|
||||
{
|
||||
uint16_t c = 0xFFFF;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8,
|
||||
"pool.add() - Didn't return expected position.");
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Adding 8 byte constant to check if pool gets aligned again.\n");
|
||||
{
|
||||
uint64_t c = ASMJIT_UINT64_C(0xFFFFFFFFFFFFFFFF);
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8 + 8,
|
||||
"pool.add() - Didn't return aligned offset.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Adding 2 byte constant verify the gap is filled.\n");
|
||||
{
|
||||
uint16_t c = 0xFFFE;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8 + 2,
|
||||
"pool.add() - Didn't fill the gap.");
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Checking reset functionality.\n");
|
||||
{
|
||||
pool.reset();
|
||||
|
||||
EXPECT(pool.getSize() == 0,
|
||||
"pool.getSize() - Expected pool size to be zero.");
|
||||
EXPECT(pool.getAlignment() == 0,
|
||||
"pool.getSize() - Expected pool alignment to be zero.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
printf("Checking pool alignment when combined constants are added.\n");
|
||||
{
|
||||
uint8_t bytes[32] = { 0 };
|
||||
uint64_t c = 0;
|
||||
size_t offset;
|
||||
|
||||
pool.add(bytes, 1, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 1,
|
||||
"pool.getSize() - Expected pool size to be 1 byte.");
|
||||
EXPECT(pool.getAlignment() == 1,
|
||||
"pool.getSize() - Expected pool alignment to be 1 byte.");
|
||||
EXPECT(offset == 0,
|
||||
"pool.getSize() - Expected offset returned to be zero.");
|
||||
|
||||
pool.add(bytes, 2, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 4,
|
||||
"pool.getSize() - Expected pool size to be 4 bytes.");
|
||||
EXPECT(pool.getAlignment() == 2,
|
||||
"pool.getSize() - Expected pool alignment to be 2 bytes.");
|
||||
EXPECT(offset == 2,
|
||||
"pool.getSize() - Expected offset returned to be 2.");
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 8,
|
||||
"pool.getSize() - Expected pool size to be 8 bytes.");
|
||||
EXPECT(pool.getAlignment() == 4,
|
||||
"pool.getSize() - Expected pool alignment to be 4 bytes.");
|
||||
EXPECT(offset == 4,
|
||||
"pool.getSize() - Expected offset returned to be 4.");
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 8,
|
||||
"pool.getSize() - Expected pool size to be 8 bytes.");
|
||||
EXPECT(pool.getAlignment() == 4,
|
||||
"pool.getSize() - Expected pool alignment to be 4 bytes.");
|
||||
EXPECT(offset == 4,
|
||||
"pool.getSize() - Expected offset returned to be 8.");
|
||||
|
||||
pool.add(bytes, 32, offset);
|
||||
EXPECT(pool.getSize() == 64,
|
||||
"pool.getSize() - Expected pool size to be 64 bytes.");
|
||||
EXPECT(pool.getAlignment() == 32,
|
||||
"pool.getSize() - Expected pool alignment to be 32 bytes.");
|
||||
EXPECT(offset == 32,
|
||||
"pool.getSize() - Expected offset returned to be 32.");
|
||||
}
|
||||
printf("Done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include <asmjit/base.h>
|
||||
|
||||
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
|
||||
#include <asmjit/x86.h>
|
||||
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Runtime]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
printf("Sizeof[Runtime]:\n");
|
||||
printf(" int8_t : %u\n", static_cast<uint32_t>(sizeof(int8_t)));
|
||||
printf(" int16_t : %u\n", static_cast<uint32_t>(sizeof(int16_t)));
|
||||
printf(" int32_t : %u\n", static_cast<uint32_t>(sizeof(int32_t)));
|
||||
printf(" int64_t : %u\n", static_cast<uint32_t>(sizeof(int64_t)));
|
||||
printf(" long : %u\n", static_cast<uint32_t>(sizeof(long)));
|
||||
printf(" size_t : %u\n", static_cast<uint32_t>(sizeof(size_t)));
|
||||
printf(" intptr_t : %u\n", static_cast<uint32_t>(sizeof(intptr_t)));
|
||||
printf(" float : %u\n", static_cast<uint32_t>(sizeof(float)));
|
||||
printf(" double : %u\n", static_cast<uint32_t>(sizeof(double)));
|
||||
printf(" void* : %u\n", static_cast<uint32_t>(sizeof(void*)));
|
||||
printf("\n");
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Core]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
printf("Sizeof[Base]:\n");
|
||||
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::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)));
|
||||
printf(" asmjit::BaseVar : %u\n", static_cast<uint32_t>(sizeof(BaseVar)));
|
||||
printf(" asmjit::BaseMem : %u\n", static_cast<uint32_t>(sizeof(BaseMem)));
|
||||
printf(" asmjit::Imm : %u\n", static_cast<uint32_t>(sizeof(Imm)));
|
||||
printf(" asmjit::Label : %u\n", static_cast<uint32_t>(sizeof(Label)));
|
||||
printf("\n");
|
||||
printf(" asmjit::Ptr : %u\n", static_cast<uint32_t>(sizeof(Ptr)));
|
||||
printf(" asmjit::SignedPtr : %u\n", static_cast<uint32_t>(sizeof(SignedPtr)));
|
||||
printf("\n");
|
||||
printf(" asmjit::LabelData : %u\n", static_cast<uint32_t>(sizeof(LabelData)));
|
||||
printf(" asmjit::RelocData : %u\n", static_cast<uint32_t>(sizeof(RelocData)));
|
||||
printf("\n");
|
||||
printf(" asmjit::Node : %u\n", static_cast<uint32_t>(sizeof(Node)));
|
||||
printf(" asmjit::AlignNode : %u\n", static_cast<uint32_t>(sizeof(AlignNode)));
|
||||
printf(" asmjit::CallNode : %u\n", static_cast<uint32_t>(sizeof(CallNode)));
|
||||
printf(" asmjit::CommentNode : %u\n", static_cast<uint32_t>(sizeof(CommentNode)));
|
||||
printf(" asmjit::EmbedNode : %u\n", static_cast<uint32_t>(sizeof(EmbedNode)));
|
||||
printf(" asmjit::FuncNode : %u\n", static_cast<uint32_t>(sizeof(FuncNode)));
|
||||
printf(" asmjit::EndNode : %u\n", static_cast<uint32_t>(sizeof(EndNode)));
|
||||
printf(" asmjit::InstNode : %u\n", static_cast<uint32_t>(sizeof(InstNode)));
|
||||
printf(" asmjit::JumpNode : %u\n", static_cast<uint32_t>(sizeof(JumpNode)));
|
||||
printf(" asmjit::TargetNode : %u\n", static_cast<uint32_t>(sizeof(TargetNode)));
|
||||
printf("\n");
|
||||
printf(" asmjit::FuncDecl : %u\n", static_cast<uint32_t>(sizeof(FuncDecl)));
|
||||
printf(" asmjit::FuncInOut : %u\n", static_cast<uint32_t>(sizeof(FuncInOut)));
|
||||
printf(" asmjit::FuncPrototype : %u\n", static_cast<uint32_t>(sizeof(FuncPrototype)));
|
||||
printf("\n");
|
||||
printf(" asmjit::VarAttr : %u\n", static_cast<uint32_t>(sizeof(VarAttr)));
|
||||
printf(" asmjit::VarData : %u\n", static_cast<uint32_t>(sizeof(VarData)));
|
||||
printf(" asmjit::BaseVarInst : %u\n", static_cast<uint32_t>(sizeof(BaseVarInst)));
|
||||
printf(" asmjit::BaseVarState : %u\n", static_cast<uint32_t>(sizeof(BaseVarState)));
|
||||
printf("\n");
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [X86/X64]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
|
||||
printf("Sizeof[X86/X64]:\n");
|
||||
printf(" asmjit::x86x64::X86X64Assembler: %u\n", static_cast<uint32_t>(sizeof(x86x64::X86X64Assembler)));
|
||||
printf(" asmjit::x86x64::X86X64Compiler : %u\n", static_cast<uint32_t>(sizeof(x86x64::X86X64Compiler)));
|
||||
printf("\n");
|
||||
printf(" asmjit::x86x64::X86X64CallNode : %u\n", static_cast<uint32_t>(sizeof(x86x64::X86X64CallNode)));
|
||||
printf(" asmjit::x86x64::X86X64FuncNode : %u\n", static_cast<uint32_t>(sizeof(x86x64::X86X64FuncNode)));
|
||||
printf("\n");
|
||||
printf(" asmjit::x86x64::X86X64FuncDecl : %u\n", static_cast<uint32_t>(sizeof(x86x64::X86X64FuncDecl)));
|
||||
printf("\n");
|
||||
printf(" asmjit::x86x64::VarInst : %u\n", static_cast<uint32_t>(sizeof(x86x64::VarInst)));
|
||||
printf(" asmjit::x86x64::VarState : %u\n", static_cast<uint32_t>(sizeof(x86x64::VarState)));
|
||||
printf("\n");
|
||||
printf(" asmjit::x86x64::InstInfo : %u\n", static_cast<uint32_t>(sizeof(x86x64::InstInfo)));
|
||||
printf(" asmjit::x86x64::VarInfo : %u\n", static_cast<uint32_t>(sizeof(x86x64::VarInfo)));
|
||||
printf("\n");
|
||||
#endif // ASMJIT_BUILD_X86
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -366,6 +366,171 @@ void ConstPool::fill(void* dst) {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool - Test]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_TEST)
|
||||
UNIT(base_constpool) {
|
||||
Zone zone(16192);
|
||||
ConstPool pool(&zone);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t kCount = 1000000;
|
||||
|
||||
INFO("Adding %u constants to the pool.", kCount);
|
||||
{
|
||||
size_t prevOffset;
|
||||
size_t curOffset;
|
||||
uint64_t c = ASMJIT_UINT64_C(0x0101010101010101);
|
||||
|
||||
EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(prevOffset == 0,
|
||||
"pool.add() - First constant should have zero offset.");
|
||||
|
||||
for (i = 1; i < kCount; i++) {
|
||||
c++;
|
||||
EXPECT(pool.add(&c, 8, curOffset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(prevOffset + 8 == curOffset,
|
||||
"pool.add() - Returned incorrect curOffset.");
|
||||
EXPECT(pool.getSize() == (i + 1) * 8,
|
||||
"pool.getSize() - Reports incorrect size.");
|
||||
prevOffset = curOffset;
|
||||
}
|
||||
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
|
||||
INFO("Retrieving %u constants from the pool.", kCount);
|
||||
{
|
||||
uint64_t c = ASMJIT_UINT64_C(0x0101010101010101);
|
||||
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == i * 8,
|
||||
"pool.add() - Should have reused constant.");
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Checking if the constants were split into 4-byte patterns.");
|
||||
{
|
||||
uint32_t c = 0x01010101;
|
||||
for (i = 0; i < kCount; i++) {
|
||||
size_t offset;
|
||||
EXPECT(pool.add(&c, 4, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == i * 8,
|
||||
"pool.add() - Should reuse existing constant.");
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Adding 2 byte constant to misalign the current offset.");
|
||||
{
|
||||
uint16_t c = 0xFFFF;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8,
|
||||
"pool.add() - Didn't return expected position.");
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
|
||||
INFO("Adding 8 byte constant to check if pool gets aligned again.");
|
||||
{
|
||||
uint64_t c = ASMJIT_UINT64_C(0xFFFFFFFFFFFFFFFF);
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 8, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8 + 8,
|
||||
"pool.add() - Didn't return aligned offset.");
|
||||
}
|
||||
|
||||
INFO("Adding 2 byte constant verify the gap is filled.");
|
||||
{
|
||||
uint16_t c = 0xFFFE;
|
||||
size_t offset;
|
||||
|
||||
EXPECT(pool.add(&c, 2, offset) == kErrorOk,
|
||||
"pool.add() - Returned error.");
|
||||
EXPECT(offset == kCount * 8 + 2,
|
||||
"pool.add() - Didn't fill the gap.");
|
||||
EXPECT(pool.getAlignment() == 8,
|
||||
"pool.getAlignment() - Expected 8-byte alignment.");
|
||||
}
|
||||
|
||||
INFO("Checking reset functionality.");
|
||||
{
|
||||
pool.reset();
|
||||
|
||||
EXPECT(pool.getSize() == 0,
|
||||
"pool.getSize() - Expected pool size to be zero.");
|
||||
EXPECT(pool.getAlignment() == 0,
|
||||
"pool.getSize() - Expected pool alignment to be zero.");
|
||||
}
|
||||
|
||||
INFO("Checking pool alignment when combined constants are added.");
|
||||
{
|
||||
uint8_t bytes[32] = { 0 };
|
||||
uint64_t c = 0;
|
||||
size_t offset;
|
||||
|
||||
pool.add(bytes, 1, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 1,
|
||||
"pool.getSize() - Expected pool size to be 1 byte.");
|
||||
EXPECT(pool.getAlignment() == 1,
|
||||
"pool.getSize() - Expected pool alignment to be 1 byte.");
|
||||
EXPECT(offset == 0,
|
||||
"pool.getSize() - Expected offset returned to be zero.");
|
||||
|
||||
pool.add(bytes, 2, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 4,
|
||||
"pool.getSize() - Expected pool size to be 4 bytes.");
|
||||
EXPECT(pool.getAlignment() == 2,
|
||||
"pool.getSize() - Expected pool alignment to be 2 bytes.");
|
||||
EXPECT(offset == 2,
|
||||
"pool.getSize() - Expected offset returned to be 2.");
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 8,
|
||||
"pool.getSize() - Expected pool size to be 8 bytes.");
|
||||
EXPECT(pool.getAlignment() == 4,
|
||||
"pool.getSize() - Expected pool alignment to be 4 bytes.");
|
||||
EXPECT(offset == 4,
|
||||
"pool.getSize() - Expected offset returned to be 4.");
|
||||
|
||||
pool.add(bytes, 4, offset);
|
||||
|
||||
EXPECT(pool.getSize() == 8,
|
||||
"pool.getSize() - Expected pool size to be 8 bytes.");
|
||||
EXPECT(pool.getAlignment() == 4,
|
||||
"pool.getSize() - Expected pool alignment to be 4 bytes.");
|
||||
EXPECT(offset == 4,
|
||||
"pool.getSize() - Expected offset returned to be 8.");
|
||||
|
||||
pool.add(bytes, 32, offset);
|
||||
EXPECT(pool.getSize() == 64,
|
||||
"pool.getSize() - Expected pool size to be 64 bytes.");
|
||||
EXPECT(pool.getAlignment() == 32,
|
||||
"pool.getSize() - Expected pool alignment to be 32 bytes.");
|
||||
EXPECT(offset == 32,
|
||||
"pool.getSize() - Expected offset returned to be 32.");
|
||||
}
|
||||
}
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
|
||||
@@ -114,9 +114,9 @@ struct ErrorHandler {
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `ErrorHandler`.
|
||||
//! Create a new `ErrorHandler` instance.
|
||||
ASMJIT_API ErrorHandler();
|
||||
//! Destroy the `ErrorHandler`.
|
||||
//! Destroy the `ErrorHandler` instance.
|
||||
ASMJIT_API virtual ~ErrorHandler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -142,17 +142,18 @@ struct ErrorHandler {
|
||||
//!
|
||||
//! Error handler is called when an error happened. An error can happen in
|
||||
//! many places, but error handler is mostly used by `BaseAssembler` and
|
||||
//! `BaseCompiler` classes to report anything that may prevent correct code
|
||||
//! `BaseCompiler` classes to report anything that may cause incorrect code
|
||||
//! generation. There are multiple ways how the error handler can be used
|
||||
//! and each has it's pros/cons.
|
||||
//!
|
||||
//! AsmJit library doesn't use exceptions and can be compiled with or without
|
||||
//! exception feature support. Even if the AsmJit library is compiled without
|
||||
//! exception handling support. Even if the AsmJit library is compiled without
|
||||
//! 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 `BaseAssembler` or `BaseCompiler`. Alternative to throwing
|
||||
//! exception is using setjmp() / longjmp() pair from the standard C library.
|
||||
//! calling AsmJit `BaseAssembler` or `BaseCompiler` methods. Alternative to
|
||||
//! throwing an exception is using `setjmp()` and `longjmp()` pair available
|
||||
//! in the standard C library.
|
||||
//!
|
||||
//! If the exception or setjmp() / longjmp() mechanism is used, the state of
|
||||
//! the `BaseAssember` or `BaseCompiler` is unchanged and if it's possible the
|
||||
@@ -162,13 +163,12 @@ struct ErrorHandler {
|
||||
//! 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 `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).
|
||||
//! Finally, if no exceptions nor setjmp() / longjmp() mechanisms were used,
|
||||
//! you can still implement a compatible handling by returning from your
|
||||
//! error handler. Returning `true` means that error was reported and AsmJit
|
||||
//! should continue execution, but `false` sets the rror 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;
|
||||
};
|
||||
|
||||
|
||||
178
src/asmjit/base/intutil.cpp
Normal file
178
src/asmjit/base/intutil.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Export]
|
||||
#define ASMJIT_EXPORTS
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/intutil.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
#if defined(ASMJIT_TEST)
|
||||
UNIT(base_intutil) {
|
||||
uint32_t i;
|
||||
|
||||
INFO("IntTraits<>.");
|
||||
EXPECT(IntTraits<signed char>::kIsSigned,
|
||||
"IntTraits<signed char> should report signed.");
|
||||
EXPECT(IntTraits<unsigned char>::kIsUnsigned,
|
||||
"IntTraits<unsigned char> should report unsigned.");
|
||||
|
||||
EXPECT(IntTraits<signed short>::kIsSigned,
|
||||
"IntTraits<signed short> should report signed.");
|
||||
EXPECT(IntTraits<unsigned short>::kIsUnsigned,
|
||||
"IntTraits<unsigned short> should report unsigned.");
|
||||
|
||||
EXPECT(IntTraits<int>::kIsSigned,
|
||||
"IntTraits<int> should report signed.");
|
||||
EXPECT(IntTraits<unsigned int>::kIsUnsigned,
|
||||
"IntTraits<unsigned int> should report unsigned.");
|
||||
|
||||
EXPECT(IntTraits<long>::kIsSigned,
|
||||
"IntTraits<long> should report signed.");
|
||||
EXPECT(IntTraits<unsigned long>::kIsUnsigned,
|
||||
"IntTraits<unsigned long> should report unsigned.");
|
||||
|
||||
EXPECT(IntTraits<intptr_t>::kIsSigned,
|
||||
"IntTraits<intptr_t> should report signed.");
|
||||
EXPECT(IntTraits<uintptr_t>::kIsUnsigned,
|
||||
"IntTraits<uintptr_t> should report unsigned.");
|
||||
|
||||
EXPECT(IntTraits<intptr_t>::kIsIntPtr,
|
||||
"IntTraits<intptr_t> should report intptr_t type.");
|
||||
EXPECT(IntTraits<uintptr_t>::kIsIntPtr,
|
||||
"IntTraits<uintptr_t> should report intptr_t type.");
|
||||
|
||||
INFO("IntUtil::iMin()/iMax().");
|
||||
EXPECT(IntUtil::iMin<int>(0, -1) == -1,
|
||||
"IntUtil::iMin<int> should return a minimum value.");
|
||||
EXPECT(IntUtil::iMin<int>(-1, -2) == -2,
|
||||
"IntUtil::iMin<int> should return a minimum value.");
|
||||
EXPECT(IntUtil::iMin<int>(1, 2) == 1,
|
||||
"IntUtil::iMin<int> should return a minimum value.");
|
||||
|
||||
EXPECT(IntUtil::iMax<int>(0, -1) == 0,
|
||||
"IntUtil::iMax<int> should return a maximum value.");
|
||||
EXPECT(IntUtil::iMax<int>(-1, -2) == -1,
|
||||
"IntUtil::iMax<int> should return a maximum value.");
|
||||
EXPECT(IntUtil::iMax<int>(1, 2) == 2,
|
||||
"IntUtil::iMax<int> should return a maximum value.");
|
||||
|
||||
INFO("IntUtil::inInterval().");
|
||||
EXPECT(IntUtil::inInterval<int>(11, 10, 20) == true,
|
||||
"IntUtil::inInterval<int> should return true if inside.");
|
||||
EXPECT(IntUtil::inInterval<int>(101, 10, 20) == false,
|
||||
"IntUtil::inInterval<int> should return false if outside.");
|
||||
|
||||
INFO("IntUtil::isInt?().");
|
||||
EXPECT(IntUtil::isInt8<int>(-128) == true,
|
||||
"IntUtil::isInt8<int> should return true if >= -128.");
|
||||
EXPECT(IntUtil::isInt8<int>(127) == true,
|
||||
"IntUtil::isInt8<int> should return true if <= 127.");
|
||||
EXPECT(IntUtil::isInt8<int>(-129) == false,
|
||||
"IntUtil::isInt8<int> should return false if < -128.");
|
||||
EXPECT(IntUtil::isInt8<int>(128) == false,
|
||||
"IntUtil::isInt8<int> should return false if > 127.");
|
||||
|
||||
EXPECT(IntUtil::isInt16<int>(-32768) == true,
|
||||
"IntUtil::isInt16<int> should return true if >= -32768.");
|
||||
EXPECT(IntUtil::isInt16<int>(32767) == true,
|
||||
"IntUtil::isInt16<int> should return true if <= 32767.");
|
||||
EXPECT(IntUtil::isInt16<int>(-32769) == false,
|
||||
"IntUtil::isInt16<int> should return false if < -32768.");
|
||||
EXPECT(IntUtil::isInt16<int>(32768) == false,
|
||||
"IntUtil::isInt16<int> should return false if > 32767.");
|
||||
|
||||
EXPECT(IntUtil::isInt32(ASMJIT_UINT64_C(0x100000000)) == false,
|
||||
"IntUtil::isInt32<int> should return false if outside.");
|
||||
EXPECT(IntUtil::isInt32(ASMJIT_UINT64_C(0x100000000)) == false,
|
||||
"IntUtil::isInt32<int> should return false if outside.");
|
||||
|
||||
INFO("IntUtil::isPower2().");
|
||||
for (i = 0; i < 64; i++) {
|
||||
EXPECT(IntUtil::isPowerOf2(static_cast<uint64_t>(1) << i) == true,
|
||||
"IntUtil::isPower2() didn't report power of 2.");
|
||||
EXPECT(IntUtil::isPowerOf2((static_cast<uint64_t>(1) << i) ^ 0x001101) == false,
|
||||
"IntUtil::isPower2() didn't report not power of 2.");
|
||||
}
|
||||
|
||||
INFO("IntUtil::mask().");
|
||||
for (i = 0; i < 32; i++) {
|
||||
EXPECT(IntUtil::mask(i) == (1 << i),
|
||||
"IntUtil::mask(%u) should return %X.", i, (1 << i));
|
||||
}
|
||||
|
||||
INFO("IntUtil::bits().");
|
||||
for (i = 0; i < 32; i++) {
|
||||
uint32_t expectedBits = 0;
|
||||
|
||||
for (uint32_t b = 0; b < i; b++)
|
||||
expectedBits |= static_cast<uint32_t>(1) << b;
|
||||
|
||||
EXPECT(IntUtil::bits(i) == expectedBits,
|
||||
"IntUtil::bits(%u) should return %X.", i, expectedBits);
|
||||
}
|
||||
|
||||
INFO("IntUtil::hasBit().");
|
||||
for (i = 0; i < 32; i++) {
|
||||
EXPECT(IntUtil::hasBit((1 << i), i) == true,
|
||||
"IntUtil::hasBit(%X, %u) should return true.", (1 << i), i);
|
||||
}
|
||||
|
||||
INFO("IntUtil::bitCount().");
|
||||
for (i = 0; i < 32; i++) {
|
||||
EXPECT(IntUtil::bitCount((1 << i)) == 1,
|
||||
"IntUtil::bitCount(%X) should return true.", (1 << i));
|
||||
}
|
||||
EXPECT(IntUtil::bitCount(0x000000F0) == 4, "");
|
||||
EXPECT(IntUtil::bitCount(0x10101010) == 4, "");
|
||||
EXPECT(IntUtil::bitCount(0xFF000000) == 8, "");
|
||||
EXPECT(IntUtil::bitCount(0xFFFFFFF7) == 31, "");
|
||||
EXPECT(IntUtil::bitCount(0x7FFFFFFF) == 31, "");
|
||||
|
||||
INFO("IntUtil::findFirstBit().");
|
||||
for (i = 0; i < 32; i++) {
|
||||
EXPECT(IntUtil::findFirstBit((1 << i)) == i,
|
||||
"IntUtil::findFirstBit(%X) should return %u.", (1 << i), i);
|
||||
}
|
||||
|
||||
INFO("IntUtil::isAligned().");
|
||||
EXPECT(IntUtil::isAligned<size_t>(0xFFFF, 4) == false, "");
|
||||
EXPECT(IntUtil::isAligned<size_t>(0xFFF4, 4) == true , "");
|
||||
EXPECT(IntUtil::isAligned<size_t>(0xFFF8, 8) == true , "");
|
||||
EXPECT(IntUtil::isAligned<size_t>(0xFFF0, 16) == true , "");
|
||||
|
||||
INFO("IntUtil::alignTo().");
|
||||
EXPECT(IntUtil::alignTo<size_t>(0xFFFF, 4) == 0x10000, "");
|
||||
EXPECT(IntUtil::alignTo<size_t>(0xFFF4, 4) == 0x0FFF4, "");
|
||||
EXPECT(IntUtil::alignTo<size_t>(0xFFF8, 8) == 0x0FFF8, "");
|
||||
EXPECT(IntUtil::alignTo<size_t>(0xFFF0, 16) == 0x0FFF0, "");
|
||||
EXPECT(IntUtil::alignTo<size_t>(0xFFF0, 32) == 0x10000, "");
|
||||
|
||||
INFO("IntUtil::alignToPowerOf2().");
|
||||
EXPECT(IntUtil::alignToPowerOf2<size_t>(0xFFFF) == 0x10000, "");
|
||||
EXPECT(IntUtil::alignToPowerOf2<size_t>(0xF123) == 0x10000, "");
|
||||
EXPECT(IntUtil::alignToPowerOf2<size_t>(0x0F00) == 0x01000, "");
|
||||
EXPECT(IntUtil::alignToPowerOf2<size_t>(0x0100) == 0x00100, "");
|
||||
EXPECT(IntUtil::alignToPowerOf2<size_t>(0x1001) == 0x02000, "");
|
||||
|
||||
INFO("IntUtil::deltaTo().");
|
||||
EXPECT(IntUtil::deltaTo<size_t>(0xFFFF, 4) == 1, "");
|
||||
EXPECT(IntUtil::deltaTo<size_t>(0xFFF4, 4) == 0, "");
|
||||
EXPECT(IntUtil::deltaTo<size_t>(0xFFF8, 8) == 0, "");
|
||||
EXPECT(IntUtil::deltaTo<size_t>(0xFFF0, 16) == 0, "");
|
||||
EXPECT(IntUtil::deltaTo<size_t>(0xFFF0, 32) == 16, "");
|
||||
}
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
@@ -31,7 +31,7 @@ namespace asmjit {
|
||||
template<typename T>
|
||||
struct IntTraits {
|
||||
enum {
|
||||
kIsSigned = (~static_cast<T>(0)) < static_cast<T>(0),
|
||||
kIsSigned = static_cast<T>(~static_cast<T>(0)) < static_cast<T>(0),
|
||||
kIsUnsigned = !kIsSigned,
|
||||
|
||||
kIs8Bit = sizeof(T) == 1,
|
||||
@@ -402,31 +402,11 @@ struct IntUtil {
|
||||
return (base + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
//! 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;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Round]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T roundUp(T base, T alignment) {
|
||||
T over = base % alignment;
|
||||
return base + (over > 0 ? alignment - over : 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T roundUpToPowerOf2(T base) {
|
||||
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
|
||||
// figure 3-3, page 48, where the function is called clp2.
|
||||
static ASMJIT_INLINE T alignToPowerOf2(T base) {
|
||||
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.
|
||||
base -= 1;
|
||||
|
||||
// I'm trying to make this portable and MSVC strikes me the warning C4293:
|
||||
// "Shift count negative or too big, undefined behavior"
|
||||
// Fixing...
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4293)
|
||||
@@ -448,6 +428,12 @@ struct IntUtil {
|
||||
|
||||
return base + 1;
|
||||
}
|
||||
|
||||
//! 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;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -78,7 +78,7 @@ struct VMemLocal {
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
alignment = info.dwAllocationGranularity;
|
||||
pageSize = IntUtil::roundUpToPowerOf2<uint32_t>(info.dwPageSize);
|
||||
pageSize = IntUtil::alignToPowerOf2<uint32_t>(info.dwPageSize);
|
||||
}
|
||||
|
||||
HANDLE hProcess;
|
||||
@@ -99,27 +99,38 @@ size_t VMemUtil::getPageSize() {
|
||||
return vm().pageSize;
|
||||
}
|
||||
|
||||
void* VMemUtil::alloc(size_t length, size_t* allocated, bool canExecute) {
|
||||
return allocProcessMemory(static_cast<HANDLE>(0), length, allocated, canExecute);
|
||||
void* VMemUtil::alloc(size_t length, size_t* allocated, uint32_t flags) {
|
||||
return allocProcessMemory(static_cast<HANDLE>(0), length, allocated, flags);
|
||||
}
|
||||
|
||||
void VMemUtil::release(void* addr, size_t length) {
|
||||
return releaseProcessMemory(static_cast<HANDLE>(0), addr, length);
|
||||
}
|
||||
|
||||
void* VMemUtil::allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute) {
|
||||
void* VMemUtil::allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, uint32_t flags) {
|
||||
VMemLocal& vmLocal = vm();
|
||||
|
||||
if (hProcess == static_cast<HANDLE>(0))
|
||||
hProcess = vmLocal.hProcess;
|
||||
|
||||
// VirtualAlloc rounds allocated size to a page size automatically.
|
||||
size_t mSize = IntUtil::roundUp(length, vmLocal.pageSize);
|
||||
size_t mSize = IntUtil::alignTo(length, vmLocal.pageSize);
|
||||
|
||||
// Windows XP SP2 / Vista allow Data Excution Prevention (DEP).
|
||||
WORD protect = canExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
LPVOID mBase = VirtualAllocEx(hProcess, NULL, mSize, MEM_COMMIT | MEM_RESERVE, protect);
|
||||
DWORD protectFlags = 0;
|
||||
|
||||
if (flags & kVMemFlagExecutable) {
|
||||
protectFlags |= (flags & kVMemFlagWritable)
|
||||
? PAGE_EXECUTE_READWRITE
|
||||
: PAGE_EXECUTE_READ;
|
||||
}
|
||||
else {
|
||||
protectFlags |= (flags & kVMemFlagWritable)
|
||||
? PAGE_READWRITE
|
||||
: PAGE_READONLY;
|
||||
}
|
||||
|
||||
LPVOID mBase = VirtualAllocEx(hProcess, NULL, mSize, MEM_COMMIT | MEM_RESERVE, protectFlags);
|
||||
if (mBase == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -170,9 +181,12 @@ size_t VMemUtil::getPageSize() {
|
||||
return vm().pageSize;
|
||||
}
|
||||
|
||||
void* VMemUtil::alloc(size_t length, size_t* allocated, bool canExecute) {
|
||||
size_t msize = IntUtil::roundUp<size_t>(length, vm().pageSize);
|
||||
int protection = PROT_READ | PROT_WRITE | (canExecute ? PROT_EXEC : 0);
|
||||
void* VMemUtil::alloc(size_t length, size_t* allocated, uint32_t flags) {
|
||||
size_t msize = IntUtil::alignTo<size_t>(length, vm().pageSize);
|
||||
int protection = PROT_READ;
|
||||
|
||||
if (flags & kVMemFlagWritable ) protection |= PROT_WRITE;
|
||||
if (flags & kVMemFlagExecutable) protection |= PROT_EXEC;
|
||||
|
||||
void* mbase = ::mmap(NULL, msize, protection, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (mbase == MAP_FAILED)
|
||||
@@ -360,10 +374,11 @@ struct VMemPrivate {
|
||||
|
||||
// Helpers to avoid ifdefs in the code.
|
||||
ASMJIT_INLINE uint8_t* allocVirtualMemory(size_t size, size_t* vsize) {
|
||||
uint32_t flags = kVMemFlagWritable | kVMemFlagExecutable;
|
||||
#if !defined(ASMJIT_OS_WINDOWS)
|
||||
return (uint8_t*)VMemUtil::alloc(size, vsize, true);
|
||||
return (uint8_t*)VMemUtil::alloc(size, vsize, flags);
|
||||
#else
|
||||
return (uint8_t*)VMemUtil::allocProcessMemory(_hProcess, size, vsize, true);
|
||||
return (uint8_t*)VMemUtil::allocProcessMemory(_hProcess, size, vsize, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1204,4 +1219,141 @@ Error VMemMgr::shrink(void* address, size_t used) {
|
||||
return d->shrink(address, used);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMem - Test]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_TEST)
|
||||
static void VMemTest_fill(void* a, void* b, int i) {
|
||||
int pattern = rand() % 256;
|
||||
*(int *)a = i;
|
||||
*(int *)b = i;
|
||||
::memset((char*)a + sizeof(int), pattern, i - sizeof(int));
|
||||
::memset((char*)b + sizeof(int), pattern, i - sizeof(int));
|
||||
}
|
||||
|
||||
static void VMemTest_verify(void* a, void* b) {
|
||||
int ai = *(int*)a;
|
||||
int bi = *(int*)b;
|
||||
|
||||
EXPECT(ai == bi,
|
||||
"The length of 'a' (%d) and 'b' (%d) should be same", ai, bi);
|
||||
|
||||
EXPECT(::memcmp(a, b, ai) == 0,
|
||||
"Pattern (%p) doesn't match", a);
|
||||
}
|
||||
|
||||
static void VMemTest_stats(VMemMgr& memmgr) {
|
||||
INFO("Used : %u", static_cast<unsigned int>(memmgr.getUsedBytes()));
|
||||
INFO("Allocated: %u", static_cast<unsigned int>(memmgr.getAllocatedBytes()));
|
||||
}
|
||||
|
||||
static void VMemTest_shuffle(void **a, void **b, size_t count) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
size_t si = (size_t)rand() % count;
|
||||
|
||||
void *ta = a[i];
|
||||
void *tb = b[i];
|
||||
|
||||
a[i] = a[si];
|
||||
b[i] = b[si];
|
||||
|
||||
a[si] = ta;
|
||||
b[si] = tb;
|
||||
}
|
||||
}
|
||||
|
||||
UNIT(base_vmem) {
|
||||
VMemMgr memmgr;
|
||||
|
||||
// Should be predictible.
|
||||
srand(100);
|
||||
|
||||
int i;
|
||||
int kCount = 200000;
|
||||
|
||||
INFO("Memory alloc/free test - %d allocations.", static_cast<int>(kCount));
|
||||
|
||||
void** a = (void**)::malloc(sizeof(void*) * kCount);
|
||||
void** b = (void**)::malloc(sizeof(void*) * kCount);
|
||||
|
||||
EXPECT(a != NULL && b != NULL,
|
||||
"Couldn't allocate %u bytes on heap.", kCount * 2);
|
||||
|
||||
INFO("Allocating virtual memory...");
|
||||
for (i = 0; i < kCount; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
EXPECT(a[i] != NULL,
|
||||
"Couldn't allocate %d bytes of virtual memory", r);
|
||||
::memset(a[i], 0, r);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
INFO("Freeing virtual memory...");
|
||||
for (i = 0; i < kCount; i++) {
|
||||
EXPECT(memmgr.release(a[i]) == kErrorOk,
|
||||
"Failed to free %p.", b[i]);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
INFO("Verified alloc/free test - %d allocations.", static_cast<int>(kCount));
|
||||
for (i = 0; i < kCount; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
EXPECT(a[i] != NULL,
|
||||
"Couldn't allocate %d bytes of virtual memory.", r);
|
||||
|
||||
b[i] = ::malloc(r);
|
||||
EXPECT(b[i] != NULL,
|
||||
"Couldn't allocate %d bytes on heap.", r);
|
||||
|
||||
VMemTest_fill(a[i], b[i], r);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
INFO("Shuffling...");
|
||||
VMemTest_shuffle(a, b, kCount);
|
||||
|
||||
INFO("Verify and free...");
|
||||
for (i = 0; i < kCount / 2; i++) {
|
||||
VMemTest_verify(a[i], b[i]);
|
||||
EXPECT(memmgr.release(a[i]) == kErrorOk,
|
||||
"Failed to free %p.", a[i]);
|
||||
::free(b[i]);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
INFO("Alloc again.");
|
||||
for (i = 0; i < kCount / 2; i++) {
|
||||
int r = (rand() % 1000) + 4;
|
||||
|
||||
a[i] = memmgr.alloc(r);
|
||||
EXPECT(a[i] != NULL,
|
||||
"Couldn't allocate %d bytes of virtual memory.", r);
|
||||
|
||||
b[i] = ::malloc(r);
|
||||
EXPECT(b[i] != NULL,
|
||||
"Couldn't allocate %d bytes on heap.");
|
||||
|
||||
VMemTest_fill(a[i], b[i], r);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
INFO("Verify and free...");
|
||||
for (i = 0; i < kCount; i++) {
|
||||
VMemTest_verify(a[i], b[i]);
|
||||
EXPECT(memmgr.release(a[i]) == kErrorOk,
|
||||
"Failed to free %p.", a[i]);
|
||||
::free(b[i]);
|
||||
}
|
||||
VMemTest_stats(memmgr);
|
||||
|
||||
::free(a);
|
||||
::free(b);
|
||||
}
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
@@ -31,6 +31,18 @@ ASMJIT_ENUM(kVMemAlloc) {
|
||||
kVMemAllocPermanent = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kVMemFlags]
|
||||
// ============================================================================
|
||||
|
||||
//! Type of virtual memory allocation, see `VMemMgr::alloc()`.
|
||||
ASMJIT_ENUM(kVMemFlags) {
|
||||
//! Memory is writable.
|
||||
kVMemFlagWritable = 0x00000001,
|
||||
//! Memory is executable.
|
||||
kVMemFlagExecutable = 0x00000002
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMemUtil]
|
||||
// ============================================================================
|
||||
@@ -58,7 +70,7 @@ struct VMemUtil {
|
||||
//! 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);
|
||||
static ASMJIT_API void* alloc(size_t length, size_t* allocated, uint32_t flags);
|
||||
|
||||
//! Free memory allocated by `alloc()`.
|
||||
static ASMJIT_API void release(void* addr, size_t length);
|
||||
@@ -67,7 +79,7 @@ struct VMemUtil {
|
||||
//! 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);
|
||||
static ASMJIT_API void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, uint32_t flags);
|
||||
|
||||
//! Free virtual memory of `hProcess`.
|
||||
//!
|
||||
@@ -164,7 +176,7 @@ struct VMemMgr {
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Pointer to private data hidden out of the public API.
|
||||
//! Pointer to a private data hidden from the public API.
|
||||
void* _d;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
// [Include]
|
||||
#if !defined(ASMJIT_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#include "./config.h"
|
||||
#endif // !ASMJIT_CONFIG_FILE
|
||||
|
||||
// Turn off deprecation warnings when compiling AsmJit.
|
||||
@@ -303,5 +303,14 @@ typedef unsigned __int64 uint64_t;
|
||||
|
||||
#endif // ASMJIT_OS_WINDOWS && !ASMJIT_SUPRESS_WINDOWS_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Test]
|
||||
// ============================================================================
|
||||
|
||||
// Include test if building for unit testing.
|
||||
#if defined(ASMJIT_TEST)
|
||||
#include "./test/test.h"
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BUILD_H
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
#ifndef _ASMJIT_CONTRIB_WINREMOTERUNTIME_H
|
||||
#define _ASMJIT_CONTRIB_WINREMOTERUNTIME_H
|
||||
|
||||
// [Dependencies]
|
||||
#include "../base.h"
|
||||
|
||||
// [Guard - Windows]
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
|
||||
namespace asmjit {
|
||||
@@ -72,8 +69,6 @@ struct WinRemoteRuntime : public Runtime {
|
||||
} // contrib namespace
|
||||
} // asmjit namespace
|
||||
|
||||
// [Guard - Windows]
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
// [Guard]
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
#endif // _ASMJIT_CONTRIB_WINREMOTERUNTIME_H
|
||||
|
||||
206
src/asmjit/test/main.cpp
Normal file
206
src/asmjit/test/main.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - MiniUnit]
|
||||
#include "./test.h"
|
||||
#include "../asmjit.h"
|
||||
|
||||
using namespace asmjit;
|
||||
|
||||
// ============================================================================
|
||||
// [DumpCpu]
|
||||
// ============================================================================
|
||||
|
||||
struct DumpCpuFeature {
|
||||
uint32_t feature;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static void dumpCpuFeatures(const BaseCpuInfo* cpuInfo, const DumpCpuFeature* data, size_t count) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
if (cpuInfo->hasFeature(data[i].feature))
|
||||
INFO(" %s", data[i].name);
|
||||
}
|
||||
|
||||
static void dumpCpu() {
|
||||
const BaseCpuInfo* cpuInfo_ = BaseCpuInfo::getHost();
|
||||
|
||||
INFO("Host CPU Info:");
|
||||
INFO(" Vendor string : %s", cpuInfo_->getVendorString());
|
||||
INFO(" Brand string : %s", cpuInfo_->getBrandString());
|
||||
INFO(" Family : %u", cpuInfo_->getFamily());
|
||||
INFO(" Model : %u", cpuInfo_->getModel());
|
||||
INFO(" Stepping : %u", cpuInfo_->getStepping());
|
||||
INFO(" Cores Count : %u", cpuInfo_->getCoresCount());
|
||||
INFO("");
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [X86]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
const x86x64::CpuInfo* cpuInfo = static_cast<const x86x64::CpuInfo*>(cpuInfo_);
|
||||
|
||||
static const DumpCpuFeature featuresList[] = {
|
||||
{ x86x64::kCpuFeatureMultithreading , "Multithreading" },
|
||||
{ x86x64::kCpuFeatureExecuteDisableBit , "Execute-Disable Bit" },
|
||||
{ x86x64::kCpuFeatureRdtsc , "Rdtsc" },
|
||||
{ x86x64::kCpuFeatureRdtscp , "Rdtscp" },
|
||||
{ x86x64::kCpuFeatureCmov , "Cmov" },
|
||||
{ x86x64::kCpuFeatureCmpXchg8B , "Cmpxchg8b" },
|
||||
{ x86x64::kCpuFeatureCmpXchg16B , "Cmpxchg16b" },
|
||||
{ x86x64::kCpuFeatureClflush , "Clflush" },
|
||||
{ x86x64::kCpuFeaturePrefetch , "Prefetch" },
|
||||
{ x86x64::kCpuFeatureLahfSahf , "Lahf/Sahf" },
|
||||
{ x86x64::kCpuFeatureFxsr , "Fxsave/Fxrstor" },
|
||||
{ x86x64::kCpuFeatureFfxsr , "Fxsave/Fxrstor Opt." },
|
||||
{ x86x64::kCpuFeatureMmx , "Mmx" },
|
||||
{ x86x64::kCpuFeatureMmxExt , "MmxExt" },
|
||||
{ x86x64::kCpuFeature3dNow , "3dnow" },
|
||||
{ x86x64::kCpuFeature3dNowExt , "3dnowExt" },
|
||||
{ x86x64::kCpuFeatureSse , "Sse" },
|
||||
{ x86x64::kCpuFeatureSse2 , "Sse2" },
|
||||
{ x86x64::kCpuFeatureSse3 , "Sse3" },
|
||||
{ x86x64::kCpuFeatureSsse3 , "Ssse3" },
|
||||
{ x86x64::kCpuFeatureSse4A , "Sse4a" },
|
||||
{ x86x64::kCpuFeatureSse41 , "Sse4.1" },
|
||||
{ x86x64::kCpuFeatureSse42 , "Sse4.2" },
|
||||
{ x86x64::kCpuFeatureMsse , "Misaligned SSE" },
|
||||
{ x86x64::kCpuFeatureMonitorMWait , "Monitor/MWait" },
|
||||
{ x86x64::kCpuFeatureMovbe , "Movbe" },
|
||||
{ x86x64::kCpuFeaturePopcnt , "Popcnt" },
|
||||
{ x86x64::kCpuFeatureLzcnt , "Lzcnt" },
|
||||
{ x86x64::kCpuFeatureAesni , "AesNI" },
|
||||
{ x86x64::kCpuFeaturePclmulqdq , "Pclmulqdq" },
|
||||
{ x86x64::kCpuFeatureRdrand , "Rdrand" },
|
||||
{ x86x64::kCpuFeatureAvx , "Avx" },
|
||||
{ x86x64::kCpuFeatureAvx2 , "Avx2" },
|
||||
{ x86x64::kCpuFeatureF16C , "F16C" },
|
||||
{ x86x64::kCpuFeatureFma3 , "Fma3" },
|
||||
{ x86x64::kCpuFeatureFma4 , "Fma4" },
|
||||
{ x86x64::kCpuFeatureXop , "Xop" },
|
||||
{ x86x64::kCpuFeatureBmi , "Bmi" },
|
||||
{ x86x64::kCpuFeatureBmi2 , "Bmi2" },
|
||||
{ x86x64::kCpuFeatureHle , "Hle" },
|
||||
{ x86x64::kCpuFeatureRtm , "Rtm" },
|
||||
{ x86x64::kCpuFeatureFsGsBase , "FsGsBase" },
|
||||
{ x86x64::kCpuFeatureRepMovsbStosbExt , "RepMovsbStosbExt" }
|
||||
};
|
||||
|
||||
INFO("Host CPU Info (X86/X64):");
|
||||
INFO(" Processor Type : %u", cpuInfo->getProcessorType());
|
||||
INFO(" Brand Index : %u", cpuInfo->getBrandIndex());
|
||||
INFO(" CL Flush Cache Line : %u", cpuInfo->getFlushCacheLineSize());
|
||||
INFO(" Max logical Processors: %u", cpuInfo->getMaxLogicalProcessors());
|
||||
INFO("");
|
||||
|
||||
INFO("Host CPU Features (X86/X64):");
|
||||
dumpCpuFeatures(cpuInfo, featuresList, ASMJIT_ARRAY_SIZE(featuresList));
|
||||
INFO("");
|
||||
#endif // ASMJIT_HOST || ASMJIT_HOST_X64
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [DumpSizeOf]
|
||||
// ============================================================================
|
||||
|
||||
#define DUMP_SIZE(_Type_) \
|
||||
INFO(" %-31s: %u", #_Type_, static_cast<uint32_t>(sizeof(_Type_)))
|
||||
|
||||
static void dumpSizeOf() {
|
||||
INFO("SizeOf Types:");
|
||||
DUMP_SIZE(int8_t);
|
||||
DUMP_SIZE(int16_t);
|
||||
DUMP_SIZE(int32_t);
|
||||
DUMP_SIZE(int64_t);
|
||||
DUMP_SIZE(int);
|
||||
DUMP_SIZE(long);
|
||||
DUMP_SIZE(size_t);
|
||||
DUMP_SIZE(intptr_t);
|
||||
DUMP_SIZE(float);
|
||||
DUMP_SIZE(double);
|
||||
DUMP_SIZE(void*);
|
||||
DUMP_SIZE(asmjit::Ptr);
|
||||
DUMP_SIZE(asmjit::SignedPtr);
|
||||
INFO("");
|
||||
|
||||
INFO("SizeOf Base:");
|
||||
DUMP_SIZE(asmjit::CodeGen);
|
||||
DUMP_SIZE(asmjit::ConstPool);
|
||||
DUMP_SIZE(asmjit::Logger);
|
||||
DUMP_SIZE(asmjit::Runtime);
|
||||
DUMP_SIZE(asmjit::Zone);
|
||||
INFO("");
|
||||
|
||||
INFO("SizeOf Operand:");
|
||||
DUMP_SIZE(asmjit::Operand);
|
||||
DUMP_SIZE(asmjit::BaseReg);
|
||||
DUMP_SIZE(asmjit::BaseVar);
|
||||
DUMP_SIZE(asmjit::BaseMem);
|
||||
DUMP_SIZE(asmjit::Imm);
|
||||
DUMP_SIZE(asmjit::Label);
|
||||
INFO("");
|
||||
|
||||
INFO("SizeOf Assembler:");
|
||||
DUMP_SIZE(asmjit::BaseAssembler);
|
||||
DUMP_SIZE(asmjit::LabelData);
|
||||
DUMP_SIZE(asmjit::RelocData);
|
||||
INFO("");
|
||||
|
||||
INFO("SizeOf Compiler:");
|
||||
DUMP_SIZE(asmjit::BaseCompiler);
|
||||
DUMP_SIZE(asmjit::Node);
|
||||
DUMP_SIZE(asmjit::AlignNode);
|
||||
DUMP_SIZE(asmjit::CallNode);
|
||||
DUMP_SIZE(asmjit::CommentNode);
|
||||
DUMP_SIZE(asmjit::EmbedNode);
|
||||
DUMP_SIZE(asmjit::FuncNode);
|
||||
DUMP_SIZE(asmjit::EndNode);
|
||||
DUMP_SIZE(asmjit::InstNode);
|
||||
DUMP_SIZE(asmjit::JumpNode);
|
||||
DUMP_SIZE(asmjit::TargetNode);
|
||||
DUMP_SIZE(asmjit::FuncDecl);
|
||||
DUMP_SIZE(asmjit::FuncInOut);
|
||||
DUMP_SIZE(asmjit::FuncPrototype);
|
||||
DUMP_SIZE(asmjit::VarAttr);
|
||||
DUMP_SIZE(asmjit::VarData);
|
||||
DUMP_SIZE(asmjit::BaseVarInst);
|
||||
DUMP_SIZE(asmjit::BaseVarState);
|
||||
INFO("");
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [X86/X64]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
|
||||
INFO("SizeOf X86/X64:");
|
||||
DUMP_SIZE(asmjit::x86x64::X86X64Assembler);
|
||||
DUMP_SIZE(asmjit::x86x64::X86X64Compiler);
|
||||
DUMP_SIZE(asmjit::x86x64::X86X64CallNode);
|
||||
DUMP_SIZE(asmjit::x86x64::X86X64FuncNode);
|
||||
DUMP_SIZE(asmjit::x86x64::X86X64FuncDecl);
|
||||
DUMP_SIZE(asmjit::x86x64::VarInst);
|
||||
DUMP_SIZE(asmjit::x86x64::VarState);
|
||||
DUMP_SIZE(asmjit::x86x64::InstInfo);
|
||||
DUMP_SIZE(asmjit::x86x64::VarInfo);
|
||||
INFO("");
|
||||
#endif // ASMJIT_BUILD_X86
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [Main]
|
||||
// ============================================================================
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (MiniUnit::init(argc, argv)) {
|
||||
dumpCpu();
|
||||
dumpSizeOf();
|
||||
|
||||
MiniUnit::run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
112
src/asmjit/test/test.cpp
Normal file
112
src/asmjit/test/test.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Dependencies - MiniUnit]
|
||||
#include "./test.h"
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit - Statics]
|
||||
// ============================================================================
|
||||
|
||||
int MiniUnit::argc;
|
||||
const char** MiniUnit::argv;
|
||||
FILE* MiniUnit::outFile;
|
||||
|
||||
MiniUnit::Unit* MiniUnit::unitList;
|
||||
MiniUnit::Unit* MiniUnit::unitRunning;
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit - Init]
|
||||
// ============================================================================
|
||||
|
||||
bool MiniUnit::init(int argc, const char* argv[]) {
|
||||
MiniUnit::argc = argc;
|
||||
MiniUnit::argv = argv;
|
||||
MiniUnit::outFile = stdout;
|
||||
|
||||
return unitList != NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit - Add]
|
||||
// ============================================================================
|
||||
|
||||
void MiniUnit::addUnit(Unit* unit) {
|
||||
Unit** pPrev = &unitList;
|
||||
Unit* current = *pPrev;
|
||||
|
||||
while (current != NULL) {
|
||||
if (::strcmp(current->name, unit->name) >= 0)
|
||||
break;
|
||||
|
||||
pPrev = ¤t->next;
|
||||
current = *pPrev;
|
||||
}
|
||||
|
||||
*pPrev = unit;
|
||||
unit->next = current;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit - Run]
|
||||
// ============================================================================
|
||||
|
||||
void MiniUnit::run() {
|
||||
MiniUnit::Unit* unit = unitList;
|
||||
while (unit != NULL) {
|
||||
runUnit(unit);
|
||||
unit = unit->next;
|
||||
}
|
||||
}
|
||||
|
||||
void MiniUnit::runUnit(Unit* unit) {
|
||||
info("[Unit] %s", unit->name);
|
||||
unitRunning = unit;
|
||||
unit->entry();
|
||||
unitRunning = NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit - Info]
|
||||
// ============================================================================
|
||||
|
||||
void MiniUnit::info(const char* fmt, ...) {
|
||||
const char* prefix = unitRunning ? " " : "";
|
||||
size_t len = ::strlen(fmt);
|
||||
|
||||
if (len != 0) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
::fputs(prefix, outFile);
|
||||
::vfprintf(outFile, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if (len == 0 || fmt[len - 1] != '\n')
|
||||
::fputs("\n", outFile);
|
||||
|
||||
::fflush(outFile);
|
||||
}
|
||||
|
||||
void MiniUnit::fail(const char* file, int line, const char* fmt, ...) {
|
||||
size_t len = ::strlen(fmt);
|
||||
|
||||
if (len != 0) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
::fputs("[Fail] ", outFile);
|
||||
::vfprintf(outFile, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if (len > 0 && fmt[len - 1] != '\n')
|
||||
::fputs("\n", outFile);
|
||||
|
||||
::fprintf(outFile, "[File] %s (Line: %d)\n", file, line);
|
||||
|
||||
::fflush(outFile);
|
||||
::exit(1);
|
||||
}
|
||||
99
src/asmjit/test/test.h
Normal file
99
src/asmjit/test/test.h
Normal file
@@ -0,0 +1,99 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef MINIUNIT_H
|
||||
#define MINIUNIT_H
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//! \internal
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [MiniUnit]
|
||||
// ============================================================================
|
||||
|
||||
//! Define a unit.
|
||||
//!
|
||||
//! `_Name_` can only contain ASCII characters, numbers and underscore.
|
||||
#define UNIT(_Name_) \
|
||||
static void unit_##_Name_##_entry(void); \
|
||||
static ::MiniUnit::AutoUnit unit_##_Name_##_autoinit(#_Name_, unit_##_Name_##_entry); \
|
||||
static void unit_##_Name_##_entry(void)
|
||||
|
||||
//! Informative message printed to stdout.
|
||||
#define INFO(...) \
|
||||
::MiniUnit::info(__VA_ARGS__)
|
||||
|
||||
//! Expect `_Exp_` to be truthy, fail otherwise.
|
||||
#define EXPECT(_Exp_, ...) \
|
||||
do { \
|
||||
if (!(_Exp_)) ::MiniUnit::fail(__FILE__, __LINE__, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
struct MiniUnit {
|
||||
//! Test entry point.
|
||||
typedef void (*Entry)(void);
|
||||
|
||||
//! Test unit.
|
||||
struct Unit {
|
||||
const char* name;
|
||||
Entry entry;
|
||||
size_t finished;
|
||||
Unit* next;
|
||||
};
|
||||
|
||||
//! Automatic unit registration by using static initialization.
|
||||
struct AutoUnit : Unit {
|
||||
inline AutoUnit(const char* _name, Entry _entry) {
|
||||
name = _name;
|
||||
entry = _entry;
|
||||
finished = false;
|
||||
next = NULL;
|
||||
|
||||
MiniUnit::addUnit(this);
|
||||
}
|
||||
};
|
||||
|
||||
//! Test arguments count.
|
||||
static int argc;
|
||||
//! Test arguments list.
|
||||
static const char** argv;
|
||||
//! File where to log.
|
||||
static FILE* outFile;
|
||||
//! Test unit list.
|
||||
static Unit* unitList;
|
||||
//! Running test reference.
|
||||
static Unit* unitRunning;
|
||||
|
||||
//! Initialize MiniUnit framework.
|
||||
//!
|
||||
//! Returns `true` if `run()` should be called.
|
||||
static bool init(int argc, const char* argv[]);
|
||||
|
||||
//! Register a new test.
|
||||
static void addUnit(Unit* unit);
|
||||
|
||||
//! Run all units.
|
||||
static void run();
|
||||
//! Run a single unit.
|
||||
static void runUnit(Unit* unit);
|
||||
|
||||
//! Log message, adds automatically new line if not present.
|
||||
static void info(const char* fmt, ...);
|
||||
//! Called on `EXPECT()` failure.
|
||||
static void fail(const char* file, int line, const char* fmt, ...);
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
// [Guard]
|
||||
#endif // MINIUNIT_H
|
||||
@@ -309,8 +309,8 @@ const char _instName[] =
|
||||
"minsd\0"
|
||||
"minss\0"
|
||||
"monitor\0"
|
||||
"mov_ptr\0"
|
||||
"mov\0"
|
||||
"mov_ptr\0"
|
||||
"movapd\0"
|
||||
"movaps\0"
|
||||
"movbe\0"
|
||||
@@ -1376,8 +1376,8 @@ enum kInstData_NameIndex {
|
||||
kInstMinsd_NameIndex = 1746,
|
||||
kInstMinss_NameIndex = 1752,
|
||||
kInstMonitor_NameIndex = 1758,
|
||||
kInstMovPtr_NameIndex = 1766,
|
||||
kInstMov_NameIndex = 1774,
|
||||
kInstMov_NameIndex = 1766,
|
||||
kInstMovPtr_NameIndex = 1770,
|
||||
kInstMovapd_NameIndex = 1778,
|
||||
kInstMovaps_NameIndex = 1785,
|
||||
kInstMovbe_NameIndex = 1792,
|
||||
@@ -2452,8 +2452,8 @@ const InstInfo _instInfo[] = {
|
||||
INST(kInstMinsd , "minsd" , G(ExtRm) , F(None) , 0 , O(Xmm) , O(XmmMem) , U , U , O_F20F00(5D,U) , U ),
|
||||
INST(kInstMinss , "minss" , G(ExtRm) , F(None) , 0 , O(Xmm) , O(XmmMem) , U , U , O_F30F00(5D,U) , U ),
|
||||
INST(kInstMonitor , "monitor" , G(X86Op) , F(None)|F(Special) , 0 , U , U , U , U , O_000F01(C8,U) , U ),
|
||||
INST(kInstMovPtr , "mov_ptr" , G(X86MovPtr) , F(Move)|F(Special) , 0 , O(Gqdwb) , O(Imm) , U , U , O_000000(A0,U) , O_000000(A2,U) ),
|
||||
INST(kInstMov , "mov" , G(X86Mov) , F(Move) , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm) , U , U , U , U ),
|
||||
INST(kInstMovPtr , "mov_ptr" , G(X86MovPtr) , F(Move)|F(Special) , 0 , O(Gqdwb) , O(Imm) , U , U , O_000000(A0,U) , O_000000(A2,U) ),
|
||||
INST(kInstMovapd , "movapd" , G(ExtMov) , F(Move) , 16, O(XmmMem) , O(XmmMem) , U , U , O_660F00(28,U) , O_660F00(29,U) ),
|
||||
INST(kInstMovaps , "movaps" , G(ExtMov) , F(Move) , 16, O(XmmMem) , O(XmmMem) , U , U , O_000F00(28,U) , O_000F00(29,U) ),
|
||||
INST(kInstMovbe , "movbe" , G(ExtMovBe) , F(Move) , 0 , O(GqdwMem) , O(GqdwMem) , U , U , O_000F38(F0,U) , O_000F38(F1,U) ),
|
||||
@@ -3324,6 +3324,37 @@ uint32_t X86InstUtil::getInstIdByName(const char* name, size_t len) {
|
||||
return kInstNone;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::x86x64::X86Util - Test]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_TEST)
|
||||
UNIT(x86_inst_name) {
|
||||
// All known instructions should be matched.
|
||||
for (uint32_t a = 0; a < _kInstCount; a++) {
|
||||
uint32_t b = X86InstUtil::getInstIdByName(_instInfo[a].getName());
|
||||
|
||||
EXPECT(a == b,
|
||||
"Should match existing instruction \"%s\" {id:%u} != \"%s\" {id:%u}.",
|
||||
_instInfo[a].getName(), a,
|
||||
_instInfo[b].getName(), b);
|
||||
}
|
||||
|
||||
// Everything else should return kInstNone
|
||||
EXPECT(X86InstUtil::getInstIdByName(NULL) == kInstNone,
|
||||
"Should return kInstNone for NULL input.");
|
||||
|
||||
EXPECT(X86InstUtil::getInstIdByName("") == kInstNone,
|
||||
"Should return kInstNone for empty string.");
|
||||
|
||||
EXPECT(X86InstUtil::getInstIdByName("_") == kInstNone,
|
||||
"Should return kInstNone for unknown instruction.");
|
||||
|
||||
EXPECT(X86InstUtil::getInstIdByName("123xyz") == kInstNone,
|
||||
"Should return kInstNone for unknown instruction.");
|
||||
}
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
} // x86x64 namespace
|
||||
} // asmjit namespace
|
||||
|
||||
|
||||
@@ -334,8 +334,8 @@ ASMJIT_ENUM(kInstCode) {
|
||||
kInstMinsd, // SSE2
|
||||
kInstMinss, // SSE
|
||||
kInstMonitor, // SSE3
|
||||
kInstMovPtr, // X86/X64
|
||||
kInstMov, // X86/X64
|
||||
kInstMovPtr, // X86/X64
|
||||
kInstMovapd, // SSE2
|
||||
kInstMovaps, // SSE
|
||||
kInstMovbe, // SSE3 - Intel-Atom
|
||||
|
||||
@@ -159,7 +159,7 @@ ASMJIT_ENUM(kRegIndex) {
|
||||
|
||||
//! X86/X64 segment codes.
|
||||
ASMJIT_ENUM(kSeg) {
|
||||
//! No segment.
|
||||
//! No/Default segment.
|
||||
kSegDefault = 0,
|
||||
//! Es segment.
|
||||
kSegEs = 1,
|
||||
|
||||
@@ -5,5 +5,5 @@ ASMJIT_BUILD_DIR="build_xcode"
|
||||
|
||||
mkdir ../${ASMJIT_BUILD_DIR}
|
||||
cd ../${ASMJIT_BUILD_DIR}
|
||||
cmake .. -G"Xcode" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Xcode" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd ${ASMJIT_CURRENT_DIR}
|
||||
|
||||
@@ -5,5 +5,5 @@ ASMJIT_BUILD_DIR="build_makefiles_dbg"
|
||||
|
||||
mkdir ../${ASMJIT_BUILD_DIR}
|
||||
cd ../${ASMJIT_BUILD_DIR}
|
||||
cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd ${ASMJIT_CURRENT_DIR}
|
||||
|
||||
@@ -5,5 +5,5 @@ ASMJIT_BUILD_DIR="build_makefiles_rel"
|
||||
|
||||
mkdir ../${ASMJIT_BUILD_DIR}
|
||||
cd ../${ASMJIT_BUILD_DIR}
|
||||
cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd ${ASMJIT_CURRENT_DIR}
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_mingw_dbg"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_mingw_rel"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2005_x64"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 8 2005 Win64" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 8 2005 Win64" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2005_x86"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 8 2005" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 8 2005" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2008_x64"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 9 2008 Win64" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 9 2008 Win64" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2008_x86"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 9 2008" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 9 2008" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2010_x64"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 10 Win64" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 10 Win64" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2010_x86"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 10" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 10" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2013_x64"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 12 Win64" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 12 Win64" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
@@ -5,5 +5,5 @@ set ASMJIT_BUILD_DIR="build_vs2013_x86"
|
||||
|
||||
mkdir ..\%ASMJIT_BUILD_DIR%
|
||||
cd ..\%ASMJIT_BUILD_DIR%
|
||||
cmake .. -G"Visual Studio 12" -DASMJIT_BUILD_SAMPLES=1
|
||||
cmake .. -G"Visual Studio 12" -DASMJIT_BUILD_TEST=1 -DASMJIT_BUILD_SAMPLES=1
|
||||
cd %ASMJIT_CURRENT_DIR%
|
||||
|
||||
Reference in New Issue
Block a user