mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-09 04:09:46 -10:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6e9fae178 | ||
|
|
7042a1ae30 | ||
|
|
7d277cc1ec | ||
|
|
1ac0465a03 | ||
|
|
3533db97ff | ||
|
|
7888cae6c7 | ||
|
|
b021beba6a | ||
|
|
684d67d12e | ||
|
|
8d7683b851 | ||
|
|
e7290d78d5 | ||
|
|
4f0e98ade5 | ||
|
|
39dbfd9fd8 | ||
|
|
2d18558dc5 | ||
|
|
5fb9397521 | ||
|
|
f85e24dff8 | ||
|
|
2ea272fcd6 | ||
|
|
d3e85b439b | ||
|
|
ea837908b6 | ||
|
|
a1573835dd | ||
|
|
34355d6b0c | ||
|
|
9557e4711f | ||
|
|
6a1b9e050a | ||
|
|
6675b43dd0 | ||
|
|
79d7e9f8eb | ||
|
|
f5c9439f91 | ||
|
|
f73e4193f0 |
No files matched your search
@@ -0,0 +1,83 @@
|
||||
### Auto build Box64 and release its binary with Github Action
|
||||
name: Build and Release Box64
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
push:
|
||||
paths:
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- "**/*.S"
|
||||
- "**/*.py"
|
||||
- "CMakeList.txt"
|
||||
- "**/*.yml"
|
||||
pull_request:
|
||||
types: [assigned, opened, synchronize, reopened]
|
||||
paths:
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- "**/*.S"
|
||||
- "**/*.py"
|
||||
- "CMakeList.txt"
|
||||
- "**/*.yml"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [X64, OTHER_ARM, RPI4ARM64, RK3326, RK3399, RK3288, TEGRAX1, PHYTIUM, SD845]
|
||||
type: [Release, Trace]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout Box64 Repository"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: "Environment preparation"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
|
||||
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
|
||||
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
|
||||
else
|
||||
if [[ ${{ matrix.platform }} == 'X64' ]]; then
|
||||
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
|
||||
echo "BOX64_COMPILER=gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git cmake make python3
|
||||
ls /bin/*gcc*
|
||||
else
|
||||
echo BOX64_PLATFORM_MARCRO="-DARM_DYNAREC=ON" >> $GITHUB_ENV
|
||||
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
|
||||
fi
|
||||
fi
|
||||
if [[ ${{ matrix.type }} == 'Release' ]]; then
|
||||
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
|
||||
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
|
||||
else
|
||||
echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
|
||||
echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: "Display Build info"
|
||||
run: |
|
||||
echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}"
|
||||
echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}"
|
||||
echo "Build type: ${{ env.BOX64_BUILD_TYPE }}"
|
||||
echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}"
|
||||
|
||||
- name: "Build Box64"
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX64_COMPILER }} ${{ env.BOX64_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
|
||||
make -j$(nproc) VERBOSE=1
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: box86-${{ matrix.platform }}-${{ matrix.type }}
|
||||
path: build/box64
|
||||
@@ -340,6 +340,9 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxslt.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldapr.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlber.c"
|
||||
)
|
||||
|
||||
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
Current Version
|
||||
v0.1.6
|
||||
======
|
||||
* Introduce "HotPage", to temporarily disable Dynarec on a page were writing is also occuring (can help speed up C# code)
|
||||
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
|
||||
* Introduce BOX64_DYNAREC_STRONGMEM for the (Arm) dynarec to emulate StrngMemory Model (needed by some games, like RimWorld)
|
||||
* More functions wrapped
|
||||
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
|
||||
* Added a workaround for streamwebhelper to not load it
|
||||
|
||||
@@ -115,6 +115,17 @@ Enables/Disables trace for generated code.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX64_DYNAREC_BIGBLOCK
|
||||
Enables/Disables Box64's Dynarec building BigBlock.
|
||||
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 1 : Build Dynarec block as big as possible (Default.)
|
||||
|
||||
#### BOX64_DYNAREC_STRONGMEM
|
||||
Enable/Disable simulation of Strong Memory model
|
||||
* 0 : Don't try anything special (Default.)
|
||||
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
|
||||
|
||||
#### BOX64_LIBGL
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
|
||||
+7
-7
@@ -270,6 +270,13 @@ void FreeBox64Context(box64context_t** context)
|
||||
if(ctx->tlsdata)
|
||||
free(ctx->tlsdata);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
if(ctx->emu_sig)
|
||||
FreeX64Emu(&ctx->emu_sig);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
@@ -282,13 +289,6 @@ void FreeBox64Context(box64context_t** context)
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
if(ctx->emu_sig)
|
||||
FreeX64Emu(&ctx->emu_sig);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 1
|
||||
#define BOX64_REVISION 5
|
||||
#define BOX64_REVISION 6
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+175
-182
@@ -31,7 +31,6 @@
|
||||
// init inside dynablocks.c
|
||||
KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
|
||||
static pthread_mutex_t mutex_mmap;
|
||||
static mmaplist_t *mmaplist = NULL;
|
||||
static size_t mmapsize = 0;
|
||||
static size_t mmapcap = 0;
|
||||
@@ -41,12 +40,12 @@ static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
|
||||
static uintptr_t* box64_jmptbldefault1[1<<JMPTABL_SHIFT];
|
||||
static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT];
|
||||
#endif
|
||||
#define MEMPROT_SHIFT 12
|
||||
#define MEMPROT_SHIFT2 (32-MEMPROT_SHIFT)
|
||||
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
|
||||
static pthread_mutex_t mutex_prot;
|
||||
KHASH_MAP_INIT_INT(memprot, uint8_t*)
|
||||
static kh_memprot_t *memprot;
|
||||
#define MEMPROT_SHIFT 12
|
||||
#define MEMPROT_SHIFT2 (16+12)
|
||||
#define MEMPROT_SIZE (1<<16)
|
||||
static uint8_t *volatile memprot[1<<20]; // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection]
|
||||
static uint8_t memprot_default[MEMPROT_SIZE];
|
||||
static int inited = 0;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
@@ -497,11 +496,9 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
if(!size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -509,7 +506,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
#else
|
||||
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -524,18 +520,14 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
|
||||
uintptr_t ret = FindFreeDynarecMap(db, size);
|
||||
if(!ret)
|
||||
ret = AddNewDynarecMap(db, size);
|
||||
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -544,7 +536,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
if(!addr || !size)
|
||||
return;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
#else
|
||||
@@ -556,12 +547,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
ActuallyFreeDynarecMap(db, addr, size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
}
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx)
|
||||
@@ -760,44 +748,35 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
}
|
||||
|
||||
// Remove the Write flag from an adress range, so DB can be executed safely
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
void protectDB(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
int ret;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
|
||||
if(memprot[i]==memprot_default) {
|
||||
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
|
||||
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
|
||||
free(newblock);
|
||||
}*/
|
||||
memprot[i] = newblock;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i>>16][i&0xffff];
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
|
||||
if((prot&PROT_WRITE)) {
|
||||
prot&=~PROT_WRITE;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
|
||||
memprot[i>>16][i&0xffff] = prot|PROT_DYNAREC; // need to use atomic exchange?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void protectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
protectDBnolock(addr, size);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void lockDB()
|
||||
{
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
}
|
||||
|
||||
void unlockDB()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
@@ -807,90 +786,109 @@ void unprotectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
|
||||
if(memprot[i]==memprot_default) {
|
||||
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
|
||||
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
|
||||
free(newblock);
|
||||
}*/
|
||||
memprot[i] = newblock;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i>>16][i&0xffff];
|
||||
if(prot&PROT_DYNAREC) {
|
||||
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
prot&=~PROT_DYNAREC;
|
||||
prot|=PROT_WRITE;
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
|
||||
memprot[i>>16][i&0xffff] = prot; // need to use atomic exchange?
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
int isprotectedDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1LL;
|
||||
if(end<idx) { // memory addresses higher than 48bits are not tracked
|
||||
dynarec_log(LOG_DEBUG, "00\n");
|
||||
return 0;
|
||||
}
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i>>16][i&0xffff];
|
||||
if((prot&PROT_WRITE)) {
|
||||
dynarec_log(LOG_DEBUG, "0\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t last = idx<<MEMPROT_SHIFT;
|
||||
uint8_t oldprot = 0xff;
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t* block = kh_value(memprot, k);
|
||||
for(uintptr_t ii = start; ii<=finish; ++ii) {
|
||||
uint32_t dyn = block[ii]&PROT_DYNAREC;
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
if(oldprot!=prot) {
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i<<MEMPROT_SHIFT;
|
||||
oldprot = prot;
|
||||
}
|
||||
} else if(prot!=0xff) {
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i << MEMPROT_SHIFT;
|
||||
oldprot = 0xff;
|
||||
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
|
||||
if(memprot[i]==memprot_default) {
|
||||
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
|
||||
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
|
||||
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
|
||||
free(newblock);
|
||||
}
|
||||
block[ii] = prot|dyn|PROT_ALLOC;
|
||||
#else
|
||||
memprot[i] = newblock;
|
||||
#endif
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t dyn=(memprot[i>>16][i&0xffff]&PROT_DYNAREC);
|
||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
memprot[i>>16][i&0xffff] = prot|dyn;
|
||||
}
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
|
||||
if(memprot[i]==memprot_default) {
|
||||
uint8_t* newblock = calloc(MEMPROT_SIZE, sizeof(uint8_t));
|
||||
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
|
||||
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
|
||||
free(newblock);
|
||||
}
|
||||
#else
|
||||
memprot[i] = newblock;
|
||||
#endif
|
||||
}
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
for (uintptr_t i=idx; i<=end; ++i)
|
||||
memprot[i>>16][i&0xffff] = prot;
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
@@ -899,18 +897,26 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
|
||||
if(memprot[i]==memprot_default) {
|
||||
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
|
||||
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
|
||||
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
|
||||
free(newblock);
|
||||
}
|
||||
#else
|
||||
memprot[i] = newblock;
|
||||
#endif
|
||||
}
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t* block = kh_value(memprot, k);
|
||||
uint8_t* block = memprot[i>>16];
|
||||
for(uintptr_t ii = start; ii<=finish; ++ii) {
|
||||
if(!block[ii])
|
||||
block[ii] = prot;
|
||||
@@ -933,7 +939,7 @@ void loadProtectionFromMap()
|
||||
uintptr_t s, e;
|
||||
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
|
||||
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
|
||||
allocProtection(s, e-s, prot);
|
||||
allocProtection(s, e-s, prot|PROT_ALLOC);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
@@ -941,8 +947,9 @@ void loadProtectionFromMap()
|
||||
|
||||
static int blockempty(uint8_t* mem)
|
||||
{
|
||||
for (int i=0; i<(MEMPROT_SIZE); ++i)
|
||||
if(mem[i])
|
||||
uint32_t *p4 = (uint32_t*)mem;
|
||||
for (int i=0; i<(MEMPROT_SIZE)/4; ++i, ++p4)
|
||||
if(*p4)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -952,19 +959,35 @@ void freeProtection(uintptr_t addr, size_t size)
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
if(end>=(1LL<<(20+16)))
|
||||
end = (1LL<<(20+16))-1;
|
||||
if(end<idx) // memory addresses higher than 48bits are not tracked
|
||||
return;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k!=kh_end(memprot)) {
|
||||
const uint32_t key = (i>>16);
|
||||
if(memprot[key]!=memprot_default) {
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
uint8_t *block = memprot[key];
|
||||
memset(block+start, 0, finish-start+1);
|
||||
if(blockempty(block)) {
|
||||
free(block);
|
||||
kh_del(memprot, memprot, k);
|
||||
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
|
||||
if (blockempty(block)) {
|
||||
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)memprot_default);
|
||||
if(!blockempty(block)) {
|
||||
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)block);
|
||||
for (int i = 0; i < 0x10000; ++i) {
|
||||
memprot[key][i] |= block[i];
|
||||
}
|
||||
}
|
||||
if (block != memprot_default) free(block);
|
||||
}
|
||||
#else
|
||||
if(blockempty(block)) {
|
||||
memprot[key] = memprot_default;
|
||||
free(block);
|
||||
}
|
||||
#endif
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
}
|
||||
@@ -973,65 +996,52 @@ void freeProtection(uintptr_t addr, size_t size)
|
||||
|
||||
uint32_t getProtection(uintptr_t addr)
|
||||
{
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
if(addr>=(1LL<<48))
|
||||
return 0;
|
||||
}
|
||||
const uintptr_t idx = ((addr&0xffffffff)>>MEMPROT_SHIFT);
|
||||
uint32_t ret = kh_val(memprot, k)[idx];
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uint32_t ret = memprot[idx>>16][idx&0xffff];
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LOWEST (void*)0x20000
|
||||
int availableBlock(uint8_t* p, size_t n)
|
||||
{
|
||||
for (size_t i=0; i<n; ++i, ++p)
|
||||
if(*p)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
static uintptr_t nextFree(uintptr_t addr)
|
||||
{
|
||||
if(addr>=(1LL<<48))
|
||||
return 0;
|
||||
do {
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
if(memprot[idx>>16]==memprot_default) {
|
||||
return addr;
|
||||
}
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
|
||||
if(!block[i]) {
|
||||
return (addr&~0xffffffffLL)+(i<<MEMPROT_SHIFT);
|
||||
for (uintptr_t i=(idx&0xffff); i<MEMPROT_SIZE; ++i)
|
||||
if(!memprot[idx>>16][i]) {
|
||||
return ((idx>>16)<<(16+12))+(i<<MEMPROT_SHIFT);
|
||||
}
|
||||
addr += 0x100000000LL;
|
||||
addr &= ~0xffffffffLL;
|
||||
addr += (1LL<<(16+12));
|
||||
addr &= ~((1LL<<(16+12)-1LL));
|
||||
} while(1);
|
||||
}
|
||||
static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
|
||||
{
|
||||
if(addr>=(1LL<<48))
|
||||
return 0;
|
||||
uintptr_t mfree = 0;
|
||||
do {
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
mfree+=0x100000000LL;
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
if(memprot[idx>>16]==memprot_default) {
|
||||
mfree+=(1LL<<(16+12));
|
||||
if(mfree>sz) {
|
||||
return addr;
|
||||
}
|
||||
} else {
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
|
||||
if(!block[i]) {
|
||||
mfree+=1<<MEMPROT_SHIFT;
|
||||
for (uintptr_t i=(idx&0xffffLL); i<MEMPROT_SIZE; ++i)
|
||||
if(!memprot[idx>>16][i]) {
|
||||
mfree+=(1<<MEMPROT_SHIFT);
|
||||
} else
|
||||
return mfree;
|
||||
}
|
||||
addr += 0x100000000LL;
|
||||
addr &= ~0xffffffffLL;
|
||||
addr += (1LL<<(12+16));
|
||||
addr &= ~((1LL<<(12+16))-1LL);
|
||||
} while(1);
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
@@ -1042,12 +1052,10 @@ void* find47bitBlock(size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = 0x100000000LL;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
@@ -1058,12 +1066,10 @@ void* find47bitBlock(size_t size)
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x100000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1071,17 +1077,14 @@ void* find47bitBlockNearHint(void* hint, size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = (uintptr_t)hint;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x800000000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1089,17 +1092,14 @@ void* findBlockNearHint(void* hint, size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = (uintptr_t)hint;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x100000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1116,9 +1116,6 @@ int unlockCustommemMutex()
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
#undef GO
|
||||
return ret;
|
||||
}
|
||||
@@ -1131,9 +1128,6 @@ void relockCustommemMutex(int locks)
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
#undef GO
|
||||
}
|
||||
|
||||
@@ -1144,9 +1138,6 @@ static void init_mutexes(void)
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
pthread_mutex_init(&mutex_prot, &attr);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&mutex_mmap, &attr);
|
||||
#endif
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
@@ -1163,7 +1154,9 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
memprot = kh_init(memprot);
|
||||
memset(memprot_default, 0, sizeof(memprot_default));
|
||||
for(int i=0; i<(1<<20); ++i)
|
||||
memprot[i] = memprot_default;
|
||||
init_mutexes();
|
||||
#ifdef DYNAREC
|
||||
#ifdef ARM64
|
||||
@@ -1226,7 +1219,6 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
}
|
||||
|
||||
free(mmaplist);
|
||||
pthread_mutex_destroy(&mutex_mmap);
|
||||
for (int i3=0; i3<(1<<DYNAMAP_SHIFT); ++i3)
|
||||
if(box64_jmptbl3[i3]!=box64_jmptbldefault2) {
|
||||
for (int i2=0; i2<(1<<DYNAMAP_SHIFT); ++i2)
|
||||
@@ -1242,10 +1234,11 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
}
|
||||
#endif
|
||||
uint8_t* m;
|
||||
kh_foreach_value(memprot, m,
|
||||
free(m);
|
||||
);
|
||||
kh_destroy(memprot, memprot);
|
||||
for(int i=0; i<(1<<20); ++i) {
|
||||
m = memprot[i];
|
||||
if(m!=memprot_default)
|
||||
free(m);
|
||||
}
|
||||
|
||||
for(int i=0; i<n_blocks; ++i)
|
||||
#ifdef USE_MMAP
|
||||
|
||||
@@ -351,6 +351,9 @@
|
||||
|
||||
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
|
||||
|
||||
// Data Memory Barrier
|
||||
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
|
||||
#define DMB_ISH() EMIT(DMB_gen(0b1011))
|
||||
|
||||
// BR and Branches
|
||||
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
|
||||
arm64_lock_read_b:
|
||||
dmb ish
|
||||
// address is x0, return is x0
|
||||
ldaxrb w0, [x0]
|
||||
ret
|
||||
@@ -29,9 +30,11 @@ arm64_lock_write_b:
|
||||
// address is x0, value is x1, return is x0
|
||||
mov x2, x0
|
||||
stlxrb w0, w1, [x2]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_read_h:
|
||||
dmb ish
|
||||
// address is x0, return is x0
|
||||
ldaxrh w0, [x0]
|
||||
ret
|
||||
@@ -40,9 +43,11 @@ arm64_lock_write_h:
|
||||
// address is x0, value is x1, return is x0
|
||||
mov x2, x0
|
||||
stlxrh w0, w1, [x2]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_read_d:
|
||||
dmb ish
|
||||
// address is x0, return is x0
|
||||
ldaxr w0, [x0]
|
||||
ret
|
||||
@@ -51,9 +56,11 @@ arm64_lock_write_d:
|
||||
// address is x0, value is w1, return is x0
|
||||
mov x2, x0
|
||||
stlxr w0, w1, [x2]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_read_dd:
|
||||
dmb ish
|
||||
// address is x0, return is x0
|
||||
ldaxr x0, [x0]
|
||||
ret
|
||||
@@ -62,9 +69,11 @@ arm64_lock_write_dd:
|
||||
// address is x0, value is x1, return is x0
|
||||
mov x2, x0
|
||||
stlxr w0, x1, [x2]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_read_dq:
|
||||
dmb ish
|
||||
// address is r2, return is r0, r1
|
||||
ldaxp x4, x3, [x2]
|
||||
str x4, [x0]
|
||||
@@ -76,37 +85,47 @@ arm64_lock_write_dq:
|
||||
// r0 needs to be aligned
|
||||
stlxp w3, x0, x1, [x2]
|
||||
mov w0, w3
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
|
||||
arm64_lock_xchg:
|
||||
dmb ish
|
||||
arm64_lock_xchg_0:
|
||||
// address is x0, value is x1, return old value in x0
|
||||
ldaxr x2, [x0]
|
||||
stlxr w3, x1, [x0]
|
||||
cbnz w3, arm64_lock_xchg
|
||||
cbnz w3, arm64_lock_xchg_0
|
||||
dmb ish
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull:
|
||||
dmb ish
|
||||
arm64_lock_storeifnull_0:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
|
||||
ldaxr x2, [x0]
|
||||
cbnz x2, arm64_lock_storeifnull_exit
|
||||
mov x2, x1
|
||||
stlxr w3, x2, [x0]
|
||||
cbnz w3, arm64_lock_storeifnull
|
||||
cbnz w3, arm64_lock_storeifnull_0
|
||||
arm64_lock_storeifnull_exit:
|
||||
dmb ish
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref:
|
||||
dmb ish
|
||||
arm64_lock_storeifref_0:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
|
||||
ldaxr x3, [x0]
|
||||
cmp x2, x3
|
||||
bne arm64_lock_storeifref_exit
|
||||
stlxr w4, x1, [x0]
|
||||
cbnz w4, arm64_lock_storeifref
|
||||
cbnz w4, arm64_lock_storeifref_0
|
||||
mov x0, x1
|
||||
ret
|
||||
arm64_lock_storeifref_exit:
|
||||
dmb ish
|
||||
mov x0, x3
|
||||
ret
|
||||
+156
-58
@@ -48,6 +48,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
|
||||
ret->text = text;
|
||||
ret->textsz = textsz;
|
||||
ret->minstart = text;
|
||||
ret->maxend = text+textsz-1;
|
||||
if(direct && textsz) {
|
||||
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
|
||||
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
||||
@@ -56,12 +58,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynablock(dynablock_t* db)
|
||||
void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(db) {
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone);
|
||||
if(db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->parent, db->father, db->sons_size, db->gone);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
// remove from direct if there
|
||||
@@ -77,16 +81,18 @@ void FreeDynablock(dynablock_t* db)
|
||||
// remove and free the sons
|
||||
for (int i=0; i<db->sons_size; ++i) {
|
||||
dynablock_t *son = (dynablock_t*)arm64_lock_xchg(&db->sons[i], 0);
|
||||
FreeDynablock(son);
|
||||
FreeDynablock(son, 0);
|
||||
}
|
||||
// only the father free the DynarecMap
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
}
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
free(db);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +106,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
if((*dynablocks)->direct) {
|
||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
||||
FreeDynablock((*dynablocks)->direct[i]);
|
||||
FreeDynablock((*dynablocks)->direct[i], 1);
|
||||
}
|
||||
free((*dynablocks)->direct);
|
||||
}
|
||||
@@ -117,7 +123,8 @@ void MarkDynablock(dynablock_t* db)
|
||||
db = db->father; // mark only father
|
||||
if(db->need_test)
|
||||
return; // already done
|
||||
db->need_test = 1; // test only blocks that can be marked (and so deleted)
|
||||
dynarec_log(LOG_DEBUG, "MarkDynablock %p with %d son(s) %p-%p\n", db, db->sons_size, db->x64_addr, db->x64_addr+db->x64_size-1);
|
||||
db->need_test = 1;
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
for(int i=0; i<db->sons_size; ++i)
|
||||
setJumpTableDefault64(db->sons[i]->x64_addr);
|
||||
@@ -146,24 +153,19 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
|
||||
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
// Mark will try to find *any* blocks that intersect the range to mark
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!dynablocks->direct)
|
||||
return;
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz -1;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size-1;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
uintptr_t sizedb = dynablocks->textsz;
|
||||
dynablock_t *db;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i)
|
||||
if((db=dynablocks->direct[i-startdb]))
|
||||
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
dynarec_log(LOG_DEBUG, "MarkDirectDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)startdb, (void*)sizedb);
|
||||
for(uintptr_t i = 0; i<sizedb; ++i)
|
||||
if((db=dynablocks->direct[i]))
|
||||
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
@@ -199,7 +201,7 @@ int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t si
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db);
|
||||
FreeDynablock(db, 1);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
// check emptyness
|
||||
@@ -214,13 +216,14 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p\n", (void*)addr, (void*)addr+size-1);
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t new_addr = addr - dynablocks->maxsz;
|
||||
uintptr_t new_size = size + dynablocks->maxsz;
|
||||
MarkDirectDynablock(dynablocks, new_addr, new_size);
|
||||
uintptr_t new_addr = dynablocks->minstart;
|
||||
uintptr_t new_size = dynablocks->maxend - new_addr + 1;
|
||||
MarkDirectDynablock(dynablocks, addr, size);
|
||||
// the blocks check before
|
||||
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
MarkDirectDynablock(getDB(idx), new_addr, new_size);
|
||||
MarkDirectDynablock(getDB(idx), addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +271,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if (!*created)
|
||||
return block;
|
||||
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
|
||||
@@ -282,12 +286,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
free(block);
|
||||
*created = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
*created = 1;
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -303,7 +309,7 @@ void cancelFillBlock()
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
|
||||
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
|
||||
{
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
@@ -332,19 +338,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(!created)
|
||||
return block; // existing block...
|
||||
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// fill the block
|
||||
block->x64_addr = (void*)addr;
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock64(block, filladdr);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
@@ -355,24 +361,20 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
free(block);
|
||||
block = NULL;
|
||||
}
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// check size
|
||||
if(block && block->x64_size) {
|
||||
if(dynablocks->minstart>addr)
|
||||
dynablocks->minstart = addr;
|
||||
int blocksz = block->x64_size;
|
||||
if(dynablocks->maxsz<blocksz) {
|
||||
dynablocks->maxsz = blocksz;
|
||||
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
if(dynablocks->maxend<addr+blocksz) {
|
||||
dynablocks->maxend = addr+blocksz;
|
||||
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz-1)>>DYNAMAP_SHIFT); ++idx) {
|
||||
dynablocklist_t* dblist;
|
||||
if((dblist = getDB(idx)))
|
||||
if(dblist->maxsz<blocksz)
|
||||
dblist->maxsz = blocksz;
|
||||
if(dblist->minstart>addr)
|
||||
dblist->minstart = addr;
|
||||
}
|
||||
}
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault64(block->x64_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i) {
|
||||
@@ -380,39 +382,133 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
block->sons[i]->done = 1;
|
||||
}
|
||||
block->done = 1;
|
||||
unlockDB();
|
||||
}
|
||||
|
||||
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
|
||||
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", GetTID(), created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
#define MAX_HOTPAGE 64
|
||||
#define HOTPAGE_STEP 64
|
||||
static int volatile hotpage_count[MAX_HOTPAGE] = {0};
|
||||
static uintptr_t volatile hotpage[MAX_HOTPAGE] = {0};
|
||||
static uintptr_t volatile hotpage_size[MAX_HOTPAGE] = {0};
|
||||
static volatile int hotpages = 0;
|
||||
|
||||
int IsInHotPage(uintptr_t addr) {
|
||||
if(!hotpages)
|
||||
return 0;
|
||||
for(int i=0; i<MAX_HOTPAGE; ++i) {
|
||||
if((hotpage_count[i]>0) && (addr>=hotpage[i]) && (addr<hotpage[i]+0x1000*(hotpage_size[i]+1))) {
|
||||
--hotpage_count[i];
|
||||
if(!hotpage_count[i]) {
|
||||
--hotpages;
|
||||
hotpage_size[i] = 0;
|
||||
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AreaInHotPage(uintptr_t start, uintptr_t end) {
|
||||
if(!hotpages)
|
||||
return 0;
|
||||
for(int i=0; i<MAX_HOTPAGE; ++i) {
|
||||
if(hotpage_count[i]>0)
|
||||
if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
|
||||
--hotpage_count[i];
|
||||
if(!hotpage_count[i]) {
|
||||
--hotpages;
|
||||
hotpage_size[i] = 0;
|
||||
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddHotPage(uintptr_t addr) {
|
||||
addr&=~0xfff;
|
||||
// look for same address
|
||||
for(int i=0; i<MAX_HOTPAGE; ++i) {
|
||||
if(addr>=hotpage[i] && addr<hotpage[i]+0x1000*(hotpage_size[i]+1)) {
|
||||
if(!hotpage_count[i])
|
||||
++hotpages;
|
||||
hotpage_count[i] = HOTPAGE_STEP;
|
||||
return;
|
||||
}
|
||||
if(addr==hotpage[i]+0x1000*(hotpage_size[i]+1)) {
|
||||
++hotpage_size[i];
|
||||
hotpage_count[i] = HOTPAGE_STEP;
|
||||
return;
|
||||
}
|
||||
if(addr+0x1000==hotpage[i]) {
|
||||
++hotpage_size[i];
|
||||
hotpage[i] = addr;
|
||||
hotpage_count[i] = HOTPAGE_STEP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// look for empty spot / minium
|
||||
int mincnt = hotpage_count[0];
|
||||
int minidx = 0;
|
||||
for(int i=1; i<MAX_HOTPAGE; ++i)
|
||||
if(hotpage_count[i]<mincnt) {
|
||||
mincnt = hotpage_count[i];
|
||||
minidx = i;
|
||||
}
|
||||
if(hotpage_count[minidx]) {
|
||||
dynarec_log(LOG_NONE, "Warning, not enough Hotpage, replacing %p(%p/%d) with %p\n", (void*)hotpage[minidx], (void*)(0x1000*(hotpage_size[minidx]+1)), hotpage_count[minidx], (void*)addr);
|
||||
hotpage_size[minidx] = 0;
|
||||
} else
|
||||
++hotpages;
|
||||
hotpage[minidx] = addr;
|
||||
hotpage_count[minidx] = HOTPAGE_STEP;
|
||||
}
|
||||
|
||||
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) with %d son(s) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->sons_size, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
if(AreaInHotPage((uintptr_t)father->x64_addr, (uintptr_t)father->x64_addr + father->x64_size - 1)) {
|
||||
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with %d son(s) for %p because it's in a hotpage\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->sons_size, (void*)addr);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
father->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// no more current if it gets invalidated too
|
||||
if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr)
|
||||
if(*current && IntervalIntersects(
|
||||
(uintptr_t)father->x64_addr,
|
||||
(uintptr_t)father->x64_addr+father->x64_size-1,
|
||||
(uintptr_t)(*current)->x64_addr,
|
||||
(uintptr_t)(*current)->x64_addr+(*current)->x64_size-1))
|
||||
*current = NULL;
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
FreeDynablock(father, 0);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->hash, father->sons_size, (void*)addr);
|
||||
protectDB((uintptr_t)father->x64_addr, father->x64_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault64(father->x64_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
|
||||
unlockDB();
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -421,26 +517,28 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
|
||||
if(hash!=father->hash) {
|
||||
father->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
FreeDynablock(father, 0);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
|
||||
protectDB((uintptr_t)father->x64_addr, father->x64_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault64(father->x64_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
|
||||
unlockDB();
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -29,7 +29,8 @@ typedef struct dynablock_s {
|
||||
typedef struct dynablocklist_s {
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
int maxsz; // maxblock size (for this block or previous block)
|
||||
uintptr_t maxend; // max address end for anyblock on this blocklist
|
||||
uintptr_t minstart; // min start address for block overlapping this blocklist
|
||||
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
|
||||
} dynablocklist_t;
|
||||
|
||||
|
||||
+11
-7
@@ -57,7 +57,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
#endif
|
||||
//tableupdate(arm64_epilog, addr, table);
|
||||
return arm64_epilog;
|
||||
@@ -114,16 +114,17 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
PushExit(emu);
|
||||
R_RIP = addr;
|
||||
emu->df = d_none;
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, ¤t);
|
||||
current = block;
|
||||
while(!emu->quit) {
|
||||
block = DBGetBlock(emu, R_RIP, 1, ¤t);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
|
||||
Run(emu, 1);
|
||||
block = DBGetBlock(emu, R_RIP, 1, ¤t);
|
||||
current = block;
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -131,6 +132,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
#ifdef ARM64
|
||||
arm64_prolog(emu, block->block);
|
||||
#endif
|
||||
block = NULL;
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
@@ -194,22 +196,24 @@ int DynaRun(x64emu_t* emu)
|
||||
return Run(emu, 0);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, ¤t);;
|
||||
current = block;
|
||||
while(!emu->quit) {
|
||||
block = DBGetBlock(emu, R_RIP, 1, ¤t);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
|
||||
Run(emu, 1);
|
||||
block = DBGetBlock(emu, R_RIP, 1, ¤t);
|
||||
current = block;
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
|
||||
// block is here, let's run it!
|
||||
#ifdef ARM64
|
||||
arm64_prolog(emu, block->block);
|
||||
#endif
|
||||
block = NULL;
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
|
||||
+66
-20
@@ -58,13 +58,15 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha
|
||||
}
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
if(!box64_dynarec_bigblock)
|
||||
return;
|
||||
for(int i=0; i<dyn->next_sz; ++i)
|
||||
if(dyn->next[i]==addr)
|
||||
return;
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 16;
|
||||
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
}
|
||||
for(int i=0; i<dyn->next_sz; ++i)
|
||||
if(dyn->next[i]==addr)
|
||||
return;
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
@@ -333,28 +335,64 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
__thread void* current_helper = NULL;
|
||||
|
||||
void CancelBlock64()
|
||||
{
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
return;
|
||||
free(helper->next);
|
||||
free(helper->insts);
|
||||
free(helper->table64);
|
||||
free(helper->sons_x64);
|
||||
free(helper->sons_arm);
|
||||
if(helper->dynablock && helper->dynablock->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
|
||||
}
|
||||
|
||||
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
// protect the 1st page
|
||||
protectDB(addr, 1);
|
||||
// init the helper
|
||||
dynarec_arm_t helper = {0};
|
||||
current_helper = &helper;
|
||||
helper.dynablock = block;
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
// no need for next anymore
|
||||
free(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
block->done = 1;
|
||||
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
CancelBlock64();
|
||||
return (void*)block;
|
||||
}
|
||||
helper.cap = helper.size+3; // needs epilog handling
|
||||
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
if(!isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
|
||||
CancelBlock64();
|
||||
return NULL;
|
||||
}
|
||||
// protect the block of it goes over the 1st page
|
||||
if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
// compute hash signature
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
// calculate barriers
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x64.jmp) {
|
||||
@@ -373,6 +411,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
helper.insts[i].x64.jmp_insts = k;
|
||||
}
|
||||
}
|
||||
// pass 1, flags
|
||||
arm_pass1(&helper, addr);
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x64.set_flags && !helper.insts[i].x64.need_flags) {
|
||||
helper.insts[i].x64.need_flags = needed_flags(&helper, i+1, helper.insts[i].x64.set_flags, 0);
|
||||
@@ -386,10 +426,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
free(helper.table64);
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock64();
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
@@ -443,8 +481,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
// ok, free the helper now
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
helper.insts = NULL;
|
||||
free(helper.table64);
|
||||
helper.table64 = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
@@ -453,13 +492,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->x64_size = end-start;
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
if((block->hash != hash)) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
FreeDynarecMap(block, (uintptr_t)p, sz);
|
||||
CancelBlock64();
|
||||
return NULL;
|
||||
} // fill sons if any
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_INFO, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
|
||||
CancelBlock64();
|
||||
return NULL;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
dynablock_t** sons = NULL;
|
||||
int sons_size = 0;
|
||||
if(helper.sons_size) {
|
||||
@@ -488,7 +531,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
free(sons);
|
||||
}
|
||||
free(helper.sons_x64);
|
||||
helper.sons_x64 = NULL;
|
||||
free(helper.sons_arm);
|
||||
helper.sons_arm = NULL;
|
||||
current_helper = NULL;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
@@ -639,17 +639,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
GETFLAGS; \
|
||||
if(dyn->insts) { \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
} \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
}
|
||||
|
||||
GOCOND(0x70, "J", "ib");
|
||||
@@ -846,6 +844,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
BFIx(eb1, x4, eb2*8, 8);
|
||||
} else {
|
||||
DMB_ISH();
|
||||
GETGB(x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
@@ -854,6 +853,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// do the swap 14 -> strb(ed), 1 -> gd
|
||||
STLXRB(x3, x4, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
DMB_ISH();
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
}
|
||||
break;
|
||||
@@ -869,6 +869,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
DMB_ISH();
|
||||
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
@@ -880,6 +881,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRxw_U12(x1, ed, 0);
|
||||
STRxw_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
DMB_ISH();
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
@@ -953,6 +955,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = wback;
|
||||
}
|
||||
} else {
|
||||
if(box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
|
||||
LDRB_U12(x4, wback, fixedaddress);
|
||||
ed = x4;
|
||||
@@ -963,9 +969,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("MOV Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
if(MODREG) {
|
||||
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
} else {
|
||||
if(box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
LDRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -1970,17 +1980,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
#define GO(Z) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8); \
|
||||
if(dyn->insts) { \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
|
||||
} \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ");
|
||||
@@ -2019,12 +2027,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
|
||||
#endif
|
||||
}
|
||||
#if STEP == 0
|
||||
if(isNativeCall(dyn, addr+i32, NULL, NULL))
|
||||
tmp = 3;
|
||||
else
|
||||
tmp = 0;
|
||||
#elif STEP < 2
|
||||
#if STEP < 2
|
||||
if(isNativeCall(dyn, addr+i32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;
|
||||
else
|
||||
@@ -2042,7 +2045,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
|
||||
// calling a native function
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
if(box64_log<2 && dyn->insts && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
|
||||
if(box64_log<2 && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
|
||||
POP1(xRIP); // pop the return address
|
||||
@@ -2104,18 +2107,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i32 = F8S;
|
||||
}
|
||||
JUMP(addr+i32);
|
||||
if(dyn->insts) {
|
||||
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
|
||||
// out of the block
|
||||
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
|
||||
// out of the block
|
||||
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||
} else {
|
||||
// inside the block
|
||||
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
|
||||
if(tmp==4) {
|
||||
NOP;
|
||||
} else {
|
||||
// inside the block
|
||||
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
|
||||
if(tmp==4) {
|
||||
NOP;
|
||||
} else {
|
||||
B(tmp);
|
||||
}
|
||||
B(tmp);
|
||||
}
|
||||
}
|
||||
*need_epilog = 0;
|
||||
@@ -2384,8 +2385,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF(dyn->insts &&
|
||||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|
||||
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
|
||||
@@ -992,18 +992,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i32_);\
|
||||
GETFLAGS; \
|
||||
if(dyn->insts) { \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i32_, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
} \
|
||||
}
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i32_, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
} \
|
||||
|
||||
GOCOND(0x80, "J", "Id");
|
||||
#undef GO
|
||||
|
||||
@@ -801,8 +801,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF(dyn->insts &&
|
||||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|
||||
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
|
||||
@@ -227,17 +227,15 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
if(dyn->insts) { \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
} \
|
||||
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
|
||||
/* out of the block */ \
|
||||
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
|
||||
Bcond(NO, i32); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
/* inside the block */ \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
|
||||
Bcond(YES, i32); \
|
||||
}
|
||||
case 0xE0:
|
||||
INST_NAME("LOOPNZ (32bits)");
|
||||
|
||||
@@ -56,6 +56,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("LOCK ADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(rex.rex) {
|
||||
@@ -77,12 +78,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("LOCK ADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -94,6 +97,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
@@ -101,6 +105,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -112,6 +117,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
@@ -123,6 +129,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
@@ -163,6 +170,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
|
||||
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
@@ -170,6 +178,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOVxw_REG(x1, ed);
|
||||
@@ -201,6 +210,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
@@ -208,6 +218,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
DMB_ISH();
|
||||
MARKLOCK;
|
||||
LDAXPxw(x2, x3, wback);
|
||||
CMPSxw_REG(xRAX, x2);
|
||||
@@ -223,6 +234,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVxw_REG(xRDX, x3);
|
||||
MOV32w(x1, 0);
|
||||
MARK3;
|
||||
DMB_ISH();
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
break;
|
||||
|
||||
@@ -236,6 +248,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -247,6 +260,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
@@ -255,6 +269,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -448,6 +463,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
@@ -456,6 +472,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD Eb, Ib");
|
||||
@@ -614,10 +631,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -794,6 +813,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
@@ -807,6 +827,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVxw_REG(ed, x1);
|
||||
} else {
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE);
|
||||
@@ -819,6 +840,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRxw_U12(x1, ed, 0);
|
||||
STRxw_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
DMB_ISH();
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
@@ -830,6 +852,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0: // INC Ed
|
||||
INST_NAME("LOCK INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_inc32(dyn, ninst, rex, ed, x3, x4);
|
||||
@@ -852,10 +875,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("LOCK DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_dec32(dyn, ninst, rex, ed, x3, x4);
|
||||
@@ -878,6 +903,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -49,7 +49,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint8_t u8;
|
||||
uint64_t u64;
|
||||
uint64_t u64, j64;
|
||||
int v0, v1;
|
||||
int q0;
|
||||
int d0, d1;
|
||||
@@ -214,9 +214,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(v1, 0);
|
||||
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
|
||||
VMOVeD(v0, 0, d0, 0); // to not erase uper part
|
||||
#else
|
||||
FCMPD(v0, v1);
|
||||
B_NEXT(cLS); //Less than or equal
|
||||
VMOVeD(v0, 0, v1, 0); // to not erase uper part
|
||||
#endif
|
||||
break;
|
||||
case 0x5E:
|
||||
INST_NAME("DIVSD Gx, Ex");
|
||||
@@ -234,9 +240,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(v1, 0);
|
||||
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
|
||||
VMOVeD(v0, 0, d0, 0); // to not erase uper part
|
||||
#else
|
||||
FCMPD(v0, v1);
|
||||
B_NEXT(cGE); //Greater than or equal
|
||||
VMOVeD(v0, 0, v1, 0); // to not erase uper part
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
@@ -282,19 +294,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
if((u8&7)==6){
|
||||
FCMPD(v1, v0);
|
||||
} else {
|
||||
FCMPD(v0, v1);
|
||||
}
|
||||
FCMPD(v0, v1);
|
||||
switch(u8&7) {
|
||||
case 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal
|
||||
case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than
|
||||
case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); break; // Less or equal
|
||||
case 0: CSETMx(x2, cEQ); break; // Equal
|
||||
case 1: CSETMx(x2, cCC); break; // Less than
|
||||
case 2: CSETMx(x2, cLS); break; // Less or equal
|
||||
case 3: CSETMx(x2, cVS); break; // NaN
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal or unordered
|
||||
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
|
||||
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 7: CSETMx(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQDfrom(v0, 0, x2);
|
||||
|
||||
@@ -259,9 +259,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
|
||||
VMOVeS(v0, 0, d0, 0); // to not erase uper part
|
||||
#else
|
||||
FCMPS(v0, v1);
|
||||
B_NEXT(cLS); //Less than or equal
|
||||
VMOVeS(v0, 0, v1, 0); // to not erase uper part
|
||||
#endif
|
||||
break;
|
||||
case 0x5E:
|
||||
INST_NAME("DIVSS Gx, Ex");
|
||||
@@ -278,9 +284,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
|
||||
VMOVeS(v0, 0, d0, 0); // to not erase uper part
|
||||
#else
|
||||
FCMPS(v0, v1);
|
||||
B_NEXT(cGE); //Greater than or equal
|
||||
VMOVeS(v0, 0, v1, 0); // to not erase uper part
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x6F:
|
||||
@@ -384,19 +396,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
if((u8&7)==6){
|
||||
FCMPS(v1, v0);
|
||||
} else {
|
||||
FCMPS(v0, v1);
|
||||
}
|
||||
FCMPS(v0, v1);
|
||||
switch(u8&7) {
|
||||
case 0: CSETMw(x2, cEQ); CSELw(x2, xZR, x2, cVS); break; // Equal
|
||||
case 1: CSETMw(x2, cMI); CSELw(x2, xZR, x2, cVS); break; // Less than
|
||||
case 2: CSETMw(x2, cLE); CSELw(x2, xZR, x2, cVS); break; // Less or equal
|
||||
case 0: CSETMw(x2, cEQ); break; // Equal
|
||||
case 1: CSETMw(x2, cCC); break; // Less than
|
||||
case 2: CSETMw(x2, cLS); break; // Less or equal
|
||||
case 3: CSETMw(x2, cVS); break; // NaN
|
||||
case 4: CSETMw(x2, cNE); break; // Not Equal
|
||||
case 4: CSETMw(x2, cNE); break; // Not Equal or unordered
|
||||
case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered
|
||||
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 6: CSETMw(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 7: CSETMw(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQSfrom(v0, 0, x2);
|
||||
|
||||
@@ -312,18 +312,18 @@
|
||||
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
|
||||
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
#define MARK dyn->insts[ninst].mark = dyn->arm_size
|
||||
#define GETMARK dyn->insts[ninst].mark
|
||||
#define MARK2 dyn->insts[ninst].mark2 = dyn->arm_size
|
||||
#define GETMARK2 dyn->insts[ninst].mark2
|
||||
#define MARK3 dyn->insts[ninst].mark3 = dyn->arm_size
|
||||
#define GETMARK3 dyn->insts[ninst].mark3
|
||||
#define MARKF dyn->insts[ninst].markf = dyn->arm_size
|
||||
#define GETMARKF dyn->insts[ninst].markf
|
||||
#define MARKSEG dyn->insts[ninst].markseg = dyn->arm_size
|
||||
#define GETMARKSEG dyn->insts[ninst].markseg
|
||||
#define MARKLOCK dyn->insts[ninst].marklock = dyn->arm_size
|
||||
#define GETMARKLOCK dyn->insts[ninst].marklock
|
||||
|
||||
// Branch to MARK if cond (use j64)
|
||||
#define B_MARK(cond) \
|
||||
@@ -430,11 +430,11 @@
|
||||
j64 = GETMARKLOCK-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
|
||||
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
|
||||
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
|
||||
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
|
||||
#define IFX(A) if((dyn->insts[ninst].x64.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
|
||||
#define IFXX(A) if((dyn->insts[ninst].x64.need_flags==(A)))
|
||||
#define IFX2X(A, B) if((dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if((dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
|
||||
|
||||
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOM(s1, s2, s3) \
|
||||
@@ -589,12 +589,12 @@
|
||||
#ifndef BARRIER_NEXT
|
||||
#define BARRIER_NEXT(A)
|
||||
#endif
|
||||
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x64.need_flags)
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts[ninst].x64.need_flags)
|
||||
#ifndef DEFAULT
|
||||
#define DEFAULT *ok = -1; BARRIER(2)
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "box64stack.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynablock.h"
|
||||
#include "dynarec_arm64.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "arm64_printer.h"
|
||||
@@ -45,7 +47,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
INIT;
|
||||
while(ok) {
|
||||
ip = addr;
|
||||
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
|
||||
if((dyn->insts[ninst].x64.barrier==1)) {
|
||||
dyn->last_ip = 0;
|
||||
NEW_BARRIER_INST;
|
||||
}
|
||||
@@ -90,17 +92,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
|
||||
INST_EPILOG;
|
||||
|
||||
if(dyn->insts && dyn->insts[ninst+1].x64.barrier) {
|
||||
if(dyn->insts[ninst+1].x64.barrier) {
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(dyn->insts[ninst+1].x64.barrier!=2) {
|
||||
dyn->state_flags = 0;
|
||||
dyn->dfnone = 0;
|
||||
}
|
||||
}
|
||||
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
|
||||
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
}
|
||||
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3)&~PROT_CUSTOM)
|
||||
#if STEP == 0
|
||||
if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM && !IsInHotPage(addr+3))
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
@@ -113,6 +116,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
|
||||
@@ -5,8 +5,16 @@
|
||||
#define SETFLAGS(A, B)
|
||||
#define READFLAGS(A)
|
||||
#define EMIT(A)
|
||||
#define JUMP(A) add_next(dyn, (uintptr_t)A)
|
||||
#define NEW_INST ++dyn->size
|
||||
#define JUMP(A) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A
|
||||
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
|
||||
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
|
||||
#define NEW_INST \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm64_t*)realloc(dyn->insts, sizeof(instruction_arm64_t)*dyn->cap*2); \
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm64_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
++dyn->size
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name)
|
||||
#define DEFAULT \
|
||||
|
||||
@@ -6,12 +6,9 @@
|
||||
#define EMIT(A)
|
||||
#define READFLAGS(A) dyn->insts[ninst].x64.use_flags = A
|
||||
#define SETFLAGS(A,B) {dyn->insts[ninst].x64.set_flags = A; dyn->insts[ninst].x64.state_flags = B;}
|
||||
#define JUMP(A) dyn->insts[ninst].x64.jmp = A
|
||||
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
|
||||
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
|
||||
|
||||
#define NEW_INST \
|
||||
dyn->insts[ninst].x64.addr = ip; \
|
||||
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;
|
||||
#define INST_EPILOG
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name)
|
||||
@@ -4,8 +4,9 @@
|
||||
#include "dynarec_private.h"
|
||||
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
|
||||
typedef struct instruction_arm_s {
|
||||
typedef struct instruction_arm64_s {
|
||||
instruction_x64_t x64;
|
||||
uintptr_t address; // (start) address of the arm emited instruction
|
||||
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
|
||||
@@ -50,6 +51,7 @@ typedef struct dynarec_arm_s {
|
||||
uintptr_t* sons_x64; // the x64 address of potential dynablock sons
|
||||
void** sons_arm; // the arm address of potential dynablock sons
|
||||
int sons_size; // number of potential dynablock sons
|
||||
dynablock_t* dynablock;
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
|
||||
@@ -185,7 +185,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
|
||||
uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
|
||||
start &= ~balign;
|
||||
if( (head->e_type == ET_DYN) ||
|
||||
(((bstart>=start) && (bstart<=end)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
|
||||
(((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
|
||||
{
|
||||
// merge
|
||||
ok = 1;
|
||||
|
||||
@@ -218,10 +218,10 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
tmp8s = 0;
|
||||
switch(tmp8u&7) {
|
||||
case 0: tmp8s=(GX->d[0] == EX->d[0]); break;
|
||||
case 1: tmp8s=isless(GX->d[0], EX->d[0]); break;
|
||||
case 2: tmp8s=islessequal(GX->d[0], EX->d[0]); break;
|
||||
case 1: tmp8s=isless(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break;
|
||||
case 2: tmp8s=islessequal(GX->d[0], EX->d[0]) && !(isnan(GX->d[0]) || isnan(EX->d[0])); break;
|
||||
case 3: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]); break;
|
||||
case 4: tmp8s=(GX->d[0] != EX->d[0]); break;
|
||||
case 4: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || (GX->d[0] != EX->d[0]); break;
|
||||
case 5: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreaterequal(GX->d[0], EX->d[0]); break;
|
||||
case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break;
|
||||
case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break;
|
||||
|
||||
@@ -318,10 +318,10 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
tmp8s = 0;
|
||||
switch(tmp8u&7) {
|
||||
case 0: tmp8s=(GX->f[0] == EX->f[0]); break;
|
||||
case 1: tmp8s=isless(GX->f[0], EX->f[0]); break;
|
||||
case 2: tmp8s=islessequal(GX->f[0], EX->f[0]); break;
|
||||
case 1: tmp8s=isless(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break;
|
||||
case 2: tmp8s=islessequal(GX->f[0], EX->f[0]) && !(isnan(GX->f[0]) || isnan(EX->f[0])); break;
|
||||
case 3: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]); break;
|
||||
case 4: tmp8s=(GX->f[0] != EX->f[0]); break;
|
||||
case 4: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || (GX->f[0] != EX->f[0]); break;
|
||||
case 5: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreaterequal(GX->f[0], EX->f[0]); break;
|
||||
case 6: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(GX->f[0], EX->f[0]); break;
|
||||
case 7: tmp8s=!isnan(GX->f[0]) && !isnan(EX->f[0]); break;
|
||||
|
||||
@@ -45,10 +45,8 @@ uint32_t getProtection(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void protectDBnolock(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size);
|
||||
void lockDB();
|
||||
void unlockDB();
|
||||
int isprotectedDB(uintptr_t addr, size_t size);
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
|
||||
@@ -13,6 +13,8 @@ extern int box64_dynarec_dump;
|
||||
extern int box64_dynarec_trace;
|
||||
extern int box64_dynarec_forced;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
extern int box64_dynarec_bigblock;
|
||||
extern int box64_dynarec_strongmem;
|
||||
#ifdef ARM64
|
||||
extern int arm64_asimd;
|
||||
extern int arm64_aes;
|
||||
|
||||
@@ -9,7 +9,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
uint32_t X31_hash_code(void* addr, int len);
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
//return 1 if Dynareblock is empty
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
@@ -31,5 +31,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
|
||||
// for use in signal handler
|
||||
void cancelFillBlock();
|
||||
int IsInHotPage(uintptr_t addr);
|
||||
void AddHotPage(uintptr_t addr);
|
||||
|
||||
#endif //__DYNABLOCK_H_
|
||||
@@ -4,6 +4,7 @@
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
|
||||
void CancelBlock64();
|
||||
void* FillBlock64(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
#endif //__DYNAREC_ARM_H_
|
||||
+1
-11
@@ -90,17 +90,7 @@ typedef struct va_list {
|
||||
memcpy(&p[6], emu->xmm, 8*16); \
|
||||
}
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
// TODO, is this correct?
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs->gpr=8; \
|
||||
sysv_varargs->fpr=8; \
|
||||
sysv_varargs->overflow_arg_area=A;
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
#error TODO!
|
||||
#elif defined(__loongarch64)
|
||||
#elif defined(__loongarch64) || defined(__powerpc64__)
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
va_list sysv_varargs = (va_list)A
|
||||
// not creating CONVERT_VALIST(A) on purpose
|
||||
|
||||
@@ -262,6 +262,13 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
|
||||
lib->priv.n.localsymbols = kh_init(mapsymbols);
|
||||
|
||||
printf_log(LOG_INFO, "Using emulated %s\n", libname);
|
||||
#ifdef DYNAREC
|
||||
if(libname && strstr(libname, "libmonobdwgc-2.0.so")) {
|
||||
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
box64_dynarec_bigblock = 0;
|
||||
box64_dynarec_strongmem = 1;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -376,7 +383,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t*
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_func) {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
|
||||
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
free(trace_func);
|
||||
|
||||
+3
-3
@@ -154,9 +154,9 @@ GO("libcups.so.2", libcups)
|
||||
//GO("libvulkan.so", vulkan)
|
||||
//GO("libwayland-client.so.0", waylandclient)
|
||||
GO("libxml2.so.2", xml2)
|
||||
//GO("libxslt.so.1", xslt)
|
||||
//GO("libldap_r-2.4.so.2", ldapr)
|
||||
//GO("liblber-2.4.so.2", lber)
|
||||
GO("libxslt.so.1", xslt)
|
||||
GO("libldap_r-2.4.so.2", ldapr)
|
||||
GO("liblber-2.4.so.2", lber)
|
||||
//GO("libnsl.so.1", nsl)
|
||||
//GO("liblcms2.so.2", lcms2)
|
||||
GO("libkrb5.so.3", krb5)
|
||||
|
||||
+47
-9
@@ -310,8 +310,8 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc
|
||||
int oldquitonlongjmp = emu->quitonlongjmp;
|
||||
emu->quitonlongjmp = 2;
|
||||
|
||||
//EmuCall(emu, fnc); // avoid DynaCall for now
|
||||
DynaCall(emu, fnc);
|
||||
EmuCall(emu, fnc); // avoid DynaCall for now
|
||||
//DynaCall(emu, fnc);
|
||||
if(nargs>6)
|
||||
R_RSP+=((nargs-6)*sizeof(void*));
|
||||
|
||||
@@ -705,6 +705,11 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void
|
||||
relockMutex(Locks);
|
||||
}
|
||||
|
||||
extern __thread void* current_helper;
|
||||
#ifdef DYNAREC
|
||||
static pthread_mutex_t mutex_dynarec_prot;
|
||||
#endif
|
||||
|
||||
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
{
|
||||
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
|
||||
@@ -728,7 +733,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
#elif defined __x86_64__
|
||||
void * pc = (void*)p->uc_mcontext.gregs[X64_RIP];
|
||||
#elif defined __powerpc64__
|
||||
void * pc = (void*)p->uc_mcontext.uc_regs->gregs[PT_NIP];
|
||||
void * pc = (void*)p->uc_mcontext.gp_regs[PT_NIP];
|
||||
#else
|
||||
void * pc = NULL; // unknow arch...
|
||||
#warning Unhandled architecture
|
||||
@@ -736,17 +741,30 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
int Locks = unlockMutex();
|
||||
uint32_t prot = getProtection((uintptr_t)addr);
|
||||
#ifdef DYNAREC
|
||||
if((Locks & (1<<8)) && (sig==SIGSEGV)) //1<<8 is mutex_dyndump
|
||||
cancelFillBlock(); // Segfault inside a Fillblock, just cancel it's creation, don't relock mutex
|
||||
if((Locks & (1<<8)) && (sig==SIGSEGV) && current_helper) {//1<<8 is mutex_dyndump
|
||||
relockMutex(Locks);
|
||||
cancelFillBlock(); // Segfault inside a Fillblock, cancel it's creation...
|
||||
}
|
||||
dynablock_t* db = NULL;
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
pthread_mutex_lock(&mutex_dynarec_prot);
|
||||
// check if SMC inside block
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x\n", pc, addr, db, db?((void*)db->x64_addr):NULL, prot);
|
||||
static uintptr_t repeated_page = 0;
|
||||
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x (old page=%p)\n", pc, addr, db, db?((void*)db->x64_addr):NULL, prot, (void*)repeated_page);
|
||||
static int repeated_count = 0;
|
||||
if(repeated_page == ((uintptr_t)addr&~0xfff)) {
|
||||
++repeated_count; // Access eoor multiple time on same page, disable dynarec on this page a few time...
|
||||
dynarec_log(LOG_DEBUG, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count);
|
||||
AddHotPage(repeated_page);
|
||||
} else {
|
||||
repeated_page = (uintptr_t)addr&~0xfff;
|
||||
repeated_count = 0;
|
||||
}
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db->need_test)) {
|
||||
// dynablock got auto-dirty! need to get out of it!!!
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
@@ -781,17 +799,21 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
dynarec_log(LOG_INFO, "Dynablock unprotected, getting out!\n");
|
||||
}
|
||||
relockMutex(Locks);
|
||||
pthread_mutex_unlock(&mutex_dynarec_prot);
|
||||
siglongjmp(ejb->jmpbuf, 2);
|
||||
}
|
||||
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
|
||||
}
|
||||
// done
|
||||
if(prot&PROT_WRITE) {
|
||||
if((prot&PROT_WRITE) || (prot&PROT_DYNAREC)) {
|
||||
pthread_mutex_unlock(&mutex_dynarec_prot);
|
||||
// if there is no write permission, don't return and continue to program signal handling
|
||||
relockMutex(Locks);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_dynarec_prot);
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
|
||||
pthread_mutex_lock(&mutex_dynarec_prot);
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) {
|
||||
@@ -808,6 +830,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
relockMutex(Locks);
|
||||
pthread_mutex_unlock(&mutex_dynarec_prot);
|
||||
return; // try again
|
||||
}
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot);
|
||||
@@ -815,6 +838,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
|
||||
glitch_addr = NULL;
|
||||
glitch_prot = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_dynarec_prot);
|
||||
}
|
||||
#else
|
||||
void* db = NULL;
|
||||
@@ -1277,7 +1301,17 @@ EXPORT int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2)
|
||||
my_setcontext(emu, ucp2);
|
||||
return 0;
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
static void atfork_child_dynarec_prot(void)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_dynarec_prot, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
#endif
|
||||
void init_signal_helper(box64context_t* context)
|
||||
{
|
||||
// setup signal handling
|
||||
@@ -1296,6 +1330,10 @@ void init_signal_helper(box64context_t* context)
|
||||
sigaction(SIGILL, &action, NULL);
|
||||
|
||||
pthread_once(&sigstack_key_once, sigstack_key_alloc);
|
||||
#ifdef DYNAREC
|
||||
atfork_child_dynarec_prot();
|
||||
pthread_atfork(NULL, NULL, atfork_child_dynarec_prot);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fini_signal_helper()
|
||||
|
||||
+22
-8
@@ -42,6 +42,8 @@ int box64_pagesize;
|
||||
int box64_dynarec = 1;
|
||||
int box64_dynarec_dump = 0;
|
||||
int box64_dynarec_forced = 0;
|
||||
int box64_dynarec_bigblock = 1;
|
||||
int box64_dynarec_strongmem = 0;
|
||||
uintptr_t box64_nodynarec_start = 0;
|
||||
uintptr_t box64_nodynarec_end = 0;
|
||||
#ifdef ARM64
|
||||
@@ -262,6 +264,24 @@ void LoadLogEnv()
|
||||
if(box64_dynarec_forced)
|
||||
printf_log(LOG_INFO, "Dynarec is Forced on all addresses\n");
|
||||
}
|
||||
p = getenv("BOX64_DYNAREC_BIGBLOCK");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_dynarec_bigblock = p[0]-'0';
|
||||
}
|
||||
if(!box64_dynarec_bigblock)
|
||||
printf_log(LOG_INFO, "Dynarec will not try to make big block\n");
|
||||
}
|
||||
p = getenv("BOX64_DYNAREC_STRONGMEM");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='2')
|
||||
box64_dynarec_strongmem = p[0]-'0';
|
||||
}
|
||||
if(box64_dynarec_strongmem)
|
||||
printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box64_dynarec_strongmem==1)?" with limited performace loss":"");
|
||||
}
|
||||
p = getenv("BOX64_NODYNAREC");
|
||||
if(p) {
|
||||
if (strchr(p,'-')) {
|
||||
@@ -838,10 +858,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
// check BOX64_LD_LIBRARY_PATH and load it
|
||||
LoadEnvVars(my_context);
|
||||
|
||||
if(argv[0][0]=='/')
|
||||
my_context->box64path = strdup(argv[0]);
|
||||
else
|
||||
my_context->box64path = ResolveFile(argv[0], &my_context->box64_path);
|
||||
my_context->box64path = ResolveFile(argv[0], &my_context->box64_path);
|
||||
// prepare all other env. var
|
||||
my_context->envc = CountEnv(environ?environ:env);
|
||||
printf_log(LOG_INFO, "Counted %d Env var\n", my_context->envc);
|
||||
@@ -883,10 +900,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
// lets build argc/argv stuff
|
||||
printf_log(LOG_INFO, "Looking for %s\n", prog);
|
||||
if(strchr(prog, '/'))
|
||||
my_context->argv[0] = strdup(prog);
|
||||
else
|
||||
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
|
||||
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
|
||||
// check if box86 is present
|
||||
{
|
||||
my_context->box86path = strdup(my_context->box64path);
|
||||
|
||||
@@ -60,7 +60,7 @@ char* ResolveFile(const char* filename, path_collection_t* paths)
|
||||
return realpath(p, NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return strdup(filename); //NULL;
|
||||
}
|
||||
|
||||
int FileIsX64ELF(const char* filename)
|
||||
|
||||
@@ -452,6 +452,7 @@
|
||||
#() LFpLp
|
||||
#() LFppi
|
||||
#() LFppL
|
||||
#() LFppp
|
||||
#() LFSpL
|
||||
#() pFEip
|
||||
#() pFEiV
|
||||
@@ -724,6 +725,7 @@
|
||||
#() iFppui
|
||||
#() iFppuu
|
||||
#() iFppup
|
||||
#() iFppdp
|
||||
#() iFppll
|
||||
#() iFpplp
|
||||
#() iFppLi
|
||||
@@ -1490,6 +1492,7 @@
|
||||
#() iFpppippp
|
||||
#() iFpppuiii
|
||||
#() iFppppiii
|
||||
#() iFppppipp
|
||||
#() iFppppdpi
|
||||
#() iFpppppip
|
||||
#() iFpppppup
|
||||
@@ -1604,7 +1607,9 @@
|
||||
#() iFpppipipi
|
||||
#() iFpppipppp
|
||||
#() iFppppiipi
|
||||
#() iFppppippp
|
||||
#() iFppppppii
|
||||
#() iFpppppppi
|
||||
#() iFpppppppp
|
||||
#() uFEipipppp
|
||||
#() uFEpiupppp
|
||||
@@ -1631,6 +1636,7 @@
|
||||
#() pFpWWiCpup
|
||||
#() pFpuuWWCuu
|
||||
#() pFpuuuupup
|
||||
#() pFpuuupwwp
|
||||
#() pFpdwwWWui
|
||||
#() pFplpppppp
|
||||
#() pFppiiiiii
|
||||
@@ -1673,6 +1679,7 @@
|
||||
#() iFEpiiiiipi
|
||||
#() iFEpppipppp
|
||||
#() iFEppplPPPP
|
||||
#() iFEpppppupp
|
||||
#() iFEppPPPPPP
|
||||
#() iFiiiiiiiip
|
||||
#() iFiiiipiiip
|
||||
@@ -1783,6 +1790,7 @@
|
||||
#() iFEpppipppppp
|
||||
#() iFEppppiiiiuu
|
||||
#() iFiiiiiiiiiip
|
||||
#() iFppippipppip
|
||||
#() iFppppiiuuiiL
|
||||
#() uFEpLiupppLuV
|
||||
#() uFEpLippppLup
|
||||
@@ -1856,12 +1864,14 @@
|
||||
#() vFppuiiiiipuiiiiiiii
|
||||
#() vFpppipppppppppppppp
|
||||
#() iFpppppppppppppppppp
|
||||
#() LFpppppppppppppppppp
|
||||
#() pFippppppppppppppppp
|
||||
#() vFpiiiiiiiiiiiiiiiiii
|
||||
#() pFiiiippppppppppppppp
|
||||
#() pFpippppppppppppppppp
|
||||
#() iFpppppppppppppppppppppp
|
||||
#() pFipppppppppppppppppppppp
|
||||
#() iFpppppppppppppppppppppppppppppppppp
|
||||
#defined(HAVE_LD80BITS) DFD
|
||||
#defined(HAVE_LD80BITS) vFppippDDC
|
||||
#!defined(HAVE_LD80BITS) KFK
|
||||
@@ -2372,6 +2382,10 @@ wrappedgtkx112:
|
||||
wrappedkrb5:
|
||||
- iFppppppipp:
|
||||
- krb5_get_init_creds_password
|
||||
wrappedlber:
|
||||
wrappedldapr:
|
||||
- iFpppppupp:
|
||||
- ldap_sasl_interactive_bind_s
|
||||
wrappedldlinux:
|
||||
- pFp:
|
||||
- __tls_get_addr
|
||||
@@ -2439,6 +2453,7 @@ wrappedlibc:
|
||||
- sigaltstack
|
||||
- swapcontext
|
||||
- iFpV:
|
||||
- __isoc99_scanf
|
||||
- execl
|
||||
- execlp
|
||||
- printf
|
||||
@@ -3448,3 +3463,8 @@ wrappedxml2:
|
||||
- xmlHashUpdateEntry3
|
||||
- pFpppppi:
|
||||
- xmlCreateIOParserCtxt
|
||||
wrappedxslt:
|
||||
- vFp:
|
||||
- xsltSetLoaderFunc
|
||||
- iFppp:
|
||||
- xsltRegisterExtModuleFunction
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlberDEFS_H_
|
||||
#define __wrappedlberDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlberDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlberTYPES_H_
|
||||
#define __wrappedlberTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedlberTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlberUNDEFS_H_
|
||||
#define __wrappedlberUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedlberUNDEFS_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedldaprDEFS_H_
|
||||
#define __wrappedldaprDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedldaprDEFS_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedldaprTYPES_H_
|
||||
#define __wrappedldaprTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFpppppupp_t)(void*, void*, void*, void*, void*, uint64_t, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(ldap_sasl_interactive_bind_s, iFpppppupp_t)
|
||||
|
||||
#endif // __wrappedldaprTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedldaprUNDEFS_H_
|
||||
#define __wrappedldaprUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedldaprUNDEFS_H_
|
||||
@@ -110,6 +110,7 @@ typedef int64_t (*iFpippppp_t)(void*, int64_t, void*, void*, void*, void*, void*
|
||||
GO(execvp, iFpp_t) \
|
||||
GO(sigaltstack, iFpp_t) \
|
||||
GO(swapcontext, iFpp_t) \
|
||||
GO(__isoc99_scanf, iFpV_t) \
|
||||
GO(execl, iFpV_t) \
|
||||
GO(execlp, iFpV_t) \
|
||||
GO(printf, iFpV_t) \
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedxsltDEFS_H_
|
||||
#define __wrappedxsltDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedxsltDEFS_H_
|
||||
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedxsltTYPES_H_
|
||||
#define __wrappedxsltTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void (*vFp_t)(void*);
|
||||
typedef int64_t (*iFppp_t)(void*, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(xsltSetLoaderFunc, vFp_t) \
|
||||
GO(xsltRegisterExtModuleFunction, iFppp_t)
|
||||
|
||||
#endif // __wrappedxsltTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedxsltUNDEFS_H_
|
||||
#define __wrappedxsltUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedxsltUNDEFS_H_
|
||||
@@ -486,6 +486,7 @@ typedef uintptr_t (*LFpLi_t)(void*, uintptr_t, int64_t);
|
||||
typedef uintptr_t (*LFpLp_t)(void*, uintptr_t, void*);
|
||||
typedef uintptr_t (*LFppi_t)(void*, void*, int64_t);
|
||||
typedef uintptr_t (*LFppL_t)(void*, void*, uintptr_t);
|
||||
typedef uintptr_t (*LFppp_t)(void*, void*, void*);
|
||||
typedef uintptr_t (*LFSpL_t)(void*, void*, uintptr_t);
|
||||
typedef void* (*pFEip_t)(x64emu_t*, int64_t, void*);
|
||||
typedef void* (*pFEiV_t)(x64emu_t*, int64_t, void*);
|
||||
@@ -758,6 +759,7 @@ typedef int64_t (*iFppuw_t)(void*, void*, uint64_t, int16_t);
|
||||
typedef int64_t (*iFppui_t)(void*, void*, uint64_t, int64_t);
|
||||
typedef int64_t (*iFppuu_t)(void*, void*, uint64_t, uint64_t);
|
||||
typedef int64_t (*iFppup_t)(void*, void*, uint64_t, void*);
|
||||
typedef int64_t (*iFppdp_t)(void*, void*, double, void*);
|
||||
typedef int64_t (*iFppll_t)(void*, void*, intptr_t, intptr_t);
|
||||
typedef int64_t (*iFpplp_t)(void*, void*, intptr_t, void*);
|
||||
typedef int64_t (*iFppLi_t)(void*, void*, uintptr_t, int64_t);
|
||||
@@ -1524,6 +1526,7 @@ typedef int64_t (*iFpppippi_t)(void*, void*, void*, int64_t, void*, void*, int64
|
||||
typedef int64_t (*iFpppippp_t)(void*, void*, void*, int64_t, void*, void*, void*);
|
||||
typedef int64_t (*iFpppuiii_t)(void*, void*, void*, uint64_t, int64_t, int64_t, int64_t);
|
||||
typedef int64_t (*iFppppiii_t)(void*, void*, void*, void*, int64_t, int64_t, int64_t);
|
||||
typedef int64_t (*iFppppipp_t)(void*, void*, void*, void*, int64_t, void*, void*);
|
||||
typedef int64_t (*iFppppdpi_t)(void*, void*, void*, void*, double, void*, int64_t);
|
||||
typedef int64_t (*iFpppppip_t)(void*, void*, void*, void*, void*, int64_t, void*);
|
||||
typedef int64_t (*iFpppppup_t)(void*, void*, void*, void*, void*, uint64_t, void*);
|
||||
@@ -1638,7 +1641,9 @@ typedef int64_t (*iFpppiippp_t)(void*, void*, void*, int64_t, int64_t, void*, vo
|
||||
typedef int64_t (*iFpppipipi_t)(void*, void*, void*, int64_t, void*, int64_t, void*, int64_t);
|
||||
typedef int64_t (*iFpppipppp_t)(void*, void*, void*, int64_t, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFppppiipi_t)(void*, void*, void*, void*, int64_t, int64_t, void*, int64_t);
|
||||
typedef int64_t (*iFppppippp_t)(void*, void*, void*, void*, int64_t, void*, void*, void*);
|
||||
typedef int64_t (*iFppppppii_t)(void*, void*, void*, void*, void*, void*, int64_t, int64_t);
|
||||
typedef int64_t (*iFpppppppi_t)(void*, void*, void*, void*, void*, void*, void*, int64_t);
|
||||
typedef int64_t (*iFpppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef uint64_t (*uFEipipppp_t)(x64emu_t*, int64_t, void*, int64_t, void*, void*, void*, void*);
|
||||
typedef uint64_t (*uFEpiupppp_t)(x64emu_t*, void*, int64_t, uint64_t, void*, void*, void*, void*);
|
||||
@@ -1665,6 +1670,7 @@ typedef void* (*pFpCuuuCup_t)(void*, uint8_t, uint64_t, uint64_t, uint64_t, uint
|
||||
typedef void* (*pFpWWiCpup_t)(void*, uint16_t, uint16_t, int64_t, uint8_t, void*, uint64_t, void*);
|
||||
typedef void* (*pFpuuWWCuu_t)(void*, uint64_t, uint64_t, uint16_t, uint16_t, uint8_t, uint64_t, uint64_t);
|
||||
typedef void* (*pFpuuuupup_t)(void*, uint64_t, uint64_t, uint64_t, uint64_t, void*, uint64_t, void*);
|
||||
typedef void* (*pFpuuupwwp_t)(void*, uint64_t, uint64_t, uint64_t, void*, int16_t, int16_t, void*);
|
||||
typedef void* (*pFpdwwWWui_t)(void*, double, int16_t, int16_t, uint16_t, uint16_t, uint64_t, int64_t);
|
||||
typedef void* (*pFplpppppp_t)(void*, intptr_t, void*, void*, void*, void*, void*, void*);
|
||||
typedef void* (*pFppiiiiii_t)(void*, void*, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t);
|
||||
@@ -1707,6 +1713,7 @@ typedef void (*vFpppppippp_t)(void*, void*, void*, void*, void*, int64_t, void*,
|
||||
typedef int64_t (*iFEpiiiiipi_t)(x64emu_t*, void*, int64_t, int64_t, int64_t, int64_t, int64_t, void*, int64_t);
|
||||
typedef int64_t (*iFEpppipppp_t)(x64emu_t*, void*, void*, void*, int64_t, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFEppplPPPP_t)(x64emu_t*, void*, void*, void*, intptr_t, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFEpppppupp_t)(x64emu_t*, void*, void*, void*, void*, void*, uint64_t, void*, void*);
|
||||
typedef int64_t (*iFEppPPPPPP_t)(x64emu_t*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFiiiiiiiip_t)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, void*);
|
||||
typedef int64_t (*iFiiiipiiip_t)(int64_t, int64_t, int64_t, int64_t, void*, int64_t, int64_t, int64_t, void*);
|
||||
@@ -1817,6 +1824,7 @@ typedef void (*vFppppppppppp_t)(void*, void*, void*, void*, void*, void*, void*,
|
||||
typedef int64_t (*iFEpppipppppp_t)(x64emu_t*, void*, void*, void*, int64_t, void*, void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFEppppiiiiuu_t)(x64emu_t*, void*, void*, void*, void*, int64_t, int64_t, int64_t, int64_t, uint64_t, uint64_t);
|
||||
typedef int64_t (*iFiiiiiiiiiip_t)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, void*);
|
||||
typedef int64_t (*iFppippipppip_t)(void*, void*, int64_t, void*, void*, int64_t, void*, void*, void*, int64_t, void*);
|
||||
typedef int64_t (*iFppppiiuuiiL_t)(void*, void*, void*, void*, int64_t, int64_t, uint64_t, uint64_t, int64_t, int64_t, uintptr_t);
|
||||
typedef uint64_t (*uFEpLiupppLuV_t)(x64emu_t*, void*, uintptr_t, int64_t, uint64_t, void*, void*, void*, uintptr_t, uint64_t, void*);
|
||||
typedef uint64_t (*uFEpLippppLup_t)(x64emu_t*, void*, uintptr_t, int64_t, void*, void*, void*, void*, uintptr_t, uint64_t, void*);
|
||||
@@ -1890,12 +1898,14 @@ typedef void* (*pFppippipipipipipip_t)(void*, void*, int64_t, void*, void*, int6
|
||||
typedef void (*vFppuiiiiipuiiiiiiii_t)(void*, void*, uint64_t, int64_t, int64_t, int64_t, int64_t, int64_t, void*, uint64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t);
|
||||
typedef void (*vFpppipppppppppppppp_t)(void*, void*, void*, int64_t, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpppppppppppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef uintptr_t (*LFpppppppppppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef void* (*pFippppppppppppppppp_t)(int64_t, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef void (*vFpiiiiiiiiiiiiiiiiii_t)(void*, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t, int64_t);
|
||||
typedef void* (*pFiiiippppppppppppppp_t)(int64_t, int64_t, int64_t, int64_t, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef void* (*pFpippppppppppppppppp_t)(void*, int64_t, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpppppppppppppppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef void* (*pFipppppppppppppppppppppp_t)(int64_t, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpppppppppppppppppppppppppppppppppp_t)(void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*);
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
typedef long double (*DFD_t)(long double);
|
||||
@@ -2375,6 +2385,7 @@ void LFpLi(x64emu_t *emu, uintptr_t fcn) { LFpLi_t fn = (LFpLi_t)fcn; R_RAX=(uin
|
||||
void LFpLp(x64emu_t *emu, uintptr_t fcn) { LFpLp_t fn = (LFpLp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX); }
|
||||
void LFppi(x64emu_t *emu, uintptr_t fcn) { LFppi_t fn = (LFppi_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX); }
|
||||
void LFppL(x64emu_t *emu, uintptr_t fcn) { LFppL_t fn = (LFppL_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX); }
|
||||
void LFppp(x64emu_t *emu, uintptr_t fcn) { LFppp_t fn = (LFppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX); }
|
||||
void LFSpL(x64emu_t *emu, uintptr_t fcn) { LFSpL_t fn = (LFSpL_t)fcn; R_RAX=(uintptr_t)fn(io_convert((void*)R_RDI), (void*)R_RSI, (uintptr_t)R_RDX); }
|
||||
void pFEip(x64emu_t *emu, uintptr_t fcn) { pFEip_t fn = (pFEip_t)fcn; R_RAX=(uintptr_t)fn(emu, (int64_t)R_RDI, (void*)R_RSI); }
|
||||
void pFEiV(x64emu_t *emu, uintptr_t fcn) { pFEiV_t fn = (pFEiV_t)fcn; R_RAX=(uintptr_t)fn(emu, (int64_t)R_RDI, (void*)(R_RSP + 8)); }
|
||||
@@ -2647,6 +2658,7 @@ void iFppuw(x64emu_t *emu, uintptr_t fcn) { iFppuw_t fn = (iFppuw_t)fcn; R_RAX=(
|
||||
void iFppui(x64emu_t *emu, uintptr_t fcn) { iFppui_t fn = (iFppui_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (int64_t)R_RCX); }
|
||||
void iFppuu(x64emu_t *emu, uintptr_t fcn) { iFppuu_t fn = (iFppuu_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (uint64_t)R_RCX); }
|
||||
void iFppup(x64emu_t *emu, uintptr_t fcn) { iFppup_t fn = (iFppup_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (void*)R_RCX); }
|
||||
void iFppdp(x64emu_t *emu, uintptr_t fcn) { iFppdp_t fn = (iFppdp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, emu->xmm[0].d[0], (void*)R_RDX); }
|
||||
void iFppll(x64emu_t *emu, uintptr_t fcn) { iFppll_t fn = (iFppll_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (intptr_t)R_RDX, (intptr_t)R_RCX); }
|
||||
void iFpplp(x64emu_t *emu, uintptr_t fcn) { iFpplp_t fn = (iFpplp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (intptr_t)R_RDX, (void*)R_RCX); }
|
||||
void iFppLi(x64emu_t *emu, uintptr_t fcn) { iFppLi_t fn = (iFppLi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (int64_t)R_RCX); }
|
||||
@@ -3413,6 +3425,7 @@ void iFpppippi(x64emu_t *emu, uintptr_t fcn) { iFpppippi_t fn = (iFpppippi_t)fcn
|
||||
void iFpppippp(x64emu_t *emu, uintptr_t fcn) { iFpppippp_t fn = (iFpppippp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
|
||||
void iFpppuiii(x64emu_t *emu, uintptr_t fcn) { iFpppuiii_t fn = (iFpppuiii_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8)); }
|
||||
void iFppppiii(x64emu_t *emu, uintptr_t fcn) { iFppppiii_t fn = (iFppppiii_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8)); }
|
||||
void iFppppipp(x64emu_t *emu, uintptr_t fcn) { iFppppipp_t fn = (iFppppipp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
|
||||
void iFppppdpi(x64emu_t *emu, uintptr_t fcn) { iFppppdpi_t fn = (iFppppdpi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, emu->xmm[0].d[0], (void*)R_R8, (int64_t)R_R9); }
|
||||
void iFpppppip(x64emu_t *emu, uintptr_t fcn) { iFpppppip_t fn = (iFpppppip_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8)); }
|
||||
void iFpppppup(x64emu_t *emu, uintptr_t fcn) { iFpppppup_t fn = (iFpppppup_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint64_t)R_R9, *(void**)(R_RSP + 8)); }
|
||||
@@ -3527,7 +3540,9 @@ void iFpppiippp(x64emu_t *emu, uintptr_t fcn) { iFpppiippp_t fn = (iFpppiippp_t)
|
||||
void iFpppipipi(x64emu_t *emu, uintptr_t fcn) { iFpppipipi_t fn = (iFpppipipi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
void iFpppipppp(x64emu_t *emu, uintptr_t fcn) { iFpppipppp_t fn = (iFpppipppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void iFppppiipi(x64emu_t *emu, uintptr_t fcn) { iFppppiipi_t fn = (iFppppiipi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
void iFppppippp(x64emu_t *emu, uintptr_t fcn) { iFppppippp_t fn = (iFppppippp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void iFppppppii(x64emu_t *emu, uintptr_t fcn) { iFppppppii_t fn = (iFppppppii_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
void iFpppppppi(x64emu_t *emu, uintptr_t fcn) { iFpppppppi_t fn = (iFpppppppi_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
void iFpppppppp(x64emu_t *emu, uintptr_t fcn) { iFpppppppp_t fn = (iFpppppppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void uFEipipppp(x64emu_t *emu, uintptr_t fcn) { uFEipipppp_t fn = (uFEipipppp_t)fcn; R_RAX=(uint64_t)fn(emu, (int64_t)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
|
||||
void uFEpiupppp(x64emu_t *emu, uintptr_t fcn) { uFEpiupppp_t fn = (uFEpiupppp_t)fcn; R_RAX=(uint64_t)fn(emu, (void*)R_RDI, (int64_t)R_RSI, (uint64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8)); }
|
||||
@@ -3554,6 +3569,7 @@ void pFpCuuuCup(x64emu_t *emu, uintptr_t fcn) { pFpCuuuCup_t fn = (pFpCuuuCup_t)
|
||||
void pFpWWiCpup(x64emu_t *emu, uintptr_t fcn) { pFpWWiCpup_t fn = (pFpWWiCpup_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (uint16_t)R_RSI, (uint16_t)R_RDX, (int64_t)R_RCX, (uint8_t)R_R8, (void*)R_R9, *(uint64_t*)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void pFpuuWWCuu(x64emu_t *emu, uintptr_t fcn) { pFpuuWWCuu_t fn = (pFpuuWWCuu_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX, (uint16_t)R_RCX, (uint16_t)R_R8, (uint8_t)R_R9, *(uint64_t*)(R_RSP + 8), *(uint64_t*)(R_RSP + 16)); }
|
||||
void pFpuuuupup(x64emu_t *emu, uintptr_t fcn) { pFpuuuupup_t fn = (pFpuuuupup_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX, (uint64_t)R_RCX, (uint64_t)R_R8, (void*)R_R9, *(uint64_t*)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void pFpuuupwwp(x64emu_t *emu, uintptr_t fcn) { pFpuuupwwp_t fn = (pFpuuupwwp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX, (uint64_t)R_RCX, (void*)R_R8, (int16_t)R_R9, *(int16_t*)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void pFpdwwWWui(x64emu_t *emu, uintptr_t fcn) { pFpdwwWWui_t fn = (pFpdwwWWui_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, emu->xmm[0].d[0], (int16_t)R_RSI, (int16_t)R_RDX, (uint16_t)R_RCX, (uint16_t)R_R8, (uint64_t)R_R9, *(int64_t*)(R_RSP + 8)); }
|
||||
void pFplpppppp(x64emu_t *emu, uintptr_t fcn) { pFplpppppp_t fn = (pFplpppppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (intptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void pFppiiiiii(x64emu_t *emu, uintptr_t fcn) { pFppiiiiii_t fn = (pFppiiiiii_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
@@ -3596,6 +3612,7 @@ void vFpppppippp(x64emu_t *emu, uintptr_t fcn) { vFpppppippp_t fn = (vFpppppippp
|
||||
void iFEpiiiiipi(x64emu_t *emu, uintptr_t fcn) { iFEpiiiiipi_t fn = (iFEpiiiiipi_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8), *(int64_t*)(R_RSP + 16)); }
|
||||
void iFEpppipppp(x64emu_t *emu, uintptr_t fcn) { iFEpppipppp_t fn = (iFEpppipppp_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void iFEppplPPPP(x64emu_t *emu, uintptr_t fcn) { iFEppplPPPP_t fn = (iFEppplPPPP_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (intptr_t)R_RCX, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); }
|
||||
void iFEpppppupp(x64emu_t *emu, uintptr_t fcn) { iFEpppppupp_t fn = (iFEpppppupp_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint64_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16)); }
|
||||
void iFEppPPPPPP(x64emu_t *emu, uintptr_t fcn) { iFEppPPPPPP_t fn = (iFEppPPPPPP_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48)); }
|
||||
void iFiiiiiiiip(x64emu_t *emu, uintptr_t fcn) { iFiiiiiiiip_t fn = (iFiiiiiiiip_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(void**)(R_RSP + 24)); }
|
||||
void iFiiiipiiip(x64emu_t *emu, uintptr_t fcn) { iFiiiipiiip_t fn = (iFiiiipiiip_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (void*)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(void**)(R_RSP + 24)); }
|
||||
@@ -3706,6 +3723,7 @@ void vFppppppppppp(x64emu_t *emu, uintptr_t fcn) { vFppppppppppp_t fn = (vFppppp
|
||||
void iFEpppipppppp(x64emu_t *emu, uintptr_t fcn) { iFEpppipppppp_t fn = (iFEpppipppppp_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32)); }
|
||||
void iFEppppiiiiuu(x64emu_t *emu, uintptr_t fcn) { iFEppppiiiiuu_t fn = (iFEppppiiiiuu_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(uint64_t*)(R_RSP + 24), *(uint64_t*)(R_RSP + 32)); }
|
||||
void iFiiiiiiiiiip(x64emu_t *emu, uintptr_t fcn) { iFiiiiiiiiiip_t fn = (iFiiiiiiiiiip_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(int64_t*)(R_RSP + 24), *(int64_t*)(R_RSP + 32), *(void**)(R_RSP + 40)); }
|
||||
void iFppippipppip(x64emu_t *emu, uintptr_t fcn) { iFppippipppip_t fn = (iFppippipppip_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (int64_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(int64_t*)(R_RSP + 32), *(void**)(R_RSP + 40)); }
|
||||
void iFppppiiuuiiL(x64emu_t *emu, uintptr_t fcn) { iFppppiiuuiiL_t fn = (iFppppiiuuiiL_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(uint64_t*)(R_RSP + 8), *(uint64_t*)(R_RSP + 16), *(int64_t*)(R_RSP + 24), *(int64_t*)(R_RSP + 32), *(uintptr_t*)(R_RSP + 40)); }
|
||||
void uFEpLiupppLuV(x64emu_t *emu, uintptr_t fcn) { uFEpLiupppLuV_t fn = (uFEpLiupppLuV_t)fcn; R_RAX=(uint64_t)fn(emu, (void*)R_RDI, (uintptr_t)R_RSI, (int64_t)R_RDX, (uint64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(uint64_t*)(R_RSP + 24), (void*)(R_RSP + 32)); }
|
||||
void uFEpLippppLup(x64emu_t *emu, uintptr_t fcn) { uFEpLippppLup_t fn = (uFEpLippppLup_t)fcn; R_RAX=(uint64_t)fn(emu, (void*)R_RDI, (uintptr_t)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(uint64_t*)(R_RSP + 24), *(void**)(R_RSP + 32)); }
|
||||
@@ -3779,12 +3797,14 @@ void pFppippipipipipipip(x64emu_t *emu, uintptr_t fcn) { pFppippipipipipipip_t f
|
||||
void vFppuiiiiipuiiiiiiii(x64emu_t *emu, uintptr_t fcn) { vFppuiiiiipuiiiiiiii_t fn = (vFppuiiiiipuiiiiiiii_t)fcn; fn((void*)R_RDI, (void*)R_RSI, (uint64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(void**)(R_RSP + 24), *(uint64_t*)(R_RSP + 32), *(int64_t*)(R_RSP + 40), *(int64_t*)(R_RSP + 48), *(int64_t*)(R_RSP + 56), *(int64_t*)(R_RSP + 64), *(int64_t*)(R_RSP + 72), *(int64_t*)(R_RSP + 80), *(int64_t*)(R_RSP + 88), *(int64_t*)(R_RSP + 96)); }
|
||||
void vFpppipppppppppppppp(x64emu_t *emu, uintptr_t fcn) { vFpppipppppppppppppp_t fn = (vFpppipppppppppppppp_t)fcn; fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96)); }
|
||||
void iFpppppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { iFpppppppppppppppppp_t fn = (iFpppppppppppppppppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96)); }
|
||||
void LFpppppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { LFpppppppppppppppppp_t fn = (LFpppppppppppppppppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96)); }
|
||||
void pFippppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { pFippppppppppppppppp_t fn = (pFippppppppppppppppp_t)fcn; R_RAX=(uintptr_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96)); }
|
||||
void vFpiiiiiiiiiiiiiiiiii(x64emu_t *emu, uintptr_t fcn) { vFpiiiiiiiiiiiiiiiiii_t fn = (vFpiiiiiiiiiiiiiiiiii_t)fcn; fn((void*)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (int64_t)R_R8, (int64_t)R_R9, *(int64_t*)(R_RSP + 8), *(int64_t*)(R_RSP + 16), *(int64_t*)(R_RSP + 24), *(int64_t*)(R_RSP + 32), *(int64_t*)(R_RSP + 40), *(int64_t*)(R_RSP + 48), *(int64_t*)(R_RSP + 56), *(int64_t*)(R_RSP + 64), *(int64_t*)(R_RSP + 72), *(int64_t*)(R_RSP + 80), *(int64_t*)(R_RSP + 88), *(int64_t*)(R_RSP + 96), *(int64_t*)(R_RSP + 104)); }
|
||||
void pFiiiippppppppppppppp(x64emu_t *emu, uintptr_t fcn) { pFiiiippppppppppppppp_t fn = (pFiiiippppppppppppppp_t)fcn; R_RAX=(uintptr_t)fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96), *(void**)(R_RSP + 104)); }
|
||||
void pFpippppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { pFpippppppppppppppppp_t fn = (pFpippppppppppppppppp_t)fcn; R_RAX=(uintptr_t)fn((void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96), *(void**)(R_RSP + 104)); }
|
||||
void iFpppppppppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { iFpppppppppppppppppppppp_t fn = (iFpppppppppppppppppppppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96), *(void**)(R_RSP + 104), *(void**)(R_RSP + 112), *(void**)(R_RSP + 120), *(void**)(R_RSP + 128)); }
|
||||
void pFipppppppppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { pFipppppppppppppppppppppp_t fn = (pFipppppppppppppppppppppp_t)fcn; R_RAX=(uintptr_t)fn((int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96), *(void**)(R_RSP + 104), *(void**)(R_RSP + 112), *(void**)(R_RSP + 120), *(void**)(R_RSP + 128), *(void**)(R_RSP + 136)); }
|
||||
void iFpppppppppppppppppppppppppppppppppp(x64emu_t *emu, uintptr_t fcn) { iFpppppppppppppppppppppppppppppppppp_t fn = (iFpppppppppppppppppppppppppppppppppp_t)fcn; R_RAX=(int64_t)fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56), *(void**)(R_RSP + 64), *(void**)(R_RSP + 72), *(void**)(R_RSP + 80), *(void**)(R_RSP + 88), *(void**)(R_RSP + 96), *(void**)(R_RSP + 104), *(void**)(R_RSP + 112), *(void**)(R_RSP + 120), *(void**)(R_RSP + 128), *(void**)(R_RSP + 136), *(void**)(R_RSP + 144), *(void**)(R_RSP + 152), *(void**)(R_RSP + 160), *(void**)(R_RSP + 168), *(void**)(R_RSP + 176), *(void**)(R_RSP + 184), *(void**)(R_RSP + 192), *(void**)(R_RSP + 200), *(void**)(R_RSP + 208), *(void**)(R_RSP + 216), *(void**)(R_RSP + 224)); }
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
void DFD(x64emu_t *emu, uintptr_t fcn) { DFD_t fn = (DFD_t)fcn; long double ld=fn(LD2localLD((void*)(R_RSP + 8))); fpu_do_push(emu); ST0val = ld; }
|
||||
@@ -4212,6 +4232,7 @@ int isSimpleWrapper(wrapper_t fun) {
|
||||
if (fun == &LFpLp) return 1;
|
||||
if (fun == &LFppi) return 1;
|
||||
if (fun == &LFppL) return 1;
|
||||
if (fun == &LFppp) return 1;
|
||||
if (fun == &pFiii) return 1;
|
||||
if (fun == &pFiiu) return 1;
|
||||
if (fun == &pFiip) return 1;
|
||||
@@ -4438,6 +4459,7 @@ int isSimpleWrapper(wrapper_t fun) {
|
||||
if (fun == &iFppui) return 1;
|
||||
if (fun == &iFppuu) return 1;
|
||||
if (fun == &iFppup) return 1;
|
||||
if (fun == &iFppdp) return 2;
|
||||
if (fun == &iFppll) return 1;
|
||||
if (fun == &iFpplp) return 1;
|
||||
if (fun == &iFppLi) return 1;
|
||||
|
||||
@@ -485,6 +485,7 @@ void LFpLi(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFpLp(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFppi(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFppL(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFSpL(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFEip(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFEiV(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -757,6 +758,7 @@ void iFppuw(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppui(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppuu(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppup(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppdp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppll(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpplp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppLi(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1523,6 +1525,7 @@ void iFpppippi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppippp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppuiii(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppiii(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppipp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppdpi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppip(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppup(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1637,7 +1640,9 @@ void iFpppiippp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppipipi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppipppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppiipi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppippp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppppii(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppppi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void uFEipipppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void uFEpiupppp(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1664,6 +1669,7 @@ void pFpCuuuCup(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpWWiCpup(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpuuWWCuu(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpuuuupup(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpuuupwwp(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpdwwWWui(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFplpppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFppiiiiii(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1706,6 +1712,7 @@ void vFpppppippp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEpiiiiipi(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEpppipppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEppplPPPP(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEpppppupp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEppPPPPPP(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFiiiipiiip(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1816,6 +1823,7 @@ void vFppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEpppipppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFEppppiiiiuu(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFiiiiiiiiiip(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppippipppip(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFppppiiuuiiL(x64emu_t *emu, uintptr_t fnc);
|
||||
void uFEpLiupppLuV(x64emu_t *emu, uintptr_t fnc);
|
||||
void uFEpLippppLup(x64emu_t *emu, uintptr_t fnc);
|
||||
@@ -1889,12 +1897,14 @@ void pFppippipipipipipip(x64emu_t *emu, uintptr_t fnc);
|
||||
void vFppuiiiiipuiiiiiiii(x64emu_t *emu, uintptr_t fnc);
|
||||
void vFpppipppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void LFpppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFippppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void vFpiiiiiiiiiiiiiiiiii(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFiiiippppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFpippppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void pFipppppppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
void iFpppppppppppppppppppppppppppppppppp(x64emu_t *emu, uintptr_t fnc);
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
void DFD(x64emu_t *emu, uintptr_t fnc);
|
||||
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "wrappedlibs.h"
|
||||
|
||||
#include "wrapper.h"
|
||||
#include "bridge.h"
|
||||
#include "librarian/library_private.h"
|
||||
#include "x64emu.h"
|
||||
|
||||
const char* lberName =
|
||||
#ifdef ANDROID
|
||||
"liblber-2.4.so"
|
||||
#else
|
||||
"liblber-2.4.so.2"
|
||||
#endif
|
||||
;
|
||||
#define LIBNAME lber
|
||||
|
||||
#include "wrappedlib_init.h"
|
||||
|
||||
Executable
+140
@@ -0,0 +1,140 @@
|
||||
#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
|
||||
#error Meh....
|
||||
#endif
|
||||
|
||||
//GO(ber_alloc,
|
||||
GO(ber_alloc_t, pFi)
|
||||
//GO(ber_bprint,
|
||||
GO(ber_bvarray_add, vFpp)
|
||||
//GO(ber_bvarray_add_x,
|
||||
//GO(ber_bvarray_dup_x,
|
||||
GO(ber_bvarray_free, vFp)
|
||||
//GO(ber_bvarray_free_x,
|
||||
GO(ber_bvdup, pFp)
|
||||
GO(ber_bvecadd, vFpp)
|
||||
//GO(ber_bvecadd_x,
|
||||
GO(ber_bvecfree, vFp)
|
||||
//GO(ber_bvecfree_x,
|
||||
GO(ber_bvfree, vFp)
|
||||
//GO(ber_bvfree_x,
|
||||
//GO(ber_bvreplace,
|
||||
//GO(ber_bvreplace_x,
|
||||
GO(ber_bvstr, pFp)
|
||||
GO(ber_bvstrdup, pFp)
|
||||
//GO(ber_decode_oid,
|
||||
//GO(ber_dump,
|
||||
//GO(ber_dup,
|
||||
GO(ber_dupbv, pFpp)
|
||||
//GO(ber_dupbv_x,
|
||||
//GO(ber_encode_oid,
|
||||
//GO(ber_errno_addr,
|
||||
//GO(ber_error_print,
|
||||
GO(ber_first_element, LFppp)
|
||||
GO(ber_flatten, iFpp)
|
||||
//GO(ber_flatten2,
|
||||
GO(ber_flush, iFppi)
|
||||
GO(ber_flush2, iFppi)
|
||||
GO(ber_free, vFpi)
|
||||
//GO(ber_free_buf,
|
||||
GO(ber_get_bitstringa, LFppp)
|
||||
GO(ber_get_boolean, LFpp)
|
||||
GO(ber_get_enum, iFpp)
|
||||
GO(ber_get_int, iFpp)
|
||||
GO(ber_get_next, LFppp)
|
||||
GO(ber_get_null, LFp)
|
||||
//GO(ber_get_option,
|
||||
GO(ber_get_stringa, LFpp)
|
||||
GO(ber_get_stringal, LFpp)
|
||||
//GO(ber_get_stringa_null,
|
||||
GO(ber_get_stringb, LFppp)
|
||||
GO(ber_get_stringbv, LFppi)
|
||||
//GO(ber_get_stringbv_null,
|
||||
//GO(ber_get_tag,
|
||||
GO(ber_init, pFp)
|
||||
GO(ber_init2, vFppi)
|
||||
//GO(ber_init_w_nullc,
|
||||
//DATAB(ber_int_errno_fn,
|
||||
//DATAB(ber_int_log_proc,
|
||||
//DATAB(ber_int_memory_fns,
|
||||
//DATAB(ber_int_options,
|
||||
//GO(ber_int_sb_close,
|
||||
//GO(ber_int_sb_destroy,
|
||||
//GO(ber_int_sb_init,
|
||||
//GO(ber_int_sb_read,
|
||||
//GO(ber_int_sb_write,
|
||||
//GO(ber_len,
|
||||
//GO(ber_log_bprint,
|
||||
//GO(ber_log_dump,
|
||||
//GO(ber_log_sos_dump,
|
||||
//GO(ber_mem2bv,
|
||||
//GO(ber_mem2bv_x,
|
||||
//GO(ber_memalloc,
|
||||
//GO(ber_memalloc_x,
|
||||
//GO(ber_memcalloc,
|
||||
//GO(ber_memcalloc_x,
|
||||
//GO(ber_memfree,
|
||||
//GO(ber_memfree_x,
|
||||
//GO(ber_memrealloc,
|
||||
//GO(ber_memrealloc_x,
|
||||
//GO(ber_memvfree,
|
||||
//GO(ber_memvfree_x,
|
||||
GO(ber_next_element, LFppp)
|
||||
//GO(ber_peek_element,
|
||||
GO(ber_peek_tag, LFpp)
|
||||
GO(ber_printf, iFpppppppppppppppppppppppppppppppppp) //VAArg. May need some wrapping...
|
||||
//GO(ber_ptrlen,
|
||||
//GO(ber_put_berval,
|
||||
GO(ber_put_bitstring, iFppLL)
|
||||
GO(ber_put_boolean, iFpiL)
|
||||
GO(ber_put_enum, iFpiL)
|
||||
GO(ber_put_int, iFpiL)
|
||||
GO(ber_put_null, iFpL)
|
||||
GO(ber_put_ostring, iFppLL)
|
||||
GO(ber_put_seq, iFp)
|
||||
GO(ber_put_set, iFp)
|
||||
GO(ber_put_string, iFppL)
|
||||
//DATAB(ber_pvt_err_file,
|
||||
//GO(ber_pvt_log_output,
|
||||
//DATA(ber_pvt_log_print,
|
||||
//GO(ber_pvt_log_printf,
|
||||
//DATAB(ber_pvt_opt_on,
|
||||
//GO(ber_pvt_sb_buf_destroy,
|
||||
//GO(ber_pvt_sb_buf_init,
|
||||
//GO(ber_pvt_sb_copy_out,
|
||||
//GO(ber_pvt_sb_do_write,
|
||||
//GO(ber_pvt_sb_grow_buffer,
|
||||
//GO(ber_pvt_socket_set_nonblock,
|
||||
//GO(ber_read,
|
||||
//GO(ber_realloc,
|
||||
//GO(ber_remaining,
|
||||
//GO(ber_reset,
|
||||
//GO(ber_rewind,
|
||||
GO(ber_scanf, LFpppppppppppppppppp) // VAArg
|
||||
//GO(ber_set_option,
|
||||
//GO(ber_skip_data,
|
||||
//GO(ber_skip_element,
|
||||
GO(ber_skip_tag, LFpp)
|
||||
//GO(ber_sockbuf_add_io,
|
||||
//GO(ber_sockbuf_alloc,
|
||||
//GO(ber_sockbuf_ctrl,
|
||||
//GO(ber_sockbuf_free,
|
||||
//DATA(ber_sockbuf_io_debug,
|
||||
//DATA(ber_sockbuf_io_fd,
|
||||
//DATA(ber_sockbuf_io_readahead,
|
||||
//DATA(ber_sockbuf_io_tcp,
|
||||
//GO(ber_sockbuf_remove_io,
|
||||
//GO(ber_sos_dump,
|
||||
//GO(ber_start,
|
||||
GO(ber_start_seq, iFpL)
|
||||
GO(ber_start_set, iFpL)
|
||||
GO(ber_str2bv, pFpLip)
|
||||
//GO(ber_str2bv_x,
|
||||
//GO(ber_strdup,
|
||||
//GO(ber_strdup_x,
|
||||
//GO(ber_strndup,
|
||||
//GO(ber_strndup_x,
|
||||
//GO(ber_strnlen,
|
||||
//GO(ber_write,
|
||||
//GO(der_alloc,
|
||||
//GO(lutil_debug,
|
||||
//GO(lutil_debug_file,
|
||||
Executable
+113
@@ -0,0 +1,113 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "wrappedlibs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "wrapper.h"
|
||||
#include "bridge.h"
|
||||
#include "librarian/library_private.h"
|
||||
#include "x64emu.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "librarian.h"
|
||||
#include "callback.h"
|
||||
|
||||
const char* ldaprName =
|
||||
#ifdef ANDROID
|
||||
"libldap_r-2.4.so"
|
||||
#else
|
||||
"libldap_r-2.4.so.2"
|
||||
#endif
|
||||
;
|
||||
#define LIBNAME ldapr
|
||||
static library_t *my_lib = NULL;
|
||||
|
||||
typedef int (*iFpppppupp_t) (void*, void*, void*, void* , void*, unsigned, void*, void*);
|
||||
|
||||
#define SUPER() \
|
||||
GO(ldap_sasl_interactive_bind_s, iFpppppupp_t) \
|
||||
|
||||
typedef struct ldapr_my_s {
|
||||
// functions
|
||||
#define GO(A, B) B A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
} ldapr_my_t;
|
||||
|
||||
void* getLdaprMy(library_t* lib)
|
||||
{
|
||||
ldapr_my_t* my = (ldapr_my_t*)calloc(1, sizeof(ldapr_my_t));
|
||||
#define GO(A, W) my->A = (W)dlsym(lib->priv.w.lib, #A);
|
||||
SUPER()
|
||||
#undef GO
|
||||
return my;
|
||||
}
|
||||
#undef SUPER
|
||||
|
||||
void freeLdaprMy(void* lib)
|
||||
{
|
||||
//ldapr_my_t *my = (ldapr_my_t *)lib;
|
||||
}
|
||||
|
||||
#define SUPER() \
|
||||
GO(0) \
|
||||
GO(1) \
|
||||
GO(2) \
|
||||
GO(3) \
|
||||
GO(4)
|
||||
|
||||
// LDAP_SASL_INTERACT_PROC ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_LDAP_SASL_INTERACT_PROC_fct_##A = 0; \
|
||||
static int my_LDAP_SASL_INTERACT_PROC_##A(void* a, unsigned b, void* c, void* d) \
|
||||
{ \
|
||||
return RunFunction(my_context, my_LDAP_SASL_INTERACT_PROC_fct_##A, 4, a, b, c, d); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* find_LDAP_SASL_INTERACT_PROC_Fct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_LDAP_SASL_INTERACT_PROC_fct_##A == (uintptr_t)fct) return my_LDAP_SASL_INTERACT_PROC_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_LDAP_SASL_INTERACT_PROC_fct_##A == 0) {my_LDAP_SASL_INTERACT_PROC_fct_##A = (uintptr_t)fct; return my_LDAP_SASL_INTERACT_PROC_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libldap_r LDAP_SASL_INTERACT_PROC callback\n");
|
||||
return NULL;
|
||||
}
|
||||
#undef SUPER
|
||||
|
||||
EXPORT int my_ldap_sasl_interactive_bind_s(x64emu_t* emu, void* ld, void* dn, void* mechs, void* sctrls, void* cctrls, unsigned flags, void* f, void* defaults)
|
||||
{
|
||||
ldapr_my_t* my = (ldapr_my_t*)my_lib->priv.w.p2;
|
||||
|
||||
return my->ldap_sasl_interactive_bind_s(ld, dn, mechs, sctrls, cctrls, flags, find_LDAP_SASL_INTERACT_PROC_Fct(f), defaults);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
#define NEEDED_LIB "liblber-2.4.so"
|
||||
#else
|
||||
#define NEEDED_LIB "liblber-2.4.so.2"
|
||||
#endif
|
||||
|
||||
#define CUSTOM_INIT \
|
||||
lib->priv.w.p2 = getLdaprMy(lib); \
|
||||
lib->priv.w.needed = 1; \
|
||||
lib->priv.w.neededlibs = (char**)calloc(lib->priv.w.needed, sizeof(char*)); \
|
||||
lib->priv.w.neededlibs[0] = strdup(NEEDED_LIB); \
|
||||
my_lib = lib;
|
||||
|
||||
#define CUSTOM_FINI \
|
||||
freeLdaprMy(lib->priv.w.p2); \
|
||||
free(lib->priv.w.p2); \
|
||||
my_lib = NULL;
|
||||
|
||||
#include "wrappedlib_init.h"
|
||||
|
||||
Executable
+510
@@ -0,0 +1,510 @@
|
||||
#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
|
||||
#error Meh....
|
||||
#endif
|
||||
|
||||
GO(ldap_abandon, iFpi)
|
||||
GO(ldap_abandon_ext, iFpipp)
|
||||
//GO(ldap_add,
|
||||
GO(ldap_add_ext, iFpppppp)
|
||||
GO(ldap_add_ext_s, iFppppp)
|
||||
//GO(ldap_add_result_entry,
|
||||
//GO(ldap_add_s,
|
||||
//GO(ldap_alloc_ber_with_options,
|
||||
//GO(ldap_append_referral,
|
||||
//GO(ldap_attributetype2bv,
|
||||
//GO(ldap_attributetype2name,
|
||||
//GO(ldap_attributetype2str,
|
||||
//GO(ldap_attributetype_free,
|
||||
GO(ldap_bind, iFpppi)
|
||||
GO(ldap_bind_s, iFpppi)
|
||||
//GO(ldap_build_add_req,
|
||||
//GO(ldap_build_bind_req,
|
||||
//GO(ldap_build_compare_req,
|
||||
//GO(ldap_build_delete_req,
|
||||
//GO(ldap_build_extended_req,
|
||||
//GO(ldap_build_moddn_req,
|
||||
//GO(ldap_build_modify_req,
|
||||
//GO(ldap_build_search_req,
|
||||
//GO(ldap_bv2dn,
|
||||
//GO(ldap_bv2dn_x,
|
||||
//GO(ldap_bv2escaped_filter_value,
|
||||
//GO(ldap_bv2escaped_filter_value_len,
|
||||
//GO(ldap_bv2escaped_filter_value_x,
|
||||
//GO(ldap_bv2rdn,
|
||||
//GO(ldap_bv2rdn_x,
|
||||
//GO(ldap_cancel,
|
||||
//GO(ldap_cancel_s,
|
||||
//GO(ldap_charray2str,
|
||||
//GO(ldap_charray_add,
|
||||
//GO(ldap_charray_dup,
|
||||
//GO(ldap_charray_free,
|
||||
//GO(ldap_charray_inlist,
|
||||
//GO(ldap_charray_merge,
|
||||
//GO(ldap_chase_referrals,
|
||||
//GO(ldap_chase_v3referrals,
|
||||
//GO(ldap_clear_select_write,
|
||||
//GO(ldap_compare,
|
||||
GO(ldap_compare_ext, iFppppppp)
|
||||
GO(ldap_compare_ext_s, iFpppppp)
|
||||
//GO(ldap_compare_s,
|
||||
//GO(ldap_connect_to_host,
|
||||
//GO(ldap_connect_to_path,
|
||||
//GO(ldap_contentrule2bv,
|
||||
//GO(ldap_contentrule2name,
|
||||
//GO(ldap_contentrule2str,
|
||||
//GO(ldap_contentrule_free,
|
||||
GO(ldap_control_create, iFpipip)
|
||||
GO(ldap_control_dup, pFp)
|
||||
GO(ldap_control_find, pFppp)
|
||||
GO(ldap_control_free, vFp)
|
||||
GO(ldap_controls_dup, pFp)
|
||||
GO(ldap_controls_free, vFp)
|
||||
GO(ldap_count_entries, iFpp)
|
||||
//GO(ldap_count_messages,
|
||||
GO(ldap_count_references, iFpp)
|
||||
GO(ldap_count_values, iFp)
|
||||
GO(ldap_count_values_len, iFp)
|
||||
//GO(ldap_create,
|
||||
//GO(ldap_create_assertion_control,
|
||||
//GO(ldap_create_assertion_control_value,
|
||||
//GO(ldap_create_control,
|
||||
//GO(ldap_create_deref_control,
|
||||
//GO(ldap_create_deref_control_value,
|
||||
//GO(ldap_create_page_control,
|
||||
//GO(ldap_create_page_control_value,
|
||||
//GO(ldap_create_passwordpolicy_control,
|
||||
//GO(ldap_create_session_tracking_control,
|
||||
//GO(ldap_create_session_tracking_value,
|
||||
GO(ldap_create_sort_control, iFppip)
|
||||
//GO(ldap_create_sort_control_value,
|
||||
//GO(ldap_create_sort_keylist,
|
||||
GO(ldap_create_vlv_control, iFppp)
|
||||
//GO(ldap_create_vlv_control_value,
|
||||
GO(ldap_dcedn2dn, pFp)
|
||||
GO(ldap_delete, iFpp)
|
||||
GO(ldap_delete_ext, iFppppp)
|
||||
GO(ldap_delete_ext_s, iFpppp)
|
||||
//GO(ldap_delete_result_entry,
|
||||
GO(ldap_delete_s, iFpp)
|
||||
//GO(ldap_derefresponse_free,
|
||||
//GO(ldap_destroy,
|
||||
GO(ldap_dn2ad_canonical, pFp)
|
||||
//GO(ldap_dn2bv,
|
||||
//GO(ldap_dn2bv_x,
|
||||
GO(ldap_dn2dcedn, pFp)
|
||||
//GO(ldap_dn2domain,
|
||||
GO(ldap_dn2str, iFppu)
|
||||
GO(ldap_dn2ufn, pFp)
|
||||
//GO(ldap_dnfree,
|
||||
//GO(ldap_dnfree_x,
|
||||
//GO(ldap_dn_normalize,
|
||||
//GO(ldap_domain2dn,
|
||||
//GO(ldap_domain2hostlist,
|
||||
//GO(ldap_dump_connection,
|
||||
//GO(ldap_dump_requests_and_responses,
|
||||
//GO(ldap_dup,
|
||||
//GO(ldap_err2string,
|
||||
GO(ldap_explode_dn, pFpi)
|
||||
GO(ldap_explode_rdn, pFpi)
|
||||
GO(ldap_extended_operation, iFpppppp)
|
||||
GO(ldap_extended_operation_s, iFppppppp)
|
||||
//GO(ldap_find_control,
|
||||
//GO(ldap_find_request_by_msgid,
|
||||
GO(ldap_first_attribute, pFppp)
|
||||
GO(ldap_first_entry, pFpp)
|
||||
//GO(ldap_first_message,
|
||||
GO(ldap_first_reference, pFpp)
|
||||
//GO(ldap_free_connection,
|
||||
//GO(ldap_free_request,
|
||||
//GO(ldap_free_select_info,
|
||||
//GO(ldap_free_sort_keylist,
|
||||
//GO(ldap_free_urldesc,
|
||||
//GO(ldap_free_urllist,
|
||||
//GO(ldap_get_attribute_ber,
|
||||
GO(ldap_get_dn, pFpp)
|
||||
//GO(ldap_get_dn_ber,
|
||||
//GO(ldap_get_entry_controls,
|
||||
//GO(ldap_get_message_ber,
|
||||
GO(ldap_get_option, iFpip)
|
||||
GO(ldap_get_values, pFppp)
|
||||
GO(ldap_get_values_len, pFppp)
|
||||
//GO(ldap_gssapi_bind,
|
||||
//GO(ldap_gssapi_bind_s,
|
||||
//GO(ldap_host_connected_to,
|
||||
GO(ldap_init, pFpi)
|
||||
GO(ldap_init_fd, iFuipp)
|
||||
GO(ldap_initialize, iFpp)
|
||||
GO(ldap_install_tls, iFp)
|
||||
//GO(ldap_int_bisect_delete,
|
||||
//GO(ldap_int_bisect_find,
|
||||
//GO(ldap_int_bisect_insert,
|
||||
//GO(ldap_int_check_async_open,
|
||||
//GO(ldap_int_client_controls,
|
||||
//GO(ldap_int_connect_cbs,
|
||||
//GO(ldap_int_error_init,
|
||||
//GO(ldap_int_flush_request,
|
||||
//DATA(ldap_int_global_options,
|
||||
//DATAB(ldap_int_gmtime_mutex,
|
||||
//DATAB(ldap_int_hostname,
|
||||
//DATAB(ldap_int_hostname_mutex,
|
||||
//DATAB(ldap_int_inet4or6,
|
||||
//GO(ldap_int_initialize,
|
||||
//GO(ldap_int_initialize_global_options,
|
||||
//GO(ldap_int_msgtype2str,
|
||||
//GO(ldap_int_open_connection,
|
||||
//GO(ldap_int_parse_numericoid,
|
||||
//GO(ldap_int_parse_ruleid,
|
||||
//GO(ldap_int_poll,
|
||||
//GO(ldap_int_put_controls,
|
||||
//DATAB(ldap_int_resolv_mutex,
|
||||
//GO(ldap_int_sasl_bind,
|
||||
//GO(ldap_int_sasl_close,
|
||||
//GO(ldap_int_sasl_config,
|
||||
//GO(ldap_int_sasl_external,
|
||||
//GO(ldap_int_sasl_get_option,
|
||||
//GO(ldap_int_sasl_init,
|
||||
//GO(ldap_int_sasl_open,
|
||||
//GO(ldap_int_sasl_set_option,
|
||||
//GO(ldap_int_select,
|
||||
//GO(ldap_int_thread_destroy,
|
||||
//GO(ldap_int_thread_initialize,
|
||||
//GO(ldap_int_thread_pool_shutdown,
|
||||
//GO(ldap_int_thread_pool_startup,
|
||||
//GO(ldap_int_timeval_dup,
|
||||
//GO(ldap_int_tls_config,
|
||||
//GO(ldap_int_tls_destroy,
|
||||
//DATA(ldap_int_tls_impl,
|
||||
//GO(ldap_int_tls_start,
|
||||
//GO(ldap_int_utils_init,
|
||||
//GO(ldap_is_ldapi_url,
|
||||
//GO(ldap_is_ldaps_url,
|
||||
//GO(ldap_is_ldap_url,
|
||||
//GO(ldap_is_read_ready,
|
||||
//GO(ldap_is_write_ready,
|
||||
//GO(ldap_ld_free,
|
||||
//GO(ldap_log_printf,
|
||||
//GO(ldap_mark_select_clear,
|
||||
//GO(ldap_mark_select_read,
|
||||
//GO(ldap_mark_select_write,
|
||||
//GO(ldap_matchingrule2bv,
|
||||
//GO(ldap_matchingrule2name,
|
||||
//GO(ldap_matchingrule2str,
|
||||
//GO(ldap_matchingrule_free,
|
||||
//GO(ldap_matchingruleuse2bv,
|
||||
//GO(ldap_matchingruleuse2name,
|
||||
//GO(ldap_matchingruleuse2str,
|
||||
//GO(ldap_matchingruleuse_free,
|
||||
GO(ldap_memalloc, pFL)
|
||||
GO(ldap_memcalloc, pFLL)
|
||||
GO(ldap_memfree, vFp)
|
||||
GO(ldap_memrealloc, pFpL)
|
||||
GO(ldap_memvfree, vFp)
|
||||
//GO(ldap_modify,
|
||||
GO(ldap_modify_ext, iFpppppp)
|
||||
GO(ldap_modify_ext_s, iFppppp)
|
||||
//GO(ldap_modify_s,
|
||||
//GO(ldap_modrdn,
|
||||
//GO(ldap_modrdn2,
|
||||
//GO(ldap_modrdn2_s,
|
||||
//GO(ldap_modrdn_s,
|
||||
GO(ldap_mods_free, vFpp)
|
||||
//GO(ldap_msgdelete,
|
||||
GO(ldap_msgfree, iFp)
|
||||
GO(ldap_msgid, iFp)
|
||||
GO(ldap_msgtype, iFp)
|
||||
//GO(ldap_nameform2bv,
|
||||
//GO(ldap_nameform2name,
|
||||
//GO(ldap_nameform2str,
|
||||
//GO(ldap_nameform_free,
|
||||
//GO(ldap_new_connection,
|
||||
//GO(ldap_new_select_info,
|
||||
GO(ldap_next_attribute, pFppp)
|
||||
GO(ldap_next_entry, pFpp)
|
||||
//GO(ldap_next_message,
|
||||
GO(ldap_next_reference, pFpp)
|
||||
//GO(ldap_ntlm_bind,
|
||||
//GO(ldap_objectclass2bv,
|
||||
//GO(ldap_objectclass2name,
|
||||
//GO(ldap_objectclass2str,
|
||||
//GO(ldap_objectclass_free,
|
||||
GO(ldap_open, pFpi)
|
||||
//GO(ldap_open_defconn,
|
||||
//GO(ldap_open_internal_connection,
|
||||
//GO(ldap_parse_deref_control,
|
||||
//GO(ldap_parse_derefresponse_control,
|
||||
GO(ldap_parse_extended_result, iFppppi)
|
||||
//GO(ldap_parse_intermediate,
|
||||
//GO(ldap_parse_ntlm_bind_result,
|
||||
//GO(ldap_parse_page_control,
|
||||
//GO(ldap_parse_pageresponse_control,
|
||||
//GO(ldap_parse_passwd,
|
||||
//GO(ldap_parse_passwordpolicy_control,
|
||||
GO(ldap_parse_reference, iFppppi)
|
||||
//GO(ldap_parse_refresh,
|
||||
GO(ldap_parse_result, iFpppppppi)
|
||||
GO(ldap_parse_sasl_bind_result, iFpppi)
|
||||
//GO(ldap_parse_session_tracking_control,
|
||||
GO(ldap_parse_sortresponse_control, iFpppp)
|
||||
GO(ldap_parse_vlvresponse_control, iFpppppp)
|
||||
//GO(ldap_parse_whoami,
|
||||
//GO(ldap_passwd,
|
||||
//GO(ldap_passwd_s,
|
||||
//GO(ldap_passwordpolicy_err2txt,
|
||||
//GO(ldap_perror,
|
||||
//GO(ldap_put_vrFilter,
|
||||
//GO(ldap_pvt_bv2scope,
|
||||
//GO(ldap_pvt_csnstr,
|
||||
//GO(ldap_pvt_ctime,
|
||||
//GO(ldap_pvt_discard,
|
||||
//GO(ldap_pvt_filter_value_unescape,
|
||||
//GO(ldap_pvt_find_wildcard,
|
||||
//GO(ldap_pvt_get_controls,
|
||||
//GO(ldap_pvt_get_fqdn,
|
||||
//GO(ldap_pvt_get_hname,
|
||||
//GO(ldap_pvt_gethostbyaddr_a,
|
||||
//GO(ldap_pvt_gethostbyname_a,
|
||||
//GO(ldap_pvt_gettime,
|
||||
//GO(ldap_pvt_hex_unescape,
|
||||
//GO(ldap_pvt_put_control,
|
||||
//GO(ldap_pvt_put_filter,
|
||||
//GO(ldap_pvt_runqueue_find,
|
||||
//GO(ldap_pvt_runqueue_insert,
|
||||
//GO(ldap_pvt_runqueue_isrunning,
|
||||
//GO(ldap_pvt_runqueue_next_sched,
|
||||
//GO(ldap_pvt_runqueue_persistent_backload,
|
||||
//GO(ldap_pvt_runqueue_remove,
|
||||
//GO(ldap_pvt_runqueue_resched,
|
||||
//GO(ldap_pvt_runqueue_runtask,
|
||||
//GO(ldap_pvt_runqueue_stoptask,
|
||||
//GO(ldap_pvt_sasl_generic_install,
|
||||
//GO(ldap_pvt_sasl_generic_remove,
|
||||
//GO(ldap_pvt_sasl_getmechs,
|
||||
//GO(ldap_pvt_sasl_install,
|
||||
//GO(ldap_pvt_sasl_mutex_dispose,
|
||||
//GO(ldap_pvt_sasl_mutex_lock,
|
||||
//GO(ldap_pvt_sasl_mutex_new,
|
||||
//GO(ldap_pvt_sasl_mutex_unlock,
|
||||
//GO(ldap_pvt_sasl_remove,
|
||||
//GO(ldap_pvt_sasl_secprops,
|
||||
//GO(ldap_pvt_sasl_secprops_unparse,
|
||||
//GO(ldap_pvt_scope2bv,
|
||||
//GO(ldap_pvt_scope2str,
|
||||
//GO(ldap_pvt_search,
|
||||
//GO(ldap_pvt_search_s,
|
||||
//DATA(ldap_pvt_sockbuf_io_sasl_generic,
|
||||
//GO(ldap_pvt_str2lower,
|
||||
//GO(ldap_pvt_str2lowerbv,
|
||||
//GO(ldap_pvt_str2scope,
|
||||
//GO(ldap_pvt_str2upper,
|
||||
//GO(ldap_pvt_str2upperbv,
|
||||
//GO(ldap_pvt_strtok,
|
||||
//GO(ldap_pvt_thread_cond_broadcast,
|
||||
//GO(ldap_pvt_thread_cond_destroy,
|
||||
//GO(ldap_pvt_thread_cond_init,
|
||||
//GO(ldap_pvt_thread_cond_signal,
|
||||
//GO(ldap_pvt_thread_cond_wait,
|
||||
//GO(ldap_pvt_thread_create,
|
||||
//GO(ldap_pvt_thread_destroy,
|
||||
//GO(ldap_pvt_thread_exit,
|
||||
//GO(ldap_pvt_thread_get_concurrency,
|
||||
//GO(ldap_pvt_thread_initialize,
|
||||
//GO(ldap_pvt_thread_join,
|
||||
//GO(ldap_pvt_thread_key_create,
|
||||
//GO(ldap_pvt_thread_key_destroy,
|
||||
//GO(ldap_pvt_thread_key_getdata,
|
||||
//GO(ldap_pvt_thread_key_setdata,
|
||||
//GO(ldap_pvt_thread_kill,
|
||||
//GO(ldap_pvt_thread_mutex_destroy,
|
||||
//GO(ldap_pvt_thread_mutex_init,
|
||||
//GO(ldap_pvt_thread_mutex_lock,
|
||||
//GO(ldap_pvt_thread_mutex_trylock,
|
||||
//GO(ldap_pvt_thread_mutex_unlock,
|
||||
//GO(ldap_pvt_thread_pool_backload,
|
||||
//GO(ldap_pvt_thread_pool_context,
|
||||
//GO(ldap_pvt_thread_pool_context_reset,
|
||||
//GO(ldap_pvt_thread_pool_destroy,
|
||||
//GO(ldap_pvt_thread_pool_getkey,
|
||||
//GO(ldap_pvt_thread_pool_idle,
|
||||
//GO(ldap_pvt_thread_pool_init,
|
||||
//GO(ldap_pvt_thread_pool_maxthreads,
|
||||
//GO(ldap_pvt_thread_pool_pause,
|
||||
//GO(ldap_pvt_thread_pool_pausecheck,
|
||||
//GO(ldap_pvt_thread_pool_pausing,
|
||||
//GO(ldap_pvt_thread_pool_purgekey,
|
||||
//GO(ldap_pvt_thread_pool_query,
|
||||
//GO(ldap_pvt_thread_pool_resume,
|
||||
//GO(ldap_pvt_thread_pool_retract,
|
||||
//GO(ldap_pvt_thread_pool_setkey,
|
||||
//GO(ldap_pvt_thread_pool_submit,
|
||||
//GO(ldap_pvt_thread_pool_tid,
|
||||
//GO(ldap_pvt_thread_pool_unidle,
|
||||
//GO(ldap_pvt_thread_rdwr_destroy,
|
||||
//GO(ldap_pvt_thread_rdwr_init,
|
||||
//GO(ldap_pvt_thread_rdwr_rlock,
|
||||
//GO(ldap_pvt_thread_rdwr_rtrylock,
|
||||
//GO(ldap_pvt_thread_rdwr_runlock,
|
||||
//GO(ldap_pvt_thread_rdwr_wlock,
|
||||
//GO(ldap_pvt_thread_rdwr_wtrylock,
|
||||
//GO(ldap_pvt_thread_rdwr_wunlock,
|
||||
//GO(ldap_pvt_thread_rmutex_destroy,
|
||||
//GO(ldap_pvt_thread_rmutex_init,
|
||||
//GO(ldap_pvt_thread_rmutex_lock,
|
||||
//GO(ldap_pvt_thread_rmutex_trylock,
|
||||
//GO(ldap_pvt_thread_rmutex_unlock,
|
||||
//GO(ldap_pvt_thread_self,
|
||||
//GO(ldap_pvt_thread_set_concurrency,
|
||||
//GO(ldap_pvt_thread_sleep,
|
||||
//GO(ldap_pvt_thread_yield,
|
||||
//GO(ldap_pvt_tls_accept,
|
||||
//GO(ldap_pvt_tls_check_hostname,
|
||||
//GO(ldap_pvt_tls_ctx_free,
|
||||
//GO(ldap_pvt_tls_destroy,
|
||||
//GO(ldap_pvt_tls_get_my_dn,
|
||||
//GO(ldap_pvt_tls_get_option,
|
||||
//GO(ldap_pvt_tls_get_peer_dn,
|
||||
//GO(ldap_pvt_tls_get_strength,
|
||||
//GO(ldap_pvt_tls_init,
|
||||
//GO(ldap_pvt_tls_init_def_ctx,
|
||||
//GO(ldap_pvt_tls_inplace,
|
||||
//GO(ldap_pvt_tls_sb_ctx,
|
||||
//GO(ldap_pvt_tls_set_option,
|
||||
//GO(ldap_pvt_url_scheme2proto,
|
||||
//GO(ldap_pvt_url_scheme2tls,
|
||||
//GO(ldap_pvt_url_scheme_port,
|
||||
//GO(ldap_rdn2bv,
|
||||
//GO(ldap_rdn2bv_x,
|
||||
//GO(ldap_rdn2str,
|
||||
//GO(ldap_rdnfree,
|
||||
//GO(ldap_rdnfree_x,
|
||||
//GO(ldap_refresh,
|
||||
//GO(ldap_refresh_s,
|
||||
GO(ldap_rename, iFppppippp)
|
||||
//GO(ldap_rename2,
|
||||
//GO(ldap_rename2_s,
|
||||
GO(ldap_rename_s, iFppppipp)
|
||||
GO(ldap_result, iFppipp)
|
||||
//GO(ldap_result2error,
|
||||
//GO(ldap_return_request,
|
||||
GO(ldap_sasl_bind, iFppppppp)
|
||||
GO(ldap_sasl_bind_s, iFppppppp)
|
||||
//GO(ldap_sasl_interactive_bind,
|
||||
GOM(ldap_sasl_interactive_bind_s, iFEpppppupp)
|
||||
//GO(ldap_scherr2str,
|
||||
//GO(ldap_search,
|
||||
GO(ldap_search_ext, iFppippipppip)
|
||||
GO(ldap_search_ext_s, iFppippipppip)
|
||||
//GO(ldap_search_s,
|
||||
//GO(ldap_search_st,
|
||||
//GO(ldap_send_initial_request,
|
||||
//GO(ldap_send_server_request,
|
||||
//GO(ldap_send_unbind,
|
||||
//GO(ldap_set_ber_options,
|
||||
//GO(ldap_set_nextref_proc,
|
||||
GO(ldap_set_option, iFpip)
|
||||
//GOM(ldap_set_rebind_proc, iFEpBp)
|
||||
//GO(ldap_set_urllist_proc,
|
||||
GO(ldap_simple_bind, iFppp)
|
||||
GO(ldap_simple_bind_s, iFppp)
|
||||
//GO(ldap_sort_entries,
|
||||
//GO(ldap_sort_strcasecmp,
|
||||
//GO(ldap_sort_values,
|
||||
GO(ldap_start_tls, iFp)
|
||||
GO(ldap_start_tls_s, iFppp)
|
||||
//GO(ldap_str2attributetype,
|
||||
//GO(ldap_str2charray,
|
||||
//GO(ldap_str2contentrule,
|
||||
GO(ldap_str2dn, iFppu)
|
||||
//GO(ldap_str2matchingrule,
|
||||
//GO(ldap_str2matchingruleuse,
|
||||
//GO(ldap_str2nameform,
|
||||
//GO(ldap_str2objectclass,
|
||||
//GO(ldap_str2rdn,
|
||||
//GO(ldap_str2structurerule,
|
||||
//GO(ldap_str2syntax,
|
||||
GO(ldap_strdup, pFp)
|
||||
//GO(ldap_structurerule2bv,
|
||||
//GO(ldap_structurerule2name,
|
||||
//GO(ldap_structurerule2str,
|
||||
//GO(ldap_structurerule_free,
|
||||
//GO(ldap_sync_destroy,
|
||||
//GO(ldap_sync_init,
|
||||
//GO(ldap_sync_initialize,
|
||||
//GO(ldap_sync_init_refresh_and_persist,
|
||||
//GO(ldap_sync_init_refresh_only,
|
||||
//GO(ldap_sync_poll,
|
||||
//GO(ldap_syntax2bv,
|
||||
//GO(ldap_syntax2name,
|
||||
//GO(ldap_syntax2str,
|
||||
//GO(ldap_syntax_free,
|
||||
GO(ldap_tls_inplace, iFp)
|
||||
//GO(ldap_turn,
|
||||
//GO(ldap_turn_s,
|
||||
//GO(ldap_ucs_to_utf8s,
|
||||
GO(ldap_unbind, iFp)
|
||||
GO(ldap_unbind_ext, iFppp)
|
||||
GO(ldap_unbind_ext_s, iFppp)
|
||||
GO(ldap_unbind_s, iFp)
|
||||
//GO(ldap_url_desc2str,
|
||||
//GO(ldap_url_dup,
|
||||
//GO(ldap_url_duplist,
|
||||
//GO(ldap_url_list2hosts,
|
||||
//GO(ldap_url_list2urls,
|
||||
//GO(ldap_url_parse,
|
||||
//GO(ldap_url_parse_ext,
|
||||
//GO(ldap_url_parsehosts,
|
||||
//GO(ldap_url_parselist,
|
||||
//GO(ldap_url_parselist_ext,
|
||||
//GO(ldap_utf8_bytes,
|
||||
//GO(ldap_utf8_charlen,
|
||||
//GO(ldap_utf8_charlen2,
|
||||
//GO(ldap_utf8_chars,
|
||||
//GO(ldap_utf8_copy,
|
||||
//GO(ldap_utf8_isalnum,
|
||||
//GO(ldap_utf8_isalpha,
|
||||
//GO(ldap_utf8_isascii,
|
||||
//GO(ldap_utf8_isdigit,
|
||||
//GO(ldap_utf8_islower,
|
||||
//GO(ldap_utf8_isspace,
|
||||
//GO(ldap_utf8_isupper,
|
||||
//GO(ldap_utf8_isxdigit,
|
||||
//GO(ldap_utf8_next,
|
||||
//GO(ldap_utf8_offset,
|
||||
//GO(ldap_utf8_prev,
|
||||
//GO(ldap_utf8_strchr,
|
||||
//GO(ldap_utf8_strcspn,
|
||||
//GO(ldap_utf8_strpbrk,
|
||||
//GO(ldap_utf8_strspn,
|
||||
//GO(ldap_utf8_strtok,
|
||||
//GO(ldap_value_dup,
|
||||
GO(ldap_value_free, vFp)
|
||||
GO(ldap_value_free_len, vFp)
|
||||
//GO(ldap_whoami,
|
||||
//GO(ldap_whoami_s,
|
||||
//GO(ldap_X509dn2bv,
|
||||
//GO(ldap_x_mbs_to_utf8s,
|
||||
//GO(ldap_x_mb_to_utf8,
|
||||
//GO(ldap_x_ucs4_to_utf8,
|
||||
//GO(ldap_x_utf8s_to_mbs,
|
||||
//GO(ldap_x_utf8s_to_wcs,
|
||||
//GO(ldap_x_utf8_to_mb,
|
||||
//GO(ldap_x_utf8_to_ucs4,
|
||||
//GO(ldap_x_utf8_to_wc,
|
||||
//GO(ldap_x_wcs_to_utf8s,
|
||||
//GO(ldap_x_wc_to_utf8,
|
||||
//GO(ldif_close,
|
||||
//GO(ldif_countlines,
|
||||
//DATAB(ldif_debug,
|
||||
//GO(ldif_fetch_url,
|
||||
//GO(ldif_getline,
|
||||
//GO(ldif_is_not_printable,
|
||||
//GO(ldif_must_b64_encode_register,
|
||||
//GO(ldif_must_b64_encode_release,
|
||||
//GO(ldif_open,
|
||||
//GO(ldif_open_url,
|
||||
//GO(ldif_parse_line,
|
||||
//GO(ldif_parse_line2,
|
||||
//GO(ldif_put,
|
||||
//GO(ldif_put_wrap,
|
||||
//GO(ldif_read_record,
|
||||
//GO(ldif_sput,
|
||||
//GO(ldif_sput_wrap,
|
||||
@@ -763,6 +763,14 @@ EXPORT int my___isoc99_fscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t*
|
||||
}
|
||||
EXPORT int my_fscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b) __attribute__((alias("my___isoc99_fscanf")));
|
||||
|
||||
EXPORT int my___isoc99_scanf(x64emu_t* emu, void* fmt, uint64_t* b)
|
||||
{
|
||||
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 1);
|
||||
PREPARE_VALIST;
|
||||
|
||||
return vscanf(fmt, VARARGS);
|
||||
}
|
||||
|
||||
EXPORT int my___isoc99_sscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
|
||||
{
|
||||
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 2);
|
||||
@@ -1653,8 +1661,6 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
|
||||
{
|
||||
// need to use BOX64_PATH / PATH here...
|
||||
char* fullpath = ResolveFile(path, &my_context->box64_path);
|
||||
if(!fullpath)
|
||||
fullpath = strdup(path);
|
||||
// use fullpath...
|
||||
int self = isProcSelf(fullpath, "exe");
|
||||
int x64 = FileIsX64ELF(fullpath);
|
||||
@@ -1705,8 +1711,6 @@ EXPORT int32_t my_execlp(x64emu_t* emu, const char* path)
|
||||
{
|
||||
// need to use BOX64_PATH / PATH here...
|
||||
char* fullpath = ResolveFile(path, &my_context->box64_path);
|
||||
if(!fullpath)
|
||||
fullpath = strdup(path);
|
||||
// use fullpath...
|
||||
int self = isProcSelf(fullpath, "exe");
|
||||
int x64 = FileIsX64ELF(fullpath);
|
||||
|
||||
@@ -920,7 +920,7 @@ GO(__isnanl, iFD)
|
||||
GOW(isnanl, iFD)
|
||||
GOM(__isoc99_fscanf, iFEppV)
|
||||
//GO(__isoc99_fwscanf, iFppV)
|
||||
//GO(__isoc99_scanf, iFpV)
|
||||
GOM(__isoc99_scanf, iFEpV)
|
||||
GOM(__isoc99_sscanf, iFEppV)
|
||||
//GO(__isoc99_swscanf, iFppV)
|
||||
GOM(__isoc99_vfscanf, iFEppp)
|
||||
|
||||
@@ -64,7 +64,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag)
|
||||
CLEARERR
|
||||
if(filename) {
|
||||
char* rfilename = (char*)filename;
|
||||
if(box64_zoom && strstr(rfilename, "/libturbojpeg.so")) {
|
||||
if(box64_zoom && rfilename && strstr(rfilename, "/libturbojpeg.so")) {
|
||||
void* sys = my_dlopen(emu, "libturbojpeg.so.0", flag);
|
||||
if(sys)
|
||||
return sys;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#error meh!
|
||||
#endif
|
||||
|
||||
//GO(xcb_shape_combine,
|
||||
//GO(xcb_shape_combine_checked,
|
||||
GO(xcb_shape_combine, pFpuuupwwp)
|
||||
GO(xcb_shape_combine_checked, pFpuuupwwp)
|
||||
//GO(xcb_shape_get_rectangles,
|
||||
//GO(xcb_shape_get_rectangles_rectangles,
|
||||
//GO(xcb_shape_get_rectangles_rectangles_iterator,
|
||||
@@ -26,9 +26,9 @@ GO(xcb_shape_mask_checked, pFpuuuwwu)
|
||||
//GO(xcb_shape_query_extents,
|
||||
//GO(xcb_shape_query_extents_reply,
|
||||
//GO(xcb_shape_query_extents_unchecked,
|
||||
//GO(xcb_shape_query_version,
|
||||
//GO(xcb_shape_query_version_reply,
|
||||
//GO(xcb_shape_query_version_unchecked,
|
||||
GO(xcb_shape_query_version, pFp)
|
||||
GO(xcb_shape_query_version_reply, pFppp)
|
||||
GO(xcb_shape_query_version_unchecked, pFp)
|
||||
//GO(xcb_shape_rectangles,
|
||||
//GO(xcb_shape_rectangles_checked,
|
||||
//GO(xcb_shape_rectangles_rectangles,
|
||||
|
||||
@@ -1606,3 +1606,10 @@ DATAM(xmlFree, sizeof(void*))
|
||||
DATAM(xmlMalloc, sizeof(void*))
|
||||
DATAM(xmlRealloc, sizeof(void*))
|
||||
DATAM(xmlMemStrdup, sizeof(void*))
|
||||
|
||||
DATA(xmlIsDigitGroup, 2*sizeof(void*)+2*sizeof(int))
|
||||
DATA(xmlStringText, sizeof(void*))
|
||||
DATA(xmlStringTextNoenc, sizeof(void*))
|
||||
DATA(xmlIsCombiningGroup, 2*sizeof(void*)+2*sizeof(int))
|
||||
DATA(xmlIsExtenderGroup, 2*sizeof(void*)+2*sizeof(int))
|
||||
DATA(xmlIsBaseCharGroup, 2*sizeof(void*)+2*sizeof(int))
|
||||
Executable
+135
@@ -0,0 +1,135 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "wrappedlibs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "wrapper.h"
|
||||
#include "bridge.h"
|
||||
#include "librarian/library_private.h"
|
||||
#include "x64emu.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "librarian.h"
|
||||
#include "callback.h"
|
||||
|
||||
const char *xsltName =
|
||||
#ifdef ANDROID
|
||||
"libxslt.so"
|
||||
#else
|
||||
"libxslt.so.1"
|
||||
#endif
|
||||
;
|
||||
#define LIBNAME xslt
|
||||
static library_t *my_lib = NULL;
|
||||
|
||||
typedef void (*vFp_t) (void*);
|
||||
typedef int (*iFppp_t) (void*, void*, void*);
|
||||
|
||||
#define SUPER() \
|
||||
GO(xsltRegisterExtModuleFunction, iFppp_t) \
|
||||
GO(xsltSetLoaderFunc, vFp_t) \
|
||||
|
||||
typedef struct xslt_my_s {
|
||||
// functions
|
||||
#define GO(A, B) B A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
} xslt_my_t;
|
||||
|
||||
void* getXsltMy(library_t* lib)
|
||||
{
|
||||
xslt_my_t* my = (xslt_my_t*)calloc(1, sizeof(xslt_my_t));
|
||||
#define GO(A, W) my->A = (W)dlsym(lib->priv.w.lib, #A);
|
||||
SUPER()
|
||||
#undef GO
|
||||
return my;
|
||||
}
|
||||
#undef SUPER
|
||||
|
||||
void freeXsltMy(void* lib)
|
||||
{
|
||||
//xslt_my_t *my = (xslt_my_t *)lib;
|
||||
}
|
||||
|
||||
#define SUPER() \
|
||||
GO(0) \
|
||||
GO(1) \
|
||||
GO(2) \
|
||||
GO(3) \
|
||||
GO(4)
|
||||
|
||||
// xmlXPathFunction ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_xmlXPathFunction_fct_##A = 0; \
|
||||
static void my_xmlXPathFunction_##A(void* a, int b) \
|
||||
{ \
|
||||
RunFunction(my_context, my_xmlXPathFunction_fct_##A, 2, a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* find_xmlXPathFunction_Fct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_xmlXPathFunction_fct_##A == (uintptr_t)fct) return my_xmlXPathFunction_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_xmlXPathFunction_fct_##A == 0) {my_xmlXPathFunction_fct_##A = (uintptr_t)fct; return my_xmlXPathFunction_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libxslt xmlXPathFunction callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// xsltDocLoaderFunc ...
|
||||
#define GO(A) \
|
||||
static uintptr_t my_xsltDocLoaderFunc_fct_##A = 0; \
|
||||
static void* my_xsltDocLoaderFunc_##A(void* a, void* b, int c, void* d, int e) \
|
||||
{ \
|
||||
return (void*)RunFunction(my_context, my_xsltDocLoaderFunc_fct_##A, 5, a, b, c, d, e); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* find_xsltDocLoaderFunc_Fct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_xsltDocLoaderFunc_fct_##A == (uintptr_t)fct) return my_xsltDocLoaderFunc_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_xsltDocLoaderFunc_fct_##A == 0) {my_xsltDocLoaderFunc_fct_##A = (uintptr_t)fct; return my_xsltDocLoaderFunc_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libxslt xsltDocLoaderFunc callback\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef SUPER
|
||||
|
||||
EXPORT int my_xsltRegisterExtModuleFunction(x64emu_t* emu, void* name, void* URI, void* f)
|
||||
{
|
||||
xslt_my_t* my = (xslt_my_t*)my_lib->priv.w.p2;
|
||||
|
||||
return my->xsltRegisterExtModuleFunction(name, URI, find_xmlXPathFunction_Fct(f));
|
||||
}
|
||||
|
||||
EXPORT void my_xsltSetLoaderFunc(x64emu_t* emu, void* f)
|
||||
{
|
||||
xslt_my_t* my = (xslt_my_t*)my_lib->priv.w.p2;
|
||||
|
||||
my->xsltSetLoaderFunc(find_xsltDocLoaderFunc_Fct(f));
|
||||
}
|
||||
|
||||
#define CUSTOM_INIT \
|
||||
lib->priv.w.p2 = getXsltMy(lib); \
|
||||
my_lib = lib;
|
||||
|
||||
#define CUSTOM_FINI \
|
||||
freeXsltMy(lib->priv.w.p2); \
|
||||
free(lib->priv.w.p2); \
|
||||
my_lib = NULL;
|
||||
|
||||
#include "wrappedlib_init.h"
|
||||
Executable
+247
@@ -0,0 +1,247 @@
|
||||
#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
|
||||
#error meh!
|
||||
#endif
|
||||
|
||||
GO(xslAddCall, iFpp)
|
||||
GO(xslDropCall, vFv)
|
||||
GO(xslHandleDebugger, vFpppp)
|
||||
//GO(xsltAddKey,
|
||||
GO(xsltAddStackElemList, iFpp)
|
||||
//GO(xsltAddTemplate,
|
||||
GO(xsltAllocateExtra, iFp)
|
||||
GO(xsltAllocateExtraCtxt, iFp)
|
||||
//GO(xsltApplyAttributeSet,
|
||||
GO(xsltApplyImports, vFpppp)
|
||||
GO(xsltApplyOneTemplate, vFppppp)
|
||||
GO(xsltApplyStripSpaces, vFpp)
|
||||
GO(xsltApplyStylesheet, pFppp)
|
||||
GO(xsltApplyStylesheetUser, pFpppppp)
|
||||
GO(xsltApplyTemplates, vFpppp)
|
||||
GO(xsltAttribute, vFpppp)
|
||||
//GO(xsltAttrListTemplateProcess,
|
||||
//GO(xsltAttrTemplateProcess,
|
||||
//GO(xsltAttrTemplateValueProcess,
|
||||
//GO(xsltAttrTemplateValueProcessNode,
|
||||
GO(xsltCalibrateAdjust, vFl)
|
||||
GO(xsltCallTemplate, vFpppp)
|
||||
GO(xsltCheckExtPrefix, iFpp)
|
||||
GO(xsltCheckExtURI, iFpp)
|
||||
GO(xsltCheckRead, iFppp)
|
||||
GO(xsltCheckWrite, iFppp)
|
||||
GO(xsltChoose, vFpppp)
|
||||
GO(xsltCleanupGlobals, vFv)
|
||||
//GO(xsltCleanupTemplates,
|
||||
GO(xsltComment, vFpppp)
|
||||
GO(xsltCompileAttr, vFpp)
|
||||
//GO(xsltCompilePattern,
|
||||
GO(xsltComputeSortResult, pFpp)
|
||||
GO(xsltCopy, vFpppp)
|
||||
//GO(xsltCopyNamespace,
|
||||
//GO(xsltCopyNamespaceList,
|
||||
GO(xsltCopyOf, vFpppp)
|
||||
GO(xsltCopyTextString, pFpppi)
|
||||
//GO(xsltCopyTree,
|
||||
GO(xsltCreateRVT, pFp)
|
||||
GO(xsltDebug, vFpppp)
|
||||
GO(xsltDebugDumpExtensions, vFp)
|
||||
GO(xsltDebugGetDefaultTrace, iFv)
|
||||
GO(xsltDebugSetDefaultTrace, vFi)
|
||||
GO(xsltDecimalFormatGetByName, pFpp)
|
||||
GO(xsltDecimalFormatGetByQName, pFppp)
|
||||
GO(xsltDefaultSortFunction, vFppi)
|
||||
//GO(xsltDocumentComp,
|
||||
GO(xsltDocumentElem, vFpppp)
|
||||
//GO(xsltDocumentFunction,
|
||||
GO(xsltDocumentSortFunction, vFp)
|
||||
GO(xsltDoSortFunction, vFppi)
|
||||
GO(xsltElement, vFpppp)
|
||||
//GO(xsltElementAvailableFunction,
|
||||
//GO(xsltEvalAttrValueTemplate,
|
||||
GO(xsltEvalAVT, pFppp)
|
||||
GO(xsltEvalGlobalVariables, iFp)
|
||||
GO(xsltEvalOneUserParam, iFppp)
|
||||
//GO(xsltEvalStaticAttrValueTemplate,
|
||||
//GO(xsltEvalTemplateString,
|
||||
GO(xsltEvalUserParams, iFpp)
|
||||
//GO(xsltEvalXPathPredicate,
|
||||
//GO(xsltEvalXPathString,
|
||||
//GO(xsltEvalXPathStringNs,
|
||||
//GOM(xsltExtElementLookup, BFEppp)
|
||||
GO(xsltExtensionInstructionResultFinalize, iFp)
|
||||
GO(xsltExtensionInstructionResultRegister, iFpp)
|
||||
//GOM(xsltExtModuleElementLookup, BFEpp)
|
||||
//GOM(xsltExtModuleElementPreComputeLookup, BFEpp)
|
||||
//GOM(xsltExtModuleFunctionLookup, BFEpp)
|
||||
//GOM(xsltExtModuleTopLevelLookup, BFEpp)
|
||||
GO(xsltFindDocument, pFpp)
|
||||
GO(xsltFindElemSpaceHandling, iFpp)
|
||||
GO(xsltFindTemplate, pFppp)
|
||||
GO(xsltFlagRVTs, iFppp)
|
||||
GO(xsltForEach, vFpppp)
|
||||
GO(xsltFormatNumberConversion, iFppdp)
|
||||
//GO(xsltFormatNumberFunction,
|
||||
//GO(xsltFreeAttributeSetsHashes,
|
||||
GO(xsltFreeAVTList, vFp)
|
||||
//GO(xsltFreeCompMatchList,
|
||||
GO(xsltFreeCtxtExts, vFp)
|
||||
//GO(xsltFreeDocumentKeys,
|
||||
GO(xsltFreeDocuments, vFp)
|
||||
GO(xsltFreeExts, vFp)
|
||||
GO(xsltFreeGlobalVariables, vFp)
|
||||
//GO(xsltFreeKeys,
|
||||
//GO(xsltFreeLocale,
|
||||
//GO(xsltFreeNamespaceAliasHashes,
|
||||
GO(xsltFreeRVTs, vFp)
|
||||
GO(xsltFreeSecurityPrefs, vFp)
|
||||
GO(xsltFreeStackElemList, vFp)
|
||||
GO(xsltFreeStyleDocuments, vFp)
|
||||
//GO(xsltFreeStylePreComps,
|
||||
GO(xsltFreeStylesheet, vFp)
|
||||
//GO(xsltFreeTemplateHashes,
|
||||
GO(xsltFreeTransformContext, vFp)
|
||||
//GO(xsltFunctionAvailableFunction,
|
||||
GO(xsltFunctionNodeSet, vFpi)
|
||||
//GO(xsltGenerateIdFunction,
|
||||
GO(xsltGetCNsProp, pFpppp)
|
||||
GO(xsltGetDebuggerStatus, iFv)
|
||||
//GO(xsltGetDefaultSecurityPrefs,
|
||||
GO(xsltGetExtData, pFpp)
|
||||
GO(xsltGetExtInfo, pFpp)
|
||||
//GO(xsltGetKey,
|
||||
//GO(xsltGetNamespace,
|
||||
GO(xsltGetNsProp, pFppp)
|
||||
//GO(xsltGetPlainNamespace,
|
||||
GO(xsltGetProfileInformation, pFp)
|
||||
GO(xsltGetQNameURI, pFpp)
|
||||
GO(xsltGetQNameURI2, pFppp)
|
||||
GO(xsltGetSecurityPrefs, pFpi)
|
||||
//GO(xsltGetSpecialNamespace,
|
||||
//GO(xsltGetTemplate,
|
||||
GO(xsltGetUTF8Char, iFpp)
|
||||
GO(xsltGetXIncludeDefault, iFv)
|
||||
GO(xsltIf, vFpppp)
|
||||
GO(xsltInit, vFv)
|
||||
GO(xsltInitAllDocKeys, iFp)
|
||||
GO(xsltInitCtxtExts, iFp)
|
||||
//GO(xsltInitCtxtKey,
|
||||
//GO(xsltInitCtxtKeys,
|
||||
//GOM(xsltInitElemPreComp, vFEpppBB)
|
||||
GO(xsltInitGlobals, vFv)
|
||||
GO(xsltIsBlank, iFp)
|
||||
//GO(xsltKeyFunction,
|
||||
GO(xsltLoadDocument, pFpp)
|
||||
GO(xsltLoadStyleDocument, pFpp)
|
||||
GO(xsltLoadStylesheetPI, pFp)
|
||||
//GO(xsltLocaleStrcmp,
|
||||
GO(xsltLocalVariablePop, vFpii)
|
||||
GO(xsltLocalVariablePush, iFppi)
|
||||
GO(xsltMessage, vFppp)
|
||||
//GO(xsltNamespaceAlias,
|
||||
GO(xsltNeedElemSpaceHandling, iFp)
|
||||
GO(xsltNewDocument, pFpp)
|
||||
//GOM(xsltNewElemPreComp, pFEppB)
|
||||
//GO(xsltNewLocale,
|
||||
GO(xsltNewSecurityPrefs, pFv)
|
||||
GO(xsltNewStyleDocument, pFpp)
|
||||
GO(xsltNewStylesheet, pFv)
|
||||
GO(xsltNewTransformContext, pFpp)
|
||||
GO(xsltNextImport, pFp)
|
||||
//GO(xsltNormalizeCompSteps,
|
||||
GO(xsltNumber, vFpppp)
|
||||
GO(xsltNumberFormat, vFppp)
|
||||
GO(xsltParseAnyXSLTElem, iFpp)
|
||||
GO(xsltParseGlobalParam, vFpp)
|
||||
GO(xsltParseGlobalVariable, vFpp)
|
||||
GO(xsltParseSequenceConstructor, vFpp)
|
||||
//GO(xsltParseStylesheetAttributeSet,
|
||||
GO(xsltParseStylesheetCallerParam, pFpp)
|
||||
GO(xsltParseStylesheetDoc, pFp)
|
||||
GO(xsltParseStylesheetFile, pFp)
|
||||
GO(xsltParseStylesheetImport, iFpp)
|
||||
GO(xsltParseStylesheetImportedDoc, pFpp)
|
||||
GO(xsltParseStylesheetInclude, iFpp)
|
||||
GO(xsltParseStylesheetOutput, vFpp)
|
||||
GO(xsltParseStylesheetParam, vFpp)
|
||||
GO(xsltParseStylesheetProcess, pFpp)
|
||||
GO(xsltParseStylesheetVariable, vFpp)
|
||||
//GO(xsltParseTemplateContent,
|
||||
GO(xsltPointerListAddSize, iFppi)
|
||||
GO(xsltPointerListClear, vFp)
|
||||
GO(xsltPointerListCreate, pFi)
|
||||
GO(xsltPointerListFree, vFp)
|
||||
GO(xsltPreComputeExtModuleElement, pFpp)
|
||||
GO(xsltPrintErrorContext, vFppp)
|
||||
GO(xsltProcessingInstruction, vFpppp)
|
||||
GO(xsltProcessOneNode, vFppp)
|
||||
GO(xsltProfileStylesheet, pFpppp)
|
||||
GO(xsltQuoteOneUserParam, iFppp)
|
||||
GO(xsltQuoteUserParams, iFpp)
|
||||
GO(xsltRegisterAllElement, vFp)
|
||||
GO(xsltRegisterAllExtras, vFv)
|
||||
//GO(xsltRegisterAllFunctions,
|
||||
//GOM(xsltRegisterExtElement, iFEpppB)
|
||||
//GOM(xsltRegisterExtFunction, iFEpppB)
|
||||
//GOM(xsltRegisterExtModule, iFEpBB)
|
||||
//GOM(xsltRegisterExtModuleElement, iFEppBB)
|
||||
//GOM(xsltRegisterExtModuleFull, iFEpBBBB)
|
||||
GOM(xsltRegisterExtModuleFunction, iFEppp)
|
||||
//GOM(xsltRegisterExtModuleTopLevel, iFEppB)
|
||||
GO(xsltRegisterExtPrefix, iFppp)
|
||||
GO(xsltRegisterExtras, vFp)
|
||||
GO(xsltRegisterLocalRVT, iFpp)
|
||||
GO(xsltRegisterPersistRVT, iFpp)
|
||||
GO(xsltRegisterTestModule, vFv)
|
||||
GO(xsltRegisterTmpRVT, iFpp)
|
||||
GO(xsltReleaseRVT, vFpp)
|
||||
//GO(xsltResolveStylesheetAttributeSet,
|
||||
GO(xsltRestoreDocumentNamespaces, iFpp)
|
||||
GO(xsltRunStylesheet, iFpppppp)
|
||||
GO(xsltRunStylesheetUser, iFpppppppp)
|
||||
GO(xsltSaveProfiling, vFpp)
|
||||
GO(xsltSaveResultTo, iFppp)
|
||||
GO(xsltSaveResultToFd, iFipp)
|
||||
GO(xsltSaveResultToFile, iFppp)
|
||||
GO(xsltSaveResultToFilename, iFpppi)
|
||||
GO(xsltSaveResultToString, iFpppp)
|
||||
GO(xsltSecurityAllow, iFppp)
|
||||
GO(xsltSecurityForbid, iFppp)
|
||||
GO(xsltSetCtxtParseOptions, iFpi)
|
||||
GO(xsltSetCtxtSecurityPrefs, iFpp)
|
||||
//GOM(xsltSetCtxtSortFunc, vFEpB)
|
||||
//GOM(xsltSetDebuggerCallbacks, iFip)
|
||||
GO(xsltSetDebuggerStatus, vFi)
|
||||
GO(xsltSetDefaultSecurityPrefs, vFp)
|
||||
//GOM(xsltSetGenericDebugFunc, vFEpB)
|
||||
//GOM(xsltSetGenericErrorFunc, vFEpB)
|
||||
GOM(xsltSetLoaderFunc, vFEp)
|
||||
//GOM(xsltSetSecurityPrefs, iFEppB)
|
||||
//GOM(xsltSetSortFunc, vFEp)
|
||||
//GO(MxsltSetTransformErrorFunc, vFEppB)
|
||||
GO(xsltSetXIncludeDefault, vFi)
|
||||
GO(xsltShutdownCtxtExts, vFp)
|
||||
GO(xsltShutdownExts, vFp)
|
||||
GO(xsltSort, vFpppp)
|
||||
GO(xsltSplitQName, pFppp)
|
||||
//GO(xsltStrxfrm,
|
||||
GO(xsltStyleGetExtData, pFpp)
|
||||
//GO(xsltStylePreCompute,
|
||||
GO(xsltStyleStylesheetLevelGetExtData, pFpp)
|
||||
//GO(xsltSystemPropertyFunction,
|
||||
//GO(xsltTemplateProcess,
|
||||
//GO(xsltTestCompMatchList,
|
||||
GO(xsltText, vFpppp)
|
||||
GO(xsltTimestamp, lFv)
|
||||
GO(xsltTransformError, vFpppppppppppppppp) //vaarg
|
||||
GO(xsltUninit, vFv)
|
||||
//GO(xsltUnparsedEntityURIFunction,
|
||||
GO(xsltUnregisterExtModule, iFp)
|
||||
GO(xsltUnregisterExtModuleElement, iFpp)
|
||||
GO(xsltUnregisterExtModuleFunction, iFpp)
|
||||
GO(xsltUnregisterExtModuleTopLevel, iFpp)
|
||||
GO(xsltValueOf, vFpppp)
|
||||
GO(xsltVariableLookup, pFppp)
|
||||
GO(xsltXPathCompile, pFpp)
|
||||
GO(xsltXPathCompileFlags, pFppi)
|
||||
GO(xsltXPathFunctionLookup, pFppp)
|
||||
GO(xsltXPathGetTransformContext, pFp)
|
||||
//GO(xsltXPathVariableLookup,
|
||||
+154
-12
@@ -1,12 +1,154 @@
|
||||
div 1, 1 => 1 / 0
|
||||
div 10, 5 => 2 / 0
|
||||
div 10, 3 => 3 / 1
|
||||
div 1, 18446744073709551615 => 0 / 1
|
||||
div 10, 18446744073709551613 => 0 / 10
|
||||
div 18446744073709551606, 18446744073709551613 => 0 / 18446744073709551606
|
||||
idiv 1, 1 => 1 / 0
|
||||
idiv 10, 5 => 2 / 0
|
||||
idiv 10, 3 => 3 / 1
|
||||
idiv 1, -1 => -1 / 0
|
||||
idiv 10, -3 => -3 / 1
|
||||
idiv -10, -3 => 3 / -1
|
||||
ucomiss 1.000000, 2.000000 => 0x202
|
||||
ucomiss 2.000000, 1.000000 => 0x203
|
||||
ucomiss 1.000000, inf => 0x202
|
||||
ucomiss inf, 1.000000 => 0x203
|
||||
ucomiss 1.000000, -inf => 0x203
|
||||
ucomiss -inf, 1.000000 => 0x202
|
||||
ucomiss 1.000000, nan => 0x247
|
||||
ucomiss nan, 1.000000 => 0x247
|
||||
ucomiss 1.000000, 1.000000 => 0x242
|
||||
ucomiss 1.000000, 1.000000 => 0x242
|
||||
ucomiss inf, inf => 0x242
|
||||
ucomiss -inf, inf => 0x202
|
||||
ucomiss inf, -inf => 0x203
|
||||
ucomiss nan, nan => 0x247
|
||||
minss 1, 2 => 1
|
||||
minss 2, 1 => 1
|
||||
minss -inf, 2 => -inf
|
||||
minss 2, -inf => -inf
|
||||
minss inf, 2 => 2
|
||||
minss 2, inf => 2
|
||||
minss nan, 2 => 2
|
||||
minss 2, nan => nan
|
||||
minss nan, 3.40282e+38 => 3.40282e+38
|
||||
minss 3.40282e+38, nan => nan
|
||||
minss -inf, 3.40282e+38 => -inf
|
||||
minss 3.40282e+38, -inf => -inf
|
||||
minss inf, 3.40282e+38 => 3.40282e+38
|
||||
minss 3.40282e+38, inf => 3.40282e+38
|
||||
maxss 1, 2 => 2
|
||||
maxss 2, 1 => 2
|
||||
maxss -inf, 2 => 2
|
||||
maxss 2, -inf => 2
|
||||
maxss inf, 2 => inf
|
||||
maxss 2, inf => inf
|
||||
maxss nan, 2 => 2
|
||||
maxss 2, nan => nan
|
||||
maxss nan, 3.40282e+38 => 3.40282e+38
|
||||
maxss 3.40282e+38, nan => nan
|
||||
maxss -inf, 3.40282e+38 => 3.40282e+38
|
||||
maxss 3.40282e+38, -inf => 3.40282e+38
|
||||
maxss inf, 3.40282e+38 => inf
|
||||
maxss 3.40282e+38, inf => inf
|
||||
cmpss 0 1.000000, 2.000000 => 0x0
|
||||
cmpss 0 2.000000, 1.000000 => 0x0
|
||||
cmpss 0 1.000000, inf => 0x0
|
||||
cmpss 0 inf, 1.000000 => 0x0
|
||||
cmpss 0 1.000000, -inf => 0x0
|
||||
cmpss 0 -inf, 1.000000 => 0x0
|
||||
cmpss 0 1.000000, nan => 0x0
|
||||
cmpss 0 nan, 1.000000 => 0x0
|
||||
cmpss 0 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 0 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 0 inf, inf => 0xffffffff
|
||||
cmpss 0 -inf, inf => 0x0
|
||||
cmpss 0 inf, -inf => 0x0
|
||||
cmpss 0 nan, nan => 0x0
|
||||
cmpss 1 1.000000, 2.000000 => 0xffffffff
|
||||
cmpss 1 2.000000, 1.000000 => 0x0
|
||||
cmpss 1 1.000000, inf => 0xffffffff
|
||||
cmpss 1 inf, 1.000000 => 0x0
|
||||
cmpss 1 1.000000, -inf => 0x0
|
||||
cmpss 1 -inf, 1.000000 => 0xffffffff
|
||||
cmpss 1 1.000000, nan => 0x0
|
||||
cmpss 1 nan, 1.000000 => 0x0
|
||||
cmpss 1 1.000000, 1.000000 => 0x0
|
||||
cmpss 1 1.000000, 1.000000 => 0x0
|
||||
cmpss 1 inf, inf => 0x0
|
||||
cmpss 1 -inf, inf => 0xffffffff
|
||||
cmpss 1 inf, -inf => 0x0
|
||||
cmpss 1 nan, nan => 0x0
|
||||
cmpss 2 1.000000, 2.000000 => 0xffffffff
|
||||
cmpss 2 2.000000, 1.000000 => 0x0
|
||||
cmpss 2 1.000000, inf => 0xffffffff
|
||||
cmpss 2 inf, 1.000000 => 0x0
|
||||
cmpss 2 1.000000, -inf => 0x0
|
||||
cmpss 2 -inf, 1.000000 => 0xffffffff
|
||||
cmpss 2 1.000000, nan => 0x0
|
||||
cmpss 2 nan, 1.000000 => 0x0
|
||||
cmpss 2 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 2 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 2 inf, inf => 0xffffffff
|
||||
cmpss 2 -inf, inf => 0xffffffff
|
||||
cmpss 2 inf, -inf => 0x0
|
||||
cmpss 2 nan, nan => 0x0
|
||||
cmpss 3 1.000000, 2.000000 => 0x0
|
||||
cmpss 3 2.000000, 1.000000 => 0x0
|
||||
cmpss 3 1.000000, inf => 0x0
|
||||
cmpss 3 inf, 1.000000 => 0x0
|
||||
cmpss 3 1.000000, -inf => 0x0
|
||||
cmpss 3 -inf, 1.000000 => 0x0
|
||||
cmpss 3 1.000000, nan => 0xffffffff
|
||||
cmpss 3 nan, 1.000000 => 0xffffffff
|
||||
cmpss 3 1.000000, 1.000000 => 0x0
|
||||
cmpss 3 1.000000, 1.000000 => 0x0
|
||||
cmpss 3 inf, inf => 0x0
|
||||
cmpss 3 -inf, inf => 0x0
|
||||
cmpss 3 inf, -inf => 0x0
|
||||
cmpss 3 nan, nan => 0xffffffff
|
||||
cmpss 4 1.000000, 2.000000 => 0xffffffff
|
||||
cmpss 4 2.000000, 1.000000 => 0xffffffff
|
||||
cmpss 4 1.000000, inf => 0xffffffff
|
||||
cmpss 4 inf, 1.000000 => 0xffffffff
|
||||
cmpss 4 1.000000, -inf => 0xffffffff
|
||||
cmpss 4 -inf, 1.000000 => 0xffffffff
|
||||
cmpss 4 1.000000, nan => 0xffffffff
|
||||
cmpss 4 nan, 1.000000 => 0xffffffff
|
||||
cmpss 4 1.000000, 1.000000 => 0x0
|
||||
cmpss 4 1.000000, 1.000000 => 0x0
|
||||
cmpss 4 inf, inf => 0x0
|
||||
cmpss 4 -inf, inf => 0xffffffff
|
||||
cmpss 4 inf, -inf => 0xffffffff
|
||||
cmpss 4 nan, nan => 0xffffffff
|
||||
cmpss 5 1.000000, 2.000000 => 0x0
|
||||
cmpss 5 2.000000, 1.000000 => 0xffffffff
|
||||
cmpss 5 1.000000, inf => 0x0
|
||||
cmpss 5 inf, 1.000000 => 0xffffffff
|
||||
cmpss 5 1.000000, -inf => 0xffffffff
|
||||
cmpss 5 -inf, 1.000000 => 0x0
|
||||
cmpss 5 1.000000, nan => 0xffffffff
|
||||
cmpss 5 nan, 1.000000 => 0xffffffff
|
||||
cmpss 5 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 5 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 5 inf, inf => 0xffffffff
|
||||
cmpss 5 -inf, inf => 0x0
|
||||
cmpss 5 inf, -inf => 0xffffffff
|
||||
cmpss 5 nan, nan => 0xffffffff
|
||||
cmpss 6 1.000000, 2.000000 => 0x0
|
||||
cmpss 6 2.000000, 1.000000 => 0xffffffff
|
||||
cmpss 6 1.000000, inf => 0x0
|
||||
cmpss 6 inf, 1.000000 => 0xffffffff
|
||||
cmpss 6 1.000000, -inf => 0xffffffff
|
||||
cmpss 6 -inf, 1.000000 => 0x0
|
||||
cmpss 6 1.000000, nan => 0xffffffff
|
||||
cmpss 6 nan, 1.000000 => 0xffffffff
|
||||
cmpss 6 1.000000, 1.000000 => 0x0
|
||||
cmpss 6 1.000000, 1.000000 => 0x0
|
||||
cmpss 6 inf, inf => 0x0
|
||||
cmpss 6 -inf, inf => 0x0
|
||||
cmpss 6 inf, -inf => 0xffffffff
|
||||
cmpss 6 nan, nan => 0xffffffff
|
||||
cmpss 7 1.000000, 2.000000 => 0xffffffff
|
||||
cmpss 7 2.000000, 1.000000 => 0xffffffff
|
||||
cmpss 7 1.000000, inf => 0xffffffff
|
||||
cmpss 7 inf, 1.000000 => 0xffffffff
|
||||
cmpss 7 1.000000, -inf => 0xffffffff
|
||||
cmpss 7 -inf, 1.000000 => 0xffffffff
|
||||
cmpss 7 1.000000, nan => 0x0
|
||||
cmpss 7 nan, 1.000000 => 0x0
|
||||
cmpss 7 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 7 1.000000, 1.000000 => 0xffffffff
|
||||
cmpss 7 inf, inf => 0xffffffff
|
||||
cmpss 7 -inf, inf => 0xffffffff
|
||||
cmpss 7 inf, -inf => 0xffffffff
|
||||
cmpss 7 nan, nan => 0x0
|
||||
Binary file not shown.
+177
-27
@@ -6,45 +6,195 @@
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__x86_64__)
|
||||
uint64_t _div_(uint64_t a, uint64_t b, uint64_t *r)
|
||||
uint64_t _ucomiss_(float a, float b)
|
||||
{
|
||||
uint64_t ret, rem;
|
||||
uint64_t ret;
|
||||
asm volatile (
|
||||
"xor %%rdx, %%rdx\n"
|
||||
"div %%rcx\n"
|
||||
"mov %%rdx, %%rbx\n"
|
||||
:"=a" (ret), "=b" (rem):"a" (a), "c" (b):"rdx","cc");
|
||||
*r = rem;
|
||||
"ucomiss %%xmm0, %%xmm1\n"
|
||||
"pushf\n"
|
||||
"pop %%rax"
|
||||
:"=a" (ret)::"xmm0","xmm1","cc");
|
||||
return ret;
|
||||
}
|
||||
uint64_t _idiv_(uint64_t a, uint64_t b, uint64_t *r)
|
||||
uint64_t _minss_(float a, float b)
|
||||
{
|
||||
uint64_t ret, rem;
|
||||
uint64_t ret;
|
||||
asm volatile (
|
||||
"cqo\n"
|
||||
"idiv %%rcx\n"
|
||||
"mov %%rdx, %%rbx\n"
|
||||
:"=a" (ret), "=b" (rem):"a" (a), "c" (b):"rdx","cc");
|
||||
*r = rem;
|
||||
"minss %%xmm1, %%xmm0\n"
|
||||
"movd %%xmm0, %%eax"
|
||||
:"=a" (ret)::"xmm0","xmm1","cc");
|
||||
return ret;
|
||||
}
|
||||
uint64_t _maxss_(float a, float b)
|
||||
{
|
||||
uint64_t ret;
|
||||
asm volatile (
|
||||
"maxss %%xmm1, %%xmm0\n"
|
||||
"movd %%xmm0, %%eax"
|
||||
:"=a" (ret)::"xmm0","xmm1","cc");
|
||||
return ret;
|
||||
}
|
||||
#define CMPSS(A) \
|
||||
uint64_t _cmpss_##A(float a, float b) \
|
||||
{ \
|
||||
uint64_t ret; \
|
||||
asm volatile ( \
|
||||
"cmpss $" #A ", %%xmm1, %%xmm0\n" \
|
||||
"movd %%xmm0, %%eax" \
|
||||
:"=a" (ret)::"xmm0","xmm1","cc"); \
|
||||
return ret; \
|
||||
}
|
||||
#else
|
||||
uint64_t _ucomiss_(float a, float b)
|
||||
{
|
||||
uint32_t ret;
|
||||
asm volatile (
|
||||
"movss %1, %%xmm0\n"
|
||||
"movss %2, %%xmm1\n"
|
||||
"ucomiss %%xmm0, %%xmm1\n"
|
||||
"pushf\n"
|
||||
"pop %%eax"
|
||||
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
|
||||
return ret;
|
||||
}
|
||||
uint64_t _minss_(float a, float b)
|
||||
{
|
||||
uint32_t ret;
|
||||
asm volatile (
|
||||
"movss %1, %%xmm0\n"
|
||||
"movss %2, %%xmm1\n"
|
||||
"minss %%xmm1, %%xmm0\n"
|
||||
"movd %%xmm0, %%eax"
|
||||
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
|
||||
return ret;
|
||||
}
|
||||
uint64_t _maxss_(float a, float b)
|
||||
{
|
||||
uint32_t ret;
|
||||
asm volatile (
|
||||
"movss %1, %%xmm0\n"
|
||||
"movss %2, %%xmm1\n"
|
||||
"maxss %%xmm1, %%xmm0\n"
|
||||
"movd %%xmm0, %%eax"
|
||||
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc");
|
||||
return ret;
|
||||
}
|
||||
#define CMPSS(A) \
|
||||
uint64_t _cmpss_##A(float a, float b) \
|
||||
{ \
|
||||
uint32_t ret; \
|
||||
asm volatile ( \
|
||||
"movss %1, %%xmm0\n" \
|
||||
"movss %2, %%xmm1\n" \
|
||||
"cmpss $" #A ", %%xmm1, %%xmm0\n" \
|
||||
"movd %%xmm0, %%eax" \
|
||||
:"=a" (ret):"m"(a), "m"(b):"xmm0", "xmm1", "cc"); \
|
||||
return ret; \
|
||||
}
|
||||
#endif
|
||||
CMPSS(0)
|
||||
CMPSS(1)
|
||||
CMPSS(2)
|
||||
CMPSS(3)
|
||||
CMPSS(4)
|
||||
CMPSS(5)
|
||||
CMPSS(6)
|
||||
CMPSS(7)
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
uint64_t datas[][2] = {{1,1},{10,5},{10,3},{1, (uint64_t)-1}, {10, (uint64_t)-3}, {(uint64_t)-10, (uint64_t)-3}};
|
||||
float a, b;
|
||||
uint64_t flags;
|
||||
uint32_t maxf = 0x7f7fffff;
|
||||
uint32_t minf = 0xff7fffff;
|
||||
uint32_t r;
|
||||
|
||||
int sz = sizeof(datas)/sizeof(datas[0]);
|
||||
for(int i=0; i<sz; ++i) {
|
||||
uint64_t rem = 0;
|
||||
uint64_t d = _div_(datas[i][0], datas[i][1], &rem);
|
||||
printf("div %llu, %llu => %llu / %llu\n", datas[i][0], datas[i][1], d, rem);
|
||||
}
|
||||
for(int i=0; i<sz; ++i) {
|
||||
uint64_t rem = 0;
|
||||
uint64_t d = _idiv_(datas[i][0], datas[i][1], &rem);
|
||||
printf("idiv %lld, %lld => %lld / %lld\n", datas[i][0], datas[i][1], d, rem);
|
||||
}
|
||||
return 0;
|
||||
#define GO1(A, N) \
|
||||
a = 1.0f; b = 2.0f; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
b = INFINITY; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
b = -INFINITY; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
b = NAN; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
b = a; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
a = b = INFINITY; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
a = -INFINITY; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags); \
|
||||
flags = A(b, a); \
|
||||
printf(N " %f, %f => 0x%lx\n", b, a, flags); \
|
||||
a = b = NAN; \
|
||||
flags = A(a, b); \
|
||||
printf(N " %f, %f => 0x%lx\n", a, b, flags);
|
||||
|
||||
#define GO2(A, N) \
|
||||
a = 1.0f; b = 2.0f; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
a = -INFINITY; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
a = +INFINITY; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
a = NAN; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
b = *(float*)&maxf; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
a = -INFINITY; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r); \
|
||||
a = +INFINITY; \
|
||||
r = A(a, b); \
|
||||
printf(N " %g, %g => %g\n", a, b, *(float*)&r); \
|
||||
r = A(b, a); \
|
||||
printf(N " %g, %g => %g\n", b, a, *(float*)&r);
|
||||
|
||||
GO1(_ucomiss_, "ucomiss")
|
||||
GO2(_minss_, "minss")
|
||||
GO2(_maxss_, "maxss")
|
||||
GO1(_cmpss_0, "cmpss 0")
|
||||
GO1(_cmpss_1, "cmpss 1")
|
||||
GO1(_cmpss_2, "cmpss 2")
|
||||
GO1(_cmpss_3, "cmpss 3")
|
||||
GO1(_cmpss_4, "cmpss 4")
|
||||
GO1(_cmpss_5, "cmpss 5")
|
||||
GO1(_cmpss_6, "cmpss 6")
|
||||
GO1(_cmpss_7, "cmpss 7")
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user