mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-09 04:09:45 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f8b96b749 | ||
|
|
a9c50ef238 | ||
|
|
984da28f40 | ||
|
|
a8babcba8d | ||
|
|
13c7029de5 | ||
|
|
148722dac4 | ||
|
|
dd5bba2aac | ||
|
|
b044c19329 | ||
|
|
fb1dbb3821 | ||
|
|
4f21d83e62 | ||
|
|
b145080d37 | ||
|
|
0829c14a73 | ||
|
|
4141748f9a | ||
|
|
25e1d8bae8 | ||
|
|
79e622a839 | ||
|
|
932045054f | ||
|
|
f5f1e1413d | ||
|
|
24f2c68805 | ||
|
|
7748d10246 | ||
|
|
22ee4685a1 | ||
|
|
35ea6fd109 | ||
|
|
3744603bcc | ||
|
|
4861b78dc4 | ||
|
|
ba017657ad | ||
|
|
811c4fccd8 | ||
|
|
3992ab5931 | ||
|
|
266392e315 | ||
|
|
83e550b122 | ||
|
|
b5f2b9c936 | ||
|
|
82f610faee | ||
|
|
ec77755952 | ||
|
|
14c9cb148d | ||
|
|
f48aeaac60 | ||
|
|
74eb4ed9d5 | ||
|
|
68503a37cf | ||
|
|
49e6609182 | ||
|
|
966bb72e9e | ||
|
|
14b978a568 | ||
|
|
8378f9b307 | ||
|
|
9dc0f8243a | ||
|
|
eaeacc6706 | ||
|
|
031dba2904 | ||
|
|
f8229ea561 | ||
|
|
e5bfe84394 | ||
|
|
5e926a266f | ||
|
|
29e97a88a2 | ||
|
|
a94e8ed659 | ||
|
|
b013c86338 | ||
|
|
29926438a8 | ||
|
|
87097f437b | ||
|
|
35f266ea94 | ||
|
|
88fd555ef0 | ||
|
|
107d792ab1 | ||
|
|
30f364f166 | ||
|
|
e259ffcf66 | ||
|
|
027605e4d5 | ||
|
|
2c58b45d8e | ||
|
|
159351fc3c | ||
|
|
d4cf4ee521 | ||
|
|
7d90fff7cd | ||
|
|
68dcf9d0bf | ||
|
|
d89c10415a | ||
|
|
99310cc9c6 | ||
|
|
57d126cddc | ||
|
|
2b35400dc5 | ||
|
|
d1d899babd | ||
|
|
fe112fece8 | ||
|
|
74a338df94 | ||
|
|
f2496984d5 | ||
|
|
3ebcc84d52 | ||
|
|
c878264ede | ||
|
|
fbf3e1b1cc | ||
|
|
e23d2167b4 | ||
|
|
3d485c6159 | ||
|
|
9af5916104 | ||
|
|
80e93dcee4 | ||
|
|
90f21fb710 | ||
|
|
41a8bc0da9 | ||
|
|
06e40a2379 | ||
|
|
78104d1b5f | ||
|
|
9626291470 | ||
|
|
6f4a8fbd5d |
No files matched your search
@@ -57,10 +57,10 @@ jobs:
|
||||
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
|
||||
sudo apt-get -y install git cmake make python3
|
||||
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
|
||||
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
|
||||
unzip android-ndk-r23b-linux.zip
|
||||
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
|
||||
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DNOLOADADDR=1" >> $GITHUB_ENV
|
||||
wget https://dl.google.com/android/repository/android-ndk-r25b-linux.zip
|
||||
unzip android-ndk-r25b-linux.zip
|
||||
echo "BOX86_COMPILER=$PWD/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
|
||||
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DBAD_SIGNAL=1" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get -y install gcc-arm-linux-gnueabihf
|
||||
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
|
||||
|
||||
+24
-6
@@ -14,6 +14,8 @@ option(RK3588 "Set to ON if targeting an Rockchip RK3588 / RK3588S based device"
|
||||
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 (ARM64) based device" ${TEGRAX1})
|
||||
option(TEGRAX1ARM32 "Set to ON if targeting an Tegra X1 (ARM32) based device" ${TEGRAX1ARM32})
|
||||
option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_T194})
|
||||
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
|
||||
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
|
||||
@@ -35,7 +37,7 @@ option(NOGIT "Set to ON if not building from a git clone repo (like when buildin
|
||||
option(NO_LIB_INSTALL "Set ON to not install a few x86 libs that are used by many program" ${NO_LIB_INSTALL})
|
||||
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
|
||||
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR TEGRA_T194 OR TEGRA_T234 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -81,7 +83,7 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "arm" _arm)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armv8l" _armv8l)
|
||||
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
|
||||
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
|
||||
@@ -188,6 +190,14 @@ elseif(TEGRAX1ARM32)
|
||||
add_definitions(-DTEGRAX1ARM32)
|
||||
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(TEGRA_T194)
|
||||
add_definitions(-DTEGRA_T194)
|
||||
add_definitions(-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a76+crypto -mtune=cortex-a76 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a76+crypto -mtune=cortex-a76 -mfloat-abi=hard")
|
||||
elseif(TEGRA_T234)
|
||||
add_definitions(-DTEGRA_T234)
|
||||
add_definitions(-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae -mfloat-abi=hard")
|
||||
elseif(PHYTIUM)
|
||||
add_definitions(-DPHYTIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
@@ -313,6 +323,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/tools/my_cpuid.c"
|
||||
"${BOX86_ROOT}/src/tools/gtkclass.c"
|
||||
"${BOX86_ROOT}/src/tools/rcfile.c"
|
||||
"${BOX86_ROOT}/src/tools/rbtree.c"
|
||||
"${BOX86_ROOT}/src/tools/wine_tools.c"
|
||||
"${BOX86_ROOT}/src/elfs/elfloader.c"
|
||||
"${BOX86_ROOT}/src/elfs/elfparser.c"
|
||||
@@ -987,14 +998,21 @@ add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
#add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
|
||||
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
|
||||
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(fpu_rounding ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26 -D TEST_OUTPUT=tmpfile26.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(fpu_rounding PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTROUND=0")
|
||||
|
||||
endif(BOX86LIB)
|
||||
Vendored
+16
@@ -1,3 +1,19 @@
|
||||
box86 (0.3.6) unstable; urgency=low
|
||||
* Wrapping: More libs and and function wrapping (gtk3, vulkan...)
|
||||
* Reworked X11 Callback handling, for better stability
|
||||
* Reworked exit and the load/unload of libs
|
||||
* Some more profiles in box86rc
|
||||
* More SSE3+ opcodes in dynarec
|
||||
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
|
||||
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
|
||||
* => should improve games stability
|
||||
* Better handling of large block in the dynarec
|
||||
* => should speedup dynarec, and allow use of BIGBLOCK 2 or 3 on more software
|
||||
* Added suport for BOX86_DYNAREC_CALLRET optimisation.
|
||||
* => backported from box64, can give 10% or more speed increase (but can also decrease speed in some cases). Still a bit crashy so use with care.
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 31 May 2024 17:30:33 -0100
|
||||
|
||||
box86 (0.3.4) unstable; urgency=low
|
||||
|
||||
* X86Libs: Updated libstdc++ & libgcc_s
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
v0.3.6
|
||||
======
|
||||
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
|
||||
* Reworked X11 Callback handling, for better stability
|
||||
* Reworked exit and the load/unload of libs
|
||||
* Some more profiles in box86rc
|
||||
* More SSE3+ opcodes in dynarec
|
||||
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
|
||||
* Better handling of the Hardware Counter and TSC emulation
|
||||
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
|
||||
* PageSize detection and handling dynamic. Larger than 4K pagesize will be handled automaticaly. Note that box64 does not emulate 4K page size, so some program might still refuse to work on larger page (like Wine for example)
|
||||
=> Linux Games can now load even on a 16K pagesize machine like a mac M1, and games (including Unity3D ones) can be played with no issues.
|
||||
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
|
||||
=> should improve games stability
|
||||
* Better handling of large block in the dynarec
|
||||
=> should speedup dynarec, and allow use of BIGBLOCK 2 or 3 on more software
|
||||
* Added suport for BOX86_DYNAREC_CALLRET optimisation.
|
||||
=> backported from box64, can give 10% or more speed increase (but can also decrease speed in some cases). Still a bit crashy so use with care.
|
||||
|
||||
v0.3.4
|
||||
======
|
||||
* X86Libs: Updated libstdc++ & libgcc_s
|
||||
|
||||
@@ -164,6 +164,7 @@ To have a trace enabled build (***the interpreter will be slightly slower***), a
|
||||
#### to have ARM Dynarec
|
||||
|
||||
###### *Note: VFPv3 and NEON are required for Dynarec.*
|
||||
###### You might need to `sudo apt install neon-support` package for CMAKE to correctly detect them.
|
||||
|
||||
###### *Note: Compiling with `ARM_DYNAREC` without selecting a hardware profile is not advised.*
|
||||
|
||||
|
||||
+1
-6
@@ -104,12 +104,7 @@ Final note: the Steam BigPicture will work, but also need steamwebhelper (and so
|
||||
- If you have trouble installing Steam, you can find `install_steam.sh` in the root folder of the box86 repo. This simple script will download and install steam in your home folder, and then create a shortcut to steam in `/usr/local/bin` (and for this it will ask for sudo permission). Simply use `steam` to launch once it's installed. Note that the installation, being in the Home folder, will only work for a single user. Don't use this script if you need a multi-user installation.
|
||||
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables (it's automatically there if you used the `install_steam.sh` script)
|
||||
|
||||
to disable `steamwebhelper` when box64 installed and running, create (or edit) `~/.box64rc` and add:
|
||||
```
|
||||
[steamwebhelper]
|
||||
BOX64_EXIT=1
|
||||
```
|
||||
in it and it will be disable. Comment with a `#` those 2 lines to enable it again
|
||||
If you have issue with steam starting, with `steamwebhelper` not starting, you'll need to start steam with `-cef-disable-gpu` or `-cef-disable-gpu-compositor`.
|
||||
|
||||
----
|
||||
|
||||
|
||||
+6
-11
@@ -162,8 +162,8 @@ Enable/Disable generation of -NAN
|
||||
|
||||
#### BOX86_DYNAREC_FASTROUND *
|
||||
Enable/Disable generation of precise x86 rounding
|
||||
* 0 : Generate float/double -> int rounding like on x86
|
||||
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (faster, Default)
|
||||
* 0 : Generate float/double -> int rounding and use current rounding mode for float/double compution like on x86
|
||||
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion, and no set rounding mode) (faster, Default)
|
||||
|
||||
#### BOX86_DYNAREC_SAFEFLAGS *
|
||||
Handling of flags on CALL/RET opcodes
|
||||
@@ -171,15 +171,10 @@ Handling of flags on CALL/RET opcodes
|
||||
* 1 : most of RET will need flags, most of CALLS will not (Default)
|
||||
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
|
||||
|
||||
#### BOX86_DYNAREC_HOTPAGE *
|
||||
Handling of HotPage (Page beeing both executed and writen)
|
||||
* 0 : Don't track hotpage
|
||||
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
|
||||
|
||||
#### BOX86_DYNAREC_FASTPAGE *
|
||||
Will use a faster handling of HotPage (Page being both executed and written)
|
||||
* 0 : use regular hotpage (Default)
|
||||
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
|
||||
#### BOX86_DYNAREC_CALLRET *
|
||||
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
|
||||
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
|
||||
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible
|
||||
|
||||
#### BOX86_DYNAREC_BLEEDING_EDGE *
|
||||
Detect MonoBleedingEdge and apply conservative settings
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ if [ "$karch" = "aarch64" ] || [ "$karch" = "aarch64-linux-gnu" ] || [ "$karch"
|
||||
libdbus-1-3:armhf libfontconfig1:armhf libfreetype6:armhf libglu1-mesa:armhf libglu1:armhf libgnutls30:armhf \
|
||||
libgssapi-krb5-2:armhf libkrb5-3:armhf libodbc1:armhf libosmesa6:armhf libsdl2-2.0-0:armhf libv4l-0:armhf \
|
||||
libxcomposite1:armhf libxcursor1:armhf libxfixes3:armhf libxi6:armhf libxinerama1:armhf libxrandr2:armhf \
|
||||
libxrender1:armhf libxxf86vm1 libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
|
||||
libxrender1:armhf libxxf86vm1:armhf libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
|
||||
# This list found by downloading...
|
||||
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel-i386_7.1~bullseye-1_i386.deb
|
||||
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/winehq-devel_7.1~bullseye-1_i386.deb
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 3
|
||||
#define BOX86_REVISION 4
|
||||
#define BOX86_REVISION 6
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+161
-264
@@ -23,7 +23,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include "custommem.h"
|
||||
#include "threads.h"
|
||||
//#define TRACE_MEMSTAT
|
||||
#include "rbtree.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/dynablock_private.h"
|
||||
@@ -54,23 +54,12 @@ static pthread_mutex_t mutex_blocks;
|
||||
#endif
|
||||
#define MEMPROT_SHIFT 12
|
||||
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
|
||||
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
|
||||
#ifdef DYNAREC
|
||||
static uint8_t hotpages[MEMPROT_SIZE] = {0};
|
||||
#endif
|
||||
#ifdef TRACE_MEMSTAT
|
||||
static uint32_t memprot_allocated = 0, memprot_max_allocated = 0;
|
||||
#endif
|
||||
//#define TRACE_MEMSTAT
|
||||
rbtree* memprot = NULL;
|
||||
static int inited = 0;
|
||||
|
||||
|
||||
typedef struct mapmem_s {
|
||||
uintptr_t begin, end;
|
||||
struct mapmem_s *next;
|
||||
} mapmem_t;
|
||||
|
||||
static mapmem_t *mapallmem = NULL;
|
||||
static mapmem_t *mmapmem = NULL;
|
||||
static rbtree* mapallmem = NULL;
|
||||
static rbtree* mmapmem = NULL;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
void* block;
|
||||
@@ -80,6 +69,7 @@ typedef struct blocklist_s {
|
||||
} blocklist_t;
|
||||
|
||||
#define MMAPSIZE (64*1024) // allocate 64kb sized blocks
|
||||
#define DYNMMAPSZ (2*1024*1024) // allocate 2Mb block for dynarec
|
||||
|
||||
static int n_blocks = 0; // number of blocks for custom malloc
|
||||
static int c_blocks = 0; // capacity of blocks for custom malloc
|
||||
@@ -402,6 +392,8 @@ void* customMalloc(size_t size)
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size, &p_blocks[i].first);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
if(mapallmem)
|
||||
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
|
||||
return ret;
|
||||
}
|
||||
void* customCalloc(size_t n, size_t size)
|
||||
@@ -539,7 +531,7 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
// check if new
|
||||
if(!list->chunks[i].size) {
|
||||
// alloc a new block, aversized or not, we are at the end of the list
|
||||
size_t allocsize = (sz>MMAPSIZE)?sz:MMAPSIZE;
|
||||
size_t allocsize = (sz>DYNMMAPSZ)?sz:DYNMMAPSZ;
|
||||
// allign sz with pagesize
|
||||
allocsize = (allocsize+(box86_pagesize-1))&~(box86_pagesize-1);
|
||||
#ifndef USE_MMAP
|
||||
@@ -551,10 +543,13 @@ uintptr_t AllocDynarecMap(size_t size)
|
||||
mprotect(p, allocsize, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#else
|
||||
void* p = mmap(NULL, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", allocsize);
|
||||
if(p==MAP_FAILED) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes (%s)\n", allocsize, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#ifdef MADV_HUGEPAGE
|
||||
madvise(p, allocsize, MADV_HUGEPAGE);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TRACE_MEMSTAT
|
||||
dynarec_allocated += allocsize;
|
||||
@@ -794,22 +789,33 @@ uintptr_t getJumpAddress64(uintptr_t addr)
|
||||
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-1)>>MEMPROT_SHIFT);
|
||||
|
||||
uintptr_t cur = addr&~(box86_pagesize-1);
|
||||
uintptr_t end = ALIGN(addr+size);
|
||||
|
||||
mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
while(cur!=end) {
|
||||
uint32_t prot = 0, oprot;
|
||||
uintptr_t bend = 0;
|
||||
rb_get_end(memprot, cur, &prot, &bend);
|
||||
if(bend>end)
|
||||
bend = end;
|
||||
oprot = prot;
|
||||
uint32_t dyn = prot&PROT_DYN;
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
|
||||
prot&=~PROT_CUSTOM;
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC;
|
||||
if(!(dyn&PROT_NEVERPROT)) {
|
||||
prot&=~PROT_CUSTOM;
|
||||
if(prot&PROT_WRITE) {
|
||||
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
memprot[i] = prot|PROT_DYNAREC; // need to use atomic exchange?
|
||||
} else
|
||||
memprot[i] = prot|PROT_DYNAREC_R;
|
||||
if(!dyn)
|
||||
mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
|
||||
prot |= PROT_DYNAREC;
|
||||
} else
|
||||
prot |= PROT_DYNAREC_R;
|
||||
}
|
||||
if (prot != oprot) // If the node doesn't exist, then prot != 0
|
||||
rb_set(memprot, cur, bend, prot);
|
||||
cur = bend;
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -819,21 +825,36 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p (mark=%d)\n", (void*)addr, (void*)(addr+size-1), mark);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
|
||||
uintptr_t cur = addr&~(box86_pagesize-1);
|
||||
uintptr_t end = ALIGN(addr+size);
|
||||
|
||||
mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
if(!(prot&PROT_NOPROT)) {
|
||||
while(cur!=end) {
|
||||
uint32_t prot = 0, oprot;
|
||||
uintptr_t bend = 0;
|
||||
if (!rb_get_end(memprot, cur, &prot, &bend)) {
|
||||
if(bend>=end) break;
|
||||
else {
|
||||
cur = bend;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
oprot = prot;
|
||||
if(bend>end)
|
||||
bend = end;
|
||||
if(!(prot&PROT_NEVERPROT)) {
|
||||
if(prot&PROT_DYNAREC) {
|
||||
prot&=~PROT_DYN;
|
||||
if(mark)
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
|
||||
memprot[i] = prot; // need to use atomic exchange?
|
||||
cleanDBFromAddressRange(cur, bend-cur, 0);
|
||||
mprotect((void*)cur, bend-cur, prot);
|
||||
} else if(prot&PROT_DYNAREC_R)
|
||||
memprot[i] = prot&~PROT_CUSTOM;
|
||||
prot &= ~PROT_CUSTOM;
|
||||
}
|
||||
if (prot != oprot)
|
||||
rb_set(memprot, cur, bend, prot);
|
||||
cur = bend;
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -841,138 +862,70 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
|
||||
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-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
if(!(prot&PROT_DYN)) {
|
||||
uintptr_t end = ALIGN(addr+size);
|
||||
addr &=~(box86_pagesize-1);
|
||||
mutex_lock(&mutex_prot);
|
||||
while (addr < end) {
|
||||
uint32_t prot;
|
||||
uintptr_t bend;
|
||||
if (!rb_get_end(memprot, addr, &prot, &bend) || !(prot&PROT_DYN)) {
|
||||
dynarec_log(LOG_DEBUG, "0\n");
|
||||
mutex_unlock(&mutex_prot);
|
||||
return 0;
|
||||
} else {
|
||||
addr = bend;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
dynarec_log(LOG_DEBUG, "1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uintptr_t hotpage = 0;
|
||||
int hotpage_cnt = 0;
|
||||
#define HOTPAGE_MARK 64
|
||||
void SetHotPage(uintptr_t addr)
|
||||
{
|
||||
hotpage = addr&~(box86_pagesize-1);
|
||||
hotpage_cnt = HOTPAGE_MARK;
|
||||
}
|
||||
int isInHotPage(uintptr_t addr)
|
||||
{
|
||||
if(!hotpage_cnt)
|
||||
return 0;
|
||||
--hotpage_cnt;
|
||||
return (addr>=hotpage) && (addr<hotpage+box86_pagesize);
|
||||
}
|
||||
int checkInHotPage(uintptr_t addr)
|
||||
{
|
||||
return hotpage_cnt && (addr>=hotpage) && (addr<hotpage+box86_pagesize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void printMapMem(mapmem_t* mapmem)
|
||||
{
|
||||
mapmem_t* m = mapmem;
|
||||
while(m) {
|
||||
printf_log(LOG_NONE, " %p-%p\n", (void*)m->begin, (void*)m->end);
|
||||
m = m->next;
|
||||
}
|
||||
}
|
||||
|
||||
void addMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
if(begin<box86_pagesize)
|
||||
begin = box86_pagesize;
|
||||
begin &=~(box86_pagesize-1);
|
||||
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
|
||||
// sanitize values
|
||||
if(end<0x10000) return;
|
||||
if(!begin) begin = 0x10000;
|
||||
// find attach point (cannot be the 1st one by construction)
|
||||
mapmem_t* m = mapmem;
|
||||
while(m->next && begin>m->next->begin) {
|
||||
m = m->next;
|
||||
}
|
||||
// attach at the end of m
|
||||
mapmem_t* newm;
|
||||
if(m->end>=begin-1) {
|
||||
if(end<=m->end)
|
||||
return; // zone completly inside current block, nothing to do
|
||||
m->end = end; // enlarge block
|
||||
newm = m;
|
||||
} else {
|
||||
// create a new block
|
||||
newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
newm->next = m->next;
|
||||
newm->begin = begin;
|
||||
newm->end = end;
|
||||
m->next = newm;
|
||||
}
|
||||
while(newm && newm->next && (newm->next->begin-1)<=newm->end) {
|
||||
// fuse with next
|
||||
if(newm->next->end>newm->end)
|
||||
newm->end = newm->next->end;
|
||||
mapmem_t* tmp = newm->next;
|
||||
newm->next = tmp->next;
|
||||
box_free(tmp);
|
||||
}
|
||||
// all done!
|
||||
}
|
||||
void removeMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
if(begin<box86_pagesize)
|
||||
begin = box86_pagesize;
|
||||
begin &=~(box86_pagesize-1);
|
||||
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
|
||||
// sanitize values
|
||||
if(end<0x10000) return;
|
||||
if(!begin) begin = 0x10000;
|
||||
mapmem_t* m = mapmem, *prev = NULL;
|
||||
while(m) {
|
||||
// check if block is beyond the zone to free
|
||||
if(m->begin > end)
|
||||
return;
|
||||
// check if the block is completly inside the zone to free
|
||||
if(m->begin>=begin && m->end<=end) {
|
||||
// just free the block
|
||||
mapmem_t *tmp = m;
|
||||
if(prev) {
|
||||
prev->next = m->next;
|
||||
m = prev;
|
||||
} else {
|
||||
mapmem = m->next; // change attach, but should never happens
|
||||
m = mapmem;
|
||||
prev = NULL;
|
||||
}
|
||||
box_free(tmp);
|
||||
} else if(begin>m->begin && end<m->end) { // the zone is totaly inside the block => split it!
|
||||
mapmem_t* newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t)); // create a new "next"
|
||||
newm->end = m->end;
|
||||
m->end = begin - 1;
|
||||
newm->begin = end + 1;
|
||||
newm->next = m->next;
|
||||
m->next = newm;
|
||||
// nothing more to free
|
||||
return;
|
||||
} else if(begin>m->begin && begin<m->end) { // free the tail of the block
|
||||
m->end = begin - 1;
|
||||
} else if(end>m->begin && end<m->end) { // free the head of the block
|
||||
m->begin = end + 1;
|
||||
}
|
||||
prev = m;
|
||||
m = m->next;
|
||||
}
|
||||
}
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t old_prot = memprot[i];
|
||||
uint32_t dyn=(old_prot&PROT_DYN);
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
uintptr_t cur = addr & ~(box86_pagesize-1);
|
||||
uintptr_t end = ALIGN(cur+size);
|
||||
rb_set(mapallmem, cur, cur+size, 1);
|
||||
while (cur < end) {
|
||||
uintptr_t bend;
|
||||
uint32_t oprot;
|
||||
rb_get_end(memprot, cur, &oprot, &bend);
|
||||
uint32_t dyn=(oprot&PROT_DYN);
|
||||
if(!(dyn&PROT_NEVERPROT)) {
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
dyn = PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
|
||||
} else if(dyn && !(prot&PROT_WRITE)) {
|
||||
dyn = PROT_DYNAREC_R;
|
||||
}
|
||||
}
|
||||
memprot[i] = prot|dyn;
|
||||
if ((prot|dyn) != oprot)
|
||||
rb_set(memprot, cur, bend, prot|dyn);
|
||||
cur = bend;
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -980,13 +933,12 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
size = ALIGN(size);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
memprot[i] = prot;
|
||||
}
|
||||
uintptr_t cur = addr & ~(box86_pagesize-1);
|
||||
uintptr_t end = ALIGN(cur+size);
|
||||
rb_set(mapallmem, cur, end, 1);
|
||||
rb_set(memprot, cur, end, prot);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
@@ -994,26 +946,29 @@ void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
if(!size)
|
||||
return;
|
||||
size = (size+box86_pagesize-1)&~(box86_pagesize-1); // round size
|
||||
addr &= ~(box86_pagesize-1);
|
||||
size = ALIGN(size);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mmapmem, addr, addr+size-1);
|
||||
rb_set(mmapmem, addr, addr+size, 1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
if(prot)
|
||||
setProtection(addr, size, prot);
|
||||
else {
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
rb_set(mapallmem, addr, addr+size, 1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
}
|
||||
|
||||
void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
size = ALIGN(size);
|
||||
addr &= ~(box86_pagesize-1);
|
||||
if(prot)
|
||||
setProtection(addr, size, prot);
|
||||
else {
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
rb_set(mapallmem, addr, addr+size, 1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
}
|
||||
@@ -1021,11 +976,11 @@ void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void refreshProtection(uintptr_t addr)
|
||||
{
|
||||
mutex_lock(&mutex_prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
int prot = memprot[idx];
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
int ret = mprotect((void*)(idx<<MEMPROT_SHIFT), box86_pagesize, prot&~PROT_CUSTOM);
|
||||
printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(idx<<MEMPROT_SHIFT), prot, ret, ret?strerror(errno):"ok");
|
||||
uint32_t prot;
|
||||
uintptr_t bend;
|
||||
if (rb_get_end(memprot, addr, &prot, &bend)) {
|
||||
int ret = mprotect((void*)(addr&~(box86_pagesize-1)), box86_pagesize, prot&~PROT_CUSTOM);
|
||||
dynarec_log(LOG_DEBUG, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(addr&~(box86_pagesize-1)), prot, ret, ret?strerror(errno):"ok");
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -1033,47 +988,14 @@ printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr
|
||||
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);
|
||||
size = ALIGN(size);
|
||||
addr &= ~(box86_pagesize-1);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
rb_set(mapallmem, addr, addr+size, 1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
// don't need to add precise tracking probably
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
int IsInHotPage(uintptr_t addr) {
|
||||
int idx = (addr>>MEMPROT_SHIFT);
|
||||
if(!hotpages[idx])
|
||||
return 0;
|
||||
// decrement hot
|
||||
arm_lock_decifnot0b(&hotpages[idx]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AreaInHotPage(uintptr_t start, uintptr_t end_) {
|
||||
uintptr_t idx = (start>>MEMPROT_SHIFT);
|
||||
uintptr_t end = (end_>>MEMPROT_SHIFT);
|
||||
int ret = 0;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t hot = hotpages[i];
|
||||
if(hot) {
|
||||
// decrement hot
|
||||
arm_lock_decifnot0b(&hotpages[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
if(ret && box86_dynarec_log>LOG_INFO)
|
||||
dynarec_log(LOG_DEBUG, "BOX64: AreaInHotPage %p-%p\n", (void*)start, (void*)end_);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void AddHotPage(uintptr_t addr) {
|
||||
int idx = (addr>>MEMPROT_SHIFT);
|
||||
arm_lock_storeb(&hotpages[idx], box86_dynarec_hotpage);
|
||||
}
|
||||
#endif
|
||||
|
||||
void loadProtectionFromMap()
|
||||
{
|
||||
if(box86_mapclean)
|
||||
@@ -1098,40 +1020,27 @@ void loadProtectionFromMap()
|
||||
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
size = ALIGN(size);
|
||||
addr &= ~(box86_pagesize-1);
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
mutex_lock(&mutex_prot);
|
||||
removeMapMem(mmapmem, addr, addr+size-1);
|
||||
removeMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
memprot[i] = 0;
|
||||
}
|
||||
rb_unset(mapallmem, addr, addr+size);
|
||||
rb_unset(mmapmem, addr, addr+size);
|
||||
rb_unset(memprot, addr, addr+size);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
uint32_t getProtection(uintptr_t addr)
|
||||
{
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
mutex_lock(&mutex_prot);
|
||||
uint32_t ret = memprot[idx];
|
||||
uint32_t ret = rb_get(memprot, addr);
|
||||
mutex_unlock(&mutex_prot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getMmapped(uintptr_t addr)
|
||||
{
|
||||
mapmem_t* m = mmapmem;
|
||||
if(addr<box86_pagesize) return 0;
|
||||
while(m) {
|
||||
uintptr_t begin = m->begin;
|
||||
uintptr_t end = m->end;
|
||||
if(addr>=begin && addr<=end)
|
||||
return 1;
|
||||
if(addr<begin)
|
||||
return 0;
|
||||
m = m->next;
|
||||
}
|
||||
return 0;
|
||||
return rb_get(mmapmem, addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -1139,22 +1048,20 @@ int getMmapped(uintptr_t addr)
|
||||
#define MEDIAN (void*)0x40000000
|
||||
static void* findBlockHinted(void* hint, size_t size, uintptr_t mask)
|
||||
{
|
||||
mapmem_t* m = mapallmem;
|
||||
uintptr_t h = (uintptr_t)hint;
|
||||
int prot;
|
||||
if(hint<LOWEST) hint = LOWEST;
|
||||
uintptr_t bend = 0;
|
||||
uintptr_t cur = (uintptr_t)hint;
|
||||
if(!mask) mask = 0xffff;
|
||||
while(m) {
|
||||
while(bend!=0xffffffffLL) {
|
||||
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
|
||||
if(bend-cur>=size)
|
||||
return (void*)cur;
|
||||
if(bend>=0xc0000000 && (uintptr_t)hint<0xc0000000)
|
||||
return NULL;
|
||||
}
|
||||
// granularity 0x10000
|
||||
uintptr_t addr = m->end+1;
|
||||
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
|
||||
// check hint and available size
|
||||
if(addr<=h && end>=h && end-h+1>=size)
|
||||
return hint;
|
||||
uintptr_t aaddr = (addr+mask)&~mask;
|
||||
if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
|
||||
return (void*)aaddr;
|
||||
if(end>=0xc0000000 && h<0xc0000000)
|
||||
return NULL;
|
||||
m = m->next;
|
||||
cur = (bend+mask)&~mask;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1182,16 +1089,12 @@ void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask)
|
||||
|
||||
int isBlockFree(void* hint, size_t size)
|
||||
{
|
||||
mapmem_t* m = mapallmem;
|
||||
uintptr_t h = (uintptr_t)hint;
|
||||
while(m) {
|
||||
uintptr_t addr = m->end+1;
|
||||
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
|
||||
if(addr<=h && end>=h && end-h+1>=size)
|
||||
int prot;
|
||||
uintptr_t bend = 0;
|
||||
uintptr_t cur = (uintptr_t)hint;
|
||||
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
|
||||
if(bend-cur>=size)
|
||||
return 1;
|
||||
if(addr>h)
|
||||
return 0;
|
||||
m = m->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1259,6 +1162,7 @@ void init_custommem_helper(box86context_t* ctx)
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
memprot = init_rbtree();
|
||||
init_mutexes();
|
||||
#ifdef DYNAREC
|
||||
#ifdef ARM
|
||||
@@ -1273,13 +1177,9 @@ void init_custommem_helper(box86context_t* ctx)
|
||||
#endif
|
||||
pthread_atfork(NULL, NULL, atfork_child_custommem);
|
||||
// init mapallmem list
|
||||
mapallmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mapallmem->begin = 0x0;
|
||||
mapallmem->end = (uintptr_t)LOWEST - 1;
|
||||
mapallmem = init_rbtree();
|
||||
// init mmapmem list
|
||||
mmapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mmapmem->begin = 0x0;
|
||||
mmapmem->end = (uintptr_t)box86_pagesize - 1;
|
||||
mmapmem = init_rbtree();
|
||||
loadProtectionFromMap();
|
||||
}
|
||||
|
||||
@@ -1298,7 +1198,7 @@ void fini_custommem_helper(box86context_t *ctx)
|
||||
}
|
||||
if (njmps_in_cur_lv1 > njmps_in_lv1_max) njmps_in_lv1_max = njmps_in_cur_lv1;
|
||||
}
|
||||
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lu kio\n- customMalloc: %zu kio\n- memprot: %lu kio (peak at %ld kio)\n- jump table: %zu kio (%zu level 1 table allocated, for %zu jumps, with at most %zu per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, memprot_allocated / 1024, memprot_max_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
|
||||
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lu kio\n- customMalloc: %zu kio\n- jump table: %zu kio (%zu level 1 table allocated, for %zu jumps, with at most %zu per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
|
||||
#endif
|
||||
if(!inited)
|
||||
return;
|
||||
@@ -1333,6 +1233,13 @@ void fini_custommem_helper(box86context_t *ctx)
|
||||
kh_destroy(lockaddress, lockaddress);
|
||||
lockaddress = NULL;
|
||||
#endif
|
||||
delete_rbtree(memprot);
|
||||
memprot = NULL;
|
||||
delete_rbtree(mmapmem);
|
||||
mmapmem = NULL;
|
||||
delete_rbtree(mapallmem);
|
||||
mapallmem = NULL;
|
||||
|
||||
for(int i=0; i<n_blocks; ++i)
|
||||
#ifdef USE_MMAP
|
||||
munmap(p_blocks[i].block, p_blocks[i].size);
|
||||
@@ -1344,16 +1251,6 @@ void fini_custommem_helper(box86context_t *ctx)
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
pthread_mutex_destroy(&mutex_prot);
|
||||
#endif
|
||||
while(mapallmem) {
|
||||
mapmem_t *tmp = mapallmem;
|
||||
mapallmem = mapallmem->next;
|
||||
box_free(tmp);
|
||||
}
|
||||
while(mmapmem) {
|
||||
mapmem_t *tmp = mmapmem;
|
||||
mmapmem = mmapmem->next;
|
||||
box_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
|
||||
@@ -192,6 +192,9 @@ Op is 20-27
|
||||
// and dst, src1, #imm ror rot*2
|
||||
#define AND_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// and.c dst, src, #(imm8)
|
||||
#define AND_IMM8_COND(cond, dst, src, imm8) \
|
||||
EMIT((cond) | 0x02000000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// and.s dst, src, #(imm8)
|
||||
#define ANDS_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
@@ -427,6 +430,8 @@ Op is 20-27
|
||||
|
||||
// blx reg
|
||||
#define BLX(reg) EMIT(0xe12fff30 | (reg) )
|
||||
// blx cond reg
|
||||
#define BLXcond(C, reg) EMIT(C | 0x012fff30 | (reg) )
|
||||
|
||||
// b cond offset
|
||||
#define Bcond(C, O) EMIT(C | (0b101<<25) | (0<<24) | (((O)>>2)&0xffffff))
|
||||
@@ -434,6 +439,10 @@ Op is 20-27
|
||||
// bl cond offset
|
||||
#define BLcond(C, O) EMIT(C | (0b101<<25) | (1<<24) | (((O)>>2)&0xffffff))
|
||||
|
||||
// adr
|
||||
#define ADR_gen(cond, P, Rd, Imm12) (cond | (1<<25) | (((P)?0b0100:0b0010)<<21) | (0b1111<<16) | ((Rd)<<12) | (Imm12))
|
||||
#define ADR(cond, Rd, Imm) EMIT(ADR_gen(cond, (Imm>=0), Rd, ((Imm>=0)?Imm:-Imm)&0b111111111111))
|
||||
|
||||
// push reg!, {list}
|
||||
// all | const |pre-index| subs | no PSR |writeback| store | base |reg list
|
||||
#define PUSH(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (1<<21) | (0<<20) | ((reg)<<16) | (list))
|
||||
@@ -909,6 +918,8 @@ Op is 20-27
|
||||
#define VMOV_igen(i, D, imm3, Vd, cmode, Q, op, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | (op)<<5 | 1<<4 | (imm4))
|
||||
#define VMOV_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 0, (imm)&15))
|
||||
#define VMOVQ_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 1, 0, (imm)&15))
|
||||
// Dd <= imm8 6bits duplicated 1bit -> 1byte
|
||||
#define VMOV_D64(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 1, (imm)&15))
|
||||
// Dd <= imm8 in high bits
|
||||
#define VMOV_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 0, 0, (imm8)&15))
|
||||
// Dd <= imm8 in high bits
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
.global arm_epilog
|
||||
arm_epilog:
|
||||
//update register -> emu
|
||||
//pop {r0}
|
||||
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be Flags now)
|
||||
// restore stack pointer
|
||||
ldr sp, [r0, #(8*4+2*4)]
|
||||
pop {r4, r5}
|
||||
str r4, [r0, #(8*4+2*4)] // put back old value
|
||||
//restore all used register
|
||||
vpop {d8-d15}
|
||||
pop {r4-r12, pc}
|
||||
@@ -20,6 +23,10 @@ arm_epilog:
|
||||
|
||||
.global arm_epilog_fast
|
||||
arm_epilog_fast:
|
||||
// restore stack pointer
|
||||
ldr sp, [r0, #(8*4+2*4)]
|
||||
pop {r4, r5}
|
||||
str r4, [r0, #(8*4+2*4)] // put back old value
|
||||
//restore all used register
|
||||
vpop {d8-d15}
|
||||
pop {r4-r12, pc}
|
||||
|
||||
@@ -101,6 +101,7 @@ arm_lock_storeifnull:
|
||||
beq arm_lock_storeifnull
|
||||
arm_lock_storeifnull_exit:
|
||||
mov r0, r2
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeifref2:
|
||||
@@ -116,6 +117,7 @@ arm_lock_storeifref2_loop:
|
||||
beq arm_lock_storeifref_loop
|
||||
mov r0, r2
|
||||
arm_lock_storeifref2_exit:
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeifref:
|
||||
@@ -175,11 +177,13 @@ arm_lock_incif0b_0:
|
||||
bx lr
|
||||
|
||||
arm_lock_stored:
|
||||
dmb ish
|
||||
str r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeb:
|
||||
dmb ish
|
||||
strb r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
@@ -3944,6 +3944,18 @@ const char* arm_print(uint32_t opcode) {
|
||||
uint8_t shift = ((opcode >> 4) & 0xFF);
|
||||
|
||||
sprintf(ret, "TEQ%s %s, %s%s", cond, regname[rn], regname[rm], print_shift(shift, 1));
|
||||
} else if ((opcode&0b00001111111111110000000000000000) == 0b00000010100011110000000000000000) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rd = (opcode >> 16) & 0xF;
|
||||
uint32_t imm12 = opcode&0b111111111111;
|
||||
|
||||
sprintf(ret, "ADR %s, #0x%x", regname[rd], imm12);
|
||||
} else if ((opcode&0b00001111111111110000000000000000) == 0b00000010010011110000000000000000) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rd = (opcode >> 16) & 0xF;
|
||||
uint32_t imm12 = opcode&0b111111111111;
|
||||
|
||||
sprintf(ret, "ADR %s, #-0x%x", regname[rd], imm12);
|
||||
} else if ((opcode & 0x0FF000F0) == 0x01400090) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rt = (opcode >> 12) & 0xF;
|
||||
|
||||
@@ -11,9 +11,12 @@ arm_prolog:
|
||||
//save all used register
|
||||
push {r4-r12, lr}
|
||||
vpush {d8-d15}
|
||||
// save Sp and setup stack for optionnal callret
|
||||
ldr r4, [r0, #(8*4+2*4)] // grab old value of xSPSave
|
||||
mov r5, #0
|
||||
push {r4-r5}
|
||||
str sp, [r0, #(8*4+2*4)]
|
||||
//setup emu -> register
|
||||
//push {r0}
|
||||
ldm r0, {r4-r12} // all 8 register in direct access, plus flags, no EIP (so r14 can be used as scratch)
|
||||
//TODO
|
||||
//jump to function
|
||||
bx r1
|
||||
+4
-20
@@ -262,33 +262,17 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
{
|
||||
if(isInHotPage(addr))
|
||||
return NULL;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
|
||||
if(db && db->done && db->block && getNeedTest(addr)) {
|
||||
if(db->always_test)
|
||||
sched_yield(); // just calm down...
|
||||
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
|
||||
emu->test.test = 0;
|
||||
if(box86_dynarec_fastpage) {
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
if(hash==db->hash) { // seems ok, run it without reprotecting it
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
return db;
|
||||
}
|
||||
db->done = 0; // invalidating the block, it's already not good
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
FreeDynablock(db, 1);
|
||||
return NULL; // not building a new one, it's still a hotpage
|
||||
} else {
|
||||
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
|
||||
if(hash!=db->hash) {
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, db->always_test, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
@@ -300,7 +284,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, db->always_test, (void*)addr);
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
|
||||
+11
-3
@@ -20,6 +20,7 @@
|
||||
#include "dynablock.h"
|
||||
#include "dynablock_private.h"
|
||||
#include "bridge.h"
|
||||
#include "custommem.h"
|
||||
void x86test_check(x86emu_t* ref, uintptr_t ip);
|
||||
#endif
|
||||
|
||||
@@ -59,9 +60,13 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
// no block, let link table as is...
|
||||
#ifdef HAVE_TRACE
|
||||
if(LOG_INFO<=box86_dynarec_log) {
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
|
||||
if(checkInHotPage(addr)) {
|
||||
dynarec_log(LOG_INFO, "Not trying to run a block from a Hotpage at %p\n", (void*)addr);
|
||||
} else {
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
@@ -137,11 +142,13 @@ int DynaRun(x86emu_t* emu)
|
||||
JUMPBUFF jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
|
||||
uintptr_t old_savesp = emu->xSPSave;
|
||||
emu->flags.jmpbuf_ready = 0;
|
||||
|
||||
while(!(emu->quit)) {
|
||||
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
|
||||
emu->jmpbuf = jmpbuf;
|
||||
emu->old_savedsp = emu->xSPSave;
|
||||
emu->flags.jmpbuf_ready = 1;
|
||||
#ifdef ANDROID
|
||||
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
|
||||
@@ -199,4 +206,5 @@ int DynaRun(x86emu_t* emu)
|
||||
}
|
||||
// clear the setjmp
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
emu->xSPSave = old_savesp;
|
||||
}
|
||||
+90
-46
@@ -73,8 +73,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
}
|
||||
// add slots
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 64;
|
||||
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
printf_log(LOG_NONE, "Warning, overallocating next\n");
|
||||
}
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
@@ -98,15 +97,14 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
void add_jump(dynarec_arm_t *dyn, int ninst) {
|
||||
// add slots
|
||||
if(dyn->jmp_sz == dyn->jmp_cap) {
|
||||
dyn->jmp_cap += 64;
|
||||
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
|
||||
printf_log(LOG_NONE, "Warning, overallocating jmps\n");
|
||||
}
|
||||
dyn->jmps[dyn->jmp_sz++] = ninst;
|
||||
}
|
||||
int get_first_jump(dynarec_arm_t *dyn, int next) {
|
||||
for(int i=0; i<dyn->jmp_sz; ++i)
|
||||
if(dyn->insts[dyn->jmps[i]].x86.jmp == next)
|
||||
return i;
|
||||
return dyn->jmps[i];
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -282,33 +280,47 @@ void addInst(instsize_t* insts, size_t* size, int x86_size, int native_size)
|
||||
}
|
||||
}
|
||||
|
||||
static void recurse_mark_alive(dynarec_arm_t* dyn, int i)
|
||||
{
|
||||
if(dyn->insts[i].x86.alive)
|
||||
return;
|
||||
dyn->insts[i].x86.alive = 1;
|
||||
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
|
||||
recurse_mark_alive(dyn, dyn->insts[i].x86.jmp_insts);
|
||||
if(i<dyn->size-1 && dyn->insts[i].x86.has_next)
|
||||
recurse_mark_alive(dyn, i+1);
|
||||
}
|
||||
|
||||
static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
static int sizePredecessors(dynarec_arm_t* dyn)
|
||||
{
|
||||
int pred_sz = 1; // to be safe
|
||||
// compute total size of predecessor to alocate the array
|
||||
// compute total size of predecessor to allocate the array
|
||||
// mark alive...
|
||||
recurse_mark_alive(dyn, 0);
|
||||
// first compute the jumps
|
||||
int jmpto;
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1) {
|
||||
++pred_sz;
|
||||
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
|
||||
if(dyn->insts[i].x86.alive && dyn->insts[i].x86.jmp && ((jmpto=dyn->insts[i].x86.jmp_insts)!=-1)) {
|
||||
pred_sz++;
|
||||
dyn->insts[jmpto].pred_sz++;
|
||||
}
|
||||
}
|
||||
// remove "has_next" from orphean branch
|
||||
// remove "has_next" from orphan branch
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(!dyn->insts[i].x86.has_next) {
|
||||
if(dyn->insts[i+1].x86.has_next && !dyn->insts[i+1].pred_sz)
|
||||
dyn->insts[i+1].x86.has_next = 0;
|
||||
}
|
||||
if(dyn->insts[i].x86.has_next && !dyn->insts[i+1].x86.alive)
|
||||
dyn->insts[i].x86.has_next = 0;
|
||||
}
|
||||
// second the "has_next"
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(dyn->insts[i].x86.has_next) {
|
||||
++pred_sz;
|
||||
++dyn->insts[i+1].pred_sz;
|
||||
pred_sz++;
|
||||
dyn->insts[i+1].pred_sz++;
|
||||
}
|
||||
}
|
||||
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
|
||||
return pred_sz;
|
||||
}
|
||||
static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
{
|
||||
// fill pred pointer
|
||||
int* p = dyn->predecessor;
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
@@ -317,7 +329,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
|
||||
}
|
||||
// fill pred
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
for(int i=0; i<dyn->size; ++i) if(dyn->insts[i].x86.alive) {
|
||||
if((i!=dyn->size-1) && dyn->insts[i].x86.has_next)
|
||||
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
|
||||
if(dyn->insts[i].x86.jmp && (dyn->insts[i].x86.jmp_insts!=-1)) {
|
||||
@@ -332,14 +344,10 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
while (ninst>=0) {
|
||||
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
|
||||
need |= dyn->insts[ninst].x86.need_after;
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET || dyn->insts[ninst].x86.state_flags==SF_SET || dyn->insts[ninst].x86.state_flags==SF_SET_NODF)) {
|
||||
need &=~X_PEND;
|
||||
need |= X_ALL;
|
||||
}
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SET)) {
|
||||
need &=~X_PEND;
|
||||
need |= dyn->insts[ninst].x86.set_flags; // SF_SET will compute all flags, it's not SUBSET!
|
||||
}
|
||||
if((need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET_PENDING) {
|
||||
need |= X_ALL&~(dyn->insts[ninst].x86.set_flags);
|
||||
}
|
||||
@@ -348,10 +356,11 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
dyn->insts[ninst].x86.gen_flags |= X_PEND;
|
||||
dyn->insts[ninst].x86.need_after = need;
|
||||
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
|
||||
|
||||
if(dyn->insts[ninst].x86.may_set)
|
||||
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
|
||||
else if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
|
||||
need &=~X_PEND; // Consume X_PEND if relevant
|
||||
need &=~X_PEND; // Consume X_PEND if relevant
|
||||
need |= dyn->insts[ninst].x86.use_flags;
|
||||
if(dyn->insts[ninst].x86.need_before == need)
|
||||
return ninst - 1;
|
||||
@@ -374,22 +383,23 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
}
|
||||
|
||||
void* current_helper = NULL;
|
||||
static int static_jmps[MAX_INSTS+2];
|
||||
static uintptr_t static_next[MAX_INSTS+2];
|
||||
static instruction_arm_t static_insts[MAX_INSTS+2] = {0};
|
||||
// TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory
|
||||
|
||||
void CancelBlock(int need_lock)
|
||||
{
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(helper) {
|
||||
dynaFree(helper->next);
|
||||
dynaFree(helper->insts);
|
||||
dynaFree(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->actual_block) {
|
||||
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
|
||||
helper->dynablock->actual_block = NULL;
|
||||
}
|
||||
}
|
||||
current_helper = NULL;
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
@@ -438,10 +448,6 @@ void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
|
||||
*/
|
||||
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
|
||||
return CreateEmptyBlock(block, addr);
|
||||
@@ -458,10 +464,19 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.dynablock = block;
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)dynaCalloc(helper.cap, sizeof(instruction_arm_t));
|
||||
helper.cap = MAX_INSTS;
|
||||
helper.insts = static_insts;
|
||||
helper.jmps = static_jmps;
|
||||
helper.jmp_cap = MAX_INSTS;
|
||||
helper.next = static_next;
|
||||
helper.next_cap = MAX_INSTS;
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
if(helper.abort) {
|
||||
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
@@ -470,7 +485,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
}
|
||||
if(!isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -483,10 +497,10 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
for(int ii=0; ii<helper.jmp_sz; ++ii) {
|
||||
int i = helper.jmps[ii];
|
||||
uintptr_t j = helper.insts[i].x86.jmp;
|
||||
helper.insts[i].x86.jmp_insts = -1;
|
||||
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
|
||||
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
|
||||
helper.always_test = 1;
|
||||
helper.insts[i].x86.jmp_insts = -1;
|
||||
helper.insts[i].x86.need_after |= X_PEND;
|
||||
} else {
|
||||
// find jump address instruction
|
||||
@@ -519,30 +533,50 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(helper.insts[i2].x86.addr==j)
|
||||
k=i2;
|
||||
}*/
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x86.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x86.jmp_insts = k;
|
||||
if(k!=-1) {
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x86.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x86.jmp_insts = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no need for next and jmps anymore
|
||||
dynaFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
dynaFree(helper.jmps);
|
||||
helper.jmp_sz = helper.jmp_cap = 0;
|
||||
helper.jmps = NULL;
|
||||
// fill predecessors with the jump address
|
||||
int alloc_size = sizePredecessors(&helper);
|
||||
helper.predecessor = (int*)alloca(alloc_size*sizeof(int));
|
||||
fillPredecessors(&helper);
|
||||
|
||||
int pos = helper.size;
|
||||
while (pos>=0)
|
||||
pos = updateNeed(&helper, pos, 0);
|
||||
// remove fpu stuff on non-executed code
|
||||
for(int i=1; i<helper.size-1; ++i)
|
||||
if(!helper.insts[i].pred_sz) {
|
||||
int ii = i;
|
||||
while(ii<helper.size && !helper.insts[ii].pred_sz)
|
||||
fpu_reset_ninst(&helper, ii++);
|
||||
i = ii;
|
||||
}
|
||||
|
||||
// pass 1, float optimisations, first pass for flags
|
||||
arm_pass1(&helper, addr);
|
||||
if(helper.abort) {
|
||||
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
if(helper.abort) {
|
||||
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
@@ -576,13 +610,16 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.arm_size = 0;
|
||||
helper.insts_size = 0; // reset
|
||||
arm_pass3(&helper, addr);
|
||||
if(helper.abort) {
|
||||
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// keep size of instructions for signal handling
|
||||
block->instsize = instsize;
|
||||
// ok, free the helper now
|
||||
dynaFree(helper.insts);
|
||||
helper.insts = NULL;
|
||||
helper.instsize = NULL;
|
||||
dynaFree(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
@@ -601,7 +638,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
// Check if something changed, to abbort if it as
|
||||
if((block->hash != hash)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%zu)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
@@ -619,15 +655,23 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// ok, free the helper now
|
||||
helper.insts = NULL;
|
||||
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%zu, marking as need_test\n", block->x86_addr, block->x86_size);
|
||||
AddHotPage(addr);
|
||||
block->dirty = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
if(getProtection(addr)&PROT_NEVERCLEAN) {
|
||||
block->dirty = 1;
|
||||
block->always_test = 1;
|
||||
}
|
||||
if(block->always_test) {
|
||||
dynarec_log(LOG_DEBUG, "Note: block marked as always dirty %p:%ld\n", block->x86_addr, block->x86_size);
|
||||
}
|
||||
current_helper = NULL;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
|
||||
@@ -352,7 +352,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("DAA");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization DAA\n");
|
||||
READFLAGS(X_AF|X_CF);
|
||||
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UXTB(x1, xEAX, 0);
|
||||
CALL_(daa8, x1, 0);
|
||||
BFI(xEAX, x1, 0, 8);
|
||||
@@ -414,7 +414,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("DAS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization DAS\n");
|
||||
READFLAGS(X_AF|X_CF);
|
||||
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UXTB(x1, xEAX, 0);
|
||||
CALL_(das8, x1, 0);
|
||||
BFI(xEAX, x1, 0, 8);
|
||||
@@ -476,7 +476,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("AAA");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization AAA\n");
|
||||
READFLAGS(X_AF);
|
||||
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UXTH(x1, xEAX, 0);
|
||||
CALL_(aaa16, x1, 0);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
@@ -544,7 +544,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("AAS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization AAS\n");
|
||||
READFLAGS(X_AF);
|
||||
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UXTH(x1, xEAX, 0);
|
||||
CALL_(aas16, x1, 0);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
@@ -1239,7 +1239,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x9D:
|
||||
INST_NAME("POPF");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
POP1(xFlags);
|
||||
MOV32(x1, 0x3F7FD7);
|
||||
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
|
||||
@@ -1441,7 +1441,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Eb, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
GETEB(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -1452,7 +1452,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Eb, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
GETEB(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -1524,7 +1524,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Ed, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
GETEDW(x14, x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -1563,7 +1563,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
WBACK;
|
||||
} else if(u8>1) {
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, u8);
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
WBACK;
|
||||
@@ -1602,11 +1602,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("RETN");
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
//SETFLAGS(X_ALL,_NODF SF_SET_NODF); // Hack, set all flags (to an unknown state...)
|
||||
if(box86_dynarec_safeflags) {
|
||||
READFLAGS(X_PEND); // lets play safe here too
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
|
||||
i32 = F16;
|
||||
retn_to_epilog(dyn, ninst, i32);
|
||||
*need_epilog = 0;
|
||||
@@ -1614,12 +1614,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xC3:
|
||||
INST_NAME("RET");
|
||||
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
// SETFLAGS(X_ALL,_NODF SF_SET_NODF); // Hack, set all flags (to an unknown state...)
|
||||
// ^^^ that hack break PlantsVsZombies and GOG Setup under wine....
|
||||
if(box86_dynarec_safeflags) {
|
||||
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
|
||||
ret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
@@ -1666,7 +1666,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
case 0xCC:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack, set all flags (to an unknown state...)
|
||||
if(PK(0)=='S' && PK(1)=='C') {
|
||||
addr+=2;
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
@@ -1734,7 +1734,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
case 0xCD:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack, set all flags (to an unknown state...)
|
||||
SKIPTEST(x14);
|
||||
SMEND();
|
||||
u8 = F8;
|
||||
@@ -1765,7 +1765,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xCF:
|
||||
INST_NAME("IRET");
|
||||
SETFLAGS(X_ALL, SF_SET); // Not a hack, EFLAGS are restored
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Not a hack, EFLAGS are restored
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
iret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
@@ -1793,7 +1793,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Eb, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEB(x1);
|
||||
CALL_(rcl8, x1, (1<<x3));
|
||||
@@ -1803,7 +1803,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Eb, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEB(x1);
|
||||
CALL_(rcr8, x1, (1<<x3));
|
||||
@@ -1855,7 +1855,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEDW(x14, x1);
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
@@ -1864,16 +1864,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, 1");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETED;
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(x3, 1);
|
||||
STR_IMM9(x3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(x3, d_rcr32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(x3);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
XOR_REG_LSR_IMM8(x3, xFlags, ed, 31);
|
||||
BFI(xFlags, x3, F_OF, 1);
|
||||
@@ -1969,7 +1961,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Eb, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEB(x1);
|
||||
CALL_(rcl8, x1, (1<<x3));
|
||||
@@ -1979,7 +1971,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Eb, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEB(x1);
|
||||
CALL_(rcr8, x1, (1<<x3));
|
||||
@@ -2084,7 +2076,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEDW(x14, x1);
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
@@ -2094,7 +2086,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEDW(x14, x1);
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
@@ -2132,7 +2124,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xD4:
|
||||
INST_NAME("AAM Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UBFX(x1, xEAX, 0, 8); // load AL
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -2141,7 +2133,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xD5:
|
||||
INST_NAME("AAD Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
UBFX(x1, xEAX, 0, 16); // load AX
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -2264,14 +2256,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
#endif
|
||||
switch(tmp) {
|
||||
case 1:
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
//SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call 0\n");
|
||||
SKIPTEST(x14);
|
||||
MOV32(xEIP, addr);
|
||||
PUSH1(xEIP);
|
||||
break;
|
||||
case 2:
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
//SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
|
||||
SKIPTEST(x14);
|
||||
u8 = PK(i32+1);
|
||||
@@ -2279,7 +2271,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(gd, addr);
|
||||
break;
|
||||
case 3:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
MOV32(x2, addr);
|
||||
@@ -2326,21 +2318,39 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
// regular call
|
||||
//BARRIER_NEXT(BARRIER_FULL);
|
||||
if(/*box86_dynarec_callret &&*/ box86_dynarec_bigblock>1) {
|
||||
/*if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}*/
|
||||
MOV32(x2, addr);
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x3, x14);
|
||||
PUSH1(x2);
|
||||
if(box86_dynarec_callret) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
|
||||
ADR(c__, x14, j32);
|
||||
} else {
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
|
||||
j32 = getJumpTableAddress(addr);
|
||||
MOV32(x14, j32);
|
||||
LDR_IMM9(x14, x14, 0);
|
||||
}
|
||||
PUSH(xSP, (1<<x2)|(1<<x14));
|
||||
} else {
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
if(u32==0) { // self modifying code maybe? so use indirect address fetching
|
||||
MOV32(x14, addr-4);
|
||||
LDR_IMM9(x14, x14, 0);
|
||||
@@ -2384,7 +2394,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
MOV32(xEIP, ip);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
@@ -2500,7 +2510,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(box86_dynarec_safeflags>1) {
|
||||
READFLAGS(X_PEND);
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
ret_to_epilog(dyn, ninst);
|
||||
@@ -2744,7 +2754,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 6:
|
||||
INST_NAME("DIV Eb");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization DIV 8b\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEB(x1);
|
||||
STM(xEmu, (1<<xEAX));
|
||||
CALL(div8, -1, 0);
|
||||
@@ -2753,7 +2763,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 7:
|
||||
INST_NAME("IDIV Eb");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization IDIV 8b\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEB(x1);
|
||||
STM(xEmu, (1<<xEAX));
|
||||
CALL(idiv8, -1, 0);
|
||||
@@ -2806,7 +2816,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
if(ninst && dyn->insts && (nextop==0xF0)
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0xB8
|
||||
@@ -2854,7 +2864,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
if(arm_div && ninst && dyn->insts
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x99) {
|
||||
@@ -2908,7 +2918,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
INST_NAME(opcode==0xFA?"STI":"CLI");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
MOV32(xEIP, ip);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
@@ -2975,14 +2985,34 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDH(xEIP);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
//BARRIER_NEXT(BARRIER_FULL);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
MOV32(x2, addr);
|
||||
if(box86_dynarec_callret) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
|
||||
ADR(c__, x3, j32);
|
||||
} else {
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
|
||||
j32 = getJumpTableAddress(addr);
|
||||
MOV32(x3, j32);
|
||||
LDR_IMM9(x3, x3, 0);
|
||||
}
|
||||
PUSH(xSP, (1<<x2)|(1<<x3));
|
||||
}
|
||||
PUSH1(x2);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
break;
|
||||
|
||||
@@ -86,9 +86,68 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x01:
|
||||
nextop = F8;
|
||||
if(MODREG)
|
||||
switch(nextop) {
|
||||
case 0xD0:
|
||||
INST_NAME("FAKE xgetbv");
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
|
||||
//CALL(arm_ud, -1, 0);
|
||||
SKIPTEST(x14);
|
||||
UDF(0);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("SMSW Ed");
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, (1<<0) | (1<<4)); // only PE and ET set...
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("SGDT Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
MOVW(x1, 0x7f);
|
||||
STRH_IMM8(x1, wback, 0);
|
||||
MOVW(x1, 0x000c);
|
||||
STRH_IMM8(x1, wback, 2);
|
||||
MOVW(x1, 0xd000);
|
||||
STRH_IMM8(x1, wback, 4);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("SIDT Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
MOVW(x1, 0xfff);
|
||||
STRH_IMM8(x1, wback, 0);
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, wback, 2);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("SMSW Ew");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
// dummy for now... Do I need to track CR0 state?
|
||||
MOVW(x1, (1<<0) | (1<<4)); // only PE and ET set...
|
||||
STRH_IMM8(x1, wback, 0);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
|
||||
//CALL(arm_ud, -1, 0);
|
||||
SKIPTEST(x14);
|
||||
UDF(0);
|
||||
@@ -385,7 +444,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if(MODREG) {
|
||||
@@ -1585,7 +1644,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xA5:
|
||||
nextop = F8;
|
||||
INST_NAME("SHLD Ed, Gd, CL");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETED;
|
||||
GETGD;
|
||||
@@ -1643,7 +1702,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xAC:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED;
|
||||
GETGD;
|
||||
u8 = F8;
|
||||
@@ -1653,7 +1712,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xAD:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, CL");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETED;
|
||||
GETGD;
|
||||
@@ -1726,7 +1785,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 5:
|
||||
INST_NAME("XRSTOR Ed (not implemented");
|
||||
FAKEED;
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_ud, -1, 0);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "dynarec_arm.h"
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "arm_printer.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
@@ -364,7 +365,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
|
||||
}
|
||||
if(MODREG) { // reg
|
||||
MOV_REG(xEIP, xEAX+(nextop&7));
|
||||
@@ -372,10 +373,31 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
|
||||
}
|
||||
BARRIER(BARRIER_FULL);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
MOV32(x2, addr);
|
||||
if(box86_dynarec_callret) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
|
||||
ADR(c__, x3, j32);
|
||||
} else {
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
|
||||
j32 = getJumpTableAddress(addr);
|
||||
MOV32(x3, j32);
|
||||
LDR_IMM9(x3, x3, 0);
|
||||
}
|
||||
PUSH(xSP, (1<<x2)|(1<<x3));
|
||||
}
|
||||
PUSH1(x2);
|
||||
jump_to_next(dyn, 0, xEIP, ninst);
|
||||
break;
|
||||
|
||||
@@ -508,7 +508,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEDO2(x14);
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
@@ -519,7 +519,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x2));
|
||||
@@ -601,7 +601,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCL Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcl32, ed, (1<<x2));
|
||||
@@ -611,7 +611,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RCR Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
|
||||
@@ -48,8 +48,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
emit_add16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -57,16 +57,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
emit_add16(dyn, ninst, x1, x2, x3, x14, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("ADD AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_add16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -124,8 +124,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
emit_adc16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -134,8 +134,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
emit_adc16(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
@@ -143,8 +143,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -154,8 +154,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
emit_sbb16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -165,7 +165,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETSEW(x2);
|
||||
GETEW(x2);
|
||||
emit_sbb16(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
@@ -173,8 +173,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sbb16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -220,8 +220,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SUB Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
emit_sub16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -229,16 +229,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SUB Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
emit_sub16(dyn, ninst, x1, x2, x3, x14, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("SUB AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -637,7 +637,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x9D:
|
||||
INST_NAME("POPF (16b)");
|
||||
SETFLAGS(X_ALL, SF_SET); // lower 16bits is all flags handled in dynarec
|
||||
SETFLAGS(X_ALL, SF_SET_NODF); // lower 16bits is all flags handled in dynarec
|
||||
LDRHA_IMM8(x2, xESP, 2);
|
||||
MOV32(x1, 0x7FD7);
|
||||
AND_REG_LSL_IMM5(x2, x2, x1, 0);
|
||||
@@ -753,7 +753,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -763,7 +763,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
@@ -774,7 +774,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, Ib");
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_shl16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
@@ -787,7 +787,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_shr16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
@@ -800,7 +800,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEW(x1);
|
||||
u8 = F8;
|
||||
emit_sar16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
@@ -849,7 +849,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, 1");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEW(x1);
|
||||
CALL_(rcl16, x1, (1<<x3));
|
||||
@@ -858,7 +858,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, 1");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
MOVW(x2, 1);
|
||||
GETEW(x1);
|
||||
CALL_(rcr16, x1, (1<<x3));
|
||||
@@ -942,7 +942,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, CL");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEW(x1);
|
||||
CALL_(rcl16, x1, (1<<x3));
|
||||
@@ -951,7 +951,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, CL");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET_DF);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEW(x1);
|
||||
CALL_(rcr16, x1, (1<<x3));
|
||||
@@ -1161,7 +1161,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("DIV Ew");
|
||||
if(arm_div) {
|
||||
GETEW(x1);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
SET_DFNONE(x2);
|
||||
UXTH(x2, xEAX, 0);
|
||||
ORR_REG_LSL_IMM5(x2, x2, xEDX, 16);
|
||||
UDIV(x3, x2, ed);
|
||||
@@ -1170,7 +1171,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(xEDX, x14, 0, 16);
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(div16, -1, 0);
|
||||
@@ -1180,7 +1181,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 7:
|
||||
INST_NAME("IDIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEW(x1);
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(idiv16, -1, 0);
|
||||
|
||||
@@ -276,7 +276,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
@@ -468,6 +468,96 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VABSQ_S32(q0, q1);
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("PACKUSDW Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VEORQ(v0, v0, v0);
|
||||
VMAXQ_S32(v1, v0, q0); // values < 0 => 0
|
||||
VQMOVN_U32(q0, v1);
|
||||
if(q0==q1) {
|
||||
VMOV_64(q0+1, q0);
|
||||
} else {
|
||||
VMAXQ_S32(v0, v0, q1);
|
||||
VQMOVN_U32(q0+1, v0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
INST_NAME("PMINSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMINQ_S8(q0, q0, q1);
|
||||
break;
|
||||
case 0x39:
|
||||
INST_NAME("PMINSD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMINQ_S32(q0, q0, q1);
|
||||
break;
|
||||
case 0x3A:
|
||||
INST_NAME("PMINUW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMINQ_U16(q0, q0, q1);
|
||||
break;
|
||||
case 0x3B:
|
||||
INST_NAME("PMINUD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMINQ_U32(q0, q0, q1);
|
||||
break;
|
||||
case 0x3C:
|
||||
INST_NAME("PMAXSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMAXQ_S8(q0, q0, q1);
|
||||
break;
|
||||
case 0x3D:
|
||||
INST_NAME("PMAXSD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMAXQ_S32(q0, q0, q1);
|
||||
break;
|
||||
case 0x3E:
|
||||
INST_NAME("PMAXUW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMAXQ_U16(q0, q0, q1);
|
||||
break;
|
||||
case 0x3F:
|
||||
INST_NAME("PMAXUD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMINQ_U32(q0, q0, q1);
|
||||
break;
|
||||
case 0x40:
|
||||
INST_NAME("PMULLD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
VMULQ_32(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0xDB:
|
||||
INST_NAME("AESIMC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
@@ -577,6 +667,34 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x3A: // these are some more SSSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0E:
|
||||
INST_NAME("PBLENDW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
u8 = F8;
|
||||
i32 = 0;
|
||||
for(int i=0; i<4; ++i)
|
||||
if((u8&(1<<i)))
|
||||
i32|=(0b11<<(i*2));
|
||||
if(i32 && (q0!=q1)) {
|
||||
VMOV_D64(v0, i32);
|
||||
VBICD(q0, q0, v0);
|
||||
VANDD(v0, q1, v0);
|
||||
VORRD(q0, q0, v0);
|
||||
}
|
||||
i32 = 0;
|
||||
for(int i=0; i<4; ++i)
|
||||
if((u8&(1<<(i+4))))
|
||||
i32|=(0b11<<(i*2));
|
||||
if(i32 && (q0!=q1)) {
|
||||
VMOV_D64(v0, i32);
|
||||
VBICD(q0+1, q0+1, v0);
|
||||
VANDD(v0, q1+1, v0);
|
||||
VORRD(q0+1, q0+1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x0F:
|
||||
INST_NAME("PALIGNR Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -686,7 +804,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
|
||||
case 0x63:
|
||||
INST_NAME("PCMPISTRI Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(!sse_reflect_reg(dyn, ninst, gd, x2)) {
|
||||
@@ -1718,7 +1836,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("SHLD Ew, Gw, CL");
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEWW(x14, x1);
|
||||
GETGW(x2);
|
||||
if(opcode==0xA4) {
|
||||
@@ -1770,7 +1888,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("SHRD Ew, Gw, CL");
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_DF);
|
||||
GETEWW(x14, x1);
|
||||
GETGW(x2);
|
||||
if(opcode==0xAC) {
|
||||
|
||||
@@ -33,6 +33,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int d1;
|
||||
int fixedaddress;
|
||||
int parity;
|
||||
uint8_t u8;
|
||||
|
||||
MAYUSE(d1);
|
||||
MAYUSE(s0);
|
||||
@@ -52,11 +53,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FADD ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, v2);
|
||||
} else {
|
||||
VADD_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -69,11 +74,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FMUL ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, v2);
|
||||
} else {
|
||||
VMUL_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -110,7 +119,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -123,11 +132,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUB ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -140,11 +153,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUBR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v1, v2, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -157,11 +174,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIV ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -174,11 +195,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIVR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v1, v2, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -196,12 +221,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VADD_F64(v1, v1, d1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, float[ED]");
|
||||
@@ -216,12 +245,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VMUL_F64(v1, v1, d1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, float[ED]");
|
||||
@@ -264,7 +297,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, d1);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, float[ED]");
|
||||
@@ -279,12 +312,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, v1, d1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, float[ED]");
|
||||
@@ -299,12 +336,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, s0, v1);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VSUB_F64(v1, d1, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, float[ED]");
|
||||
@@ -319,12 +360,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, s0);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, v1, d1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, float[ED]");
|
||||
@@ -339,12 +384,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
VMOVtoV(s0, ed);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, s0, v1);
|
||||
} else {
|
||||
VCVT_F64_F32(d1, s0);
|
||||
VDIV_F64(v1, d1, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
+110
-62
@@ -67,7 +67,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FLD STx");
|
||||
v2 = x87_do_push(dyn, ninst, x3, X87_ST(nextop&7));
|
||||
X87_PUSH_OR_FAIL(v2, dyn, ninst, x3, X87_ST(nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_32(v2, v1);
|
||||
@@ -134,25 +134,29 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i1 = x87_get_current_cache(dyn, ninst, 0, NEON_CACHE_ST_D);
|
||||
// value put in x14
|
||||
if(i1==-1) {
|
||||
// not in cache, so check Empty status and load it
|
||||
// x14 will be the actual top
|
||||
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
|
||||
i2 = -dyn->n.x87stack;
|
||||
if(i2) {
|
||||
if(i2<0) {
|
||||
SUB_IMM8(x14, x14, -i2);
|
||||
} else {
|
||||
ADD_IMM8(x14, x14, i2);
|
||||
if(fpu_is_st_freed(dyn, ninst, 0)) {
|
||||
MOV32(x14, 0b100000100000000);
|
||||
B_MARK3(c__);
|
||||
} else { // not in cache, so check Empty status and load it
|
||||
// x14 will be the actual top
|
||||
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
|
||||
i2 = -dyn->n.x87stack;
|
||||
if(i2) {
|
||||
if(i2<0) {
|
||||
SUB_IMM8(x14, x14, -i2);
|
||||
} else {
|
||||
ADD_IMM8(x14, x14, i2);
|
||||
}
|
||||
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
|
||||
}
|
||||
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
|
||||
// load tag
|
||||
LDRH_IMM8(x3, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
TSTS_IMM8(x3, 0b11);
|
||||
MOVW_COND(cNE, x14, 0b100000100000000);
|
||||
B_MARK3(cNE);
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
|
||||
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
|
||||
}
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
|
||||
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x14, 2);
|
||||
LDR_IMM9(x1, x1, offsetof(x86emu_t, p_regs));
|
||||
CMPS_IMM8(x1, 0b11);
|
||||
MOVW_COND(cEQ, x14, 0b100000100000000); // empty: C3,C2,C0 = 101
|
||||
B_MARK3(cEQ);
|
||||
} else {
|
||||
// simply move from cache reg to r2/r3
|
||||
v1 = dyn->n.x87reg[i1];
|
||||
@@ -194,7 +198,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("FLD1");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_i_32(v1, 0b01110000);
|
||||
} else {
|
||||
@@ -204,7 +208,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FLDL2T");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_l2t));
|
||||
VLDR_32(v1, x2, 0);
|
||||
@@ -216,7 +220,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xEA:
|
||||
INST_NAME("FLDL2E");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_l2e));
|
||||
VLDR_32(v1, x2, 0);
|
||||
@@ -228,7 +232,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("FLDPI");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_pi));
|
||||
VLDR_32(v1, x2, 0);
|
||||
@@ -240,7 +244,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("FLDLG2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_lg2));
|
||||
VLDR_32(v1, x2, 0);
|
||||
@@ -252,7 +256,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("FLDLN2");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
MOV32(x2, (&f_ln2));
|
||||
VLDR_32(v1, x2, 0);
|
||||
@@ -264,7 +268,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xEE:
|
||||
INST_NAME("FLDZ");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_8(v1/2, 0); // float is *2...
|
||||
} else {
|
||||
@@ -281,18 +285,20 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CALL(arm_f2xm1, -1, 0);
|
||||
#else
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
//if(ST0.d!=0.0)
|
||||
// ST0.d = exp2(ST0.d)-1.0;
|
||||
VMOV_64(0, v1);
|
||||
CALL_1D(exp2, 0); // return is d0
|
||||
if((PK(0)==0xD9 && PK(1)==0xE8) && // next inst is FLD1
|
||||
(PK(2)==0xDE && PK(3)==0xC1)) {
|
||||
MESSAGE(LOG_DUMP, "Hack for fld1 / faddp st1, st0\n");
|
||||
VMOV_64(0, v1);
|
||||
CALL_1D(exp2, 0); // return is d0
|
||||
VMOV_64(v1, 0);
|
||||
addr+=4;
|
||||
} else {
|
||||
VMOV_i_64(v1, 0b01110000); // 1.0
|
||||
VSUB_F64(v1, 0, v1);
|
||||
//ST0.d = expm1(LN2 * ST0.d);
|
||||
MOV32(x2, (&d_ln2));
|
||||
VLDR_64(0, x2, 0);
|
||||
VMUL_F64(0, 0, v1);
|
||||
CALL_1D(expm1, 0); // return is d0
|
||||
VMOV_64(v1, 0);
|
||||
}
|
||||
#endif
|
||||
// should set C1 to 0
|
||||
@@ -301,19 +307,25 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FYL2X");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
|
||||
VMOV_64(0, v1); // prepare call to log2
|
||||
CALL_1D(log2, 0);
|
||||
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d)*ST(1).d
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
// should set C1 to 0
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FPTAN");
|
||||
v2 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
// seems that tan of glib doesn't follow the rounding direction mode
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMOV_64(0, v1); // prepare call to tan
|
||||
CALL_1D(tan, 0);
|
||||
CALL_1D(tan, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VMOV_64(v1, 0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
//emu->sw.f.F87_C2 = 0;
|
||||
//emu->sw.f.F87_C1 = 0;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
@@ -321,8 +333,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
if(PK(0)==0xdd && PK(1)==0xd8) {
|
||||
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
|
||||
u8 = F8;
|
||||
u8 = F8;
|
||||
} else {
|
||||
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
|
||||
// and want 1.0 = 0x3ff0000000000000
|
||||
@@ -340,11 +350,15 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FPATAN");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMOV_64(0, v2); // prepare call to atan2
|
||||
VMOV_64(1, v1);
|
||||
CALL_2D(atan2, 0);
|
||||
CALL_2D(atan2, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VMOV_64(v2, 0); //ST(1).d = atan2(ST1.d, ST0.d);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
// should set C1 to 0
|
||||
break;
|
||||
case 0xF4:
|
||||
@@ -352,7 +366,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
s0 = x87_stackcount(dyn, ninst, x3);
|
||||
CALL(arm_fxtract, -1, 0);
|
||||
x87_unstackcount(dyn, ninst, x3, s0);
|
||||
// C1 set only if stack under/overflow occurs
|
||||
break;
|
||||
case 0xF5:
|
||||
@@ -451,32 +467,45 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FYL2XP1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
VMOV_i_64(0, 0b01110000); // D0 = 1.0
|
||||
VADD_F64(0, 0, v1); // prepare call to log2
|
||||
CALL_1D(log2, 0);
|
||||
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
|
||||
//ST(1).d = (ST(1).d * log1p(ST0.d)) / M_LN2;
|
||||
VMOV_64(0, v1); // prepare call to log1p
|
||||
CALL_1D(log1p, 0);
|
||||
VMUL_F64(v2, v2, 0);
|
||||
MOV32(x2, (&d_ln2));
|
||||
VLDR_64(0, x2, 0);
|
||||
VDIV_F64(v2, v2, 0);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
// should set C1 to 0
|
||||
break;
|
||||
case 0xFA:
|
||||
INST_NAME("FSQRT");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSQRT_F32(v1, v1);
|
||||
} else {
|
||||
VSQRT_F64(v1, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
// should set C1 to 0
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v2, dyn, ninst, x3, NEON_CACHE_ST_D);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
// seems that sin and cos function of glibc don't follow the rounding mode
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMOV_64(0, v1);
|
||||
CALL_1D(sin, 0);
|
||||
CALL_1D(sin, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VSWP(v1, 0);
|
||||
CALL_1D(cos, 0); // would it be faster to do sqrt(1-sin()²) ???
|
||||
CALL_1D(cos, box86_dynarec_fastround ? 0 : (1 << u8)); // would it be faster to do sqrt(1-sin()²) ???
|
||||
VMOV_64(v2, 0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
//emu->sw.f.F87_C2 = 0; C1 too
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 9, 2); //C2 C1 = 0 0
|
||||
@@ -511,26 +540,32 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
|
||||
//if(ST0.d!=0.0)
|
||||
// ST0.d *= exp2(trunc(ST1.d));
|
||||
VCMP_F64_0(v1);
|
||||
VMRS_APSR();
|
||||
B_NEXT(cEQ);
|
||||
if(!arm_v8) {
|
||||
VMOV_64(0, v2);
|
||||
CALL_1DD(trunc, exp2, 0);
|
||||
} else {
|
||||
VRINTZ_F64(0, v2);
|
||||
CALL_1D(exp2, 0);
|
||||
}
|
||||
VMUL_F64(v1, v1, 0);
|
||||
// ST0.d = ldexp(ST0.d, trunc(ST1.d));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
// value of s0 =
|
||||
// 2^31-1 (ST1 >= 2^31), -2^31 (ST1 < -2^31) or int(ST1) (other situations)
|
||||
VCVT_S32_F64(s0 , v2);
|
||||
VMOVfrV(x2, s0);
|
||||
VMOV_64(0, v1);
|
||||
CALL_1DDR(ldexp, x2, x3, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VMOV_64(v1, 0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
// should set C1 to 0
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
// seems that sin of glib doesn't follow the rounding direction mode
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMOV_64(0, v1); // prepare call to sin
|
||||
CALL_1D(sin, 0);
|
||||
CALL_1D(sin, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VMOV_64(v1, 0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
//emu->sw.f.F87_C2 = 0; C1 too
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 9, 2); //C2 C1 = 0 0
|
||||
@@ -539,9 +574,14 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
// seems that cos of glib doesn't follow the rounding direction mode
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMOV_64(0, v1); // prepare call to cos
|
||||
CALL_1D(cos, 0);
|
||||
CALL_1D(cos, box86_dynarec_fastround ? 0 : (1 << u8));
|
||||
VMOV_64(v1, 0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
//emu->sw.f.F87_C2 = 0; C1 too
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 9, 2); //C2 C1 = 0 0
|
||||
@@ -574,7 +614,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else
|
||||
@@ -600,7 +640,11 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = v1;
|
||||
else {
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
@@ -619,7 +663,11 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = v1;
|
||||
else {
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VCVT_F32_F64(s0, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
@@ -630,7 +678,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMOVfrV(x2, s0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
|
||||
@@ -33,6 +33,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int d0;
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
uint8_t u8;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(d0);
|
||||
@@ -128,8 +129,8 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
@@ -155,7 +156,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VADD_F64(v1, v1, d0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FIMUL ST0, Ed");
|
||||
@@ -165,7 +170,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMUL_F64(v1, v1, d0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FICOM ST0, Ed");
|
||||
@@ -188,7 +197,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCVT_F64_S32(d0, s0);
|
||||
VCMP_F64(v1, d0);
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FISUB ST0, Ed");
|
||||
@@ -198,7 +207,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VSUB_F64(v1, v1, d0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FISUBR ST0, Ed");
|
||||
@@ -208,7 +221,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VSUB_F64(v1, d0, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FIDIV ST0, Ed");
|
||||
@@ -218,7 +235,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VDIV_F64(v1, v1, d0);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FIDIVR ST0, Ed");
|
||||
@@ -228,7 +249,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
VMOVtoV(s0, ed);
|
||||
VCVT_F64_S32(d0, s0);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VDIV_F64(v1, d0, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -160,7 +160,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -183,7 +183,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
@@ -218,7 +218,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
|
||||
WBACK;
|
||||
VMSR(x14); // put back values
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ed, ST0");
|
||||
@@ -260,7 +260,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
|
||||
WBACK;
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 5:
|
||||
@@ -268,20 +268,18 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDR_IMM9(x2, ed, 0);
|
||||
LDR_IMM9(x3, ed, 4);
|
||||
LDM(ed, (1<<x2)|(1<<x3));
|
||||
LDRH_IMM8(x14, ed, 8);
|
||||
// no persistant scratch register, so unrool both instruction here...
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
STM(ed, (1<<x2)|(1<<x3));
|
||||
STRH_IMM8(x14, ed, 8);
|
||||
} else {
|
||||
if(box86_x87_no80bits) {
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
@@ -298,10 +296,10 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
X87_PUSH_OR_FAIL_empty( , dyn, ninst, x3);
|
||||
CALL(arm_fld, -1, 0);
|
||||
#else
|
||||
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x2, NEON_CACHE_ST_D);
|
||||
// copy 10bytes of *ED to STld(0)
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
|
||||
int a = -dyn->n.x87stack;
|
||||
@@ -407,7 +405,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MARK2;
|
||||
#endif
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -31,6 +31,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int d1;
|
||||
int fixedaddress;
|
||||
int parity;
|
||||
uint8_t u8;
|
||||
|
||||
MAYUSE(d1);
|
||||
MAYUSE(v2);
|
||||
@@ -48,11 +49,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FADD STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v1, v1, v2);
|
||||
} else {
|
||||
VADD_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -65,11 +70,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FMUL STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v1, v1, v2);
|
||||
} else {
|
||||
VMUL_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -106,7 +115,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -119,11 +128,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUBR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v1, v2, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -136,11 +149,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUB STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v1, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -153,11 +170,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIVR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v1, v2, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -170,11 +191,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIV STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v1, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v1, v1, v2);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -192,7 +217,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VADD_F64(v1, v1, d1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, double[ED]");
|
||||
@@ -208,7 +237,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VMUL_F64(v1, v1, d1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, double[ED]");
|
||||
@@ -243,7 +276,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
VCMP_F64(v1, d1);
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
@@ -259,7 +292,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VSUB_F64(v1, v1, d1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, double[ED]");
|
||||
@@ -275,7 +312,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VSUB_F64(v1, d1, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, double[ED]");
|
||||
@@ -291,7 +332,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VDIV_F64(v1, v1, d1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, double[ED]");
|
||||
@@ -307,7 +352,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
VDIV_F64(v1, d1, v1);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,21 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREE STx");
|
||||
#if 1
|
||||
if((nextop&7)==0 && PK(0)==0xD9 && PK(1)==0xF7) {
|
||||
MESSAGE(LOG_DUMP, "Hack for FFREE ST0 / FINCSTP\n");
|
||||
X87_POP_OR_FAIL(dyn, ninst, x1);
|
||||
addr+=2;
|
||||
SKIPTEST(x1);
|
||||
} else
|
||||
x87_free(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
#else
|
||||
INST_NAME("FFREE STx");
|
||||
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
MOVW(x1, nextop&7);
|
||||
CALL(fpu_do_free, -1, 0);
|
||||
#endif
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -69,7 +80,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("FSTP ST0, ST0");
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
@@ -81,7 +92,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSTP ST0, STx");
|
||||
// copy the cache value for st0 to stx
|
||||
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
@@ -119,7 +130,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
@@ -153,7 +164,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD double");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
@@ -171,7 +182,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fistt64, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST double");
|
||||
@@ -200,7 +211,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
@@ -215,6 +226,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fsave, -1, 0);
|
||||
CALL(reset_fpu, -1, 0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
#include "dynarec.h"
|
||||
#include "dynarec/arm_emitter.h"
|
||||
#include "emu/x86emu_private.h"
|
||||
#include "emu/x86run_private.h"
|
||||
#include "x86run.h"
|
||||
@@ -27,6 +28,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
int v1, v2;
|
||||
uint8_t u8;
|
||||
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
@@ -43,12 +45,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FADDP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VADD_F32(v2, v2, v1);
|
||||
} else {
|
||||
VADD_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -61,12 +67,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FMULP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VMUL_F32(v2, v2, v1);
|
||||
} else {
|
||||
VMUL_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -85,7 +95,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xD9:
|
||||
@@ -98,8 +108,8 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
@@ -112,12 +122,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUBRP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v2, v1, v2);
|
||||
} else {
|
||||
VSUB_F64(v2, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -130,12 +144,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FSUBP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VSUB_F32(v2, v2, v1);
|
||||
} else {
|
||||
VSUB_F64(v2, v2, v1);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -148,12 +166,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIVRP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v2, v1, v2);
|
||||
} else {
|
||||
VDIV_F64(v2, v1, v2);
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround)
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -166,11 +188,21 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIVP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastnan) {
|
||||
if(!box86_dynarec_fastround || !box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
} else if(!box86_dynarec_fastround)
|
||||
MOV_REG(x3, x14);
|
||||
if(!box86_dynarec_fastround){
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
|
||||
UBFX(x1, x1, 10, 2); // extract round...
|
||||
UBFX(x2, x1, 1, 1); // swap bits 0 and 1
|
||||
BFI(x2, x1, 1, 1);
|
||||
BFI(x3, x2, 22, 2); // inject new round
|
||||
}
|
||||
VMSR(x3); // put new fpscr
|
||||
}
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v2, v2, v1);
|
||||
@@ -185,9 +217,10 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
VNEG_F64_cond(cNE, v2, v2);
|
||||
}
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
if(!box86_dynarec_fastround || !box86_dynarec_fastnan)
|
||||
VMSR(x14); // restore fpscr
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xD8:
|
||||
|
||||
@@ -53,7 +53,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC7:
|
||||
INST_NAME("FFREEP STx");
|
||||
// not handling Tag...
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
@@ -81,7 +81,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0))
|
||||
@@ -91,7 +91,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -102,7 +102,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_NODF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(ST_IS_F(0))
|
||||
@@ -112,7 +112,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VCMP_F64(v1, v2);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
@@ -161,7 +161,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRSH_IMM8(x1, wback, fixedaddress);
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -197,7 +197,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
|
||||
MOVW_COND(cNE, x3, 0x8000); // saturated
|
||||
STRH_IMM8(x3, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
VMSR(x14);
|
||||
break;
|
||||
case 2:
|
||||
@@ -242,20 +242,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
|
||||
MOVW_COND(cNE, x3, 0x8000); // saturated
|
||||
STRH_IMM8(x3, wback, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FBLD ST0, tbytes");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
s0 = x87_stackcount(dyn, ninst, x3);
|
||||
CALL(fpu_fbld, -1, 0);
|
||||
x87_unstackcount(dyn, ninst, x3, s0);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FILD ST0, i64");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
@@ -314,8 +316,10 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
s0 = x87_stackcount(dyn, ninst, x3);
|
||||
CALL(fpu_fbst, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
x87_unstackcount(dyn, ninst, x3, s0);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 7: // could be inlined for most thing, but is it usefull?
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
@@ -440,7 +444,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CALL(arm_fistp64, -1, 0);
|
||||
#endif
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -986,6 +986,52 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFE:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Eb
|
||||
INST_NAME("INC Eb");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1);
|
||||
emit_inc8(dyn, ninst, x1, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_inc8(dyn, ninst, x1, x3, x14);
|
||||
STREXB(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("DEC Eb");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1);
|
||||
emit_dec8(dyn, ninst, x1, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_dec8(dyn, ninst, x1, x3, x14);
|
||||
STREXB(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
|
||||
@@ -487,13 +487,18 @@ void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
|
||||
dyn->n.neoncache[i+1].v = 0;
|
||||
}
|
||||
// Reset fpu regs counter
|
||||
static void fpu_reset_reg_neoncache(neoncache_t* n)
|
||||
{
|
||||
n->fpu_reg = 0;
|
||||
for (int i=0; i<24; ++i) {
|
||||
n->fpuused[i]=0;
|
||||
n->neoncache[i].v = 0;
|
||||
}
|
||||
|
||||
}
|
||||
void fpu_reset_reg(dynarec_arm_t* dyn)
|
||||
{
|
||||
dyn->n.fpu_reg = 0;
|
||||
for (int i=0; i<24; ++i) {
|
||||
dyn->n.fpuused[i]=0;
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
}
|
||||
fpu_reset_reg_neoncache(&dyn->n);
|
||||
}
|
||||
|
||||
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
|
||||
@@ -740,6 +745,7 @@ void neoncacheUnwind(neoncache_t* cache)
|
||||
// unswap
|
||||
int a = -1;
|
||||
int b = -1;
|
||||
// in neoncache
|
||||
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
|
||||
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
|
||||
if(cache->neoncache[j].n == cache->combined1)
|
||||
@@ -756,7 +762,7 @@ void neoncacheUnwind(neoncache_t* cache)
|
||||
cache->combined1 = cache->combined2 = 0;
|
||||
}
|
||||
if(cache->news) {
|
||||
// reove the newly created neoncache
|
||||
// remove the newly created neoncache
|
||||
for(int i=0; i<24; ++i)
|
||||
if(cache->news&(1<<i))
|
||||
cache->neoncache[i].v = 0;
|
||||
@@ -773,11 +779,23 @@ void neoncacheUnwind(neoncache_t* cache)
|
||||
}
|
||||
}
|
||||
cache->x87stack-=cache->stack_push;
|
||||
cache->tags>>=(cache->stack_push*2);
|
||||
cache->stack-=cache->stack_push;
|
||||
if(cache->pushed>=cache->stack_push)
|
||||
cache->pushed-=cache->stack_push;
|
||||
else
|
||||
cache->pushed = 0;
|
||||
cache->stack_push = 0;
|
||||
}
|
||||
cache->x87stack+=cache->stack_pop;
|
||||
cache->stack_next = cache->stack;
|
||||
if(cache->stack_pop) {
|
||||
if(cache->poped>=cache->stack_pop)
|
||||
cache->poped-=cache->stack_pop;
|
||||
else
|
||||
cache->poped = 0;
|
||||
cache->tags<<=(cache->stack_pop*2);
|
||||
}
|
||||
cache->stack_pop = 0;
|
||||
cache->barrier = 0;
|
||||
// And now, rebuild the x87cache info with neoncache
|
||||
@@ -1028,3 +1046,56 @@ void print_opcode(dynarec_arm_t* dyn, int ninst, uint32_t opcode)
|
||||
{
|
||||
dynarec_log(LOG_NONE, "\t%08x\t%s\n", opcode, arm_print(opcode));
|
||||
}
|
||||
|
||||
static void x87_reset(neoncache_t* n)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
n->x87cache[i] = -1;
|
||||
n->x87stack = 0;
|
||||
n->stack = 0;
|
||||
n->stack_next = 0;
|
||||
n->stack_pop = 0;
|
||||
n->stack_push = 0;
|
||||
n->combined1 = n->combined2 = 0;
|
||||
n->swapped = 0;
|
||||
n->barrier = 0;
|
||||
n->pushed = 0;
|
||||
n->poped = 0;
|
||||
|
||||
for(int i=0; i<24; ++i)
|
||||
if(n->neoncache[i].t == NEON_CACHE_ST_F || n->neoncache[i].t == NEON_CACHE_ST_D)
|
||||
n->neoncache[i].v = 0;
|
||||
}
|
||||
static void mmx_reset(neoncache_t* n)
|
||||
{
|
||||
n->mmxcount = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
n->mmxcache[i] = -1;
|
||||
}
|
||||
static void sse_reset(neoncache_t* n)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
n->ssecache[i].v = -1;
|
||||
}
|
||||
|
||||
|
||||
void fpu_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
x87_reset(&dyn->n);
|
||||
mmx_reset(&dyn->n);
|
||||
sse_reset(&dyn->n);
|
||||
fpu_reset_reg(dyn);
|
||||
}
|
||||
|
||||
void fpu_reset_ninst(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
x87_reset(&dyn->insts[ninst].n);
|
||||
mmx_reset(&dyn->insts[ninst].n);
|
||||
sse_reset(&dyn->insts[ninst].n);
|
||||
fpu_reset_reg_neoncache(&dyn->insts[ninst].n);
|
||||
}
|
||||
|
||||
int fpu_is_st_freed(dynarec_arm_t* dyn, int ninst, int st)
|
||||
{
|
||||
return (dyn->n.tags&(0b11<<(st*2)))?1:0;
|
||||
}
|
||||
@@ -101,4 +101,10 @@ const char* getCacheName(int t, int n);
|
||||
void inst_name_pass3(dynarec_arm_t* dyn, int ninst, const char* name);
|
||||
void print_opcode(dynarec_arm_t* dyn, int ninst, uint32_t opcode);
|
||||
|
||||
// reset the cache
|
||||
void fpu_reset(dynarec_arm_t* dyn);
|
||||
void fpu_reset_ninst(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
// is st freed
|
||||
int fpu_is_st_freed(dynarec_arm_t* dyn, int ninst, int st);
|
||||
#endif //__DYNAREC_ARM_FUNCTIONS_H__
|
||||
+337
-190
@@ -288,47 +288,68 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
|
||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Ret next\n");
|
||||
POP1(xEIP);
|
||||
MOV32(x2, getJumpTable());
|
||||
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
MOV_REG(x1, xEIP);
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
SMEND();
|
||||
BX(x3);
|
||||
MESSAGE(LOG_DUMP, "Ret next\n");
|
||||
POP1(xEIP);
|
||||
SMEND();
|
||||
if(box86_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
POP(xSP, (1<<x2)|(1<<x3));
|
||||
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
|
||||
BXcond(cEQ, x3);
|
||||
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
|
||||
CMPS_IMM8(x3, 0); // that was already the top of the stack...
|
||||
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave)); // load pointer only if not already on top
|
||||
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
|
||||
}
|
||||
MOV32(x2, getJumpTable());
|
||||
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
MOV_REG(x1, xEIP);
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
BX(x3);
|
||||
}
|
||||
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Retn epilog\n");
|
||||
POP1(xEIP);
|
||||
if(n>0xff) {
|
||||
MOVW(x1, n);
|
||||
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
|
||||
} else {
|
||||
ADD_IMM8(xESP, xESP, n);
|
||||
}
|
||||
MOV32(x2, getJumpTable());
|
||||
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
MOV_REG(x1, xEIP);
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
SMEND();
|
||||
BX(x3);
|
||||
MESSAGE(LOG_DUMP, "Retn epilog\n");
|
||||
POP1(xEIP);
|
||||
if(n>0xff) {
|
||||
MOVW(x1, n);
|
||||
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
|
||||
} else {
|
||||
ADD_IMM8(xESP, xESP, n);
|
||||
}
|
||||
SMEND();
|
||||
if(box86_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
POP(xSP, (1<<x2)|(1<<x3));
|
||||
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
|
||||
BXcond(cEQ, x3);
|
||||
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
|
||||
CMPS_IMM8(x3, 0); // that was already the top of the stack...
|
||||
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave));
|
||||
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
|
||||
}
|
||||
MOV32(x2, getJumpTable());
|
||||
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
|
||||
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
|
||||
MOV_REG(x1, xEIP);
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
BX(x3);
|
||||
}
|
||||
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "IRet epilog\n");
|
||||
SET_DFNONE(x1);
|
||||
// POP IP
|
||||
POP1(xEIP);
|
||||
// POP CS
|
||||
@@ -375,7 +396,6 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
SET_NODF();
|
||||
}
|
||||
|
||||
#if defined(__ARM_PCS) && !defined(__ARM_PCS_VFP)
|
||||
@@ -427,7 +447,6 @@ void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
SET_NODF();
|
||||
}
|
||||
// call a function with n double args (taking care of the SOFTFP / HARD call) that return a double too
|
||||
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags)
|
||||
@@ -476,8 +495,53 @@ void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
SET_NODF();
|
||||
}
|
||||
// call a function with 1 double arg (taking care of the SOFTFP / HARD call) and 1 non-float arg that return a double
|
||||
void call_ddr(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int arg, int reg, int ret, uint32_t mask, int saveflags)
|
||||
{
|
||||
if(ret!=-2 && !mask) {
|
||||
// ARM ABI require the stack to be 8-bytes aligned!
|
||||
// so, if no mask asked, add one to stay 8-bytes aligned
|
||||
if(ret!=xFlags) mask=1<<xFlags; else mask=1<<x3;
|
||||
}
|
||||
if(ret!=-2) {
|
||||
PUSH(xSP, (1<<xEmu) | mask);
|
||||
}
|
||||
fpu_pushcache(dyn, ninst, reg);
|
||||
if(saveflags) {
|
||||
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
#ifdef ARM_SOFTFP
|
||||
VMOVfrV_64(0, 1, 0);// D0 -> r0:r1
|
||||
MOV_REG(2, arg);
|
||||
#else
|
||||
MOV_REG(0, arg);
|
||||
#endif
|
||||
MOV32(reg, (uintptr_t)fnc);
|
||||
BLX(reg);
|
||||
if(fnc2) {
|
||||
#ifdef ARM_SOFTFP
|
||||
// result are already in r0:r1 for next call
|
||||
#endif
|
||||
MOV32(reg, (uintptr_t)fnc2);
|
||||
BLX(reg);
|
||||
}
|
||||
#ifdef ARM_SOFTFP
|
||||
POP(xSP, (1<<2) | (1<<3));
|
||||
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
|
||||
#endif
|
||||
fpu_popcache(dyn, ninst, reg);
|
||||
if(ret>=0) {
|
||||
MOV_REG(ret, 0);
|
||||
}
|
||||
if(ret!=-2) {
|
||||
POP(xSP, (1<<xEmu) | mask);
|
||||
}
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
}
|
||||
|
||||
// call a function with 1 arg, (taking care of the SOFTFP / HARD call) that return a double, using s1 as scratch
|
||||
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags)
|
||||
{
|
||||
@@ -539,27 +603,10 @@ void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
}
|
||||
|
||||
// x87 stuffs
|
||||
static void x87_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->n.x87cache[i] = -1;
|
||||
dyn->n.x87stack = 0;
|
||||
dyn->n.stack = 0;
|
||||
dyn->n.stack_next = 0;
|
||||
dyn->n.stack_pop = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.combined1 = dyn->n.combined2 = 0;
|
||||
dyn->n.swapped = 0;
|
||||
dyn->n.barrier = 0;
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].t == NEON_CACHE_ST_F || dyn->n.neoncache[i].t == NEON_CACHE_ST_D)
|
||||
dyn->n.neoncache[i].v = 0;
|
||||
}
|
||||
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
{
|
||||
if(!dyn->n.x87stack)
|
||||
return;
|
||||
return 0;
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, scratch);
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->n.x87stack);
|
||||
@@ -586,6 +633,39 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
dyn->n.stack_next -= dyn->n.stack;
|
||||
dyn->n.stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
return a;
|
||||
}
|
||||
|
||||
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count)
|
||||
{
|
||||
if(!count)
|
||||
return;
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, scratch);
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Unstackcount (%d)\n", dyn->n.x87stack);
|
||||
int a = -count;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(scratch, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADD_IMM8(scratch, scratch, a);
|
||||
} else {
|
||||
SUB_IMM8(scratch, scratch, -a);
|
||||
}
|
||||
STR_IMM9(scratch, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(scratch, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
SUB_IMM8(scratch, scratch, a);
|
||||
} else {
|
||||
ADD_IMM8(scratch, scratch, -a);
|
||||
}
|
||||
AND_IMM8(scratch, scratch, 7);
|
||||
STR_IMM9(scratch, xEmu, offsetof(x86emu_t, top));
|
||||
// reset x87stack, but not the stack count of neoncache
|
||||
dyn->n.x87stack = count;
|
||||
dyn->n.stack = count;
|
||||
dyn->n.stack_next += dyn->n.stack;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Unstackcount\n");
|
||||
}
|
||||
|
||||
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b)
|
||||
@@ -610,11 +690,15 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t)
|
||||
dyn->n.stack+=1;
|
||||
dyn->n.stack_next+=1;
|
||||
dyn->n.stack_push+=1;
|
||||
++dyn->n.pushed;
|
||||
if(dyn->n.poped)
|
||||
--dyn->n.poped;
|
||||
// move all regs in cache, and find a free one
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
|
||||
++dyn->n.neoncache[j].n;
|
||||
int ret = -1;
|
||||
dyn->n.tags<<=2;
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->n.x87cache[i]!=-1)
|
||||
++dyn->n.x87cache[i];
|
||||
@@ -639,6 +723,9 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
dyn->n.stack+=1;
|
||||
dyn->n.stack_next+=1;
|
||||
dyn->n.stack_push+=1;
|
||||
++dyn->n.pushed;
|
||||
if(dyn->n.poped)
|
||||
--dyn->n.poped;
|
||||
// move all regs in cache
|
||||
for(int j=0; j<24; ++j)
|
||||
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
|
||||
@@ -646,17 +733,12 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->n.x87cache[i]!=-1)
|
||||
++dyn->n.x87cache[i];
|
||||
dyn->n.tags<<=2;
|
||||
if(s1)
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
}
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
void static internal_x87_dopop(dynarec_arm_t* dyn)
|
||||
{
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
dyn->n.x87stack-=1;
|
||||
dyn->n.stack_next-=1;
|
||||
dyn->n.stack_pop+=1;
|
||||
// move all regs in cache, poping ST0
|
||||
for(int i=0; i<8; ++i)
|
||||
if(dyn->n.x87cache[i]!=-1) {
|
||||
--dyn->n.x87cache[i];
|
||||
@@ -666,6 +748,30 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
}
|
||||
}
|
||||
int static internal_x87_dofree(dynarec_arm_t* dyn)
|
||||
{
|
||||
if(dyn->n.tags&0b11) {
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 FREED ST0, poping 1 more\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
if(dyn->n.mmxcount)
|
||||
mmx_purgecache(dyn, ninst, 0, s1);
|
||||
do {
|
||||
dyn->n.x87stack-=1;
|
||||
dyn->n.stack_next-=1;
|
||||
dyn->n.stack_pop+=1;
|
||||
dyn->n.tags>>=2;
|
||||
++dyn->n.poped;
|
||||
if(dyn->n.pushed)
|
||||
--dyn->n.pushed;
|
||||
// move all regs in cache, poping ST0
|
||||
internal_x87_dopop(dyn);
|
||||
} while(internal_x87_dofree(dyn));
|
||||
}
|
||||
|
||||
static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
|
||||
{
|
||||
@@ -685,20 +791,11 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
}
|
||||
// Setting all 8 xp_regs to "FULL"
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
MOVW(s3, 0);
|
||||
for (int i=0; i<8; ++i) {
|
||||
STRAI_IMM9_W(s3, s1, sizeof(fpu_p_reg_t));
|
||||
}
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
// setup TOP => full stack so = 0
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
|
||||
offs = offsetof(x86emu_t, x87);
|
||||
uintptr_t offs = offsetof(x86emu_t, x87);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
@@ -709,28 +806,28 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
|
||||
//Stack is full, so STi is just x87reg[i]
|
||||
int j=0;
|
||||
while(dyn->n.x87cache[j]!=i) ++j; // look for STi
|
||||
int st = dyn->n.x87cache[j]+dyn->n.stack_pop;
|
||||
#if STEP == 1
|
||||
if(!next) { // don't force promotion here
|
||||
// pre-apply pop, because purge happens in-between
|
||||
neoncache_promote_double(dyn, ninst, dyn->n.x87cache[j]+dyn->n.stack_pop);
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
}
|
||||
#endif
|
||||
if(next) {
|
||||
// need to check if a ST_F need local promotion
|
||||
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[j])>=0) {
|
||||
#if STEP == 3
|
||||
if(!next && neoncache_get_current_st(dyn, ninst, st)!=NEON_CACHE_ST_D) {
|
||||
MESSAGE(LOG_DUMP, "Warning, incoherency with purged ST%d cache\n", st);
|
||||
}
|
||||
#endif
|
||||
switch(neoncache_get_current_st(dyn, ninst, st)) {
|
||||
case NEON_CACHE_ST_D:
|
||||
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
|
||||
break;
|
||||
case NEON_CACHE_ST_F:
|
||||
VCVT_F64_F32(0, dyn->n.x87reg[j]*2);
|
||||
VSTM_64_W(0, s1); // save the value
|
||||
} else {
|
||||
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
|
||||
}
|
||||
} else {
|
||||
// need to check if a ST_F need local promotion
|
||||
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[j])>=0) {
|
||||
VCVT_F64_F32(0, dyn->n.x87reg[j]*2);
|
||||
VSTM_64_W(0, s1); // save the value
|
||||
} else {
|
||||
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!next) {
|
||||
fpu_free_reg_double(dyn, dyn->n.x87reg[j]);
|
||||
dyn->n.x87reg[j] = -1;
|
||||
dyn->n.x87cache[j] = -1;
|
||||
@@ -739,9 +836,13 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
|
||||
}
|
||||
if(!next) {
|
||||
dyn->n.stack_next = 0;
|
||||
dyn->n.tags = 0;
|
||||
#if STEP < 2
|
||||
// refresh the cached valued, in case it's a purge outside a instruction
|
||||
dyn->insts[ninst].n.barrier = 1;
|
||||
dyn->n.pushed = 0;
|
||||
dyn->n.poped = 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t---Purge Full x87 Cache and Synch Stackcount\n");
|
||||
@@ -776,44 +877,37 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
|
||||
SUB_IMM8(s2, s2, -a);
|
||||
}
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// update tags (and top at the same time)
|
||||
// update tags
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
if(a>0) {
|
||||
// new tag to fulls
|
||||
MOVW(s3, 0);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<a; ++i) {
|
||||
SUB_IMM8(s2, s2, 1);
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
|
||||
STR_REG_LSL_IMM5(s3, s1, s2, 2); // that slot is full
|
||||
}
|
||||
MOV_REG_LSL_IMM5(s1, s1, a*2);
|
||||
} else {
|
||||
// empty tags
|
||||
MOVW(s3, 0b11);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, p_regs));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<-a; ++i) {
|
||||
STR_REG_LSL_IMM5(s3, s1, s2, 2); // empty slot before leaving it
|
||||
ADD_IMM8(s2, s2, 1);
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
|
||||
}
|
||||
MOV32(s2, 0xffff);
|
||||
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
|
||||
MOV_REG_LSR_IMM5(s1, s1, -a*2);
|
||||
}
|
||||
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
SUB_IMM8(s2, s2, a);
|
||||
} else {
|
||||
ADD_IMM8(s2, s2, -a);
|
||||
}
|
||||
AND_IMM8(s2, s2, 7);
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
} else {
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
}
|
||||
// check if free is used
|
||||
if(dyn->n.tags) {
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
MOV32(s3, dyn->n.tags);
|
||||
ORR_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
}
|
||||
|
||||
if(ret!=0) {
|
||||
// --- set values
|
||||
// Get top
|
||||
@@ -857,9 +951,13 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
|
||||
}
|
||||
if(!next) {
|
||||
dyn->n.stack_next = 0;
|
||||
dyn->n.tags = 0;
|
||||
#if STEP < 2
|
||||
// refresh the cached valued, in case it's a purge outside a instruction
|
||||
dyn->insts[ninst].n.barrier = 1;
|
||||
dyn->n.pushed = 0;
|
||||
dyn->n.poped = 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
|
||||
@@ -878,6 +976,16 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
SUB_IMM8(s2, s2, -a);
|
||||
}
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// update tags
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
if(a>0) {
|
||||
MOV_REG_LSL_IMM5(s1, s1, a*2);
|
||||
} else {
|
||||
MOV32(s2, 0xffff);
|
||||
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
|
||||
MOV_REG_LSR_IMM5(s1, s1, -a*2);
|
||||
}
|
||||
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
@@ -931,6 +1039,16 @@ static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, in
|
||||
ADD_IMM8(s1, s1, -a);
|
||||
}
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// update tags
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
if(a>0) {
|
||||
MOV32(s2, 0xffff);
|
||||
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
|
||||
MOV_REG_LSR_IMM5(s1, s1, -a*2);
|
||||
} else {
|
||||
MOV_REG_LSL_IMM5(s1, s1, a*2);
|
||||
}
|
||||
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
@@ -1133,6 +1251,65 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
}
|
||||
|
||||
void x87_free(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int st)
|
||||
{
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
if(dyn->n.x87cache[i] == st)
|
||||
ret = i;
|
||||
MESSAGE(LOG_DUMP, "\tFFREE%s x87 Cache for ST%d\n", (ret!=-1)?" (and Forget)":"", st);
|
||||
if(ret!=-1) {
|
||||
const int reg = dyn->n.x87reg[ret];
|
||||
#if STEP == 1
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F)
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
#endif
|
||||
// prepare offset to fpu => s1
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// Update
|
||||
int ast = st - dyn->n.x87stack;
|
||||
if(ast) {
|
||||
if(ast>0) {
|
||||
ADD_IMM8(s2, s2, ast);
|
||||
} else {
|
||||
SUB_IMM8(s2, s2, -ast);
|
||||
}
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
}
|
||||
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
|
||||
// this should not happens
|
||||
VCVT_F64_F32(0, reg*2); // use D0 as scratch...
|
||||
VSTR_64(0, s2, 0);
|
||||
} else {
|
||||
VSTR_64(reg, s2, 0); // save the value
|
||||
}
|
||||
// and forget that cache
|
||||
fpu_free_reg_double(dyn, reg);
|
||||
dyn->n.neoncache[reg].v = 0;
|
||||
dyn->n.x87cache[ret] = -1;
|
||||
dyn->n.x87reg[ret] = -1;
|
||||
} else {
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
// Update
|
||||
int ast = st - dyn->n.x87stack;
|
||||
if(ast) {
|
||||
if(ast>0) {
|
||||
ADD_IMM8(s2, s2, ast);
|
||||
} else {
|
||||
SUB_IMM8(s2, s2, -ast);
|
||||
}
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
}
|
||||
}
|
||||
// add mark in the freed array
|
||||
dyn->n.tags |= 0b11<<(st*2);
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 FFREE for ST%d\n", st);
|
||||
}
|
||||
|
||||
// Set rounding according to cw flags, return reg to restore flags
|
||||
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
@@ -1141,7 +1318,8 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
|
||||
BFI(s2, s1, 1, 1);
|
||||
VMRS(s1); // get fpscr
|
||||
MOV_REG(s3, s1);
|
||||
if (s3 >= 0)
|
||||
MOV_REG(s3, s1);
|
||||
BFI(s1, s2, 22, 2); // inject new round
|
||||
VMSR(s1); // put new fpscr
|
||||
return s3;
|
||||
@@ -1218,12 +1396,6 @@ void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
|
||||
// MMX helpers
|
||||
static void mmx_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
dyn->n.mmxcount = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->n.mmxcache[i] = -1;
|
||||
}
|
||||
static int isx87Empty(dynarec_arm_t* dyn)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -1305,11 +1477,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
|
||||
|
||||
// SSE / SSE2 helpers
|
||||
static void sse_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->n.ssecache[i].v = -1;
|
||||
}
|
||||
// get neon register for a SSE reg, create the entry if needed
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite)
|
||||
{
|
||||
@@ -1765,55 +1932,6 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
}
|
||||
int stack_cnt = dyn->n.stack_next;
|
||||
int s3_top = 0xffff;
|
||||
if(stack_cnt != cache_i2.stack) {
|
||||
MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack);
|
||||
int a = stack_cnt - cache_i2.stack;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s3, s3, a);
|
||||
} else {
|
||||
SUB_IMM8(s3, s3, -a);
|
||||
}
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
|
||||
// update tags (and top at the same time)
|
||||
if(a>0) {
|
||||
// new tag to fulls
|
||||
MOVW(s2, 0);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<a; ++i) {
|
||||
SUB_IMM8(s3, s3, 1);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
|
||||
STR_REG_LSL_IMM5(s2, s1, s3, 2); // that slot is full
|
||||
}
|
||||
} else {
|
||||
// empty tags
|
||||
MOVW(s2, 0b11);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, p_regs));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<-a; ++i) {
|
||||
STR_REG_LSL_IMM5(s2, s1, s3, 2); // empty slot before leaving it
|
||||
ADD_IMM8(s3, s3, 1);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
|
||||
}
|
||||
}
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
|
||||
s3_top = 0;
|
||||
stack_cnt = cache_i2.stack;
|
||||
}
|
||||
neoncache_t cache = dyn->n;
|
||||
// sanitize XMM regs alocation, cache_i2 has been sanitized in neoncacheUnwind already
|
||||
for(int i=0; i<24; i+=2) {
|
||||
@@ -1882,6 +2000,40 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
}
|
||||
}
|
||||
}
|
||||
if(stack_cnt != cache_i2.stack) {
|
||||
MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack);
|
||||
int a = stack_cnt - cache_i2.stack;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s3, s3, a);
|
||||
} else {
|
||||
SUB_IMM8(s3, s3, -a);
|
||||
}
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// update tags
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
if(a>0) {
|
||||
MOV_REG_LSL_IMM5(s1, s1, a*2);
|
||||
} else {
|
||||
// empty tags
|
||||
MOV32(s3, 0xffff);
|
||||
ORR_REG_LSL_IMM5(s1, s1, s3, 16);
|
||||
MOV_REG_LSR_IMM5(s1, s1, -a*2);
|
||||
}
|
||||
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
SUB_IMM8(s3, s3, a);
|
||||
} else {
|
||||
ADD_IMM8(s3, s3, -a);
|
||||
}
|
||||
AND_IMM8(s3, s3, 7);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
|
||||
s3_top = 0;
|
||||
stack_cnt = cache_i2.stack;
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
|
||||
#endif
|
||||
}
|
||||
@@ -1949,14 +2101,6 @@ void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
x87_unreflectcache(dyn, ninst, s1, s2, s3);
|
||||
}
|
||||
|
||||
void fpu_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
x87_reset(dyn);
|
||||
mmx_reset(dyn);
|
||||
sse_reset(dyn);
|
||||
fpu_reset_reg(dyn);
|
||||
}
|
||||
|
||||
// get the single reg that from the double "reg" (so Dx[idx])
|
||||
int fpu_get_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx)
|
||||
{
|
||||
@@ -1991,8 +2135,14 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
|
||||
#if STEP > 1
|
||||
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
|
||||
dyn->n = dyn->insts[ninst].n;
|
||||
#else
|
||||
dyn->n = dyn->insts[reset_n].n;
|
||||
#endif
|
||||
neoncacheUnwind(&dyn->n);
|
||||
#ifdef HAVE_TRACE
|
||||
#if STEP == 0
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "New x87stack=%d\n", dyn->n.x87stack);
|
||||
#endif
|
||||
#if defined(HAVE_TRACE) && (STEP>2)
|
||||
if(box86_dynarec_dump)
|
||||
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
|
||||
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
|
||||
@@ -2022,9 +2172,6 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
|
||||
MESSAGE(LOG_DEBUG, "\n");
|
||||
}
|
||||
#endif //HAVE_TRACE
|
||||
#else
|
||||
dyn->n = dyn->insts[reset_n].n;
|
||||
#endif
|
||||
}
|
||||
|
||||
// propagate ST stack state, especial stack pop that are deferred
|
||||
|
||||
@@ -262,8 +262,10 @@
|
||||
#define CALL_1DD(F, F2, M) call_d(dyn, ninst, F, F2, 1, x3, -1, M, 0)
|
||||
// CALL_1D_U64 will use S as scratch. Return value in ret/ret2, 1 ARG in D0
|
||||
#define CALL_1DR_U64(R, ret, ret2, S, M) call_dr(dyn, ninst, R, 1, S, ret, ret2, M, 1)
|
||||
// CALL_1D will use S as scratch. Return value in D0, 1 ARG in D0
|
||||
// CALL_1DR will use S as scratch. Return value in D0, 1 ARG in D0
|
||||
#define CALL_1DR(R, S, M) call_dr(dyn, ninst, R, 1, S, -1, -1, M, 0)
|
||||
// CALL_1DI will use S as scratch. Return value in D0, 1 ARG in D0, 1 ARG in R0
|
||||
#define CALL_1DDR(F, R, S, M) call_ddr(dyn, ninst, F, NULL, R, S, -1, M, 0)
|
||||
// CALL_1RD will use S as scratch. Return value in D0, 1 ARG in R
|
||||
#define CALL_1RD(F, R, S, M) call_rd(dyn, ninst, F, R, S, M, 0);
|
||||
|
||||
@@ -341,6 +343,37 @@
|
||||
} \
|
||||
|
||||
|
||||
#if STEP == 0
|
||||
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) var = x87_do_push(dyn, ninst, scratch, t)
|
||||
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) x87_do_push_empty(dyn, ninst, scratch)
|
||||
#define X87_POP_OR_FAIL(dyn, ninst, scratch) x87_do_pop(dyn, ninst, scratch)
|
||||
#else
|
||||
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
|
||||
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
|
||||
dyn->abort = 1; \
|
||||
return addr; \
|
||||
} \
|
||||
var = x87_do_push(dyn, ninst, scratch, t)
|
||||
|
||||
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
|
||||
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
|
||||
dyn->abort = 1; \
|
||||
return addr; \
|
||||
} \
|
||||
x87_do_push_empty(dyn, ninst, scratch)
|
||||
|
||||
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
|
||||
if ((dyn->n.x87stack==-8) || (dyn->n.poped==8)) { \
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Pop, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.poped, ninst); \
|
||||
dyn->abort = 1; \
|
||||
return addr; \
|
||||
} \
|
||||
x87_do_pop(dyn, ninst, scratch)
|
||||
#endif
|
||||
|
||||
|
||||
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
|
||||
#define SET_DF(S, N) \
|
||||
if(N) { \
|
||||
@@ -386,6 +419,8 @@
|
||||
if(dyn->insts[ninst].x86.gen_flags) switch(B) { \
|
||||
case SF_SUBSET: \
|
||||
case SF_SET: dyn->f.pending = SF_SET; break; \
|
||||
case SF_SET_DF: dyn->f.pending = SF_SET; dyn->f.dfnone = 1; break; \
|
||||
case SF_SET_NODF: dyn->f.pending = SF_SET; dyn->f.dfnone = 0; break; \
|
||||
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
|
||||
case SF_SUBSET_PENDING: \
|
||||
case SF_SET_PENDING: \
|
||||
@@ -402,6 +437,9 @@
|
||||
#ifndef BARRIER_NEXT
|
||||
#define BARRIER_NEXT(A)
|
||||
#endif
|
||||
#ifndef SET_HASCALLRET
|
||||
#define SET_HASCALLRET()
|
||||
#endif
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
|
||||
@@ -460,6 +498,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog_)
|
||||
#define call_c STEPNAME(call_c_)
|
||||
#define call_d STEPNAME(call_d_)
|
||||
#define call_ddr STEPNAME(call_ddr_)
|
||||
#define call_dr STEPNAME(call_dr_)
|
||||
#define call_rd STEPNAME(call_rd_)
|
||||
#define grab_fsdata STEPNAME(grab_fsdata_)
|
||||
@@ -562,10 +601,12 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
|
||||
#define x87_get_st STEPNAME(x87_get_st)
|
||||
#define x87_get_st_empty STEPNAME(x87_get_st)
|
||||
#define x87_free STEPNAME(x87_free)
|
||||
#define x87_refresh STEPNAME(x87_refresh)
|
||||
#define x87_forget STEPNAME(x87_forget)
|
||||
#define x87_reget_st STEPNAME(x87_reget_st)
|
||||
#define x87_stackcount STEPNAME(x87_stackcount)
|
||||
#define x87_unstackcount STEPNAME(x87_unstackcount)
|
||||
#define x87_setround STEPNAME(x87_setround)
|
||||
#define x87_setround_reset STEPNAME(x87_setround_reset)
|
||||
#define x87_restoreround STEPNAME(x87_restoreround)
|
||||
@@ -581,7 +622,6 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
#define fpu_reset STEPNAME(fpu_reset)
|
||||
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
|
||||
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
|
||||
#define fpu_purgecache STEPNAME(fpu_purgecache)
|
||||
@@ -613,6 +653,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
|
||||
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags);
|
||||
void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int ret2, uint32_t mask, int saveflags);
|
||||
void call_ddr(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int arg, int reg, int ret, uint32_t mask, int saveflags);
|
||||
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags);
|
||||
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
@@ -708,7 +749,9 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
// x87 helper
|
||||
// cache of the local stack counter, to avoid upadte at every call
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
|
||||
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
|
||||
// restore the local stack counter
|
||||
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count);
|
||||
// fpu push. Return the Dd value to be used
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
|
||||
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
|
||||
@@ -725,6 +768,8 @@ int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
|
||||
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
|
||||
// get vfpu register for a x87 reg, create the entry if needed. Do not fetch the Stx if not already in cache
|
||||
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
|
||||
// Free st, using the FFREE opcode (so it's freed but stack is not moved)
|
||||
void x87_free(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int st);
|
||||
// refresh a value from the cache ->emu (nothing done if value is not cached)
|
||||
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
|
||||
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
|
||||
@@ -793,8 +838,6 @@ void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
|
||||
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
|
||||
|
||||
// common coproc helpers
|
||||
// reset the cache
|
||||
void fpu_reset(dynarec_arm_t* dyn);
|
||||
// reset the cache with n
|
||||
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n);
|
||||
// propagate stack state
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
#error No STEP defined
|
||||
#endif
|
||||
|
||||
#if STEP == 0
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 0x1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
{
|
||||
int ok = 1;
|
||||
@@ -43,12 +49,28 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
#if STEP == 0
|
||||
memset(&dyn->insts[ninst], 0, sizeof(instruction_arm_t));
|
||||
#endif
|
||||
fpu_reset(dyn);
|
||||
int reset_n = -1;
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3 // ok, go now
|
||||
INIT;
|
||||
#if STEP == 0
|
||||
uintptr_t cur_page = (addr)&~box86_pagesize;
|
||||
#endif
|
||||
while(ok) {
|
||||
#if STEP == 0
|
||||
if(cur_page != (addr)&~box86_pagesize) {
|
||||
cur_page = (addr)&~box86_pagesize;
|
||||
if(!(getProtection(addr)&PROT_READ)) {
|
||||
need_epilog = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ip = addr;
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
if (reset_n!=-1) {
|
||||
if(reset_n==-2) {
|
||||
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
|
||||
@@ -70,8 +92,12 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
reset_n = -1;
|
||||
}
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
NEW_INST;
|
||||
#if STEP == 0
|
||||
if(ninst && dyn->insts[ninst-1].x86.barrier_next) {
|
||||
BARRIER(dyn->insts[ninst-1].x86.barrier_next);
|
||||
}
|
||||
#endif
|
||||
if(!ninst) {
|
||||
GOTEST(x1, x2);
|
||||
}
|
||||
@@ -116,7 +142,6 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
#if STEP > 0
|
||||
if(!dyn->insts[ninst].x86.has_next && dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts!=-1)
|
||||
next = dyn->insts[ninst].x86.jmp_insts;
|
||||
#endif
|
||||
if(dyn->insts[ninst].x86.has_next && dyn->insts[next].x86.barrier) {
|
||||
if(dyn->insts[next].x86.barrier&BARRIER_FLOAT)
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
@@ -125,6 +150,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->f.dfnone = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
@@ -133,8 +159,8 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
ok = 1;
|
||||
// we use the 1st predecessor here
|
||||
int ii = ninst+1;
|
||||
if(ii<dyn->size && !dyn->insts[ii].pred_sz) {
|
||||
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
|
||||
if(ii<dyn->size && !dyn->insts[ii].x86.alive) {
|
||||
while(ii<dyn->size && !dyn->insts[ii].x86.alive) {
|
||||
// may need to skip opcodes to advance
|
||||
++ninst;
|
||||
NEW_INST;
|
||||
@@ -156,16 +182,25 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#else
|
||||
// check if block need to be stopped, because it's a 00 00 opcode (unreadeable is already checked earlier)
|
||||
if((ok>0) && !dyn->forward && !(*(uint8_t*)addr) && !(*(uint8_t*)(addr+1))) {
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Stopping block at %p reason: %s\n", (void*)addr, "Next opcode is 00 00");
|
||||
ok = 0;
|
||||
need_epilog = 1;
|
||||
}
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr && !need_epilog) {
|
||||
if(dyn->forward_to == addr && !need_epilog && ok>=0) {
|
||||
// we made it!
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
reset_n = get_first_jump(dyn, addr);
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p (ninst %d - %d)\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x86.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to, reset_n, ninst);
|
||||
if(dyn->insts[dyn->forward_ninst].x86.has_callret && !dyn->insts[dyn->forward_ninst].x86.has_next)
|
||||
dyn->insts[dyn->forward_ninst].x86.has_next = 1; // this block actually continue
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
ok = 1; // in case it was 0
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
} else if ((dyn->forward_to < addr) || ok<=0) {
|
||||
// something when wrong! rollback
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
ok = 0;
|
||||
@@ -186,10 +221,14 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
|
||||
{
|
||||
ok = 1;
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
// and pred table is not ready yet
|
||||
reset_n = get_first_jump(dyn, next);
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
if(dyn->insts[ninst].x86.has_callret && !dyn->insts[ninst].x86.has_next) {
|
||||
dyn->insts[ninst].x86.has_next = 1; // this block actually continue
|
||||
} else {
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
// and pred table is not ready yet
|
||||
reset_n = get_first_jump(dyn, next);
|
||||
}
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %s%p -> %p (ninst=%d, jump from %d)\n", dyn, dyn->insts[ninst].x86.has_callret?"(opt. call) ":"", (void*)addr, (void*)next, ninst, dyn->insts[ninst].x86.has_callret?ninst:reset_n);
|
||||
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
|
||||
if(dyn->forward) {
|
||||
@@ -232,12 +271,15 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if((ok>0) && dyn->insts[ninst].x86.has_callret)
|
||||
reset_n = -2;
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|
||||
memset(&dyn->insts[ninst], 0, sizeof(instruction_arm_t));
|
||||
if((ok>0) && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)))
|
||||
#else
|
||||
if(ok && (ninst==dyn->size))
|
||||
if((ok>0) && (ninst==dyn->size))
|
||||
#endif
|
||||
{
|
||||
#if STEP == 0
|
||||
|
||||
@@ -12,20 +12,16 @@
|
||||
dyn->f.pending=SF_SET
|
||||
#define SETFLAGS(A,B) \
|
||||
dyn->insts[ninst].x86.set_flags = A; \
|
||||
dyn->insts[ninst].x86.state_flags = B; \
|
||||
dyn->insts[ninst].x86.state_flags = (B)&~SF_DF; \
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C; dyn->insts[ninst].x86.jmp_insts = 0
|
||||
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
|
||||
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
|
||||
#define BARRIER_NEXT(A) dyn->insts[ninst].x86.barrier_next = A
|
||||
#define SET_HASCALLRET() dyn->insts[ninst].x86.has_callret = 1
|
||||
#define NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm_t*)dynaRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
dyn->insts[ninst].x86.addr = ip; \
|
||||
dyn->n.combined1 = dyn->n.combined2 = 0;\
|
||||
dyn->n.swapped = 0; dyn->n.barrier = 0; \
|
||||
|
||||
@@ -41,10 +41,13 @@ typedef struct neoncache_s {
|
||||
uint8_t combined2;
|
||||
uint8_t swapped; // the combined reg were swapped
|
||||
uint8_t barrier; // is there a barrier at instruction epilog?
|
||||
uint8_t pushed; // positive pushed value (to check for overflow)
|
||||
uint8_t poped; // positive poped value (to check for underflow)
|
||||
uint32_t news; // bitmask, wich neoncache are new for this opcode
|
||||
// fpu cache
|
||||
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
||||
int8_t x87reg[8]; // reg used for x87cache entry
|
||||
int16_t tags; // similar to fpu_tags
|
||||
int8_t mmxcache[8];// cache status for the 8 MMX registers
|
||||
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
|
||||
int8_t fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
|
||||
@@ -111,6 +114,7 @@ typedef struct dynarec_arm_s {
|
||||
int32_t forward_size; // size at the forward point
|
||||
int forward_ninst; // ninst at the forward point
|
||||
uint8_t always_test;
|
||||
uint8_t abort; // abort the creation of the block
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
|
||||
@@ -24,15 +24,22 @@
|
||||
#define SF_SUB 4
|
||||
#define SF_SUBSET (SF_SUB|SF_SET)
|
||||
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
|
||||
#define SF_DF 8
|
||||
#define SF_SET_DF (SF_SET|SF_DF)
|
||||
#define SF_NODF 16
|
||||
#define SF_SET_NODF (SF_SET|SF_NODF)
|
||||
|
||||
typedef struct instruction_x86_s {
|
||||
uintptr_t addr; //address of the instruction
|
||||
int32_t size; // size of the instruction
|
||||
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
|
||||
int jmp_insts; // instuction to jump to (-1 if out of the block)
|
||||
uint8_t jmp_cond; // 1 of conditionnal jump
|
||||
uint8_t has_next; // does this opcode can continue to the next?
|
||||
uint8_t jmp_cond:1; // 1 of conditionnal jump
|
||||
uint8_t has_next:1; // does this opcode can continue to the next?
|
||||
uint8_t has_callret:1; // this instruction have an optimised call setup
|
||||
uint8_t alive:1; // this opcode gets executed (0 if dead code in that block)
|
||||
uint8_t barrier; // next instruction is a jump point, so no optim allowed
|
||||
uint8_t barrier_next; // next instruction needs a barrier
|
||||
uint8_t state_flags;// One of SF_XXX state
|
||||
uint8_t use_flags; // 0 or combination of X_?F
|
||||
uint8_t set_flags; // 0 or combination of X_?F
|
||||
|
||||
+84
-49
@@ -172,7 +172,7 @@ const char* ElfPath(elfheader_t* head)
|
||||
return NULL;
|
||||
return head->path;
|
||||
}
|
||||
#define ALIGN(p) (((p)+box86_pagesize-1)&~(box86_pagesize-1))
|
||||
|
||||
int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
{
|
||||
uintptr_t offs = 0;
|
||||
@@ -183,8 +183,6 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
uintptr_t max_align = (box86_pagesize-1);
|
||||
for (size_t i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
|
||||
if(max_align < head->PHEntries[i].p_align-1)
|
||||
max_align = head->PHEntries[i].p_align-1;
|
||||
++head->multiblock_n;
|
||||
}
|
||||
|
||||
@@ -195,16 +193,24 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
}
|
||||
if(!offs && !head->vaddr)
|
||||
offs = (uintptr_t)find32bitBlockElf(head->memsz, mainbin, max_align);
|
||||
|
||||
// prereserve the whole elf image, without populating
|
||||
void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
if(image!=MAP_FAILED && head->vaddr && image!=(void*)offs && (((uintptr_t)image)&max_align)) {
|
||||
munmap(image, head->memsz);
|
||||
image = mmap64(find32bitBlockElf(head->memsz, mainbin, max_align), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
size_t sz = head->memsz;
|
||||
void* raw = NULL;
|
||||
void* image = NULL;
|
||||
if(!head->vaddr) {
|
||||
sz += head->align;
|
||||
raw = mmap64((void*)offs, sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
image = (void*)(((uintptr_t)raw+max_align)&~max_align);
|
||||
} else {
|
||||
image = raw = mmap64((void*)head->vaddr, sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
}
|
||||
if(image!=MAP_FAILED && !head->vaddr && image!=(void*)offs) {
|
||||
printf_log(LOG_INFO, "%s: Mmap64 for (@%p 0x%zx) for elf \"%s\" returned %p(%p/0x%zx) instead\n", (((uintptr_t)image)&max_align)?"Error":"Warning", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image, raw, head->align);
|
||||
offs = (uintptr_t)image;
|
||||
printf_log(LOG_INFO, "Mamp64 for (@%p 0x%zx) for elf \"%s\" returned %p instead", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image);
|
||||
if(((uintptr_t)image)&max_align) {
|
||||
munmap(raw, sz);
|
||||
return 1; // that's an error, alocated memory is not aligned properly
|
||||
}
|
||||
}
|
||||
if(image==MAP_FAILED || image!=(void*)(head->vaddr?head->vaddr:offs)) {
|
||||
printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name);
|
||||
@@ -217,12 +223,14 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
return 1;
|
||||
offs = (uintptr_t)image-head->vaddr;
|
||||
}
|
||||
printf_log(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
|
||||
printf_dump(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
|
||||
head->delta = offs;
|
||||
printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\" (0x%zx bytes)\n", (void*)offs, (void*)head->vaddr, head->name, head->memsz);
|
||||
printf_dump(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
|
||||
|
||||
head->image = image;
|
||||
setProtection_elf((uintptr_t)image, head->memsz, 0);
|
||||
head->raw = raw;
|
||||
head->raw_size = sz;
|
||||
setProtection_elf((uintptr_t)raw, sz, 0);
|
||||
|
||||
head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
|
||||
head->tlsbase = AddTLSPartition(context, head->tlssize);
|
||||
@@ -241,36 +249,35 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0);
|
||||
// check if alignment is correct
|
||||
uintptr_t balign = head->multiblocks[n].align-1;
|
||||
if(balign<(box86_pagesize-1)) balign = (box86_pagesize-1);
|
||||
head->multiblocks[n].asize = ALIGN(e->p_memsz+(e->p_paddr&balign));
|
||||
if(balign<4095) balign = 4095;
|
||||
head->multiblocks[n].asize = (e->p_memsz+(e->p_paddr&balign)+4095)&~4095;
|
||||
int try_mmap = 1;
|
||||
if(e->p_paddr&balign)
|
||||
try_mmap = 0;
|
||||
if(e->p_offset&(box86_pagesize-1))
|
||||
try_mmap = 0;
|
||||
if(e->p_memsz-e->p_filesz>(box86_pagesize-1))
|
||||
if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz))
|
||||
try_mmap = 0;
|
||||
if(!e->p_filesz)
|
||||
try_mmap = 0;
|
||||
if(e->p_align<box86_pagesize)
|
||||
try_mmap = 0;
|
||||
if(try_mmap) {
|
||||
printf_log(log_level, "Mmaping 0x%zx memory @%p for Elf \"%s\"\n", head->multiblocks[n].size, (void*)head->multiblocks[n].paddr, head->name);
|
||||
printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name);
|
||||
void* p = mmap64(
|
||||
(void*)head->multiblocks[n].paddr,
|
||||
head->multiblocks[n].size,
|
||||
prot,
|
||||
MAP_PRIVATE|MAP_FIXED,
|
||||
MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED,
|
||||
head->fileno,
|
||||
e->p_offset
|
||||
);
|
||||
if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) {
|
||||
try_mmap = 0;
|
||||
printf_log(log_level, "Mapping failed, using regular mmap+read");
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(log_level, " err=%d/%s\n", errno, strerror(errno));
|
||||
} else {
|
||||
printf_log(log_level, " got %p instead\n", p);
|
||||
}
|
||||
printf_dump(log_level, "Mapping failed, using regular mmap+read");
|
||||
} else {
|
||||
if(e->p_memsz>e->p_filesz && (prot&PROT_WRITE))
|
||||
memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz);
|
||||
setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot);
|
||||
head->multiblocks[n].p = p;
|
||||
|
||||
@@ -279,15 +286,43 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
if(!try_mmap) {
|
||||
uintptr_t paddr = head->multiblocks[n].paddr&~balign;
|
||||
size_t asize = head->multiblocks[n].asize;
|
||||
printf_log(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
|
||||
void* p = mmap64(
|
||||
(void*)paddr,
|
||||
asize,
|
||||
prot,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
void* p = MAP_FAILED;
|
||||
if(paddr==(paddr&~(box86_pagesize-1)) && (asize==ALIGN(asize))) {
|
||||
printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
|
||||
p = mmap64(
|
||||
(void*)paddr,
|
||||
asize,
|
||||
prot|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
// difference in pagesize, so need to mmap only what needed to be...
|
||||
//check startint point
|
||||
uintptr_t new_addr = paddr;
|
||||
ssize_t new_size = asize;
|
||||
while(getProtection(new_addr) && (new_size>0)) {
|
||||
new_size -= ALIGN(new_addr) - new_addr;
|
||||
new_addr = ALIGN(new_addr);
|
||||
}
|
||||
if(new_size>0) {
|
||||
printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
|
||||
p = mmap64(
|
||||
(void*)new_addr,
|
||||
ALIGN(new_size),
|
||||
prot|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
if(p==(void*)new_addr)
|
||||
p = (void*)paddr;
|
||||
} else {
|
||||
p = (void*)paddr;
|
||||
printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
|
||||
}
|
||||
}
|
||||
if(p==MAP_FAILED || p!=(void*)paddr) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name);
|
||||
if(p==MAP_FAILED) {
|
||||
@@ -306,6 +341,8 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(!(prot&PROT_WRITE) && (paddr==(paddr&(box86_pagesize-1)) && (asize==ALIGN(asize))))
|
||||
mprotect((void*)paddr, asize, prot);
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && (e->p_flags & PF_X)) {
|
||||
@@ -347,18 +384,20 @@ void FreeElfMemory(elfheader_t* head)
|
||||
if(head->multiblock_n) {
|
||||
#ifdef DYNAREC
|
||||
for(int i=0; i<head->multiblock_n; ++i) {
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks %p-%p for %s\n", head->multiblocks[i].p, head->multiblocks[i].p+head->multiblocks[i].asize, head->path);
|
||||
if(box86_dynarec)
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1);
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize, 1);
|
||||
freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize);
|
||||
}
|
||||
#endif
|
||||
box_free(head->multiblocks);
|
||||
}
|
||||
// we only need to free the overall mmap, no need to free individual part as they are inside the big one
|
||||
if(head->image && head->memsz)
|
||||
munmap(head->image, head->memsz);
|
||||
freeProtection((uintptr_t)head->image, head->memsz);
|
||||
if(head->raw && head->raw_size) {
|
||||
dynarec_log(LOG_INFO, "Unmap elf memory %p-%p for %s\n", head->raw, head->raw+head->raw_size, head->path);
|
||||
munmap(head->raw, head->raw_size);
|
||||
}
|
||||
freeProtection((uintptr_t)head->raw, head->raw_size);
|
||||
}
|
||||
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
|
||||
@@ -391,14 +430,14 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
|
||||
int t = ELF32_R_TYPE(rel[i].r_info);
|
||||
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel[i].r_info)];
|
||||
const char* symname = SymName(h, sym);
|
||||
if(t==R_386_COPY && symname && !strcmp(symname, name) && sym->st_size==size) {
|
||||
if((t==R_386_COPY) && symname && !strcmp(symname, name) && (sym->st_size==size)) {
|
||||
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
if(offs) *offs = sym->st_value + h->delta;
|
||||
if(p) *p = (uint32_t*)(rel[i].r_offset + h->delta);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -551,7 +590,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
}
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
if((head!=my_context->elfs[0]) && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
@@ -569,11 +608,9 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
}
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
if((size==0 )&& GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}*/
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
|
||||
printf_log((bind==STB_GLOBAL)?LOG_NONE:LOG_INFO, "%s: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", (bind==STB_GLOBAL)?"Error":"Warning", symname, p, *(void**)p, head->name);
|
||||
@@ -860,11 +897,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
}
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
if((size==0 )&& GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}*/
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
|
||||
@@ -50,6 +50,8 @@ typedef struct elfheader_s {
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
void* image;
|
||||
void* raw; // raw pointer (might be unaligned vs image and max_align of elf)
|
||||
size_t raw_size;
|
||||
|
||||
uintptr_t entrypoint;
|
||||
uintptr_t initentry;
|
||||
|
||||
@@ -81,8 +81,15 @@ uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int l
|
||||
intres1 = (1<<n_packed)-1;
|
||||
for(int j=0; j<n_packed; ++j)
|
||||
for(int i=0; i<n_packed-j; ++i) {
|
||||
#if 1
|
||||
if(!overrideIfDataInvalid(mem, lmem, reg, lreg, i+j, i, imm8)) {
|
||||
intres1 &= ~(1<<j);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
int k = i+j;
|
||||
intres1 &= (((1<<n_packed)-1)^(1<<j)) | overrideIfDataInvalid(mem, lmem, reg, lreg, k, i, imm8)<<j;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -98,7 +105,7 @@ uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int l
|
||||
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
|
||||
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CONDITIONAL_SET_FLAG(((!intres2) && (lmem==n_packed)), F_AF);
|
||||
CLEAR_FLAG(F_PF);
|
||||
|
||||
return intres2;
|
||||
|
||||
+2
-2
@@ -219,7 +219,7 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->fpu_tags = emu->fpu_tags;
|
||||
newemu->cw = emu->cw;
|
||||
newemu->sw = emu->sw;
|
||||
newemu->top = emu->top;
|
||||
@@ -252,7 +252,7 @@ void CopyEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->fpu_tags = emu->fpu_tags;
|
||||
newemu->cw = emu->cw;
|
||||
newemu->sw = emu->sw;
|
||||
newemu->top = emu->top;
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef struct x86emu_s {
|
||||
reg32_t regs[8];
|
||||
x86flags_t eflags;
|
||||
reg32_t ip;
|
||||
uintptr_t xSPSave;
|
||||
// fpu / mmx
|
||||
x87control_t cw;
|
||||
x87flags_t sw;
|
||||
@@ -61,9 +62,9 @@ typedef struct x86emu_s {
|
||||
mmx87_regs_t mmx[8];
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
uint32_t fpu_tags; // tags for the x87 regs, stacked, only on a 16bits anyway
|
||||
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
|
||||
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
|
||||
fpu_p_reg_t p_regs[8];
|
||||
// sse
|
||||
sse_regs_t xmm[8];
|
||||
mmxcontrol_t mxcsr;
|
||||
@@ -102,6 +103,7 @@ typedef struct x86emu_s {
|
||||
void* init_stack; // initial stack (owned or not)
|
||||
uint32_t size_stack; // stack size (owned or not)
|
||||
JUMPBUFF* jmpbuf;
|
||||
uintptr_t old_savedsp;
|
||||
|
||||
i386_ucontext_t *uc_link; // to handle setcontext
|
||||
|
||||
|
||||
+3
-5
@@ -43,7 +43,9 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
|
||||
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
|
||||
v = forkpty(emu->forkpty_info->amaster, emu->forkpty_info->name, emu->forkpty_info->termp, emu->forkpty_info->winp);
|
||||
emu->forkpty_info = NULL;
|
||||
} else
|
||||
} else if(forktype==3)
|
||||
v = vfork();
|
||||
else
|
||||
v = fork();
|
||||
if(type == EMUTYPE_MAIN)
|
||||
thread_set_emu(emu);
|
||||
@@ -54,10 +56,6 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
if(my_context->atforks[i].parent)
|
||||
EmuCall(emu, my_context->atforks[i].parent);
|
||||
if(forktype==3) {
|
||||
// vfork, the parent wait the end or execve of the son
|
||||
waitpid(v, NULL, WEXITED);
|
||||
}
|
||||
} else if(v==0) {
|
||||
// execute atforks child functions
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
|
||||
+21
-4
@@ -61,6 +61,7 @@ int Run(x86emu_t *emu, int step)
|
||||
uintptr_t addr = R_EIP;
|
||||
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
|
||||
int unimp = 0;
|
||||
int tf_next = 0;
|
||||
|
||||
if(emu->quit)
|
||||
return 0;
|
||||
@@ -704,8 +705,12 @@ x86emurun:
|
||||
Push(emu, emu->eflags.x32);
|
||||
break;
|
||||
case 0x9D: /* POPF */
|
||||
if(ACCESS_FLAG(F_TF) && !tf_next)
|
||||
--tf_next;
|
||||
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
RESET_FLAGS(emu);
|
||||
if(ACCESS_FLAG(F_TF))
|
||||
++tf_next;
|
||||
break;
|
||||
case 0x9E: /* SAHF */
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
@@ -1090,7 +1095,15 @@ x86emurun:
|
||||
R_ESP = R_EBP;
|
||||
R_EBP = Pop(emu);
|
||||
break;
|
||||
|
||||
case 0xCA: /* FAR RETN */
|
||||
tmp16u = F16;
|
||||
addr = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu); // no check, no use....
|
||||
emu->segs_serial[_CS] = 0;
|
||||
R_ESP += tmp16u;
|
||||
// need to check status of CS register!
|
||||
STEP2;
|
||||
break;
|
||||
case 0xCB: /* FAR RET */
|
||||
addr = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu); // no check, no use....
|
||||
@@ -1593,9 +1606,13 @@ x86emurun:
|
||||
}
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(ACCESS_FLAG(F_TF)) {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
if(tf_next) {
|
||||
tf_next = 0;
|
||||
} else {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
R_EIP = addr;
|
||||
|
||||
+37
-18
@@ -89,28 +89,47 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x01: /* XGETBV, SGDT, etc... */
|
||||
// this is a privilege opcode...
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* SGDT Ed */
|
||||
GET_ED;
|
||||
ED->word[0] = 0x7f; // dummy return...
|
||||
ED->word[1] = 0x000c;
|
||||
ED->word[2] = 0xd000;
|
||||
GET_ED;
|
||||
if(MODREG)
|
||||
switch(nextop) {
|
||||
case 0xD0:
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* SIDT Ed */
|
||||
GET_ED;
|
||||
ED->word[0] = 0xfff; // dummy return, like "disabled"
|
||||
ED->word[1] = 0;
|
||||
ED->word[2] = 0;
|
||||
break;
|
||||
case 4: /* SMSW Ew */
|
||||
GET_ED;
|
||||
// dummy for now... Do I need to track CR0 state?
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7: /* SMSW Ew */
|
||||
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
} else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* SGDT Ed */
|
||||
ED->word[0] = 0x7f; // dummy return...
|
||||
ED->word[1] = 0x000c;
|
||||
ED->word[2] = 0xd000;
|
||||
break;
|
||||
case 1: /* SIDT Ed */
|
||||
ED->word[0] = 0xfff; // dummy return, like "disabled"
|
||||
ED->word[1] = 0;
|
||||
ED->word[2] = 0;
|
||||
break;
|
||||
case 4: /* SMSW Ew */
|
||||
// dummy for now... Do I need to track CR0 state?
|
||||
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1209,7 +1228,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
break;
|
||||
case 0xBC: /* BSF Ed,Gd */
|
||||
case 0xBC: /* BSF Gd, Ed */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -1223,7 +1242,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
SET_FLAG(F_ZF);
|
||||
}
|
||||
break;
|
||||
case 0xBD: /* BSR Ed,Gd */
|
||||
case 0xBD: /* BSR Gd, Ed */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
|
||||
@@ -1101,12 +1101,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
|
||||
if(tmp8u&0b1000000) {
|
||||
switch(tmp8u&1) {
|
||||
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
}
|
||||
} else {
|
||||
GX.q[1] = GX.q[0] = 0;
|
||||
GX.uw[0] = tmp32u;
|
||||
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
|
||||
emu->xmm[0].uw[0] = tmp32u;
|
||||
}
|
||||
break;
|
||||
case 0x61: /* PCMPESTRI */
|
||||
@@ -1128,12 +1128,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
|
||||
if(tmp8u&0b1000000) {
|
||||
switch(tmp8u&1) {
|
||||
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
}
|
||||
} else {
|
||||
GX.q[1] = GX.q[0] = 0;
|
||||
GX.uw[0] = tmp32u;
|
||||
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
|
||||
emu->xmm[0].uw[0] = tmp32u;
|
||||
}
|
||||
break;
|
||||
case 0x63: /* PCMPISTRI */
|
||||
|
||||
@@ -49,7 +49,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
|
||||
emu->quit = 1; // finished!
|
||||
}
|
||||
#else
|
||||
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
|
||||
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int (*main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
|
||||
{
|
||||
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
|
||||
// let's cheat and set all args...
|
||||
@@ -59,11 +59,16 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
|
||||
if(init) {
|
||||
PushExit(emu);
|
||||
R_EIP=(uint32_t)*init;
|
||||
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
|
||||
printf_dump(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
|
||||
DynaRun(emu);
|
||||
if(emu->error) // any error, don't bother with more
|
||||
return 0;
|
||||
emu->quit = 0;
|
||||
} else {
|
||||
if(my_context->elfs[0]) {
|
||||
printf_dump(LOG_DEBUG, "Calling init from main elf\n");
|
||||
RunElfInit(my_context->elfs[0], emu);
|
||||
}
|
||||
}
|
||||
MarkElfInitDone(my_context->elfs[0]);
|
||||
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
|
||||
|
||||
+6
-1
@@ -1,3 +1,4 @@
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -11,6 +12,7 @@
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x87emu_setround.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
@@ -32,6 +34,7 @@ uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
int oldround = fpu_setround(emu);
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
@@ -192,9 +195,11 @@ uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fesetround(oldround);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
fesetround(oldround);
|
||||
return addr;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
+50
-11
@@ -1,4 +1,5 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x87emu_setround.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
@@ -33,6 +35,7 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
int oldround;
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
@@ -110,7 +113,13 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0xF0: /* F2XM1 */
|
||||
ST0.d = exp2(ST0.d) - 1.0;
|
||||
if (ST0.d == 0)
|
||||
break;
|
||||
// Using the expm1 instead of exp2(ST0)-1 can avoid losing precision much,
|
||||
// expecially when ST0 is close to zero (which loses the precise when -1).
|
||||
// printf("%a, %a\n", LN2 * ST0.d, expm1(LN2 * ST0.d));
|
||||
ST0.d = expm1(LN2 * ST0.d);
|
||||
// = 2^ST0 - 1 + error. (in math)
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xF1: /* FYL2X */
|
||||
@@ -119,14 +128,18 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xF2: /* FPTAN */
|
||||
oldround = fpu_setround(emu);
|
||||
ST0.d = tan(ST0.d);
|
||||
fesetround(oldround);
|
||||
fpu_do_push(emu);
|
||||
ST0.d = 1.0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xF3: /* FPATAN */
|
||||
oldround = fpu_setround(emu);
|
||||
ST1.d = atan2(ST1.d, ST0.d);
|
||||
fesetround(oldround);
|
||||
fpu_do_pop(emu);
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
@@ -184,20 +197,30 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
emu->top=(emu->top-1)&7; // this will probably break a few things
|
||||
break;
|
||||
case 0xF7: /* FINCSTP */
|
||||
emu->top=(emu->top+1)&7; // this will probably break a few things
|
||||
if(emu->fpu_tags&0b11)
|
||||
fpu_do_pop(emu);
|
||||
else
|
||||
emu->top=(emu->top+1)&7; // this will probably break a few things
|
||||
break;
|
||||
case 0xF9: /* FYL2XP1 */
|
||||
ST(1).d *= log2(ST0.d + 1.0);
|
||||
// Using the log1p instead of log2(ST0+1) can avoid losing precision much,
|
||||
// expecially when ST0 is close to zero (which loses the precise when +1).
|
||||
ST(1).d = (ST(1).d * log1p(ST0.d)) / M_LN2;
|
||||
// = ST1 * log2(ST0 + 1) + error. (in math)
|
||||
fpu_do_pop(emu);
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xFA: /* FSQRT */
|
||||
oldround = fpu_setround(emu);
|
||||
ST0.d = sqrt(ST0.d);
|
||||
fesetround(oldround);
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xFB: /* FSINCOS */
|
||||
fpu_do_push(emu);
|
||||
oldround = fpu_setround(emu);
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
fesetround(oldround);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
@@ -206,18 +229,30 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xFD: /* FSCALE */
|
||||
// this could probably be done by just altering the exponant part of the float...
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if (ST1.d > INT32_MAX)
|
||||
tmp32s = INT32_MAX;
|
||||
else if (ST1.d < INT32_MIN)
|
||||
tmp32s = INT32_MIN;
|
||||
else
|
||||
tmp32s = ST1.d;
|
||||
if(ST0.d!=0.0) {
|
||||
oldround = fpu_setround(emu);
|
||||
ST0.d = ldexp(ST0.d, tmp32s);
|
||||
fesetround(oldround);
|
||||
}
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
oldround = fpu_setround(emu);
|
||||
ST0.d = sin(ST0.d);
|
||||
fesetround(oldround);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
case 0xFF: /* FCOS */
|
||||
oldround = fpu_setround(emu);
|
||||
ST0.d = cos(ST0.d);
|
||||
fesetround(oldround);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
break;
|
||||
@@ -256,18 +291,22 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
case 2: /* FST Ed, ST0 */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
if(!(((uintptr_t)ED)&3)) {
|
||||
oldround = fpu_setround(emu);
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
fesetround(oldround);
|
||||
} else {
|
||||
f = ST0.d;
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
break;
|
||||
case 3: /* FSTP Ed, ST0 */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
if(!(((uintptr_t)ED)&3)) {
|
||||
oldround = fpu_setround(emu);
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
fesetround(oldround);
|
||||
} else {
|
||||
f = ST0.d;
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
@@ -303,5 +342,5 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
return addr;
|
||||
}
|
||||
+5
-2
@@ -1,3 +1,4 @@
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -11,6 +12,7 @@
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x87emu_setround.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
@@ -24,7 +26,6 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
float f;
|
||||
reg32_t *oped;
|
||||
@@ -101,7 +102,8 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
|
||||
case 0xF9:
|
||||
case 0xFD:
|
||||
return 0;
|
||||
default:
|
||||
default:;
|
||||
int oldround = fpu_setround(emu);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ed int */
|
||||
GET_ED;
|
||||
@@ -137,6 +139,7 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
|
||||
ST0.d = (double)ED->sdword[0] / ST0.d;
|
||||
break;
|
||||
}
|
||||
fesetround(oldround);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -11,6 +12,7 @@
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x87emu_setround.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
@@ -32,6 +34,7 @@ uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
int oldround = fpu_setround(emu);
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -184,8 +187,10 @@ uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fesetround(oldround);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fesetround(oldround);
|
||||
return addr;
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x87emu_setround.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
@@ -32,6 +33,7 @@ uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
int oldround = fpu_setround(emu);
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0: /* FADDP STx, ST0 */
|
||||
@@ -158,8 +160,10 @@ uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
|
||||
ST0.d = (double)EW->sword[0] / ST0.d;
|
||||
break;
|
||||
default:
|
||||
fesetround(oldround);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fesetround(oldround);
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -555,6 +555,39 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
return addr-1; // let the normal XCHG execute, it have integrated LOCK
|
||||
|
||||
case 0xFE: /* GRP 5 Eb */
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
} while(arm_lock_write_b(EB, inc8(emu, tmp8u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
EB->byte[0] = inc8(emu, EB->byte[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
} while(arm_lock_write_d(EB, dec8(emu, tmp8u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
EB->byte[0] = dec8(emu, EB->byte[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFE 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
|
||||
@@ -770,7 +770,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
case 449:
|
||||
#ifdef __NR_futex_waitv
|
||||
if(box86_futex_waitv)
|
||||
S_EAX = syscall(R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
S_EAX = syscall(__NR_futex_waitv, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
else
|
||||
#endif
|
||||
S_EAX = -ENOSYS;
|
||||
|
||||
+4
-4
@@ -75,16 +75,16 @@ void x86test_check(x86emu_t* ref, uintptr_t ip)
|
||||
for(int i=0; i<ref->fpu_stack; ++i) {
|
||||
if(ref->x87[(ref->top+i)&7].d != emu->x87[(emu->top+i)&7].d) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "ST%d: %g | %g\n", i, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
|
||||
printf_log(LOG_NONE, "ST%d: %g (%a) | %g (%a)\n", i, ref->x87[(ref->top+i)&7].d, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
|
||||
}
|
||||
}
|
||||
}
|
||||
//memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
//memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
/*if(ref->p_regs != emu->p_regs) {
|
||||
if(ref->fpu_tags != emu->fpu_tags) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
|
||||
}*/
|
||||
printf_log(LOG_NONE, "X87 TAGS: %x | %x\n", ref->fpu_tags, emu->fpu_tags);
|
||||
}
|
||||
if(ref->cw.x16 != emu->cw.x16) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
|
||||
|
||||
+10
-14
@@ -1,3 +1,4 @@
|
||||
#include <fenv.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -17,8 +18,7 @@ void reset_fpu(x86emu_t* emu)
|
||||
emu->sw.x16 = 0x0000;
|
||||
emu->top = 0;
|
||||
emu->fpu_stack = 0;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = 0b11; // STx is empty
|
||||
emu->fpu_tags = TAGS_EMPTY;
|
||||
}
|
||||
|
||||
void fpu_fbst(x86emu_t* emu, uint8_t* d) {
|
||||
@@ -248,9 +248,7 @@ void fpu_loadenv(x86emu_t* emu, char* p, int b16)
|
||||
p+=(b16)?2:4;
|
||||
// tagword: 2bits*8
|
||||
// tags... (only full = 0b11 / free = 0b00)
|
||||
uint16_t tags = *(uint16_t*)p;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = (tags>>(i*2))&0b11;
|
||||
emu->fpu_tags = *(uint16_t*)p;
|
||||
// intruction pointer: 16bits
|
||||
// data (operand) pointer: 16bits
|
||||
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
|
||||
@@ -267,10 +265,7 @@ void fpu_savenv(x86emu_t* emu, char* p, int b16)
|
||||
if(!b16) {*(uint16_t*)p = 0; p+=2;}
|
||||
// tagword: 2bits*8
|
||||
// tags...
|
||||
uint16_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= (emu->p_regs[i].tag)<<(i*2);
|
||||
*(uint16_t*)p = tags;
|
||||
*(uint16_t*)p = emu->fpu_tags;
|
||||
// other stuff are not pushed....
|
||||
}
|
||||
|
||||
@@ -300,7 +295,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
stack = (emu->fpu_tags&0b11)?8:0;
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
@@ -308,7 +303,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
p->MxCsr_Mask = 0;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
|
||||
tags |= ((emu->fpu_tags>>(i*2))&0b11)?0:1;
|
||||
p->TagWord = tags;
|
||||
p->ErrorOpcode = 0;
|
||||
p->ErrorOffset = 0;
|
||||
@@ -330,13 +325,14 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
emu->mxcsr.x32 = p->MxCsr;
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
uint8_t tags = p->TagWord;
|
||||
emu->fpu_tags = 0;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = ((tags>>(i*2))&0b1)?0:0b11;
|
||||
emu->fpu_tags |= (((tags>>(i*2))&0b1)?0:0b11)<<(i*2);
|
||||
// copy back MMX regs...
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
stack = (emu->fpu_tags&0b11)?8:0;
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
@@ -345,7 +341,7 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
|
||||
void fpu_fxam(x86emu_t* emu) {
|
||||
emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
|
||||
if(emu->p_regs[emu->top].tag == 0b11) {
|
||||
if((emu->fpu_stack<=0) || (emu->fpu_tags&0b11)) {
|
||||
//Empty
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
|
||||
@@ -14,6 +14,8 @@ typedef struct x86emu_s x86emu_t;
|
||||
#define LN2 0.69314718055994531
|
||||
#define LG2 0.3010299956639812
|
||||
|
||||
#define TAGS_EMPTY 0b1111111111111111
|
||||
|
||||
#define ST0 emu->x87[emu->top]
|
||||
#define ST1 emu->x87[(emu->top+1)&7]
|
||||
#define ST(a) emu->x87[(emu->top+(a))&7]
|
||||
@@ -36,7 +38,8 @@ static inline void fpu_do_push(x86emu_t* emu)
|
||||
return;
|
||||
}
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
emu->p_regs[newtop].tag = 0; // full
|
||||
emu->fpu_tags<<=2; // st0 full
|
||||
emu->fpu_tags &= TAGS_EMPTY;
|
||||
emu->top = newtop;
|
||||
}
|
||||
|
||||
@@ -51,17 +54,24 @@ static inline void fpu_do_pop(x86emu_t* emu)
|
||||
if(emu->fpu_stack>0)
|
||||
--emu->fpu_stack;
|
||||
|
||||
emu->p_regs[curtop].tag = 0b11; // empty
|
||||
emu->fpu_tags>>=2;
|
||||
emu->fpu_tags |= 0b1100000000000000; // top empty
|
||||
emu->top = (emu->top+1)&7;
|
||||
// check tags
|
||||
/*while((emu->fpu_tags&0b11) && emu->fpu_stack) {
|
||||
--emu->fpu_stack;
|
||||
emu->top = (emu->top+1)&7;
|
||||
emu->fpu_tags>>=2;
|
||||
emu->fpu_tags |= 0b1100000000000000; // top empty
|
||||
}*/
|
||||
}
|
||||
|
||||
static inline void fpu_do_free(x86emu_t* emu, int i)
|
||||
{
|
||||
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
|
||||
emu->fpu_tags |= 0b11 << (i); // empty
|
||||
// check if all empty
|
||||
for(int i=0; i<8; ++i)
|
||||
if(emu->p_regs[i].tag != 0b11)
|
||||
return;
|
||||
if(emu->fpu_tags != TAGS_EMPTY)
|
||||
return;
|
||||
emu->fpu_stack = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef __SETROUND_H__
|
||||
#define __SETROUND_H__
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include "x86emu.h"
|
||||
#include "x86emu_private.h"
|
||||
// set the rounding mode to the emulator's one, and return the old one
|
||||
static inline int fpu_setround(x86emu_t* emu) {
|
||||
int ret = fegetround();
|
||||
int rounding_direction;
|
||||
switch (emu->cw.f.C87_RD) {
|
||||
case ROUND_Nearest:
|
||||
rounding_direction = FE_TONEAREST;
|
||||
break;
|
||||
case ROUND_Down:
|
||||
rounding_direction = FE_DOWNWARD;
|
||||
break;
|
||||
case ROUND_Up:
|
||||
rounding_direction = FE_UPWARD;
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
rounding_direction = FE_TOWARDZERO;
|
||||
break;
|
||||
}
|
||||
fesetround(rounding_direction);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -99,6 +99,9 @@ typedef struct box86context_s {
|
||||
int envc;
|
||||
char** envv;
|
||||
|
||||
int orig_argc;
|
||||
char** orig_argv;
|
||||
|
||||
char* fullpath;
|
||||
char* box86path; // path of current box86 executable
|
||||
char* box64path; // path of box64 executable (beside box86, if it exists)
|
||||
|
||||
+10
-5
@@ -16,6 +16,8 @@ void customFree(void* p);
|
||||
#define krealloc customRealloc
|
||||
#define kfree customFree
|
||||
|
||||
#define ALIGN(p) (((p)+box86_pagesize-1)&~(box86_pagesize-1))
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
@@ -37,11 +39,13 @@ uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
uintptr_t getJumpAddress(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_NEVERCLEAN 0x100
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_NOPROT 0x20
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
#define PROT_NEVERPROT (PROT_NOPROT | PROT_NEVERCLEAN)
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
@@ -56,9 +60,6 @@ void loadProtectionFromMap();
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
|
||||
int isprotectedDB(uintptr_t addr, size_t size);
|
||||
int IsInHotPage(uintptr_t addr);
|
||||
int AreaInHotPage(uintptr_t start, uintptr_t end);
|
||||
void AddHotPage(uintptr_t addr);
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask);
|
||||
@@ -77,6 +78,10 @@ void fini_custommem_helper(box86context_t* ctx);
|
||||
// ---- StrongMemoryModel
|
||||
void addLockAddress(uintptr_t addr); // add an address to the list of "LOCK"able
|
||||
int isLockAddress(uintptr_t addr); // return 1 is the address is used as a LOCK, 0 else
|
||||
|
||||
void SetHotPage(uintptr_t addr);
|
||||
int isInHotPage(uintptr_t addr);
|
||||
int checkInHotPage(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
@@ -20,6 +20,7 @@ extern int box86_dynarec_forward;
|
||||
extern int box86_dynarec_strongmem;
|
||||
extern int box86_dynarec_x87double;
|
||||
extern int box86_dynarec_safeflags;
|
||||
extern int box86_dynarec_callret;
|
||||
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
|
||||
extern int box86_dynarec_fastnan;
|
||||
extern int box86_dynarec_fastround;
|
||||
|
||||
@@ -5,6 +5,8 @@ typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
#define MAX_INSTS 32760
|
||||
|
||||
void addInst(instsize_t* insts, size_t* size, int x86_size, int arm_size);
|
||||
|
||||
void CancelBlock();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef RBTREE_H
|
||||
#define RBTREE_H
|
||||
|
||||
typedef struct rbtree rbtree;
|
||||
|
||||
rbtree* init_rbtree();
|
||||
void delete_rbtree(rbtree *tree);
|
||||
|
||||
uint32_t rb_get(rbtree *tree, uintptr_t addr);
|
||||
int rb_get_end(rbtree* tree, uintptr_t addr, uint32_t* val, uintptr_t* end);
|
||||
int rb_set(rbtree *tree, uintptr_t start, uintptr_t end, uint32_t data);
|
||||
int rb_unset(rbtree *tree, uintptr_t start, uintptr_t end);
|
||||
|
||||
void print_rbtree(const rbtree *tree);
|
||||
|
||||
#endif // RBTREE_H
|
||||
@@ -20,10 +20,6 @@ typedef union {
|
||||
uint8_t byte[4];
|
||||
} reg32_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tag;
|
||||
} fpu_p_reg_t;
|
||||
|
||||
typedef enum {
|
||||
ROUND_Nearest = 0,
|
||||
ROUND_Down = 1,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
} else \
|
||||
} \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
@@ -30,7 +30,7 @@
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
} else \
|
||||
} \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
@@ -130,6 +130,11 @@ void my_updateGlobalOpt()
|
||||
TOGLOB(optind, "GLIBC_2.2.5");
|
||||
TOGLOB(opterr, "GLIBC_2.2.5");
|
||||
TOGLOB(optopt, "GLIBC_2.2.5");
|
||||
|
||||
TOGLOB(optarg, "GLIBC_2.0");
|
||||
TOGLOB(optind, "GLIBC_2.0");
|
||||
TOGLOB(opterr, "GLIBC_2.0");
|
||||
TOGLOB(optopt, "GLIBC_2.0");
|
||||
}
|
||||
|
||||
void my_checkGlobalOpt()
|
||||
@@ -139,4 +144,9 @@ void my_checkGlobalOpt()
|
||||
GLOB(optind, "GLIBC_2.2.5");
|
||||
GLOB(opterr, "GLIBC_2.2.5");
|
||||
GLOB(optopt, "GLIBC_2.2.5");
|
||||
}
|
||||
|
||||
GLOB(optarg, "GLIBC_2.0");
|
||||
GLOB(optind, "GLIBC_2.0");
|
||||
GLOB(opterr, "GLIBC_2.0");
|
||||
GLOB(optopt, "GLIBC_2.0");
|
||||
}
|
||||
@@ -39,12 +39,12 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
library_t* owner = (*maplib)->owner;
|
||||
(*maplib)->owner = NULL; // to avoid recursive free...
|
||||
|
||||
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
for(int i=0; i<(*maplib)->libsz; ++i) {
|
||||
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
DecRefCount(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
box_free((*maplib)->libraries);
|
||||
(*maplib)->libraries = NULL;
|
||||
|
||||
|
||||
+86
-16
@@ -98,11 +98,15 @@ void WrappedLib_CommonInit(library_t *lib) {
|
||||
lib->w.mydatamap = kh_init(datamap);
|
||||
}
|
||||
|
||||
static void initDummyLib(library_t *lib);
|
||||
|
||||
void EmuLib_Fini(library_t* lib)
|
||||
{
|
||||
}
|
||||
void WrappedLib_FinishFini(library_t* lib)
|
||||
{
|
||||
if(lib->type!=LIB_WRAPPED)
|
||||
return;
|
||||
if(lib->w.lib)
|
||||
dlclose(lib->w.lib);
|
||||
lib->w.lib = NULL;
|
||||
@@ -115,6 +119,9 @@ void WrappedLib_FinishFini(library_t* lib)
|
||||
}
|
||||
FreeBridge(&lib->w.bridge);
|
||||
}
|
||||
void DummyLib_Fini(library_t* lib)
|
||||
{
|
||||
}
|
||||
|
||||
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
@@ -148,6 +155,11 @@ int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
// ignoring asked size on wrapped libs
|
||||
@@ -178,6 +190,10 @@ int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
// ignoring asked size on wrapped libs
|
||||
@@ -197,6 +213,11 @@ int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintp
|
||||
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
|
||||
return 0;
|
||||
}
|
||||
int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void initWrappedLib(library_t *lib, box86context_t* context) {
|
||||
int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t);
|
||||
@@ -345,6 +366,18 @@ static void initEmulatedLib(const char* path, library_t *lib, box86context_t* co
|
||||
}
|
||||
}
|
||||
|
||||
static void initDummyLib(library_t *lib)
|
||||
{
|
||||
memset(lib, 0, sizeof(library_t));
|
||||
lib->fini = DummyLib_Fini;
|
||||
lib->getglobal = DummyLib_GetGlobal;
|
||||
lib->getweak = DummyLib_GetWeak;
|
||||
lib->getlocal = DummyLib_GetLocal;
|
||||
lib->name = NULL;
|
||||
lib->path = NULL;
|
||||
lib->type = LIB_UNNKNOW;
|
||||
}
|
||||
|
||||
static const char* essential_libs[] = {
|
||||
"libc.so.6", "libpthread.so.0", "librt.so.1", "libGL.so.1", "libGL.so", "libX11.so.6",
|
||||
"libasound.so.2", "libdl.so.2", "libm.so.6",
|
||||
@@ -363,10 +396,34 @@ static int isEssentialLib(const char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NLIBS 16
|
||||
typedef struct lib_brick_s {
|
||||
library_t libs[NLIBS];
|
||||
struct lib_brick_s* next;
|
||||
} lib_brick_t;
|
||||
|
||||
static lib_brick_t* lib_head = NULL;
|
||||
static lib_brick_t* cur_brick = NULL;
|
||||
static size_t cur_lib = 0;
|
||||
static size_t lib_cap = 0;
|
||||
|
||||
library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* verneeded)
|
||||
{
|
||||
printf_dump(LOG_DEBUG, "Trying to load \"%s\"\n", path);
|
||||
library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
|
||||
//library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
|
||||
if(cur_lib==lib_cap) {
|
||||
lib_brick_t *new_brick = calloc(1, sizeof(lib_brick_t));
|
||||
if(!lib_head)
|
||||
cur_brick = lib_head = new_brick;
|
||||
else {
|
||||
cur_brick->next = new_brick;
|
||||
cur_brick = new_brick;
|
||||
}
|
||||
lib_cap += NLIBS;
|
||||
}
|
||||
library_t *lib = &cur_brick->libs[cur_lib%NLIBS];
|
||||
++cur_lib;
|
||||
memset(lib, 0, sizeof(library_t));
|
||||
lib->path = box_realpath(path, NULL);
|
||||
if(!lib->path)
|
||||
lib->path = box_strdup(path);
|
||||
@@ -381,7 +438,8 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
box_free(lib->name);
|
||||
box_free(lib->path);
|
||||
box_free(lib);
|
||||
initDummyLib(lib);
|
||||
//box_free(lib);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -389,7 +447,8 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
|
||||
if(strstr(lib->name, "libvulkan.so")==lib->name) {
|
||||
box_free(lib->name);
|
||||
box_free(lib->path);
|
||||
box_free(lib);
|
||||
initDummyLib(lib);
|
||||
//box_free(lib);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -418,7 +477,8 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
|
||||
{
|
||||
box_free(lib->name);
|
||||
box_free(lib->path);
|
||||
box_free(lib);
|
||||
initDummyLib(lib);
|
||||
//box_free(lib);
|
||||
return NULL;
|
||||
}
|
||||
lib->gbridgemap = kh_init(bridgemap);
|
||||
@@ -495,7 +555,7 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
|
||||
|
||||
library_t* lib = *the_lib;
|
||||
|
||||
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name);
|
||||
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name?:"???");
|
||||
// remove lib from maplib/local_maplib...
|
||||
if(my_context) {
|
||||
MapLibRemoveLib(my_context->maplib, lib);
|
||||
@@ -558,10 +618,11 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
|
||||
kh_destroy(symbol2map, lib->w.symbol2map);
|
||||
}
|
||||
|
||||
// remove frim the dlopen collection
|
||||
// remove from the dlopen collection
|
||||
if(lib->dlopen)
|
||||
RemoveDlopen(the_lib, lib->dlopen);
|
||||
box_free(lib);
|
||||
initDummyLib(lib);
|
||||
//box_free(lib);
|
||||
if(*the_lib == lib)
|
||||
*the_lib = NULL;
|
||||
}
|
||||
@@ -604,7 +665,7 @@ int IsSameLib(library_t* lib, const char* path)
|
||||
}
|
||||
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!lib || !name[0])
|
||||
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
@@ -631,7 +692,7 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start,
|
||||
}
|
||||
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!name[0] || !lib)
|
||||
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
@@ -658,7 +719,7 @@ int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
|
||||
}
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!name[0])
|
||||
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
@@ -1105,23 +1166,28 @@ void setNeededLibs(library_t* lib, int n, ...)
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
#define LIB_MAXCNT 255
|
||||
void IncRefCount(library_t* lib, x86emu_t* emu)
|
||||
{
|
||||
if(!lib || lib->type==LIB_UNNKNOW)
|
||||
return;
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED:
|
||||
if(lib->w.refcnt==LIB_MAXCNT)
|
||||
return;
|
||||
++lib->w.refcnt;
|
||||
/*if(lib->w.needed)
|
||||
if(lib->w.needed)
|
||||
for(int i=0; i<lib->w.needed->size; ++i) {
|
||||
IncRefCount(lib->w.needed->libs[i], emu);
|
||||
}*/
|
||||
}
|
||||
break;
|
||||
case LIB_EMULATED:
|
||||
if(lib->e.elf->refcnt==LIB_MAXCNT)
|
||||
return;
|
||||
++lib->e.elf->refcnt;
|
||||
/*if(lib->e.elf->needed)
|
||||
if(lib->e.elf->needed)
|
||||
for(int i=0; i<lib->e.elf->needed->size; ++i) // some libs may not be loaded yet
|
||||
IncRefCount(lib->e.elf->needed->libs[i], emu);*/
|
||||
IncRefCount(lib->e.elf->needed->libs[i], emu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,6 +1204,8 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
|
||||
int freed = 0;
|
||||
switch ((*lib)->type) {
|
||||
case LIB_WRAPPED:
|
||||
if((*lib)->w.refcnt==LIB_MAXCNT)
|
||||
return ret;
|
||||
needed = (*lib)->w.needed;
|
||||
ret=--(*lib)->w.refcnt;
|
||||
if(!ret) {
|
||||
@@ -1147,6 +1215,8 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
|
||||
}
|
||||
break;
|
||||
case LIB_EMULATED:
|
||||
if((*lib)->e.elf->refcnt==LIB_MAXCNT)
|
||||
return ret;
|
||||
needed = (*lib)->e.elf->needed;
|
||||
ret=--(*lib)->e.elf->refcnt;
|
||||
if(!ret) {
|
||||
@@ -1158,9 +1228,9 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*if(needed)
|
||||
if(needed)
|
||||
for(int i=0; i<needed->size; ++i)
|
||||
DecRefCount(&needed->libs[i], emu);*/
|
||||
DecRefCount(&needed->libs[i], emu);
|
||||
if(freed)
|
||||
free_neededlib(needed);
|
||||
return ret;
|
||||
|
||||
@@ -230,8 +230,8 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver);
|
||||
if(s) {
|
||||
*start = s->sym.offs;
|
||||
*end = *start + s->sym.sz;
|
||||
if(start) *start = s->sym.offs;
|
||||
if(end) *end = *start + s->sym.sz;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+16
-7
@@ -745,6 +745,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock(1);
|
||||
#endif
|
||||
emu->xSPSave = emu->old_savedsp;
|
||||
#ifdef ANDROID
|
||||
siglongjmp(*emu->jmpbuf, 1);
|
||||
#else
|
||||
@@ -803,10 +804,17 @@ static pthread_mutex_t mutex_dynarec_prot = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
|
||||
#define unlock_signal()
|
||||
#endif
|
||||
|
||||
extern int box86_quit;
|
||||
extern int box86_exit_code;
|
||||
|
||||
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
{
|
||||
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
|
||||
int log_minimum = (box86_showsegv)?LOG_NONE:((my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_DEBUG:LOG_INFO);
|
||||
if((sig==SIGSEGV || sig==SIGBUS) && box86_quit) {
|
||||
printf_log(LOG_INFO, "Sigfault/Segbus while quitting, exiting silently\n");
|
||||
_exit(box86_exit_code); // Hack, segfault while quiting, exit silently
|
||||
}
|
||||
ucontext_t *p = (ucontext_t *)ucntx;
|
||||
void* addr = (void*)info->si_addr; // address that triggered the issue
|
||||
uintptr_t x86pc = (uintptr_t)-1;
|
||||
@@ -842,23 +850,24 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) {
|
||||
lock_signal();
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
// check if SMC inside block
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
int db_need_test = (db && !box86_dynarec_fastpage)?getNeedTest((uintptr_t)db->x86_addr):0;
|
||||
dynarec_log(LOG_INFO/*LOG_DEBUG*/, "SIGSEGV with Access error on %p for %p , db=%p(%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL);
|
||||
static uintptr_t repeated_page = 0;
|
||||
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%hhx (old page=%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL, prot, (void*)repeated_page);
|
||||
static int repeated_count = 0;
|
||||
if(repeated_page == ((uintptr_t)addr&~0xfff)) {
|
||||
if(repeated_page == ((uintptr_t)addr&~(box86_pagesize-1))) {
|
||||
++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);
|
||||
SetHotPage(repeated_page);
|
||||
} else {
|
||||
repeated_page = (uintptr_t)addr&~0xfff;
|
||||
repeated_page = (uintptr_t)addr&~(box86_pagesize-1);
|
||||
repeated_count = 0;
|
||||
}
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
int db_need_test = (db && !box86_dynarec_fastpage)?getNeedTest((uintptr_t)db->x86_addr):0;
|
||||
dynarec_log(LOG_INFO/*LOG_DEBUG*/, "SIGSEGV with Access error on %p for %p , db=%p(%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL);
|
||||
if(db && ((addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) || db_need_test)) {
|
||||
if(db && p->uc_mcontext.arm_r0>0x10000)
|
||||
emu = (x86emu_t*)p->uc_mcontext.arm_r0;
|
||||
|
||||
@@ -454,7 +454,14 @@ int EXPORT my_pthread_once(x86emu_t* emu, int* once, void* cb)
|
||||
#endif
|
||||
if(old)
|
||||
return 0;
|
||||
// make some room and align R_RSP before doing the call (maybe it would be simpler to just use Callback functions)
|
||||
Push32(emu, R_EBP); // push rbp
|
||||
R_EBP = R_ESP; // mov rbp, rsp
|
||||
R_ESP -= 0x200;
|
||||
R_ESP &= ~63LL;
|
||||
DynaCall(emu, (uintptr_t)cb); // using DynaCall now, speedup wine 7.21 (proabbly other too) init
|
||||
R_ESP = R_EBP; // mov rsp, rbp
|
||||
R_EBP = Pop32(emu); // pop rbp
|
||||
return 0;
|
||||
}
|
||||
EXPORT int my___pthread_once(x86emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));
|
||||
|
||||
@@ -737,6 +737,13 @@ typedef enum VkStructureType {
|
||||
VK_STRUCTURE_TYPE_OPTICAL_FLOW_SESSION_CREATE_PRIVATE_DATA_INFO_NV = 1000464010,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT = 1000465000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT = 1000466000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR = 1000470000,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR = 1000470001,
|
||||
VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR = 1000338002,
|
||||
VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR = 1000470003,
|
||||
VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO_KHR = 1000470004,
|
||||
VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR = 1000470005,
|
||||
VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR = 1000470006,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM = 1000484000,
|
||||
VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM = 1000484001,
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC = 1000485000,
|
||||
@@ -1073,6 +1080,12 @@ typedef struct my_vkhead_s {
|
||||
case VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT: \
|
||||
case VK_STRUCTURE_TYPE_PRESENT_ID_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: \
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR: \
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES_KHR: \
|
||||
case VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_KHR: \
|
||||
case VK_STRUCTURE_TYPE_RENDERING_AREA_INFO_KHR: \
|
||||
case VK_STRUCTURE_TYPE_PIPELINE_CREATE_FLAGS_2_CREATE_INFO_KHR: \
|
||||
case VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR: \
|
||||
|
||||
#define CH(C, B, A) \
|
||||
case C: \
|
||||
@@ -1144,6 +1157,7 @@ typedef struct my_vkhead_s {
|
||||
CH(VK_STRUCTURE_TYPE_OPTICAL_FLOW_IMAGE_FORMAT_PROPERTIES_NV, "uPi", A) \
|
||||
CH(VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT, "uPUup", A) \
|
||||
CH(VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, "uPSuuu", A) \
|
||||
CH(VK_STRUCTURE_TYPE_DEVICE_IMAGE_SUBRESOURCE_INFO_KHR, "uPPP", A) \
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
+77
-41
@@ -56,6 +56,7 @@ int box86_nosandbox = 0;
|
||||
int box86_malloc_hack = 0;
|
||||
int box86_mutex_aligned = 0;
|
||||
int box86_quit = 0;
|
||||
int box86_exit_code = 0;
|
||||
#ifdef DYNAREC
|
||||
int box86_dynarec = 1;
|
||||
int box86_dynarec_dump = 0;
|
||||
@@ -68,6 +69,7 @@ int box86_dynarec_x87double = 0;
|
||||
int box86_dynarec_fastnan = 1;
|
||||
int box86_dynarec_fastround = 1;
|
||||
int box86_dynarec_safeflags = 1;
|
||||
int box86_dynarec_callret = 0;
|
||||
int box86_dynarec_hotpage = 16;
|
||||
int box86_dynarec_bleeding_edge = 1;
|
||||
int box86_dynarec_jvm = 1;
|
||||
@@ -189,6 +191,7 @@ void my_child_fork()
|
||||
// open a new ftrace...
|
||||
fclose(ftrace);
|
||||
openFTrace(NULL);
|
||||
//printf_log(/*LOG_DEBUG*/LOG_INFO, "Forked child of %s\n", GetLastApplyName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +434,7 @@ void LoadLogEnv()
|
||||
box86_dynarec_fastround = p[0]-'0';
|
||||
}
|
||||
if(!box86_dynarec_fastround)
|
||||
printf_log(LOG_INFO, "Dynarec will try to generate x86 precise IEEE->int rounding\n");
|
||||
printf_log(LOG_INFO, "Dynarec will try to generate x86 precise IEEE->int rounding and set rounding mode for computation\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_SAFEFLAGS");
|
||||
if(p) {
|
||||
@@ -444,6 +447,17 @@ void LoadLogEnv()
|
||||
else
|
||||
printf_log(LOG_INFO, "Dynarec will play %s safe with x86 flags\n", (box86_dynarec_safeflags==1)?"moderatly":"it");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_CALLRET");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_callret = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_callret)
|
||||
printf_log(LOG_INFO, "Dynarec will optimize CALL/RET\n");
|
||||
else
|
||||
printf_log(LOG_INFO, "Dynarec will not optimize CALL/RET\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_WAIT");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -453,27 +467,6 @@ void LoadLogEnv()
|
||||
if(!box86_dynarec_wait)
|
||||
printf_log(LOG_INFO, "Dynarec will not wait for FillBlock to ready and use Interpreter instead\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_HOTPAGE");
|
||||
if(p) {
|
||||
int val = -1;
|
||||
if(sscanf("%d", p, &val)==1) {
|
||||
if(val>=0)
|
||||
box86_dynarec_hotpage = val;
|
||||
}
|
||||
if(!box86_dynarec_hotpage)
|
||||
printf_log(LOG_INFO, "Dynarec will have HotPage tagged for %d attempts\n", box86_dynarec_hotpage);
|
||||
else
|
||||
printf_log(LOG_INFO, "Dynarec will not tag HotPage\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_FASTPAGE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_fastpage = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_fastpage)
|
||||
printf_log(LOG_INFO, "Dynarec will use Fast HotPage\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_BLEEDING_EDGE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -529,6 +522,7 @@ void LoadLogEnv()
|
||||
if(box86_dynarec_test) {
|
||||
box86_dynarec_fastnan = 0;
|
||||
box86_dynarec_fastround = 0;
|
||||
box86_dynarec_callret = 0;
|
||||
printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter (super slow, only for testing)\n");
|
||||
}
|
||||
}
|
||||
@@ -1123,6 +1117,7 @@ void setupTrace()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void endMallocHook();
|
||||
|
||||
void endBox86()
|
||||
{
|
||||
@@ -1130,15 +1125,18 @@ void endBox86()
|
||||
return;
|
||||
|
||||
box86_quit = 1;
|
||||
endMallocHook();
|
||||
x86emu_t* emu = thread_get_emu();
|
||||
//atexit first
|
||||
printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
|
||||
CallAllCleanup(emu);
|
||||
// then call all the fini
|
||||
printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n");
|
||||
RunElfFini(my_context->elfs[0], emu);
|
||||
FreeLibrarian(&my_context->local_maplib, emu); // unload all libs
|
||||
FreeLibrarian(&my_context->maplib, emu); // unload all libs
|
||||
void closeAllDLOpenned();
|
||||
closeAllDLOpenned(); // close residual dlopenned libs
|
||||
#if 0
|
||||
// waiting for all thread except this one to finish
|
||||
int this_thread = GetTID();
|
||||
// int pid = getpid();
|
||||
@@ -1177,27 +1175,51 @@ void endBox86()
|
||||
closedir(proc_dir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// all done, free context
|
||||
FreeBox86Context(&my_context);
|
||||
#ifdef DYNAREC
|
||||
// disable dynarec now
|
||||
box86_dynarec = 0;
|
||||
#endif
|
||||
if(box86_libGL) {
|
||||
box_free(box86_libGL);
|
||||
box86_libGL = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void add_argv(const char* what) {
|
||||
int there = 0;
|
||||
for(int i=1; i<my_context->argc && !there; ++i)
|
||||
if(!strcmp(my_context->argv[i], what))
|
||||
there = 1;
|
||||
if(!there) {
|
||||
my_context->argv = (char**)box_realloc(my_context->argv, (my_context->argc+1)*sizeof(char*));
|
||||
my_context->argv[my_context->argc] = box_strdup(what);
|
||||
my_context->argc++;
|
||||
}
|
||||
}
|
||||
|
||||
static void load_rcfiles()
|
||||
{
|
||||
char* rcpath = getenv("BOX86_RCFILE");
|
||||
|
||||
if(rcpath && FileExist(rcpath, IS_FILE))
|
||||
LoadRCFile(rcpath);
|
||||
|
||||
#ifndef TERMUX
|
||||
if(FileExist("/etc/box86.box86rc", IS_FILE))
|
||||
else if(FileExist("/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/etc/box86.box86rc");
|
||||
#else
|
||||
if(FileExist("/data/data/com.termux/files/usr/etc/box86.box86rc", IS_FILE))
|
||||
else if(FileExist("/data/data/com.termux/files/usr/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/data/data/com.termux/files/usr/etc/box86.box86rc");
|
||||
#endif
|
||||
#ifdef PANDORA
|
||||
if(FileExist("/mnt/utmp/codeblocks/usr/etc/box86.box86rc", IS_FILE))
|
||||
else if(FileExist("/mnt/utmp/codeblocks/usr/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/mnt/utmp/codeblocks/usr/etc/box86.box86rc");
|
||||
#endif
|
||||
// else
|
||||
// LoadRCFile(NULL); // load default rcfile
|
||||
char* p = getenv("HOME");
|
||||
if(p) {
|
||||
char tmp[4096];
|
||||
@@ -1350,6 +1372,7 @@ int main(int argc, const char **argv, char **env)
|
||||
}
|
||||
box86_wine = 1;
|
||||
}
|
||||
int wine_steam = 0;
|
||||
// check if this is wine
|
||||
if(!strcmp(prog, "wine") || (strlen(prog)>5 && !strcmp(prog+strlen(prog)-strlen("/wine"), "/wine"))) {
|
||||
const char* prereserve = getenv("WINEPRELOADRESERVE");
|
||||
@@ -1367,15 +1390,28 @@ int main(int argc, const char **argv, char **env)
|
||||
}
|
||||
}
|
||||
box86_wine = 1;
|
||||
// if program being called is wine_steam (rudimentary check...) and if no other argument are there
|
||||
if(argv[nextarg+1] && argv[nextarg+1][0]!='-' /*&& argc==(nextarg+2)*/) {
|
||||
if(!strcasecmp(argv[nextarg+1], "steam.exe"))
|
||||
wine_steam = 1;
|
||||
else if(!strcasecmp(argv[nextarg+1], "steam"))
|
||||
wine_steam = 1;
|
||||
if(!wine_steam) {
|
||||
const char* pp = strrchr(argv[nextarg+1], '/');
|
||||
if(pp && !strcasecmp(pp+1, "steam.exe"))
|
||||
wine_steam = 1;
|
||||
else {
|
||||
pp = strrchr(argv[nextarg+1], '\\');
|
||||
if(pp && !strcasecmp(pp+1, "steam.exe"))
|
||||
wine_steam = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if this is wineserver
|
||||
if(!strcmp(prog, "wineserver") || (strlen(prog)>9 && !strcmp(prog+strlen(prog)-strlen("/wineserver"), "/wineserver"))) {
|
||||
box86_wine = 1;
|
||||
}
|
||||
if(box86_wine) {
|
||||
// disabling the use of futex_waitv for now
|
||||
setenv("WINEFSYNC", "0", 1);
|
||||
}
|
||||
// Create a new context
|
||||
my_context = NewBox86Context(argc - nextarg);
|
||||
|
||||
@@ -1535,18 +1571,16 @@ int main(int argc, const char **argv, char **env)
|
||||
}
|
||||
if(box86_nosandbox)
|
||||
{
|
||||
// check if sandbox is already there
|
||||
int there = 0;
|
||||
for(int i=1; i<my_context->argc && !there; ++i)
|
||||
if(!strcmp(my_context->argv[i], "--no-sandbox"))
|
||||
there = 1;
|
||||
if(!there) {
|
||||
my_context->argv = (char**)box_realloc(my_context->argv, (my_context->argc+1)*sizeof(char*));
|
||||
my_context->argv[my_context->argc] = box_strdup("--no-sandbox");
|
||||
my_context->argc++;
|
||||
}
|
||||
add_argv("--no-sandbox");
|
||||
}
|
||||
if(wine_steam /*|| box86_steam*/) {
|
||||
printf_log(LOG_INFO, "Steam%s detected, adding -cef-single-process -cef-in-process-gpu -cef-disable-sandbox -no-cef-sandbox -cef-disable-breakpad to parameters", wine_steam?".exe":"");
|
||||
add_argv("-cef-single-process");
|
||||
add_argv("-cef-in-process-gpu");
|
||||
add_argv("-cef-disable-sandbox");
|
||||
add_argv("-no-cef-sandbox");
|
||||
add_argv("-cef-disable-breakpad");
|
||||
}
|
||||
|
||||
// check if file exist
|
||||
if(!my_context->argv[0] || !FileExist(my_context->argv[0], IS_FILE)) {
|
||||
printf_log(LOG_NONE, "Error: file is not found (check BOX86_PATH)\n");
|
||||
@@ -1702,6 +1736,8 @@ int main(int argc, const char **argv, char **env)
|
||||
memset(endp - diff, 0, diff); // fill reminder with NULL
|
||||
for(int i=nextarg; i<argc; ++i)
|
||||
argv[i] -= diff; // adjust strings
|
||||
my_context->orig_argc = argc;
|
||||
my_context->orig_argv = (char**)argv;
|
||||
}
|
||||
box86_isglibc234 = GetNeededVersionForLib(elf_header, "libc.so.6", "GLIBC_2.34");
|
||||
if(box86_isglibc234)
|
||||
|
||||
@@ -11,6 +11,15 @@
|
||||
int get_cpuMhz()
|
||||
{
|
||||
int MHz = 0;
|
||||
#ifdef PANDORA
|
||||
FILE *f = fopen("//proc/pandora/cpu_mhz_max", "r");
|
||||
if(f) {
|
||||
int r;
|
||||
if(1==fscanf(f, "%d", &r))
|
||||
MHz = r;
|
||||
fclose(f);
|
||||
}
|
||||
#else
|
||||
FILE *f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
|
||||
if(f) {
|
||||
int r;
|
||||
@@ -46,6 +55,7 @@ int get_cpuMhz()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(!MHz)
|
||||
MHz = 1000; // default to 1Ghz...
|
||||
return MHz;
|
||||
@@ -102,6 +112,9 @@ const char* getCpuName()
|
||||
if(done)
|
||||
return name;
|
||||
done = 1;
|
||||
#ifdef PANDORA
|
||||
strcpy(name, "Cortex-A8");
|
||||
#else
|
||||
FILE* f = popen("lscpu | grep \"Model name:\" | sed -r 's/Model name:\\s{1,}//g'", "r");
|
||||
if(f) {
|
||||
char tmp[200] = "";
|
||||
@@ -139,6 +152,7 @@ const char* getCpuName()
|
||||
return name;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Nope, bye
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,902 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef RBTREE_TEST
|
||||
#define rbtreeMalloc malloc
|
||||
#define rbtreeFree free
|
||||
#else
|
||||
#include "custommem.h"
|
||||
#include "debug.h"
|
||||
#include "rbtree.h"
|
||||
#if 0
|
||||
#define rbtreeMalloc box_malloc
|
||||
#define rbtreeFree box_free
|
||||
#else
|
||||
#define rbtreeMalloc customMalloc
|
||||
#define rbtreeFree customFree
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct rbnode {
|
||||
struct rbnode *left, *right, *parent;
|
||||
uintptr_t start, end;
|
||||
uint32_t data;
|
||||
uint8_t meta;
|
||||
} rbnode;
|
||||
|
||||
typedef struct rbtree {
|
||||
rbnode *root;
|
||||
int is_unstable;
|
||||
} rbtree;
|
||||
|
||||
rbtree* init_rbtree() {
|
||||
rbtree* tree = rbtreeMalloc(sizeof(rbtree));
|
||||
tree->root = NULL;
|
||||
tree->is_unstable = 0;
|
||||
return tree;
|
||||
}
|
||||
|
||||
void delete_rbnode(rbnode *root) {
|
||||
if (!root) return;
|
||||
delete_rbnode(root->left);
|
||||
delete_rbnode(root->right);
|
||||
rbtreeFree(root);
|
||||
}
|
||||
void delete_rbtree(rbtree *tree) {
|
||||
delete_rbnode(tree->root);
|
||||
rbtreeFree(tree);
|
||||
}
|
||||
|
||||
#define IS_LEFT 0x1
|
||||
#define IS_BLACK 0x2
|
||||
|
||||
// Make sure prev is either the rightmost node before start or the leftmost range after start
|
||||
int add_range_next_to(rbtree *tree, rbnode *prev, uintptr_t start, uintptr_t end, uint32_t data) {
|
||||
// printf("Adding %lX-%lX:%hhX next to %p\n", start, end, data, prev);
|
||||
rbnode *node = rbtreeMalloc(sizeof(*node));
|
||||
if (!node) return -1;
|
||||
node->start = start;
|
||||
node->end = end;
|
||||
node->data = data;
|
||||
node->left = NULL;
|
||||
node->right = NULL;
|
||||
|
||||
if (tree->is_unstable) {
|
||||
printf_log(LOG_NONE, "Warning, unstable Red-Black tree; trying to add a node anyways\n");
|
||||
}
|
||||
tree->is_unstable = 1;
|
||||
|
||||
if (!tree->root) {
|
||||
node->parent = NULL;
|
||||
node->meta = IS_BLACK;
|
||||
tree->root = node;
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
node->parent = prev;
|
||||
if (prev->start < start) {
|
||||
prev->right = node;
|
||||
node->meta = 0;
|
||||
} else {
|
||||
prev->left = node;
|
||||
node->meta = IS_LEFT;
|
||||
}
|
||||
|
||||
while (!(node->meta & IS_BLACK)) {
|
||||
if (!node->parent) {
|
||||
node->meta = IS_BLACK;
|
||||
tree->root = node;
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
if (node->parent->meta & IS_BLACK) {
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!node->parent->parent) {
|
||||
tree->is_unstable = 0;
|
||||
return 0; // Cannot happen as the root is black, unless the tree is unstable
|
||||
}
|
||||
if (node->parent->meta & IS_LEFT) {
|
||||
if (node->parent->parent->right && !(node->parent->parent->right->meta & IS_BLACK)) {
|
||||
node->parent->meta |= IS_BLACK;
|
||||
node = node->parent->parent;
|
||||
node->meta &= ~IS_BLACK;
|
||||
node->right->meta |= IS_BLACK;
|
||||
} else {
|
||||
if (!(node->meta & IS_LEFT)) {
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = y->parent;
|
||||
// ((Bz->left), Rz, ((By->left), Ry, (By->right)))
|
||||
// y = RED, rchild of z
|
||||
// z = RED, child of z->parent
|
||||
// target = (((Bz->left), Rz, (By->left)), Ry, (By->right))
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
y->meta = z->meta; // red + same side as z
|
||||
z->meta = IS_LEFT; // red + left
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->right = y->left;
|
||||
y->left = z;
|
||||
if (z->right) {
|
||||
z->right->meta &= ~IS_LEFT;
|
||||
z->right->parent = z;
|
||||
}
|
||||
node = z;
|
||||
}
|
||||
rbnode *y, *z;
|
||||
y = node->parent;
|
||||
z = y->parent;
|
||||
// (((Rnode), Ry, (By->right)), Bz, (Bz->right))
|
||||
// node = RED, lchild of y
|
||||
// y = RED, lchild of z
|
||||
// z = BLACK, child of z->parent OR ROOT
|
||||
// target = ((Rnode), By, ((By->right), Rz, (Bz->right)))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = 0; // red + right
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->left = y->right;
|
||||
y->right = z;
|
||||
if (z->left) {
|
||||
z->left->meta |= IS_LEFT;
|
||||
z->left->parent = z;
|
||||
}
|
||||
if (!y->parent) tree->root = y;
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (node->parent->parent->left && !(node->parent->parent->left->meta & IS_BLACK)) {
|
||||
node->parent->meta |= IS_BLACK;
|
||||
node = node->parent->parent;
|
||||
node->meta &= ~IS_BLACK;
|
||||
node->left->meta |= IS_BLACK;
|
||||
} else {
|
||||
if (node->meta & IS_LEFT) {
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = y->parent;
|
||||
// (((By->left), Ry, (By->right)), Rz, (Bz->right))
|
||||
// y = RED, lchild of z
|
||||
// z = RED, child of z->parent
|
||||
// target = ((By->left), Ry, ((By->right), Rz, (Bz->right)))
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
y->meta = z->meta; // red + same side as z
|
||||
z->meta = 0; // red + right
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->left = y->right;
|
||||
y->right = z;
|
||||
if (z->left) {
|
||||
z->left->meta |= IS_LEFT;
|
||||
z->left->parent = z;
|
||||
}
|
||||
node = z;
|
||||
}
|
||||
rbnode *y, *z;
|
||||
y = node->parent;
|
||||
z = y->parent;
|
||||
// ((Bz->left), Bz, ((By->left), Ry, (Rnode)))
|
||||
// node = RED, rchild of y
|
||||
// y = RED, rchild of z
|
||||
// z = BLACK, child of z->parent OR ROOT
|
||||
// target = (((Bz->left), Rz, (By->left)), By, (Rnode))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = IS_LEFT; // red + left
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->right = y->left;
|
||||
y->left = z;
|
||||
if (z->right) {
|
||||
z->right->meta &= ~IS_LEFT;
|
||||
z->right->parent = z;
|
||||
}
|
||||
if (!y->parent) tree->root = y;
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
tree->is_unstable = 0;
|
||||
return -1; // unreachable
|
||||
}
|
||||
int add_range(rbtree *tree, uintptr_t start, uintptr_t end, uint32_t data) {
|
||||
// printf("add_range\n");
|
||||
rbnode *cur = tree->root, *prev = NULL;
|
||||
while (cur) {
|
||||
prev = cur;
|
||||
if (cur->start < start) cur = cur->right;
|
||||
else cur = cur->left;
|
||||
}
|
||||
return add_range_next_to(tree, prev, start, end, data);
|
||||
}
|
||||
|
||||
rbnode *find_addr(rbtree *tree, uintptr_t addr) {
|
||||
rbnode *node = tree->root;
|
||||
while (node) {
|
||||
if ((node->start <= addr) && (node->end > addr)) return node;
|
||||
if (addr < node->start) node = node->left;
|
||||
else node = node->right;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// node must be a valid node in the tree
|
||||
int remove_node(rbtree *tree, rbnode *node) {
|
||||
// printf("Removing %p\n", node); print_rbtree(tree); fflush(stdout);
|
||||
if (tree->is_unstable) {
|
||||
printf_log(LOG_NONE, "Warning, unstable Red-Black tree; trying to add a node anyways\n");
|
||||
}
|
||||
tree->is_unstable = 1;
|
||||
|
||||
if (node->left && node->right) {
|
||||
// Swap node and its successor
|
||||
// Do NOT free the successor as a reference to it can exist
|
||||
rbnode *cur = node->right, *prev;
|
||||
while (cur) {
|
||||
prev = cur;
|
||||
cur = cur->left;
|
||||
}
|
||||
// Swap the position of node and prev != node
|
||||
uint8_t tmp8 = node->meta;
|
||||
node->meta = prev->meta;
|
||||
prev->meta = tmp8;
|
||||
prev->left = node->left;
|
||||
node->left = NULL;
|
||||
if (prev->left) prev->left->parent = prev;
|
||||
if (node->meta & IS_LEFT) {
|
||||
cur = node->parent;
|
||||
node->parent = prev->parent;
|
||||
prev->parent = cur;
|
||||
cur = node->right;
|
||||
node->right = prev->right;
|
||||
prev->right = cur;
|
||||
if (cur) cur->parent = prev;
|
||||
} else {
|
||||
node->right = prev->right;
|
||||
prev->right = node;
|
||||
prev->parent = node->parent;
|
||||
node->parent = prev;
|
||||
}
|
||||
if (node->right) node->right->parent = node; // Should be overriden later
|
||||
if (!prev->parent) {
|
||||
tree->root = prev; // prev is already black
|
||||
} else if (prev->meta & IS_LEFT) {
|
||||
prev->parent->left = prev;
|
||||
} else {
|
||||
prev->parent->right = prev;
|
||||
}
|
||||
}
|
||||
rbnode *child = node->left ? node->left : node->right, *parent = node->parent;
|
||||
if (child) {
|
||||
child->parent = parent;
|
||||
if (!parent) {
|
||||
tree->root = child;
|
||||
child->meta |= IS_BLACK; // Needs to be an or
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
} else if (node->meta & IS_LEFT) {
|
||||
child->meta |= IS_LEFT;
|
||||
parent->left = child;
|
||||
} else {
|
||||
child->meta &= ~IS_LEFT;
|
||||
parent->right = child;
|
||||
}
|
||||
} else {
|
||||
if (!parent) {
|
||||
tree->root = NULL;
|
||||
rbtreeFree(node);
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
} else if (node->meta & IS_LEFT) {
|
||||
parent->left = NULL;
|
||||
} else {
|
||||
parent->right = NULL;
|
||||
}
|
||||
}
|
||||
// Node has been removed, now to fix the tree
|
||||
if (!(node->meta & IS_BLACK)) {
|
||||
rbtreeFree(node);
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
rbtreeFree(node);
|
||||
|
||||
// Add a black node before child
|
||||
// Notice that the sibling cannot be NULL.
|
||||
while (parent && (!child || (child->meta & IS_BLACK))) {
|
||||
if ((child && child->meta & IS_LEFT) || (!child && !parent->left)) {
|
||||
node = parent->right;
|
||||
if (!(node->meta & IS_BLACK)) {
|
||||
// rotate ===
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = parent;
|
||||
// ((Bchild), Bz, ((y->left), Ry, (y->right)))
|
||||
// y = RED, rchild of z
|
||||
// z = BLACK, child of z->parent OR ROOT
|
||||
// target = (((Bchild), Rz, (y->left)), By, (y->right))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
} else {
|
||||
tree->root = y;
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = IS_LEFT; // red + left
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->right = y->left;
|
||||
y->left = z;
|
||||
if (z->right) {
|
||||
z->right->meta &= ~IS_LEFT;
|
||||
z->right->parent = z;
|
||||
}
|
||||
// ===
|
||||
node = parent->right;
|
||||
}
|
||||
if (node->right && !(node->right->meta & IS_BLACK)) {
|
||||
case4_l: {
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = parent;
|
||||
// ((Bchild), ?z, ((?y->left), By, (Ry->right)))
|
||||
// y = BLACK, rchild of z
|
||||
// z = ?, child of z->parent OR ROOT
|
||||
// target = (((Bchild), Bz, (?y->left)), ?y, (By->right))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
}
|
||||
y->meta = z->meta; // same color as z + same side as z
|
||||
z->meta = IS_BLACK | IS_LEFT; // black + left
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->right = y->left;
|
||||
y->left = z;
|
||||
if (z->right) {
|
||||
z->right->meta &= ~IS_LEFT;
|
||||
z->right->parent = z;
|
||||
}
|
||||
if (!y->parent) tree->root = y;
|
||||
node->right->meta |= IS_BLACK;
|
||||
tree->is_unstable = 0;
|
||||
return 0; }
|
||||
} else if (!node->left || (node->left->meta & IS_BLACK)) {
|
||||
// case2_l:
|
||||
child = parent; // Remember that child can be NULL
|
||||
parent = child->parent;
|
||||
node->meta &= ~IS_BLACK;
|
||||
} else {
|
||||
// case3_l:
|
||||
rbnode *y, *z;
|
||||
y = node->left;
|
||||
z = node;
|
||||
// (((y->left), Ry, (y->right)), Bz, (Bz->right))
|
||||
// y = RED, rchild of z
|
||||
// z = BLACK, child of z->parent
|
||||
// target = ((y->left), By, ((y->right), Rz, (z->right)))
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = 0; // red + right
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->left = y->right;
|
||||
y->right = z;
|
||||
if (z->left) {
|
||||
z->left->meta |= IS_LEFT;
|
||||
z->left->parent = z;
|
||||
}
|
||||
node = y;
|
||||
goto case4_l;
|
||||
}
|
||||
} else {
|
||||
node = parent->left;
|
||||
if (!(node->meta & IS_BLACK)) {
|
||||
// rotate ===
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = parent;
|
||||
// (((y->left), Ry, (y->right)), Bz, (Bchild))
|
||||
// y = RED, lchild of z
|
||||
// z = BLACK, child of z->parent OR ROOT
|
||||
// target = ((y->left), By, ((y->right), Rz, (Bchild)))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = 0; // red + right
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->left = y->right;
|
||||
y->right = z;
|
||||
if (z->left) {
|
||||
z->left->meta |= IS_LEFT;
|
||||
z->left->parent = z;
|
||||
}
|
||||
if (!y->parent) tree->root = y;
|
||||
// ===
|
||||
node = parent->left;
|
||||
}
|
||||
if (node->left && !(node->left->meta & IS_BLACK)) {
|
||||
case4_r: {
|
||||
rbnode *y, *z;
|
||||
y = node;
|
||||
z = y->parent;
|
||||
// (((?y->left), By, (Ry->right)), ?z, (Bchild))
|
||||
// y = BLACK, rchild of z
|
||||
// z = ?, child of z->parent OR ROOT
|
||||
// target = ((?y->left), ?y, ((Ry->right), Bz, (Bchild)))
|
||||
if (z->parent) {
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
}
|
||||
y->meta = z->meta; // same color as z + same side as z
|
||||
z->meta = IS_BLACK; // black + right
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->left = y->right;
|
||||
y->right = z;
|
||||
if (z->left) {
|
||||
z->left->meta |= IS_LEFT;
|
||||
z->left->parent = z;
|
||||
}
|
||||
if (!y->parent) tree->root = y;
|
||||
node->left->meta |= IS_BLACK;
|
||||
tree->is_unstable = 0;
|
||||
return 0; }
|
||||
} else if (!node->right || (node->right->meta & IS_BLACK)) {
|
||||
// case2_r:
|
||||
child = parent;
|
||||
parent = child->parent;
|
||||
node->meta &= ~IS_BLACK;
|
||||
} else {
|
||||
// case3_r:
|
||||
rbnode *y, *z;
|
||||
y = node->right;
|
||||
z = node;
|
||||
// ((Bz->left), Bz, ((y->left), Ry, (y->right)))
|
||||
// y = RED, rchild of z
|
||||
// z = BLACK, child of z->parent
|
||||
// target = (((Bz->left), Rz, (y->left)), By, (y->right))
|
||||
if (z->meta & IS_LEFT) {
|
||||
z->parent->left = y;
|
||||
} else {
|
||||
z->parent->right = y;
|
||||
}
|
||||
y->meta = z->meta; // black + same side as z
|
||||
z->meta = IS_LEFT; // red + left
|
||||
y->parent = z->parent;
|
||||
z->parent = y;
|
||||
z->right = y->left;
|
||||
y->left = z;
|
||||
if (z->right) {
|
||||
z->right->meta &= ~IS_LEFT;
|
||||
z->right->parent = z;
|
||||
}
|
||||
node = y;
|
||||
goto case4_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (child)
|
||||
child->meta |= IS_BLACK;
|
||||
tree->is_unstable = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rbnode *first_node(rbtree *tree) {
|
||||
rbnode *node = tree->root, *prev = node;
|
||||
while (node) {
|
||||
prev = node;
|
||||
node = node->left;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
rbnode *pred_node(rbnode *node) {
|
||||
if (!node) return NULL;
|
||||
if (node->left) {
|
||||
node = node->left;
|
||||
while (node->right) node = node->right;
|
||||
return node;
|
||||
} else {
|
||||
while (node->parent && node->meta & IS_LEFT) node = node->parent;
|
||||
return node->parent;
|
||||
}
|
||||
}
|
||||
rbnode *succ_node(rbnode *node) {
|
||||
if (!node) return NULL;
|
||||
if (node->right) {
|
||||
node = node->right;
|
||||
while (node->left) node = node->left;
|
||||
return node;
|
||||
} else {
|
||||
while (node->parent && !(node->meta & IS_LEFT)) node = node->parent;
|
||||
return node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rb_get(rbtree *tree, uintptr_t addr) {
|
||||
rbnode *node = find_addr(tree, addr);
|
||||
if (node) return node->data;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int rb_get_end(rbtree* tree, uintptr_t addr, uint32_t* val, uintptr_t* end) {
|
||||
rbnode *node = tree->root, *next = NULL;
|
||||
while (node) {
|
||||
if ((node->start <= addr) && (node->end > addr)) {
|
||||
*val = node->data;
|
||||
*end = node->end;
|
||||
return 1;
|
||||
}
|
||||
if (node->end <= addr) {
|
||||
node = node->right;
|
||||
} else {
|
||||
next = node;
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
*val = 0;
|
||||
if (next) {
|
||||
*end = next->start;
|
||||
} else {
|
||||
*end = (uintptr_t)-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_set(rbtree *tree, uintptr_t start, uintptr_t end, uint32_t data) {
|
||||
// printf("rb_set( "); print_rbtree(tree); printf(" , 0x%lX, 0x%lX, %hhu);\n", start, end, data); fflush(stdout);
|
||||
dynarec_log(LOG_DEBUG, "set 0x%lX, 0x%lX, %hhu\n", start, end, data);
|
||||
if (!tree->root) {
|
||||
return add_range(tree, start, end, data);
|
||||
}
|
||||
|
||||
rbnode *node = tree->root, *prev = NULL, *last = NULL;
|
||||
while (node) {
|
||||
if (node->start < start) {
|
||||
prev = node;
|
||||
node = node->right;
|
||||
} else if (node->start == start) {
|
||||
if (node->left) {
|
||||
prev = node->left;
|
||||
while (prev->right) prev = prev->right;
|
||||
}
|
||||
if (node->right) {
|
||||
last = node->right;
|
||||
while (last->left) last = last->left;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
last = node;
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
|
||||
// prev is the largest node starting strictly before start, or NULL if there is none
|
||||
// node is the node starting exactly at start, or NULL if there is none
|
||||
// last is the smallest node starting strictly after start, or NULL if there is none
|
||||
// Note that prev may contain start
|
||||
|
||||
if (prev && (prev->end >= start) && (prev->data == data)) {
|
||||
// Merge with prev
|
||||
if (end <= prev->end) return 0; // Nothing to do!
|
||||
|
||||
if (node && (node->end > end)) {
|
||||
node->start = end;
|
||||
prev->end = end;
|
||||
return 0;
|
||||
} else if (node && (node->end == end)) {
|
||||
remove_node(tree, node);
|
||||
prev->end = end;
|
||||
return 0;
|
||||
} else if (node) {
|
||||
remove_node(tree, node);
|
||||
}
|
||||
while (last && (last->start < end) && (last->end <= end)) {
|
||||
// Remove the entire node
|
||||
node = last;
|
||||
last = succ_node(last);
|
||||
remove_node(tree, node);
|
||||
}
|
||||
if (last && (last->start <= end) && (last->data == data)) {
|
||||
// Merge node and last
|
||||
prev->end = last->end;
|
||||
remove_node(tree, last);
|
||||
return 0;
|
||||
}
|
||||
if (last && (last->start < end)) last->start = end;
|
||||
prev->end = end;
|
||||
return 0;
|
||||
} else if (prev && (prev->end > start)) {
|
||||
if (prev->end > end) {
|
||||
// Split in three
|
||||
// Note that here, succ(prev) = last and node = NULL
|
||||
int ret;
|
||||
ret = add_range_next_to(tree, prev->right ? last : prev, end, prev->end, prev->data);
|
||||
ret = ret ? ret : add_range_next_to(tree, prev->right ? succ_node(prev) : prev, start, end, data);
|
||||
prev->end = start;
|
||||
return ret;
|
||||
}
|
||||
// Cut prev and continue
|
||||
prev->end = start;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
// Change node
|
||||
if (node->end >= end) {
|
||||
if (node->data == data) return 0; // Nothing to do!
|
||||
// Cut node
|
||||
if (node->end > end) {
|
||||
int ret = add_range_next_to(tree, node->right ? last : node, end, node->end, node->data);
|
||||
node->end = end;
|
||||
node->data = data;
|
||||
return ret;
|
||||
}
|
||||
// Fallthrough
|
||||
}
|
||||
|
||||
// Overwrite and extend node
|
||||
while (last && (last->start < end) && (last->end <= end)) {
|
||||
// Remove the entire node
|
||||
prev = last;
|
||||
last = succ_node(last);
|
||||
remove_node(tree, prev);
|
||||
}
|
||||
if (last && (last->start <= end) && (last->data == data)) {
|
||||
// Merge node and last
|
||||
remove_node(tree, node);
|
||||
last->start = start;
|
||||
return 0;
|
||||
}
|
||||
if (last && (last->start < end)) last->start = end;
|
||||
if (node->end < end) node->end = end;
|
||||
node->data = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (last && (last->start < end) && (last->end <= end)) {
|
||||
// Remove the entire node
|
||||
node = last;
|
||||
last = succ_node(last);
|
||||
remove_node(tree, node);
|
||||
}
|
||||
if (!last) {
|
||||
// Add a new node next to prev, the largest node of the tree
|
||||
// It exists since the tree is nonempty
|
||||
return add_range_next_to(tree, prev, start, end, data);
|
||||
}
|
||||
if ((last->start <= end) && (last->data == data)) {
|
||||
// Extend
|
||||
last->start = start;
|
||||
return 0;
|
||||
} else if (last->start < end) {
|
||||
// Cut
|
||||
last->start = end;
|
||||
}
|
||||
// Probably 'last->left ? prev : last' is enough
|
||||
return add_range_next_to(tree, last->left ? pred_node(last) : last, start, end, data);
|
||||
}
|
||||
|
||||
int rb_unset(rbtree *tree, uintptr_t start, uintptr_t end) {
|
||||
// printf("rb_unset( "); print_rbtree(tree); printf(" , 0x%lX, 0x%lX);\n", start, end); fflush(stdout);
|
||||
dynarec_log(LOG_DEBUG, "rb_unset(tree, 0x%lX, 0x%lX);\n", start, end);
|
||||
if (!tree->root) return 0;
|
||||
|
||||
rbnode *node = tree->root, *prev = NULL, *next = NULL;
|
||||
while (node) {
|
||||
if (node->start < start) {
|
||||
prev = node;
|
||||
node = node->right;
|
||||
} else if (node->start == start) {
|
||||
if (node->left) {
|
||||
prev = node->left;
|
||||
while (prev->right) prev = prev->right;
|
||||
}
|
||||
if (node->right) {
|
||||
next = node->right;
|
||||
while (next->left) next = next->left;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
next = node;
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
|
||||
if (node) {
|
||||
if (node->end > end) {
|
||||
node->start = end;
|
||||
return 0;
|
||||
} else if (node->end == end) {
|
||||
remove_node(tree, node);
|
||||
return 0;
|
||||
} else {
|
||||
remove_node(tree, node);
|
||||
}
|
||||
} else if (prev && (prev->end > start)) {
|
||||
if (prev->end > end) {
|
||||
// Split prev
|
||||
int ret = add_range_next_to(tree, prev->right ? next : prev, end, prev->end, prev->data);
|
||||
prev->end = start;
|
||||
return ret;
|
||||
} else if (prev->end == end) {
|
||||
prev->end = start;
|
||||
return 0;
|
||||
} // else fallthrough
|
||||
}
|
||||
while (next && (next->start < end) && (next->end <= end)) {
|
||||
// Remove the entire node
|
||||
node = next;
|
||||
next = succ_node(next);
|
||||
remove_node(tree, node);
|
||||
}
|
||||
if (next && (next->start < end)) {
|
||||
// next->end > end: cut the node
|
||||
next->start = end;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
void print_rbnode(const rbnode *node, unsigned depth, uintptr_t minstart, uintptr_t maxend, unsigned *bdepth) {
|
||||
if (!node) {
|
||||
if (!*bdepth || *bdepth == depth + 1) {
|
||||
*bdepth = depth + 1;
|
||||
printf("[%u]", depth);
|
||||
} else
|
||||
printf("<invalid black depth %u>", depth);
|
||||
return;
|
||||
}
|
||||
if (node->start < minstart) {
|
||||
printf("<invalid start>");
|
||||
return;
|
||||
}
|
||||
if (node->end > maxend) {
|
||||
printf("<invalid end>");
|
||||
return;
|
||||
}
|
||||
printf("(");
|
||||
if (node->left && !(node->left->meta & IS_LEFT)) {
|
||||
printf("<invalid meta>");
|
||||
} else if (node->left && (node->left->parent != node)) {
|
||||
printf("<invalid parent %p instead of %p>", node->left->parent, node);
|
||||
} else if (node->left && !(node->meta & IS_BLACK) && !(node->left->meta & IS_BLACK)) {
|
||||
printf("<invalid red-red node> ");
|
||||
print_rbnode(node->left, depth + ((node->meta & IS_BLACK) ? 1 : 0), minstart, node->start, bdepth);
|
||||
} else {
|
||||
print_rbnode(node->left, depth + ((node->meta & IS_BLACK) ? 1 : 0), minstart, node->start, bdepth);
|
||||
}
|
||||
printf(", (%c/%p) %lX-%lX: %hhu, ", node->meta & IS_BLACK ? 'B' : 'R', node, node->start, node->end, node->data);
|
||||
if (node->right && (node->right->meta & IS_LEFT)) {
|
||||
printf("<invalid meta>");
|
||||
} else if (node->right && (node->right->parent != node)) {
|
||||
printf("<invalid parent %p instead of %p>", node->right->parent, node);
|
||||
} else if (node->right && !(node->meta & IS_BLACK) && !(node->right->meta & IS_BLACK)) {
|
||||
printf("<invalid red-red node> ");
|
||||
print_rbnode(node->right, depth + ((node->meta & IS_BLACK) ? 1 : 0), node->end, maxend, bdepth);
|
||||
} else {
|
||||
print_rbnode(node->right, depth + ((node->meta & IS_BLACK) ? 1 : 0), node->end, maxend, bdepth);
|
||||
}
|
||||
printf(")");
|
||||
}
|
||||
void print_rbtree(const rbtree *tree) {
|
||||
if (!tree) {
|
||||
printf("<NULL>\n");
|
||||
return;
|
||||
}
|
||||
if (tree->root && tree->root->parent) {
|
||||
printf("Root has parent\n");
|
||||
return;
|
||||
}
|
||||
if (tree->root && !(tree->root->meta & IS_BLACK)) {
|
||||
printf("Root is red\n");
|
||||
return;
|
||||
}
|
||||
unsigned bdepth = 0;
|
||||
print_rbnode(tree->root, 0, 0, (uintptr_t)-1, &bdepth);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#ifdef RBTREE_TEST
|
||||
int main() {
|
||||
rbtree* tree = init_rbtree();
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
/*int ret;
|
||||
ret = rb_set(tree, 0x43, 0x44, 0x01);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
ret = rb_set(tree, 0x42, 0x43, 0x01);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
ret = rb_set(tree, 0x41, 0x42, 0x01);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
ret = rb_set(tree, 0x40, 0x41, 0x01);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
ret = rb_set(tree, 0x20, 0x40, 0x03);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
ret = rb_set(tree, 0x10, 0x20, 0x01);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
|
||||
uint32_t val = rb_get(tree, 0x33);
|
||||
printf("0x33 has attribute %hhu\n", val); fflush(stdout);*/
|
||||
/* rbnode *node = find_addr(tree, 0x33);
|
||||
printf("0x33 is at %p: ", node); print_rbnode(node, 0); printf("\n"); fflush(stdout);
|
||||
ret = remove_node(tree, node);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout);
|
||||
node = find_addr(tree, 0x20);
|
||||
printf("0x20 is at %p\n", node);
|
||||
node = find_addr(tree, 0x1F);
|
||||
printf("0x1F is at %p: ", node); print_rbnode(node, 0); printf("\n"); fflush(stdout);
|
||||
ret = remove_node(tree, node);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout); */
|
||||
/* ret = rb_set(tree, 0x15, 0x42, 0x00);
|
||||
printf("%d; ", ret); print_rbtree(tree); fflush(stdout); */
|
||||
/*rb_unset(tree, 0x15, 0x42);
|
||||
print_rbtree(tree); fflush(stdout);*/
|
||||
|
||||
// tree->root = node27; print_rbtree(tree); fflush(stdout);
|
||||
// rb_set(tree, 2, 3, 1); print_rbtree(tree); fflush(stdout);
|
||||
// add_range_next_to(tree, node24, 0x0E7000, 0x0E8000, 69); print_rbtree(tree); fflush(stdout);
|
||||
// print_rbtree(tree); fflush(stdout);
|
||||
// uint32_t val = rb_get(tree, 0x11003000);
|
||||
// printf("0x11003000 has attribute %hhu\n", val); fflush(stdout);
|
||||
// remove_node(tree, node0); print_rbtree(tree); fflush(stdout);
|
||||
// add_range_next_to(tree, node1, 0x0E7000, 0x0E8000, 69); print_rbtree(tree); fflush(stdout);
|
||||
rb_set(tree, 0x130000, 0x140000, 7);
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
rb_set(tree, 0x141000, 0x142000, 135);
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
rb_set(tree, 0x140000, 0x141000, 135);
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
rb_set(tree, 0x140000, 0x141000, 7);
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
rb_set(tree, 0x140000, 0x141000, 135);
|
||||
print_rbtree(tree); fflush(stdout);
|
||||
uint32_t val = rb_get(tree, 0x141994); printf("0x141994 has attribute %hhu\n", val); fflush(stdout);
|
||||
delete_rbtree(tree);
|
||||
}
|
||||
#endif
|
||||
+10
-2
@@ -86,8 +86,9 @@ ENTRYBOOL(BOX86_DYNAREC_X87DOUBLE, box86_dynarec_x87double) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTNAN, box86_dynarec_fastnan) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTROUND, box86_dynarec_fastround) \
|
||||
ENTRYINT(BOX86_DYNAREC_SAFEFLAGS, box86_dynarec_safeflags, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_HOTPAGE, box86_dynarec_hotpage, 0, 255, 8) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTPAGE, box86_dynarec_fastpage) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_CALLRET, box86_dynarec_callret) \
|
||||
IGNORE(BOX86_DYNAREC_HOTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_FASTPAGE) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_WAIT, box86_dynarec_wait) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_BLEEDING_EDGE, box86_dynarec_bleeding_edge) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_JVM, box86_dynarec_jvm) \
|
||||
@@ -108,6 +109,7 @@ IGNORE(BOX86_DYNAREC_X87DOUBLE) \
|
||||
IGNORE(BOX86_DYNAREC_FASTNAN) \
|
||||
IGNORE(BOX86_DYNAREC_FASTROUND) \
|
||||
IGNORE(BOX86_DYNAREC_SAFEFLAGS) \
|
||||
IGNORE(BOX64_DYNAREC_CALLRET) \
|
||||
IGNORE(BOX86_DYNAREC_HOTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_FASTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_WAIT) \
|
||||
@@ -362,6 +364,7 @@ void LoadRCFile(const char* filename)
|
||||
if(current_name)
|
||||
addParam(current_name, ¤t_param);
|
||||
free(line);
|
||||
fclose(f);
|
||||
printf_log(LOG_INFO, "Params database has %d entries\n", kh_size(params));
|
||||
}
|
||||
|
||||
@@ -528,6 +531,11 @@ void ApplyParams(const char* name, path_collection_t* preload)
|
||||
}
|
||||
if(!olddynarec && box86_dynarec)
|
||||
GatherDynarecExtensions();
|
||||
if(param->is_box86_dynarec_test_present && box86_dynarec_test) {
|
||||
box86_dynarec_fastnan = 0;
|
||||
box86_dynarec_fastround = 0;
|
||||
box86_dynarec_callret = 0;
|
||||
}
|
||||
#endif
|
||||
if(box86_log==3) {
|
||||
box86_log = 2;
|
||||
|
||||
@@ -168,7 +168,10 @@
|
||||
#() vFGG
|
||||
#() cFpp
|
||||
#() iFEv
|
||||
#() iFEi
|
||||
#() iFEu
|
||||
#() iFEf
|
||||
#() iFEd
|
||||
#() iFEL
|
||||
#() iFEp
|
||||
#() iFwp
|
||||
@@ -203,6 +206,8 @@
|
||||
#() iFpG
|
||||
#() iFSi
|
||||
#() iFGG
|
||||
#() IFEf
|
||||
#() IFEd
|
||||
#() IFEp
|
||||
#() IFII
|
||||
#() IFpu
|
||||
@@ -236,6 +241,7 @@
|
||||
#() UFUp
|
||||
#() UFpp
|
||||
#() UFss
|
||||
#() fFEf
|
||||
#() fFEp
|
||||
#() fFif
|
||||
#() fFfi
|
||||
@@ -243,6 +249,7 @@
|
||||
#() fFfD
|
||||
#() fFfp
|
||||
#() fFpp
|
||||
#() dFEd
|
||||
#() dFid
|
||||
#() dFuu
|
||||
#() dFdi
|
||||
@@ -754,6 +761,7 @@
|
||||
#() vFpUUu
|
||||
#() vFpUUp
|
||||
#() vFpUpp
|
||||
#() vFpUPP
|
||||
#() vFpfff
|
||||
#() vFpdii
|
||||
#() vFpddi
|
||||
@@ -2390,7 +2398,6 @@
|
||||
#defined(NOALIGN) iFipV
|
||||
#defined(NOALIGN) iFiipV
|
||||
#defined(NOALIGN) iFppiiiip
|
||||
#!defined(NOALIGN) iFEi
|
||||
#!defined(NOALIGN) iFEO
|
||||
#!defined(NOALIGN) dFEp
|
||||
#!defined(NOALIGN) iFEpI
|
||||
@@ -2405,6 +2412,9 @@
|
||||
#defined(POWERPCLE) iFEiiiN
|
||||
#!defined(POWERPCLE) iFiiiN
|
||||
#defined(HAVE_LD80BITS) DFD
|
||||
#defined(HAVE_LD80BITS) iFED
|
||||
#defined(HAVE_LD80BITS) IFED
|
||||
#defined(HAVE_LD80BITS) DFED
|
||||
#defined(HAVE_LD80BITS) DFDD
|
||||
#defined(HAVE_LD80BITS) DFDp
|
||||
#defined(HAVE_LD80BITS) DFppi
|
||||
@@ -2412,6 +2422,8 @@
|
||||
#defined(HAVE_LD80BITS) DFppip
|
||||
#defined(HAVE_LD80BITS) iFDipppL
|
||||
#defined(HAVE_LD80BITS) vFppippDDC
|
||||
#!defined(HAVE_LD80BITS) iFK
|
||||
#!defined(HAVE_LD80BITS) IFK
|
||||
#!defined(HAVE_LD80BITS) KFK
|
||||
#!defined(HAVE_LD80BITS) KFKK
|
||||
#!defined(HAVE_LD80BITS) KFKp
|
||||
@@ -2542,6 +2554,7 @@ wrappedexpat:
|
||||
- vFpp:
|
||||
- XML_SetCharacterDataHandler
|
||||
- vFppp:
|
||||
- XML_SetDoctypeDeclHandler
|
||||
- XML_SetElementHandler
|
||||
wrappedfaudio:
|
||||
- vFpp:
|
||||
@@ -3211,6 +3224,9 @@ wrappedlibc:
|
||||
- iFppp:
|
||||
- _IO_vfscanf
|
||||
- iFppV:
|
||||
- __isoc23_fscanf
|
||||
- __isoc23_sscanf
|
||||
- __isoc23_sscanf
|
||||
- __isoc99_fscanf
|
||||
- __isoc99_sscanf
|
||||
- __isoc99_swscanf
|
||||
@@ -3220,12 +3236,18 @@ wrappedlibc:
|
||||
- iFpOu:
|
||||
- __libc_open
|
||||
- iFpOV:
|
||||
- IFppi:
|
||||
- __isoc23_strtoll
|
||||
- UFppi:
|
||||
- __isoc23_strtoull
|
||||
- KFppi:
|
||||
- __strtold_internal
|
||||
- KFppu:
|
||||
- strtold_l
|
||||
- lFipL:
|
||||
- __read_nocancel
|
||||
- lFppi:
|
||||
- __isoc23_strtol
|
||||
- pFpii:
|
||||
- pFpip:
|
||||
- vFiipV:
|
||||
@@ -3256,6 +3278,10 @@ wrappedlibc:
|
||||
- iFppiV:
|
||||
- iFpppp:
|
||||
- _IO_vfprintf
|
||||
- IFppip:
|
||||
- __isoc23_strtoll_l
|
||||
- UFppip:
|
||||
- __isoc23_strtoull_l
|
||||
- KFppip:
|
||||
- __strtold_l
|
||||
- lFipiI:
|
||||
@@ -3296,6 +3322,7 @@ wrappedlibdl:
|
||||
- pFv:
|
||||
- dlerror
|
||||
- iFpp:
|
||||
- _dl_find_object
|
||||
- dladdr
|
||||
- pFpi:
|
||||
- dlopen
|
||||
@@ -3421,6 +3448,26 @@ wrappedlibjpeg62:
|
||||
- vFpipu:
|
||||
- jpeg_write_marker
|
||||
wrappedlibm:
|
||||
- iFv:
|
||||
- fegetround
|
||||
- iFi:
|
||||
- fesetround
|
||||
- iFf:
|
||||
- lrintf
|
||||
- iFd:
|
||||
- lrint
|
||||
- iFD:
|
||||
- lrintl
|
||||
- iFK:
|
||||
- lrintl
|
||||
- IFf:
|
||||
- llrintf
|
||||
- IFd:
|
||||
- llrint
|
||||
- IFD:
|
||||
- llrintl
|
||||
- IFK:
|
||||
- llrintl
|
||||
- UFs:
|
||||
- cacosf
|
||||
- cacoshf
|
||||
@@ -3450,6 +3497,8 @@ wrappedlibm:
|
||||
- __logf_finite
|
||||
- __sinhf_finite
|
||||
- __sqrtf_finite
|
||||
- nearbyintf
|
||||
- rintf
|
||||
- dFd:
|
||||
- __acos_finite
|
||||
- __acosh_finite
|
||||
@@ -3462,8 +3511,12 @@ wrappedlibm:
|
||||
- __log_finite
|
||||
- __sinh_finite
|
||||
- __sqrt_finite
|
||||
- nearbyint
|
||||
- rint
|
||||
- DFD:
|
||||
- nearbyintl
|
||||
- pow10l
|
||||
- rintl
|
||||
- KFK:
|
||||
- acoshl
|
||||
- acosl
|
||||
@@ -3477,7 +3530,9 @@ wrappedlibm:
|
||||
- ldexpl
|
||||
- lgammal
|
||||
- logl
|
||||
- nearbyintl
|
||||
- pow10l
|
||||
- rintl
|
||||
- tgammal
|
||||
- fFff:
|
||||
- __atan2f_finite
|
||||
|
||||
@@ -16,6 +16,7 @@ typedef void (*vFppp_t)(void*, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(XML_SetCharacterDataHandler, vFpp_t) \
|
||||
GO(XML_SetDoctypeDeclHandler, vFppp_t) \
|
||||
GO(XML_SetElementHandler, vFppp_t)
|
||||
|
||||
#endif // __wrappedexpatTYPES_H_
|
||||
@@ -64,9 +64,12 @@ typedef int32_t (*iFppp_t)(void*, void*, void*);
|
||||
typedef int32_t (*iFppV_t)(void*, void*, ...);
|
||||
typedef int32_t (*iFpOu_t)(void*, int32_t, uint32_t);
|
||||
typedef int32_t (*iFpOV_t)(void*, int32_t, ...);
|
||||
typedef int64_t (*IFppi_t)(void*, void*, int32_t);
|
||||
typedef uint64_t (*UFppi_t)(void*, void*, int32_t);
|
||||
typedef double (*KFppi_t)(void*, void*, int32_t);
|
||||
typedef double (*KFppu_t)(void*, void*, uint32_t);
|
||||
typedef intptr_t (*lFipL_t)(int32_t, void*, uintptr_t);
|
||||
typedef intptr_t (*lFppi_t)(void*, void*, int32_t);
|
||||
typedef void* (*pFpii_t)(void*, int32_t, int32_t);
|
||||
typedef void* (*pFpip_t)(void*, int32_t, void*);
|
||||
typedef void (*vFiipV_t)(int32_t, int32_t, void*, ...);
|
||||
@@ -91,6 +94,8 @@ typedef int32_t (*iFpLpV_t)(void*, uintptr_t, void*, ...);
|
||||
typedef int32_t (*iFppii_t)(void*, void*, int32_t, int32_t);
|
||||
typedef int32_t (*iFppiV_t)(void*, void*, int32_t, ...);
|
||||
typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
|
||||
typedef int64_t (*IFppip_t)(void*, void*, int32_t, void*);
|
||||
typedef uint64_t (*UFppip_t)(void*, void*, int32_t, void*);
|
||||
typedef double (*KFppip_t)(void*, void*, int32_t, void*);
|
||||
typedef intptr_t (*lFipiI_t)(int32_t, void*, int32_t, int64_t);
|
||||
typedef intptr_t (*lFpupp_t)(void*, uint32_t, void*, void*);
|
||||
@@ -151,6 +156,9 @@ typedef int32_t (*iFpLiLppp_t)(void*, uintptr_t, int32_t, uintptr_t, void*, void
|
||||
GO(getopt, iFipp_t) \
|
||||
GO(dprintf, iFipV_t) \
|
||||
GO(_IO_vfscanf, iFppp_t) \
|
||||
GO(__isoc23_fscanf, iFppV_t) \
|
||||
GO(__isoc23_sscanf, iFppV_t) \
|
||||
GO(__isoc23_sscanf, iFppV_t) \
|
||||
GO(__isoc99_fscanf, iFppV_t) \
|
||||
GO(__isoc99_sscanf, iFppV_t) \
|
||||
GO(__isoc99_swscanf, iFppV_t) \
|
||||
@@ -158,15 +166,20 @@ typedef int32_t (*iFpLiLppp_t)(void*, uintptr_t, int32_t, uintptr_t, void*, void
|
||||
GO(sscanf, iFppV_t) \
|
||||
GO(swscanf, iFppV_t) \
|
||||
GO(__libc_open, iFpOu_t) \
|
||||
GO(__isoc23_strtoll, IFppi_t) \
|
||||
GO(__isoc23_strtoull, UFppi_t) \
|
||||
GO(__strtold_internal, KFppi_t) \
|
||||
GO(strtold_l, KFppu_t) \
|
||||
GO(__read_nocancel, lFipL_t) \
|
||||
GO(__isoc23_strtol, lFppi_t) \
|
||||
GO(__syslog_chk, vFiipV_t) \
|
||||
GO(__libc_init, vFpppp_t) \
|
||||
GO(ptrace, iFiupp_t) \
|
||||
GO(readlinkat, iFippL_t) \
|
||||
GO(__vfwprintf_chk, iFpvpp_t) \
|
||||
GO(_IO_vfprintf, iFpppp_t) \
|
||||
GO(__isoc23_strtoll_l, IFppip_t) \
|
||||
GO(__isoc23_strtoull_l, UFppip_t) \
|
||||
GO(__strtold_l, KFppip_t) \
|
||||
GO(prctl, iFiLLLL_t) \
|
||||
GO(getopt_long, iFipppp_t) \
|
||||
|
||||
@@ -24,6 +24,7 @@ typedef int32_t (*iFpppi_t)(void*, void*, void*, int32_t);
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(dlclose, iFp_t) \
|
||||
GO(dlerror, pFv_t) \
|
||||
GO(_dl_find_object, iFpp_t) \
|
||||
GO(dladdr, iFpp_t) \
|
||||
GO(dlopen, pFpi_t) \
|
||||
GO(dlsym, pFpp_t) \
|
||||
|
||||
@@ -11,6 +11,16 @@
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int32_t (*iFv_t)(void);
|
||||
typedef int32_t (*iFi_t)(int32_t);
|
||||
typedef int32_t (*iFf_t)(float);
|
||||
typedef int32_t (*iFd_t)(double);
|
||||
typedef int32_t (*iFD_t)(long double);
|
||||
typedef int32_t (*iFK_t)(double);
|
||||
typedef int64_t (*IFf_t)(float);
|
||||
typedef int64_t (*IFd_t)(double);
|
||||
typedef int64_t (*IFD_t)(long double);
|
||||
typedef int64_t (*IFK_t)(double);
|
||||
typedef uint64_t (*UFs_t)(void*);
|
||||
typedef float (*fFf_t)(float);
|
||||
typedef double (*dFd_t)(double);
|
||||
@@ -25,6 +35,16 @@ typedef uint64_t (*UFsvvs_t)(void*, void, void, void*);
|
||||
typedef void* (*pFpsvvvvs_t)(void*, void*, void, void, void, void, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(fegetround, iFv_t) \
|
||||
GO(fesetround, iFi_t) \
|
||||
GO(lrintf, iFf_t) \
|
||||
GO(lrint, iFd_t) \
|
||||
GO(lrintl, iFD_t) \
|
||||
GO(lrintl, iFK_t) \
|
||||
GO(llrintf, IFf_t) \
|
||||
GO(llrint, IFd_t) \
|
||||
GO(llrintl, IFD_t) \
|
||||
GO(llrintl, IFK_t) \
|
||||
GO(cacosf, UFs_t) \
|
||||
GO(cacoshf, UFs_t) \
|
||||
GO(casinf, UFs_t) \
|
||||
@@ -52,6 +72,8 @@ typedef void* (*pFpsvvvvs_t)(void*, void*, void, void, void, void, void*);
|
||||
GO(__logf_finite, fFf_t) \
|
||||
GO(__sinhf_finite, fFf_t) \
|
||||
GO(__sqrtf_finite, fFf_t) \
|
||||
GO(nearbyintf, fFf_t) \
|
||||
GO(rintf, fFf_t) \
|
||||
GO(__acos_finite, dFd_t) \
|
||||
GO(__acosh_finite, dFd_t) \
|
||||
GO(__asin_finite, dFd_t) \
|
||||
@@ -63,7 +85,11 @@ typedef void* (*pFpsvvvvs_t)(void*, void*, void, void, void, void, void*);
|
||||
GO(__log_finite, dFd_t) \
|
||||
GO(__sinh_finite, dFd_t) \
|
||||
GO(__sqrt_finite, dFd_t) \
|
||||
GO(nearbyint, dFd_t) \
|
||||
GO(rint, dFd_t) \
|
||||
GO(nearbyintl, DFD_t) \
|
||||
GO(pow10l, DFD_t) \
|
||||
GO(rintl, DFD_t) \
|
||||
GO(acoshl, KFK_t) \
|
||||
GO(acosl, KFK_t) \
|
||||
GO(asinhl, KFK_t) \
|
||||
@@ -76,7 +102,9 @@ typedef void* (*pFpsvvvvs_t)(void*, void*, void, void, void, void, void*);
|
||||
GO(ldexpl, KFK_t) \
|
||||
GO(lgammal, KFK_t) \
|
||||
GO(logl, KFK_t) \
|
||||
GO(nearbyintl, KFK_t) \
|
||||
GO(pow10l, KFK_t) \
|
||||
GO(rintl, KFK_t) \
|
||||
GO(tgammal, KFK_t) \
|
||||
GO(__atan2f_finite, fFff_t) \
|
||||
GO(__hypotf_finite, fFff_t) \
|
||||
|
||||
@@ -240,7 +240,10 @@ typedef void (*vFGp_t)(void*, void*);
|
||||
typedef void (*vFGG_t)(void*, void*);
|
||||
typedef int8_t (*cFpp_t)(void*, void*);
|
||||
typedef int32_t (*iFEv_t)(x86emu_t*);
|
||||
typedef int32_t (*iFEi_t)(x86emu_t*, int32_t);
|
||||
typedef int32_t (*iFEu_t)(x86emu_t*, uint32_t);
|
||||
typedef int32_t (*iFEf_t)(x86emu_t*, float);
|
||||
typedef int32_t (*iFEd_t)(x86emu_t*, double);
|
||||
typedef int32_t (*iFEL_t)(x86emu_t*, uintptr_t);
|
||||
typedef int32_t (*iFEp_t)(x86emu_t*, void*);
|
||||
typedef int32_t (*iFwp_t)(int16_t, void*);
|
||||
@@ -275,6 +278,8 @@ typedef int32_t (*iFpP_t)(void*, void*);
|
||||
typedef int32_t (*iFpG_t)(void*, void*);
|
||||
typedef int32_t (*iFSi_t)(void*, int32_t);
|
||||
typedef int32_t (*iFGG_t)(void*, void*);
|
||||
typedef int64_t (*IFEf_t)(x86emu_t*, float);
|
||||
typedef int64_t (*IFEd_t)(x86emu_t*, double);
|
||||
typedef int64_t (*IFEp_t)(x86emu_t*, void*);
|
||||
typedef int64_t (*IFII_t)(int64_t, int64_t);
|
||||
typedef int64_t (*IFpu_t)(void*, uint32_t);
|
||||
@@ -308,6 +313,7 @@ typedef uint64_t (*UFUU_t)(uint64_t, uint64_t);
|
||||
typedef uint64_t (*UFUp_t)(uint64_t, void*);
|
||||
typedef uint64_t (*UFpp_t)(void*, void*);
|
||||
typedef uint64_t (*UFss_t)(void*, void*);
|
||||
typedef float (*fFEf_t)(x86emu_t*, float);
|
||||
typedef float (*fFEp_t)(x86emu_t*, void*);
|
||||
typedef float (*fFif_t)(int32_t, float);
|
||||
typedef float (*fFfi_t)(float, int32_t);
|
||||
@@ -315,6 +321,7 @@ typedef float (*fFff_t)(float, float);
|
||||
typedef float (*fFfD_t)(float, long double);
|
||||
typedef float (*fFfp_t)(float, void*);
|
||||
typedef float (*fFpp_t)(void*, void*);
|
||||
typedef double (*dFEd_t)(x86emu_t*, double);
|
||||
typedef double (*dFid_t)(int32_t, double);
|
||||
typedef double (*dFuu_t)(uint32_t, uint32_t);
|
||||
typedef double (*dFdi_t)(double, int32_t);
|
||||
@@ -826,6 +833,7 @@ typedef void (*vFpUUi_t)(void*, uint64_t, uint64_t, int32_t);
|
||||
typedef void (*vFpUUu_t)(void*, uint64_t, uint64_t, uint32_t);
|
||||
typedef void (*vFpUUp_t)(void*, uint64_t, uint64_t, void*);
|
||||
typedef void (*vFpUpp_t)(void*, uint64_t, void*, void*);
|
||||
typedef void (*vFpUPP_t)(void*, uint64_t, void*, void*);
|
||||
typedef void (*vFpfff_t)(void*, float, float, float);
|
||||
typedef void (*vFpdii_t)(void*, double, int32_t, int32_t);
|
||||
typedef void (*vFpddi_t)(void*, double, double, int32_t);
|
||||
@@ -2467,7 +2475,6 @@ typedef int32_t (*iFppiiiip_t)(void*, void*, int32_t, int32_t, int32_t, int32_t,
|
||||
#endif
|
||||
|
||||
#if !defined(NOALIGN)
|
||||
typedef int32_t (*iFEi_t)(x86emu_t*, int32_t);
|
||||
typedef int32_t (*iFEO_t)(x86emu_t*, int32_t);
|
||||
typedef double (*dFEp_t)(x86emu_t*, void*);
|
||||
typedef int32_t (*iFEpI_t)(x86emu_t*, void*, int64_t);
|
||||
@@ -2491,6 +2498,9 @@ typedef int32_t (*iFiiiN_t)(int32_t, int32_t, int32_t, ...);
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
typedef long double (*DFD_t)(long double);
|
||||
typedef int32_t (*iFED_t)(x86emu_t*, long double);
|
||||
typedef int64_t (*IFED_t)(x86emu_t*, long double);
|
||||
typedef long double (*DFED_t)(x86emu_t*, long double);
|
||||
typedef long double (*DFDD_t)(long double, long double);
|
||||
typedef long double (*DFDp_t)(long double, void*);
|
||||
typedef long double (*DFppi_t)(void*, void*, int32_t);
|
||||
@@ -2501,6 +2511,8 @@ typedef void (*vFppippDDC_t)(void*, void*, int32_t, void*, void*, long double, l
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LD80BITS)
|
||||
typedef int32_t (*iFK_t)(double);
|
||||
typedef int64_t (*IFK_t)(double);
|
||||
typedef double (*KFK_t)(double);
|
||||
typedef double (*KFKK_t)(double, double);
|
||||
typedef double (*KFKp_t)(double, void*);
|
||||
@@ -2682,7 +2694,10 @@ void vFGp(x86emu_t *emu, uintptr_t fcn) { vFGp_t fn = (vFGp_t)fcn; my_GValue_t a
|
||||
void vFGG(x86emu_t *emu, uintptr_t fcn) { vFGG_t fn = (vFGG_t)fcn; my_GValue_t arg4; alignGValue(&arg4, *(void**)(R_ESP + 4)); my_GValue_t arg8; alignGValue(&arg8, *(void**)(R_ESP + 8)); fn(&arg4, &arg8); unalignGValue(*(void**)(R_ESP + 4), &arg4); unalignGValue(*(void**)(R_ESP + 8), &arg8); }
|
||||
void cFpp(x86emu_t *emu, uintptr_t fcn) { cFpp_t fn = (cFpp_t)fcn; R_EAX=fn(*(void**)(R_ESP + 4), *(void**)(R_ESP + 8)); }
|
||||
void iFEv(x86emu_t *emu, uintptr_t fcn) { iFEv_t fn = (iFEv_t)fcn; R_EAX=fn(emu); }
|
||||
void iFEi(x86emu_t *emu, uintptr_t fcn) { iFEi_t fn = (iFEi_t)fcn; R_EAX=fn(emu, *(int32_t*)(R_ESP + 4)); }
|
||||
void iFEu(x86emu_t *emu, uintptr_t fcn) { iFEu_t fn = (iFEu_t)fcn; R_EAX=fn(emu, *(uint32_t*)(R_ESP + 4)); }
|
||||
void iFEf(x86emu_t *emu, uintptr_t fcn) { iFEf_t fn = (iFEf_t)fcn; R_EAX=fn(emu, *(float*)(R_ESP + 4)); }
|
||||
void iFEd(x86emu_t *emu, uintptr_t fcn) { iFEd_t fn = (iFEd_t)fcn; R_EAX=fn(emu, *(double*)(R_ESP + 4)); }
|
||||
void iFEL(x86emu_t *emu, uintptr_t fcn) { iFEL_t fn = (iFEL_t)fcn; R_EAX=fn(emu, *(uintptr_t*)(R_ESP + 4)); }
|
||||
void iFEp(x86emu_t *emu, uintptr_t fcn) { iFEp_t fn = (iFEp_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4)); }
|
||||
void iFwp(x86emu_t *emu, uintptr_t fcn) { iFwp_t fn = (iFwp_t)fcn; R_EAX=fn(*(int16_t*)(R_ESP + 4), *(void**)(R_ESP + 8)); }
|
||||
@@ -2717,6 +2732,8 @@ void iFpP(x86emu_t *emu, uintptr_t fcn) { iFpP_t fn = (iFpP_t)fcn; void *arg8 =
|
||||
void iFpG(x86emu_t *emu, uintptr_t fcn) { iFpG_t fn = (iFpG_t)fcn; my_GValue_t arg8; alignGValue(&arg8, *(void**)(R_ESP + 8)); R_EAX=fn(*(void**)(R_ESP + 4), &arg8); unalignGValue(*(void**)(R_ESP + 8), &arg8); }
|
||||
void iFSi(x86emu_t *emu, uintptr_t fcn) { iFSi_t fn = (iFSi_t)fcn; R_EAX=fn(io_convert(*(void**)(R_ESP + 4)), *(int32_t*)(R_ESP + 8)); }
|
||||
void iFGG(x86emu_t *emu, uintptr_t fcn) { iFGG_t fn = (iFGG_t)fcn; my_GValue_t arg4; alignGValue(&arg4, *(void**)(R_ESP + 4)); my_GValue_t arg8; alignGValue(&arg8, *(void**)(R_ESP + 8)); R_EAX=fn(&arg4, &arg8); unalignGValue(*(void**)(R_ESP + 4), &arg4); unalignGValue(*(void**)(R_ESP + 8), &arg8); }
|
||||
void IFEf(x86emu_t *emu, uintptr_t fcn) { IFEf_t fn = (IFEf_t)fcn; ui64_t r; r.i=fn(emu, *(float*)(R_ESP + 4)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void IFEd(x86emu_t *emu, uintptr_t fcn) { IFEd_t fn = (IFEd_t)fcn; ui64_t r; r.i=fn(emu, *(double*)(R_ESP + 4)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void IFEp(x86emu_t *emu, uintptr_t fcn) { IFEp_t fn = (IFEp_t)fcn; ui64_t r; r.i=fn(emu, *(void**)(R_ESP + 4)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void IFII(x86emu_t *emu, uintptr_t fcn) { IFII_t fn = (IFII_t)fcn; ui64_t r; r.i=fn(*(int64_t*)(R_ESP + 4), *(int64_t*)(R_ESP + 12)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void IFpu(x86emu_t *emu, uintptr_t fcn) { IFpu_t fn = (IFpu_t)fcn; ui64_t r; r.i=fn(*(void**)(R_ESP + 4), *(uint32_t*)(R_ESP + 8)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
@@ -2750,6 +2767,7 @@ void UFUU(x86emu_t *emu, uintptr_t fcn) { UFUU_t fn = (UFUU_t)fcn; ui64_t r; r.u
|
||||
void UFUp(x86emu_t *emu, uintptr_t fcn) { UFUp_t fn = (UFUp_t)fcn; ui64_t r; r.u=(uint64_t)fn(*(uint64_t*)(R_ESP + 4), *(void**)(R_ESP + 12)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void UFpp(x86emu_t *emu, uintptr_t fcn) { UFpp_t fn = (UFpp_t)fcn; ui64_t r; r.u=(uint64_t)fn(*(void**)(R_ESP + 4), *(void**)(R_ESP + 8)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void UFss(x86emu_t *emu, uintptr_t fcn) { UFss_t fn = (UFss_t)fcn; ui64_t r; r.u=(uint64_t)fn((void*)(R_ESP + 4), (void*)(R_ESP + 4)); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void fFEf(x86emu_t *emu, uintptr_t fcn) { fFEf_t fn = (fFEf_t)fcn; float fl=fn(emu, *(float*)(R_ESP + 4)); fpu_do_push(emu); ST0val = fl; }
|
||||
void fFEp(x86emu_t *emu, uintptr_t fcn) { fFEp_t fn = (fFEp_t)fcn; float fl=fn(emu, *(void**)(R_ESP + 4)); fpu_do_push(emu); ST0val = fl; }
|
||||
void fFif(x86emu_t *emu, uintptr_t fcn) { fFif_t fn = (fFif_t)fcn; float fl=fn(*(int32_t*)(R_ESP + 4), *(float*)(R_ESP + 8)); fpu_do_push(emu); ST0val = fl; }
|
||||
void fFfi(x86emu_t *emu, uintptr_t fcn) { fFfi_t fn = (fFfi_t)fcn; float fl=fn(*(float*)(R_ESP + 4), *(int32_t*)(R_ESP + 8)); fpu_do_push(emu); ST0val = fl; }
|
||||
@@ -2757,6 +2775,7 @@ void fFff(x86emu_t *emu, uintptr_t fcn) { fFff_t fn = (fFff_t)fcn; float fl=fn(*
|
||||
void fFfD(x86emu_t *emu, uintptr_t fcn) { fFfD_t fn = (fFfD_t)fcn; float fl=fn(*(float*)(R_ESP + 4), LD2localLD((void*)(R_ESP + 8))); fpu_do_push(emu); ST0val = fl; }
|
||||
void fFfp(x86emu_t *emu, uintptr_t fcn) { fFfp_t fn = (fFfp_t)fcn; float fl=fn(*(float*)(R_ESP + 4), *(void**)(R_ESP + 8)); fpu_do_push(emu); ST0val = fl; }
|
||||
void fFpp(x86emu_t *emu, uintptr_t fcn) { fFpp_t fn = (fFpp_t)fcn; float fl=fn(*(void**)(R_ESP + 4), *(void**)(R_ESP + 8)); fpu_do_push(emu); ST0val = fl; }
|
||||
void dFEd(x86emu_t *emu, uintptr_t fcn) { dFEd_t fn = (dFEd_t)fcn; double db=fn(emu, *(double*)(R_ESP + 4)); fpu_do_push(emu); ST0val = db; }
|
||||
void dFid(x86emu_t *emu, uintptr_t fcn) { dFid_t fn = (dFid_t)fcn; double db=fn(*(int32_t*)(R_ESP + 4), *(double*)(R_ESP + 8)); fpu_do_push(emu); ST0val = db; }
|
||||
void dFuu(x86emu_t *emu, uintptr_t fcn) { dFuu_t fn = (dFuu_t)fcn; double db=fn(*(uint32_t*)(R_ESP + 4), *(uint32_t*)(R_ESP + 8)); fpu_do_push(emu); ST0val = db; }
|
||||
void dFdi(x86emu_t *emu, uintptr_t fcn) { dFdi_t fn = (dFdi_t)fcn; double db=fn(*(double*)(R_ESP + 4), *(int32_t*)(R_ESP + 12)); fpu_do_push(emu); ST0val = db; }
|
||||
@@ -3268,6 +3287,7 @@ void vFpUUi(x86emu_t *emu, uintptr_t fcn) { vFpUUi_t fn = (vFpUUi_t)fcn; fn(*(vo
|
||||
void vFpUUu(x86emu_t *emu, uintptr_t fcn) { vFpUUu_t fn = (vFpUUu_t)fcn; fn(*(void**)(R_ESP + 4), *(uint64_t*)(R_ESP + 8), *(uint64_t*)(R_ESP + 16), *(uint32_t*)(R_ESP + 24)); }
|
||||
void vFpUUp(x86emu_t *emu, uintptr_t fcn) { vFpUUp_t fn = (vFpUUp_t)fcn; fn(*(void**)(R_ESP + 4), *(uint64_t*)(R_ESP + 8), *(uint64_t*)(R_ESP + 16), *(void**)(R_ESP + 24)); }
|
||||
void vFpUpp(x86emu_t *emu, uintptr_t fcn) { vFpUpp_t fn = (vFpUpp_t)fcn; fn(*(void**)(R_ESP + 4), *(uint64_t*)(R_ESP + 8), *(void**)(R_ESP + 16), *(void**)(R_ESP + 20)); }
|
||||
void vFpUPP(x86emu_t *emu, uintptr_t fcn) { vFpUPP_t fn = (vFpUPP_t)fcn; void *arg16 = VulkanFromx86(*(void**)(R_ESP + 16)); void *arg20 = VulkanFromx86(*(void**)(R_ESP + 20)); fn(*(void**)(R_ESP + 4), *(uint64_t*)(R_ESP + 8), arg16, arg20); VulkanTox86(arg16); VulkanTox86(arg20); }
|
||||
void vFpfff(x86emu_t *emu, uintptr_t fcn) { vFpfff_t fn = (vFpfff_t)fcn; fn(*(void**)(R_ESP + 4), *(float*)(R_ESP + 8), *(float*)(R_ESP + 12), *(float*)(R_ESP + 16)); }
|
||||
void vFpdii(x86emu_t *emu, uintptr_t fcn) { vFpdii_t fn = (vFpdii_t)fcn; fn(*(void**)(R_ESP + 4), *(double*)(R_ESP + 8), *(int32_t*)(R_ESP + 16), *(int32_t*)(R_ESP + 20)); }
|
||||
void vFpddi(x86emu_t *emu, uintptr_t fcn) { vFpddi_t fn = (vFpddi_t)fcn; fn(*(void**)(R_ESP + 4), *(double*)(R_ESP + 8), *(double*)(R_ESP + 16), *(int32_t*)(R_ESP + 24)); }
|
||||
@@ -4909,7 +4929,6 @@ void iFppiiiip(x86emu_t *emu, uintptr_t fcn) { iFppiiiip_t fn = (iFppiiiip_t)fcn
|
||||
#endif
|
||||
|
||||
#if !defined(NOALIGN)
|
||||
void iFEi(x86emu_t *emu, uintptr_t fcn) { iFEi_t fn = (iFEi_t)fcn; R_EAX=fn(emu, *(int32_t*)(R_ESP + 4)); }
|
||||
void iFEO(x86emu_t *emu, uintptr_t fcn) { iFEO_t fn = (iFEO_t)fcn; R_EAX=fn(emu, of_convert(*(int32_t*)(R_ESP + 4))); }
|
||||
void dFEp(x86emu_t *emu, uintptr_t fcn) { dFEp_t fn = (dFEp_t)fcn; double db=fn(emu, *(void**)(R_ESP + 4)); fpu_do_push(emu); ST0val = db; }
|
||||
void iFEpI(x86emu_t *emu, uintptr_t fcn) { iFEpI_t fn = (iFEpI_t)fcn; R_EAX=fn(emu, *(void**)(R_ESP + 4), *(int64_t*)(R_ESP + 8)); }
|
||||
@@ -4933,6 +4952,9 @@ void iFiiiN(x86emu_t *emu, uintptr_t fcn) { iFiiiN_t fn = (iFiiiN_t)fcn; R_EAX=f
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
void DFD(x86emu_t *emu, uintptr_t fcn) { DFD_t fn = (DFD_t)fcn; long double ld=fn(LD2localLD((void*)(R_ESP + 4))); fpu_do_push(emu); ST0val = ld; }
|
||||
void iFED(x86emu_t *emu, uintptr_t fcn) { iFED_t fn = (iFED_t)fcn; R_EAX=fn(emu, LD2localLD((void*)(R_ESP + 4))); }
|
||||
void IFED(x86emu_t *emu, uintptr_t fcn) { IFED_t fn = (IFED_t)fcn; ui64_t r; r.i=fn(emu, LD2localLD((void*)(R_ESP + 4))); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void DFED(x86emu_t *emu, uintptr_t fcn) { DFED_t fn = (DFED_t)fcn; long double ld=fn(emu, LD2localLD((void*)(R_ESP + 4))); fpu_do_push(emu); ST0val = ld; }
|
||||
void DFDD(x86emu_t *emu, uintptr_t fcn) { DFDD_t fn = (DFDD_t)fcn; long double ld=fn(LD2localLD((void*)(R_ESP + 4)), LD2localLD((void*)(R_ESP + 16))); fpu_do_push(emu); ST0val = ld; }
|
||||
void DFDp(x86emu_t *emu, uintptr_t fcn) { DFDp_t fn = (DFDp_t)fcn; long double ld=fn(LD2localLD((void*)(R_ESP + 4)), *(void**)(R_ESP + 16)); fpu_do_push(emu); ST0val = ld; }
|
||||
void DFppi(x86emu_t *emu, uintptr_t fcn) { DFppi_t fn = (DFppi_t)fcn; long double ld=fn(*(void**)(R_ESP + 4), *(void**)(R_ESP + 8), *(int32_t*)(R_ESP + 12)); fpu_do_push(emu); ST0val = ld; }
|
||||
@@ -4943,6 +4965,8 @@ void vFppippDDC(x86emu_t *emu, uintptr_t fcn) { vFppippDDC_t fn = (vFppippDDC_t)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LD80BITS)
|
||||
void iFK(x86emu_t *emu, uintptr_t fcn) { iFK_t fn = (iFK_t)fcn; R_EAX=fn(FromLD((void*)(R_ESP + 4))); }
|
||||
void IFK(x86emu_t *emu, uintptr_t fcn) { IFK_t fn = (IFK_t)fcn; ui64_t r; r.i=fn(FromLD((void*)(R_ESP + 4))); R_EAX=r.d[0]; R_EDX=r.d[1]; }
|
||||
void KFK(x86emu_t *emu, uintptr_t fcn) { KFK_t fn = (KFK_t)fcn; double db=fn(FromLD((void*)(R_ESP + 4))); fpu_do_push(emu); ST0val = db; }
|
||||
void KFKK(x86emu_t *emu, uintptr_t fcn) { KFKK_t fn = (KFKK_t)fcn; double db=fn(FromLD((void*)(R_ESP + 4)), FromLD((void*)(R_ESP + 16))); fpu_do_push(emu); ST0val = db; }
|
||||
void KFKp(x86emu_t *emu, uintptr_t fcn) { KFKp_t fn = (KFKp_t)fcn; double db=fn(FromLD((void*)(R_ESP + 4)), *(void**)(R_ESP + 16)); fpu_do_push(emu); ST0val = db; }
|
||||
@@ -4980,6 +5004,7 @@ int isRetX87Wrapper(wrapper_t fun) {
|
||||
if (fun == &dFd) return 1;
|
||||
if (fun == &dFp) return 1;
|
||||
if (fun == &dFG) return 1;
|
||||
if (fun == &fFEf) return 1;
|
||||
if (fun == &fFEp) return 1;
|
||||
if (fun == &fFif) return 1;
|
||||
if (fun == &fFfi) return 1;
|
||||
@@ -4987,6 +5012,7 @@ int isRetX87Wrapper(wrapper_t fun) {
|
||||
if (fun == &fFfD) return 1;
|
||||
if (fun == &fFfp) return 1;
|
||||
if (fun == &fFpp) return 1;
|
||||
if (fun == &dFEd) return 1;
|
||||
if (fun == &dFid) return 1;
|
||||
if (fun == &dFuu) return 1;
|
||||
if (fun == &dFdi) return 1;
|
||||
@@ -5015,6 +5041,7 @@ int isRetX87Wrapper(wrapper_t fun) {
|
||||
#endif
|
||||
#if defined(HAVE_LD80BITS)
|
||||
if (fun == &DFD) return 1;
|
||||
if (fun == &DFED) return 1;
|
||||
if (fun == &DFDD) return 1;
|
||||
if (fun == &DFDp) return 1;
|
||||
if (fun == &DFppi) return 1;
|
||||
|
||||
@@ -200,7 +200,10 @@ void vFGp(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFGG(x86emu_t *emu, uintptr_t fnc);
|
||||
void cFpp(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEv(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEi(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEu(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEf(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEd(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEL(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEp(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFwp(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -235,6 +238,8 @@ void iFpP(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFpG(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFSi(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFGG(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFEf(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFEd(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFEp(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFII(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFpu(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -268,6 +273,7 @@ void UFUU(x86emu_t *emu, uintptr_t fnc);
|
||||
void UFUp(x86emu_t *emu, uintptr_t fnc);
|
||||
void UFpp(x86emu_t *emu, uintptr_t fnc);
|
||||
void UFss(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFEf(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFEp(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFif(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFfi(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -275,6 +281,7 @@ void fFff(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFfD(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFfp(x86emu_t *emu, uintptr_t fnc);
|
||||
void fFpp(x86emu_t *emu, uintptr_t fnc);
|
||||
void dFEd(x86emu_t *emu, uintptr_t fnc);
|
||||
void dFid(x86emu_t *emu, uintptr_t fnc);
|
||||
void dFuu(x86emu_t *emu, uintptr_t fnc);
|
||||
void dFdi(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -786,6 +793,7 @@ void vFpUUi(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpUUu(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpUUp(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpUpp(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpUPP(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpfff(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpdii(x86emu_t *emu, uintptr_t fnc);
|
||||
void vFpddi(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -2427,7 +2435,6 @@ void iFppiiiip(x86emu_t *emu, uintptr_t fnc);
|
||||
#endif
|
||||
|
||||
#if !defined(NOALIGN)
|
||||
void iFEi(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEO(x86emu_t *emu, uintptr_t fnc);
|
||||
void dFEp(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFEpI(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -2451,6 +2458,9 @@ void iFiiiN(x86emu_t *emu, uintptr_t fnc);
|
||||
|
||||
#if defined(HAVE_LD80BITS)
|
||||
void DFD(x86emu_t *emu, uintptr_t fnc);
|
||||
void iFED(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFED(x86emu_t *emu, uintptr_t fnc);
|
||||
void DFED(x86emu_t *emu, uintptr_t fnc);
|
||||
void DFDD(x86emu_t *emu, uintptr_t fnc);
|
||||
void DFDp(x86emu_t *emu, uintptr_t fnc);
|
||||
void DFppi(x86emu_t *emu, uintptr_t fnc);
|
||||
@@ -2461,6 +2471,8 @@ void vFppippDDC(x86emu_t *emu, uintptr_t fnc);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LD80BITS)
|
||||
void iFK(x86emu_t *emu, uintptr_t fnc);
|
||||
void IFK(x86emu_t *emu, uintptr_t fnc);
|
||||
void KFK(x86emu_t *emu, uintptr_t fnc);
|
||||
void KFKK(x86emu_t *emu, uintptr_t fnc);
|
||||
void KFKp(x86emu_t *emu, uintptr_t fnc);
|
||||
|
||||
@@ -98,6 +98,50 @@ static void* find_CharData_Fct(void* fct)
|
||||
printf_log(LOG_NONE, "Warning, no more slot for expat CharData callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// StartDoctypeDeclHandler
|
||||
#define GO(A) \
|
||||
static uintptr_t my_StartDoctypeDeclHandler_fct_##A = 0; \
|
||||
static void* my_StartDoctypeDeclHandler_##A(void* data, void* name, void* sysid, void* pubid, int has_internal_subset) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_StartDoctypeDeclHandler_fct_##A, "ppppi", data, name, sysid, pubid, has_internal_subset);\
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* find_StartDoctypeDeclHandler_Fct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_StartDoctypeDeclHandler_fct_##A == (uintptr_t)fct) return my_StartDoctypeDeclHandler_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_StartDoctypeDeclHandler_fct_##A == 0) {my_StartDoctypeDeclHandler_fct_##A = (uintptr_t)fct; return my_StartDoctypeDeclHandler_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for expat StartDoctypeDeclHandler callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// EndDoctypeDeclHandler
|
||||
#define GO(A) \
|
||||
static uintptr_t my_EndDoctypeDeclHandler_fct_##A = 0; \
|
||||
static void* my_EndDoctypeDeclHandler_##A(void* data) \
|
||||
{ \
|
||||
return (void*)RunFunctionFmt(my_EndDoctypeDeclHandler_fct_##A, "p", data);\
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* find_EndDoctypeDeclHandler_Fct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_EndDoctypeDeclHandler_fct_##A == (uintptr_t)fct) return my_EndDoctypeDeclHandler_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_EndDoctypeDeclHandler_fct_##A == 0) {my_EndDoctypeDeclHandler_fct_##A = (uintptr_t)fct; return my_EndDoctypeDeclHandler_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for expat EndDoctypeDeclHandler callback\n");
|
||||
return NULL;
|
||||
}
|
||||
#undef SUPER
|
||||
|
||||
EXPORT void my_XML_SetElementHandler(x86emu_t* emu, void* p, void* start, void* end)
|
||||
@@ -106,6 +150,12 @@ EXPORT void my_XML_SetElementHandler(x86emu_t* emu, void* p, void* start, void*
|
||||
my->XML_SetElementHandler(p, find_Start_Fct(start), find_End_Fct(end));
|
||||
}
|
||||
|
||||
EXPORT void my_XML_SetDoctypeDeclHandler(x86emu_t* emu, void* p, void* start, void* end)
|
||||
{
|
||||
(void)emu;
|
||||
my->XML_SetDoctypeDeclHandler(p, find_StartDoctypeDeclHandler_Fct(start), find_EndDoctypeDeclHandler_Fct(end));
|
||||
}
|
||||
|
||||
EXPORT void my_XML_SetCharacterDataHandler(x86emu_t* emu, void* p, void* h)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
@@ -39,7 +39,7 @@ GOM(XML_SetCharacterDataHandler, vFEpp)
|
||||
//GO(XML_SetCommentHandler,
|
||||
//GO(XML_SetDefaultHandler,
|
||||
//GO(XML_SetDefaultHandlerExpand,
|
||||
//GO(XML_SetDoctypeDeclHandler,
|
||||
GOM(XML_SetDoctypeDeclHandler, vFEppp)
|
||||
//GO(XML_SetElementDeclHandler,
|
||||
GOM(XML_SetElementHandler, vFEppp)
|
||||
//GO(XML_SetEncoding,
|
||||
|
||||
@@ -42,7 +42,7 @@ GO(FcConfigAppFontAddFile, iFpp)
|
||||
//GO(FcConfigAppFontClear,
|
||||
//GO(FcConfigBuildFonts,
|
||||
//GO(FcConfigCreate,
|
||||
//GO(FcConfigDestroy,
|
||||
GO(FcConfigDestroy, vFp)
|
||||
//GO(FcConfigEnableHome,
|
||||
//GO(FcConfigFilename,
|
||||
GO(FcConfigGetBlanks, pFp)
|
||||
@@ -98,7 +98,7 @@ GO(FcGetVersion, iFv)
|
||||
GO(FcInit, iFv)
|
||||
GO(FcInitBringUptoDate, iFv)
|
||||
//GO(FcInitLoadConfig,
|
||||
//GO(FcInitLoadConfigAndFonts,
|
||||
GO(FcInitLoadConfigAndFonts, pFv)
|
||||
GO(FcInitReinitialize, iFv)
|
||||
//GO(FcLangGetCharSet,
|
||||
GO(FcLangSetAdd, iFpp)
|
||||
|
||||
@@ -43,7 +43,7 @@ GO(FT_Get_Charmap_Index, iFp)
|
||||
//GO(FT_Get_CID_From_Glyph_Index,
|
||||
//GO(FT_Get_CID_Is_Internally_CID_Keyed,
|
||||
//GO(FT_Get_CID_Registry_Ordering_Supplement,
|
||||
//GO(FT_Get_CMap_Format,
|
||||
GO(FT_Get_CMap_Format, LFp)
|
||||
//GO(FT_Get_CMap_Language_ID,
|
||||
GO(FT_Get_First_Char, LFpp)
|
||||
//GO(FT_Get_Font_Format,
|
||||
@@ -200,3 +200,6 @@ GO(FTC_SBitCache_New, iFpp)
|
||||
|
||||
//GO(TT_New_Context,
|
||||
//GO(TT_RunIns,
|
||||
|
||||
GO(FT_Set_MM_WeightVector, iFpUp)
|
||||
GO(FT_Get_MM_WeightVector, iFppp)
|
||||
+260
-25
@@ -463,7 +463,7 @@ static void* findon_exitFct(void* fct)
|
||||
#undef SUPER
|
||||
|
||||
// some my_XXX declare and defines
|
||||
int32_t my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *),
|
||||
int32_t my___libc_start_main(x86emu_t* emu, int (*main) (int, char * *, char * *),
|
||||
int argc, char * * ubp_av, void (*init) (void), void (*fini) (void),
|
||||
void (*rtld_fini) (void), void (* stack_end)); // implemented in x86run_private.c
|
||||
EXPORT void my___libc_init_first(x86emu_t* emu, int argc, char* arg0, char** b)
|
||||
@@ -527,13 +527,11 @@ int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data);
|
||||
|
||||
pid_t EXPORT my_fork(x86emu_t* emu)
|
||||
{
|
||||
/* #if 1
|
||||
#if 1
|
||||
emu->quit = 1;
|
||||
emu->fork = 1;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif*/
|
||||
// execute atforks prepare functions, in reverse order
|
||||
for (int i=my_context->atfork_sz-1; i>=0; --i)
|
||||
if(my_context->atforks[i].prepare)
|
||||
@@ -559,6 +557,7 @@ pid_t EXPORT my_fork(x86emu_t* emu)
|
||||
RunFunctionWithEmu(emu, 0, my_context->atforks[i].child, 0);
|
||||
}
|
||||
return v;
|
||||
#endif
|
||||
}
|
||||
pid_t EXPORT my___fork(x86emu_t* emu) __attribute__((alias("my_fork")));
|
||||
pid_t EXPORT my_vfork(x86emu_t* emu)
|
||||
@@ -692,6 +691,17 @@ EXPORT void my___longjmp_chk(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/voi
|
||||
//EXPORT int32_t my__setjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
|
||||
//EXPORT int32_t my___sigsetjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp")));
|
||||
extern int box86_quit;
|
||||
extern int box86_exit_code;
|
||||
void endBox86();
|
||||
#if !defined(ANDROID)
|
||||
static void* timed_exit_thread(void* a)
|
||||
{
|
||||
// this is a workaround if unloading hang
|
||||
// waiting on a pthread_cond_destroy or something similar
|
||||
usleep(500000); // wait 1/2 a second
|
||||
_exit(box86_exit_code); // force exit, something is wrong
|
||||
}
|
||||
#endif
|
||||
EXPORT void my_exit(x86emu_t* emu, int code)
|
||||
{
|
||||
if(emu->flags.quitonexit) {
|
||||
@@ -701,7 +711,12 @@ EXPORT void my_exit(x86emu_t* emu, int code)
|
||||
return;
|
||||
}
|
||||
emu->quit = 1;
|
||||
box86_quit = 1;
|
||||
box86_exit_code = code;
|
||||
endBox86();
|
||||
#if !defined(ANDROID)
|
||||
pthread_t exit_thread;
|
||||
pthread_create(&exit_thread, NULL, timed_exit_thread, NULL);
|
||||
#endif
|
||||
exit(code);
|
||||
}
|
||||
|
||||
@@ -1646,6 +1661,19 @@ static int isProcSelf(const char *path, const char* w)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isSysCpuCache(const char *path, const char* w, int* _cpu, int* _index)
|
||||
{
|
||||
char tmp[128];
|
||||
int cpu, index;
|
||||
if(sscanf(path, "/sys/devices/system/cpu/cpu%d/cache/index%d/%s", &cpu, &index, tmp)!=3)
|
||||
return 0;
|
||||
if(strcmp(tmp, w))
|
||||
return 0;
|
||||
if(_cpu) * _cpu = cpu;
|
||||
if(_index) *_index = index;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT int32_t my_readlink(x86emu_t* emu, void* path, void* buf, uint32_t sz)
|
||||
{
|
||||
if(isProcSelf((const char*)path, "exe")) {
|
||||
@@ -1736,7 +1764,52 @@ static void CreateCPUTopologyCoreID(int fd, int cpu)
|
||||
size_t dummy = write(fd, buf, strlen(buf));
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
void CreateCPUPresentFile(int fd)
|
||||
{
|
||||
size_t dummy;
|
||||
char buff[600];
|
||||
int n = getNCpu();
|
||||
// generate fake CPUINFO
|
||||
sprintf(buff, "0-%d\n", n-1);
|
||||
dummy = write(fd, buff, strlen(buff));
|
||||
(void)dummy;
|
||||
}
|
||||
void CreateClocksourceFile(int fd)
|
||||
{
|
||||
size_t dummy;
|
||||
dummy = write(fd, "tsc\n", strlen("tsc\n"));
|
||||
(void)dummy;
|
||||
}
|
||||
void CreateCpuCacheAssoc(int fd, int cpu, int index)
|
||||
{
|
||||
size_t dummy;
|
||||
char tmp[64];
|
||||
sprintf(tmp, "%d\n", (index>=3)?16:8); // Random be coherent values...
|
||||
dummy = write(fd, tmp, strlen(tmp));
|
||||
(void)dummy;
|
||||
}
|
||||
void CreateCpuCacheCoher(int fd, int cpu, int index)
|
||||
{
|
||||
size_t dummy;
|
||||
char tmp[64];
|
||||
sprintf(tmp, "%d\n", 64); // Random be coherent values...
|
||||
dummy = write(fd, tmp, strlen(tmp));
|
||||
(void)dummy;
|
||||
}
|
||||
void CreateCpuCacheSize(int fd, int cpu, int index)
|
||||
{
|
||||
size_t dummy;
|
||||
char tmp[64];
|
||||
int cachesize = 12288;
|
||||
switch(index) {
|
||||
case 0: cachesize = 32; break;
|
||||
case 1: cachesize = 32; break;
|
||||
case 2: cachesize = 256; break;
|
||||
}
|
||||
sprintf(tmp, "%dK\n", cachesize); // Random be coherent values...
|
||||
dummy = write(fd, tmp, strlen(tmp));
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static int shm_open(const char *name, int oflag, mode_t mode) {
|
||||
@@ -1752,6 +1825,10 @@ static int shm_unlink(const char *name) {
|
||||
#endif
|
||||
#define TMP_MEMMAP "box86_tmpmemmap"
|
||||
#define TMP_CMDLINE "box86_tmpcmdline"
|
||||
#define TMP_CPUPRESENT "box86_cpupresent"
|
||||
#define TMP_CPUCACHE_ASSOC "box86_cpucacheassoc"
|
||||
#define TMP_CPUCACHE_COHER "box86_cpucachecoher"
|
||||
#define TMP_CPUCACHE_SIZE "box86_cpucachesize"
|
||||
EXPORT int32_t my_open(x86emu_t* emu, void* pathname, int32_t flags, uint32_t mode)
|
||||
{
|
||||
if(isProcSelf((const char*) pathname, "cmdline")) {
|
||||
@@ -1804,6 +1881,34 @@ EXPORT int32_t my_open(x86emu_t* emu, void* pathname, int32_t flags, uint32_t mo
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
int cpu, index;
|
||||
if(isSysCpuCache(pathname, "ways_of_associativity", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_ASSOC); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
if(isSysCpuCache(pathname, "coherency_line_size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_COHER); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheCoher(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
if(isSysCpuCache(pathname, "size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_SIZE); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
int ret = open(pathname, flags, mode);
|
||||
return ret;
|
||||
@@ -1893,6 +1998,34 @@ EXPORT int32_t my_open64(x86emu_t* emu, void* pathname, int32_t flags, uint32_t
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
int cpu, index;
|
||||
if(isSysCpuCache(pathname, "ways_of_associativity", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_ASSOC); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
if(isSysCpuCache(pathname, "coherency_line_size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_COHER); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheCoher(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
if(isSysCpuCache(pathname, "size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return open(pathname, flags, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_SIZE); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
return open64(pathname, flags, mode);
|
||||
}
|
||||
@@ -1929,6 +2062,43 @@ EXPORT FILE* my_fopen(x86emu_t* emu, const char* path, const char* mode)
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);;
|
||||
}
|
||||
if(box86_wine && (!strcmp(path, "/sys/devices/system/cpu/present") || !strcmp(path, "/sys/devices/system/cpu/online")) && (getNCpu()>=32)) {
|
||||
// special case for cpu present (to limit to 64 cores)
|
||||
int tmp = shm_open(TMP_CPUPRESENT, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUPRESENT); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCPUPresentFile(tmp);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
int cpu, index;
|
||||
if(isSysCpuCache(path, "ways_of_associativity", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_ASSOC); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
if(isSysCpuCache(path, "coherency_line_size", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_COHER); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheCoher(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
if(isSysCpuCache(path, "size", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_SIZE); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
#endif
|
||||
if(isProcSelf(path, "exe")) {
|
||||
return fopen(emu->context->fullpath, mode);
|
||||
@@ -1962,12 +2132,49 @@ EXPORT FILE* my_fopen64(x86emu_t* emu, const char* path, const char* mode)
|
||||
char buf[512];
|
||||
snprintf(buf, 512, TMP_CPUTOPO, n);
|
||||
int tmp = shm_open(buf, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen(path, mode); // error fallback
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(buf); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCPUTopologyCoreID(tmp, n);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);;
|
||||
}
|
||||
if(box86_wine && (!strcmp(path, "/sys/devices/system/cpu/present") || !strcmp(path, "/sys/devices/system/cpu/online")) && (getNCpu()>=32)) {
|
||||
// special case for cpu present (to limit to 64 cores)
|
||||
int tmp = shm_open(TMP_CPUPRESENT, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUPRESENT); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCPUPresentFile(tmp);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
int cpu, index;
|
||||
if(isSysCpuCache(path, "ways_of_associativity", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_ASSOC); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
if(isSysCpuCache(path, "coherency_line_size", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_COHER); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheCoher(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
if(isSysCpuCache(path, "size", &cpu, &index) && !FileExist(path, IS_FILE)) {
|
||||
// Create a dummy one
|
||||
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
|
||||
if(tmp<0) return fopen64(path, mode); // error fallback
|
||||
shm_unlink(TMP_CPUCACHE_SIZE); // remove the shm file, but it will still exist because it's currently in use
|
||||
CreateCpuCacheAssoc(tmp, cpu, index);
|
||||
lseek(tmp, 0, SEEK_SET);
|
||||
return fdopen(tmp, mode);
|
||||
}
|
||||
#endif
|
||||
if(isProcSelf(path, "exe")) {
|
||||
return fopen64(emu->context->fullpath, mode);
|
||||
@@ -2784,33 +2991,33 @@ EXPORT void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot,
|
||||
#endif
|
||||
void* ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
#ifndef NOALIGN
|
||||
if(!addr && ret!=new_addr && ret!=(void*)-1) {
|
||||
if(!addr && ret!=new_addr && ret!=MAP_FAILED) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
} else if(addr && ret!=(void*)-1 && ret!=new_addr &&
|
||||
} else if(addr && ret!=MAP_FAILED && ret!=new_addr &&
|
||||
((uintptr_t)ret&0xffff) && !(flags&MAP_FIXED) && box86_wine) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
if(ret!=MAP_FAILED && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
// addr is probably too high, start again with a low address
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(NULL, length, 0); // is this the best way?
|
||||
ret = mmap(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && (uintptr_t)ret&0xffff) {
|
||||
if(ret!=MAP_FAILED && (uintptr_t)ret&0xffff) {
|
||||
munmap(ret, length);
|
||||
ret = (void*)-1;
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(box86_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && ret!=(void*)-1) {
|
||||
if(box86_dynarec && ret!=MAP_FAILED) {
|
||||
/*if(flags&0x100000 && addr!=ret)
|
||||
{
|
||||
// program used MAP_FIXED_NOREPLACE but the host linux didn't support it
|
||||
@@ -2823,8 +3030,19 @@ EXPORT void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ret!=(void*)-1 && emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
if(ret!=MAP_FAILED) {
|
||||
if((flags&MAP_SHARED) && (fd>0)) {
|
||||
uint32_t flags = fcntl(fd, F_GETFL);
|
||||
if((flags&O_ACCMODE)==O_RDWR) {
|
||||
if((box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "Note: Marking the region (%p-%p prot=%x) as NEVERCLEAN because fd have O_RDWR attribute\n", ret, ret+length, prot);}
|
||||
prot |= PROT_NEVERCLEAN;
|
||||
}
|
||||
}
|
||||
if(emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
else
|
||||
setProtection((uintptr_t)ret, length, prot);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2841,34 +3059,34 @@ EXPORT void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot
|
||||
#endif
|
||||
void* ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
#ifndef NOALIGN
|
||||
if(!addr && ret!=new_addr && ret!=(void*)-1) {
|
||||
if(!addr && ret!=new_addr && ret!=MAP_FAILED) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = (flags&MAP_FIXED)?addr:(addr?findBlockNearHint(addr, length, 0):find32bitBlock(length));
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
} else if(addr && ret!=(void*)-1 && ret!=new_addr &&
|
||||
} else if(addr && ret!=MAP_FAILED && ret!=new_addr &&
|
||||
((uintptr_t)ret&0xffff) && !(flags&MAP_FIXED) && box86_wine) {
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(addr, length, 0);
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
if(ret!=MAP_FAILED && ret!=addr && ((uintptr_t)ret&0xffff) && box86_wine) {
|
||||
// addr is probably too high, start again with a low address
|
||||
munmap(ret, length);
|
||||
loadProtectionFromMap(); // reload map, because something went wrong previously
|
||||
new_addr = findBlockNearHint(NULL, length, 0); // is this the best way?
|
||||
ret = mmap64(new_addr, length, prot, flags, fd, offset);
|
||||
if(ret!=(void*)-1 && (uintptr_t)ret&0xffff) {
|
||||
if(ret!=MAP_FAILED && (uintptr_t)ret&0xffff) {
|
||||
munmap(ret, length);
|
||||
errno = EEXIST;
|
||||
ret = (void*)-1;
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(box86_log<LOG_DEBUG) {dynarec_log(LOG_DEBUG, "%p\n", ret);}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && ret!=(void*)-1) {
|
||||
if(box86_dynarec && ret!=MAP_FAILED) {
|
||||
/*if(flags&0x100000 && addr!=ret)
|
||||
{
|
||||
// program used MAP_FIXED_NOREPLACE but the host linux didn't support it
|
||||
@@ -2881,8 +3099,19 @@ EXPORT void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ret!=(void*)-1 && emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
if(ret!=MAP_FAILED) {
|
||||
if((flags&MAP_SHARED) && (fd>0)) {
|
||||
uint32_t flags = fcntl(fd, F_GETFL);
|
||||
if((flags&O_ACCMODE)==O_RDWR) {
|
||||
if((box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "Note: Marking the region (%p-%p prot=%x) as NEVERCLEAN because fd have O_RDWR attribute\n", ret, ret+length, prot);}
|
||||
prot |= PROT_NEVERCLEAN;
|
||||
}
|
||||
}
|
||||
if(emu)
|
||||
setProtection_mmap((uintptr_t)ret, length, prot);
|
||||
else
|
||||
setProtection((uintptr_t)ret, length, prot);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2892,7 +3121,7 @@ EXPORT void* my_mremap(x86emu_t* emu, void* old_addr, size_t old_size, size_t ne
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_NONE, "mremap(%p, 0x%x, 0x%x, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);
|
||||
void* ret = mremap(old_addr, old_size, new_size, flags, new_addr);
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_NONE, "%p\n", ret);
|
||||
if(ret==(void*)-1)
|
||||
if(ret==MAP_FAILED)
|
||||
return ret; // failed...
|
||||
uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM;
|
||||
if(ret==old_addr) {
|
||||
@@ -3285,6 +3514,11 @@ EXPORT int my_prctl(x86emu_t* emu, int option, unsigned long arg2, unsigned long
|
||||
if(option==PR_SET_NAME) {
|
||||
printf_log(LOG_DEBUG, "BOX86: set process name to \"%s\"\n", (char*)arg2);
|
||||
ApplyParams((char*)arg2, NULL);
|
||||
size_t l = strlen((char*)arg2);
|
||||
if(l>4 && !strcasecmp((char*)arg2+l-4, ".exe")) {
|
||||
printf_log(LOG_DEBUG, "BOX86: hacking orig command line to \"%s\"\n", (char*)arg2);
|
||||
strcpy(my_context->orig_argv[0], (char*)arg2);
|
||||
}
|
||||
}
|
||||
return prctl(option, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
@@ -3370,6 +3604,7 @@ EXPORT char my___libc_single_threaded = 0;
|
||||
setNeededLibs(lib, NEEDED_LIBS);
|
||||
|
||||
#define CUSTOM_FINI \
|
||||
freeMy();
|
||||
freeMy(); \
|
||||
return; // do not unload...
|
||||
|
||||
#include "wrappedlib_init.h"
|
||||
@@ -409,6 +409,7 @@ GO(freopen64, pFppp)
|
||||
// frexpf // Weak
|
||||
// frexpl // Weak
|
||||
GO2(fscanf, iFppV, vfscanf)
|
||||
GO2(__isoc23_fscanf, iFppV, vfscanf)
|
||||
GO(fseek, iFpli)
|
||||
GO(fseeko, iFpli)
|
||||
GO(fseeko64, iFpIi)
|
||||
@@ -910,6 +911,7 @@ GOM(__isoc99_vsscanf, iFEppp) //%% TODO: check if ok
|
||||
// __isoc99_vswscanf
|
||||
// __isoc99_vwscanf
|
||||
// __isoc99_wscanf
|
||||
GO2(__isoc23_sscanf, iFEppV, my___isoc99_sscanf)
|
||||
#else
|
||||
GO2(__isoc99_fscanf, iFppV, __isoc99_vfscanf)
|
||||
// __isoc99_fwscanf
|
||||
@@ -923,6 +925,7 @@ GO(__isoc99_vsscanf, iFppp)
|
||||
// __isoc99_vswscanf
|
||||
// __isoc99_vwscanf
|
||||
// __isoc99_wscanf
|
||||
GO2(__isoc23_sscanf, iFppV, __isoc99_sscanf)
|
||||
#endif
|
||||
GO(isprint, iFi)
|
||||
// __isprint_l
|
||||
@@ -1735,6 +1738,7 @@ GO(__strtok_r, pFppp)
|
||||
GOW(strtok_r, pFppp)
|
||||
// __strtok_r_1c
|
||||
GO(strtol, lFppi)
|
||||
GO2(__isoc23_strtol, lFppi, strtol)
|
||||
#ifdef HAVE_LD80BITS
|
||||
GO(strtold, DFpp)
|
||||
GO(__strtold_internal, DFppi)
|
||||
@@ -1748,19 +1752,23 @@ GOW2(strtold_l, KFppu, strtod_l)
|
||||
#endif
|
||||
GO(__strtol_internal, lFppi)
|
||||
GO(strtoll, IFppi)
|
||||
GO2(__isoc23_strtoll, IFppi, strtoll)
|
||||
GO(__strtol_l, lFppiip)
|
||||
GOW(strtol_l, lFppiip)
|
||||
GO(__strtoll_internal, IFppii)
|
||||
GO(__strtoll_l, IFppip)
|
||||
GOW(strtoll_l, IFppip)
|
||||
GO2(__isoc23_strtoll_l, IFppip, strtoll_l)
|
||||
GOW(strtoq, IFppi) // is that ok?
|
||||
GO(strtoul, LFppi)
|
||||
GO(__strtoul_internal, LFppii)
|
||||
GO(strtoull, UFppi)
|
||||
GO2(__isoc23_strtoull, UFppi, strtoull)
|
||||
GO(__strtoul_l, uFppip)
|
||||
GOW(strtoul_l, LFppip)
|
||||
GO(__strtoull_internal, UFppii)
|
||||
GO(__strtoull_l, UFppip)
|
||||
GO2(__isoc23_strtoull_l, UFppip, strtoull_l)
|
||||
GOW(strtoull_l, UFppip)
|
||||
GO(strtoumax, UFppi)
|
||||
GOW(strtouq, UFppi) // ok?
|
||||
|
||||
@@ -177,8 +177,16 @@ void* my_dlopen(x86emu_t* emu, void *filename, int flag)
|
||||
return NULL;
|
||||
}
|
||||
dlopened = (lib==NULL);
|
||||
// Then open the lib
|
||||
// cleanup the old deferredInit state
|
||||
int old_deferredInit = my_context->deferredInit;
|
||||
my_context->deferredInit = 1;
|
||||
elfheader_t** old_deferredInitList = my_context->deferredInitList;
|
||||
my_context->deferredInitList = NULL;
|
||||
int old_deferredInitSz = my_context->deferredInitSz;
|
||||
int old_deferredInitCap = my_context->deferredInitCap;
|
||||
my_context->deferredInitSz = my_context->deferredInitCap = 0;
|
||||
|
||||
// Then open the lib
|
||||
int bindnow = (!box86_musl && (flag&0x2))?1:0;
|
||||
needed_libs_t *tmp = new_neededlib(1);
|
||||
tmp->names[0] = rfilename;
|
||||
@@ -188,11 +196,21 @@ void* my_dlopen(x86emu_t* emu, void *filename, int flag)
|
||||
dl->last_error = box_malloc(129);
|
||||
snprintf(dl->last_error, 129, "Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag);
|
||||
RemoveNeededLib(NULL, is_local, tmp, my_context, emu);
|
||||
if(my_context->deferredInitList)
|
||||
box_free(my_context->deferredInitList);
|
||||
my_context->deferredInit = old_deferredInit;
|
||||
my_context->deferredInitList = old_deferredInitList;
|
||||
my_context->deferredInitSz = old_deferredInitSz;
|
||||
my_context->deferredInitCap = old_deferredInitCap;
|
||||
return NULL;
|
||||
}
|
||||
free_neededlib(tmp);
|
||||
lib = GetLibInternal(rfilename);
|
||||
RunDeferredElfInit(emu);
|
||||
my_context->deferredInit = old_deferredInit;
|
||||
my_context->deferredInitList = old_deferredInitList;
|
||||
my_context->deferredInitSz = old_deferredInitSz;
|
||||
my_context->deferredInitCap = old_deferredInitCap;
|
||||
} else {
|
||||
// check if already dlopenned...
|
||||
for (size_t i=MIN_NLIB; i<dl->lib_sz; ++i) {
|
||||
@@ -591,6 +609,21 @@ EXPORT int my__dl_find_object(x86emu_t* emu, void* addr, my_dl_find_object_t* re
|
||||
if(!box86_isglibc234) setNeededLibs(lib, 1, "libc.so.6");
|
||||
#endif
|
||||
|
||||
void closeAllDLOpenned()
|
||||
{
|
||||
dlprivate_t *dl = my_context->dlprivate;
|
||||
if(dl) {
|
||||
x86emu_t* emu = thread_get_emu();
|
||||
for(size_t i=0; i<dl->lib_sz; ++i)
|
||||
while(dl->dllibs[i].count) {
|
||||
printf_log(LOG_DEBUG, " closing %s\n", dl->dllibs[i].lib->name);
|
||||
my_dlclose(emu, (void*)(i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CUSTOM_FINI \
|
||||
closeAllDLOpenned();
|
||||
|
||||
// define all standard library functions
|
||||
#include "wrappedlib_init.h"
|
||||
@@ -12,3 +12,4 @@ GOM(dlmopen, pFEppi)
|
||||
GOM(dlopen, pFEpi)
|
||||
GOM(dlsym, pFEpp)
|
||||
GOM(dlvsym, pFEppp) // Weak
|
||||
GOM(_dl_find_object, iFEpp)
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "bridge.h"
|
||||
#include "librarian/library_private.h"
|
||||
#include "x86emu.h"
|
||||
#include "emu/x86emu_private.h"
|
||||
#include "emu/x87emu_setround.h"
|
||||
#include "debug.h"
|
||||
|
||||
const char* libmName =
|
||||
@@ -25,6 +27,18 @@ const char* libmName =
|
||||
|
||||
static library_t* my_lib = NULL;
|
||||
|
||||
EXPORT int my_fesetround (x86emu_t* emu, int __rounding_direction) {
|
||||
if ((~0xc00 & (unsigned int)__rounding_direction) != 0) // invalid rounding
|
||||
return 1;
|
||||
emu->cw.f.C87_RD = __rounding_direction >> 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT int my_fegetround (x86emu_t* emu) {
|
||||
return emu->cw.f.C87_RD << 10;
|
||||
}
|
||||
|
||||
|
||||
typedef float (*fFff_t) (float, float);
|
||||
typedef double (*dFdd_t) (double, double);
|
||||
typedef float (*fFf_t) (float);
|
||||
@@ -35,6 +49,11 @@ typedef union my_float_complex_s {
|
||||
uint64_t u64;
|
||||
} my_float_complex_t;
|
||||
|
||||
#define set_round() \
|
||||
int oldround = fpu_setround(emu)
|
||||
#define restore_round() \
|
||||
fesetround(oldround)
|
||||
|
||||
// complex <- FUNC(complex) wrapper
|
||||
#define GO_cFc(N) \
|
||||
EXPORT void* my_##N(void* p, void* c) \
|
||||
@@ -145,6 +164,50 @@ F1D(log)
|
||||
#undef F1F
|
||||
#undef FINITE
|
||||
|
||||
#define WITH_ROUND(N, R, P, ...) \
|
||||
EXPORT R my_##N P \
|
||||
{ \
|
||||
set_round(); \
|
||||
R ret = N(__VA_ARGS__); \
|
||||
restore_round(); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#ifdef HAVE_LD80BITS
|
||||
#define RFr(N, r) \
|
||||
WITH_ROUND(N ## f, r, (x86emu_t* emu, float a), a) \
|
||||
WITH_ROUND(N, r, (x86emu_t* emu, double a), a) \
|
||||
WITH_ROUND(N ## l, r, (x86emu_t* emu, long double a), a)
|
||||
#define RrFr(N) \
|
||||
WITH_ROUND(N ## f, float, (x86emu_t* emu, float a), a) \
|
||||
WITH_ROUND(N, double, (x86emu_t* emu, double a), a) \
|
||||
WITH_ROUND(N ## l, double, (x86emu_t* emu, long double a), a)
|
||||
#define RrFrr(N) \
|
||||
WITH_ROUND(N ## f, float, (x86emu_t* emu, float a, float b), a, b) \
|
||||
WITH_ROUND(N, double, (x86emu_t* emu, double a, double b), a, b) \
|
||||
WITH_ROUND(N ## l, double, (x86emu_t* emu, long double a, long double b), a, b)
|
||||
#else
|
||||
#define RFr(N, r) \
|
||||
WITH_ROUND(N ## f, r, (x86emu_t* emu, float a), a) \
|
||||
WITH_ROUND(N, r, (x86emu_t* emu, double a), a)
|
||||
#define RrFr(N) \
|
||||
WITH_ROUND(N ## f, float, (x86emu_t* emu, float a), a) \
|
||||
WITH_ROUND(N, double, (x86emu_t* emu, double a), a)
|
||||
#define RrFrr(N) \
|
||||
WITH_ROUND(N ## f, float, (x86emu_t* emu, float a, float b), a, b) \
|
||||
WITH_ROUND(N, double, (x86emu_t* emu, double a, double b), a, b)
|
||||
#endif
|
||||
|
||||
RrFr(nearbyint)
|
||||
RrFr(rint)
|
||||
RFr(llrint, long long)
|
||||
RFr(lrint, int)
|
||||
|
||||
#undef RFr
|
||||
#undef RrFr
|
||||
#undef RrFrr
|
||||
#undef WITH_ROUND
|
||||
|
||||
#define PRE_INIT\
|
||||
if(1) \
|
||||
lib->w.lib = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); \
|
||||
|
||||
@@ -196,12 +196,12 @@ GO(feenableexcept, iFi)
|
||||
GO(fegetenv, iFp)
|
||||
GO(fegetexcept, iFv)
|
||||
GO(fegetexceptflag, iFpi)
|
||||
GO(fegetround, iFv)
|
||||
GOM(fegetround, iFEv)
|
||||
GO(feholdexcept, iFp)
|
||||
GO(feraiseexcept, iFi)
|
||||
GO(fesetenv, iFp)
|
||||
GO(fesetexceptflag, iFpi)
|
||||
GO(fesetround, iFi)
|
||||
GOM(fesetround, iFEi)
|
||||
GO(fetestexcept, iFi)
|
||||
GO(feupdateenv, iFp)
|
||||
GOW(finite, iFd)
|
||||
@@ -301,9 +301,13 @@ GOW2(lgammal_r, KFKp, lgamma_r)
|
||||
GOW(lgamma_r, dFdp)
|
||||
// __lgamma_r_finite
|
||||
DATAV(_LIB_VERSION, 4)
|
||||
GOW(llrint, IFd)
|
||||
GOW(llrintf, IFf)
|
||||
// llrintl // Weak
|
||||
GOM(llrint, IFEd)
|
||||
GOM(llrintf, IFEf)
|
||||
#ifdef HAVE_LD80BITS
|
||||
GOM(llrintl, IFED)
|
||||
#else
|
||||
GO2(llrintl, IFK, llrint)
|
||||
#endif
|
||||
GOW(llround, IFd)
|
||||
GOW(llroundf, IFf)
|
||||
// llroundl // Weak
|
||||
@@ -332,9 +336,13 @@ GOW(logl, DFD)
|
||||
#else
|
||||
GOW2(logl, KFK, log)
|
||||
#endif
|
||||
GOW(lrint, iFd)
|
||||
GOW(lrintf, iFf)
|
||||
// lrintl // Weak
|
||||
GOM(lrint, iFEd)
|
||||
GOM(lrintf, iFEf)
|
||||
#ifdef HAVE_LD80BITS
|
||||
GOM(lrintl, iFED)
|
||||
#else
|
||||
GO2(lrintl, iFK, lrint)
|
||||
#endif
|
||||
GOW(lround, iFd)
|
||||
GOW(lroundf, iFf)
|
||||
// lroundl // Weak
|
||||
@@ -345,9 +353,13 @@ GOW(modff, fFfp)
|
||||
// nan // Weak
|
||||
// nanf // Weak
|
||||
// nanl // Weak
|
||||
GOW(nearbyint, dFd)
|
||||
GOW(nearbyintf, fFf)
|
||||
// nearbyintl // Weak
|
||||
GOM(nearbyint, dFEd)
|
||||
GOM(nearbyintf, fFEf)
|
||||
#ifdef HAVE_LD80BITS
|
||||
GOM(nearbyintl, DFED)
|
||||
#else
|
||||
GO2(nearbyintl, KFK, nearbyint)
|
||||
#endif
|
||||
GOW(nextafter, dFdd)
|
||||
GOW(nextafterf, fFff)
|
||||
// nextafterl // Weak
|
||||
@@ -378,9 +390,13 @@ GOW(remainderf, fFff)
|
||||
GOW(remquo, dFddp)
|
||||
GOW(remquof, fFffp)
|
||||
// remquol // Weak
|
||||
GOW(rint, dFd)
|
||||
GOW(rintf, fFf)
|
||||
// rintl // Weak
|
||||
GOM(rint, dFEd)
|
||||
GOM(rintf, fFEf)
|
||||
#ifdef HAVE_LD80BITS
|
||||
GOM(rintl, DFED)
|
||||
#else
|
||||
GO2(rintl, KFK, rint)
|
||||
#endif
|
||||
GOW(round, dFd)
|
||||
GOW(roundf, fFf)
|
||||
// roundl // Weak
|
||||
|
||||
+295
-38
@@ -495,6 +495,293 @@ typedef struct {
|
||||
#define XNR6PreeditCallback "r6PreeditCallback"
|
||||
#define XNStringConversionCallback "stringConversionCallback"
|
||||
|
||||
// utility functions
|
||||
#define SUPER() \
|
||||
GO(0) \
|
||||
GO(1) \
|
||||
GO(2) \
|
||||
GO(3) \
|
||||
GO(4)
|
||||
|
||||
// XNGeometryCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNGeometryCallback_fct_##A = 0; \
|
||||
static void my_XNGeometryCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNGeometryCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNGeometryCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNGeometryCallback_fct_##A == (uintptr_t)fct) return my_XNGeometryCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNGeometryCallback_fct_##A == 0) {my_XNGeometryCallback_fct_##A = (uintptr_t)fct; return my_XNGeometryCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNGeometryCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNDestroyCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNDestroyCallback_fct_##A = 0; \
|
||||
static void my_XNDestroyCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNDestroyCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNDestroyCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNDestroyCallback_fct_##A == (uintptr_t)fct) return my_XNDestroyCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNDestroyCallback_fct_##A == 0) {my_XNDestroyCallback_fct_##A = (uintptr_t)fct; return my_XNDestroyCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNDestroyCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNPreeditStartCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNPreeditStartCallback_fct_##A = 0; \
|
||||
static void my_XNPreeditStartCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNPreeditStartCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNPreeditStartCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNPreeditStartCallback_fct_##A == (uintptr_t)fct) return my_XNPreeditStartCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNPreeditStartCallback_fct_##A == 0) {my_XNPreeditStartCallback_fct_##A = (uintptr_t)fct; return my_XNPreeditStartCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNPreeditStartCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNPreeditDoneCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNPreeditDoneCallback_fct_##A = 0; \
|
||||
static void my_XNPreeditDoneCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNPreeditDoneCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNPreeditDoneCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNPreeditDoneCallback_fct_##A == (uintptr_t)fct) return my_XNPreeditDoneCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNPreeditDoneCallback_fct_##A == 0) {my_XNPreeditDoneCallback_fct_##A = (uintptr_t)fct; return my_XNPreeditDoneCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNPreeditDoneCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNPreeditDrawCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNPreeditDrawCallback_fct_##A = 0; \
|
||||
static void my_XNPreeditDrawCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNPreeditDrawCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNPreeditDrawCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNPreeditDrawCallback_fct_##A == (uintptr_t)fct) return my_XNPreeditDrawCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNPreeditDrawCallback_fct_##A == 0) {my_XNPreeditDrawCallback_fct_##A = (uintptr_t)fct; return my_XNPreeditDrawCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNPreeditDrawCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNPreeditCaretCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNPreeditCaretCallback_fct_##A = 0; \
|
||||
static void my_XNPreeditCaretCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNPreeditCaretCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNPreeditCaretCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNPreeditCaretCallback_fct_##A == (uintptr_t)fct) return my_XNPreeditCaretCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNPreeditCaretCallback_fct_##A == 0) {my_XNPreeditCaretCallback_fct_##A = (uintptr_t)fct; return my_XNPreeditCaretCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNPreeditCaretCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNPreeditStateNotifyCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNPreeditStateNotifyCallback_fct_##A = 0; \
|
||||
static void my_XNPreeditStateNotifyCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNPreeditStateNotifyCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNPreeditStateNotifyCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNPreeditStateNotifyCallback_fct_##A == (uintptr_t)fct) return my_XNPreeditStateNotifyCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNPreeditStateNotifyCallback_fct_##A == 0) {my_XNPreeditStateNotifyCallback_fct_##A = (uintptr_t)fct; return my_XNPreeditStateNotifyCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNPreeditStateNotifyCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNStatusStartCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNStatusStartCallback_fct_##A = 0; \
|
||||
static void my_XNStatusStartCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNStatusStartCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNStatusStartCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNStatusStartCallback_fct_##A == (uintptr_t)fct) return my_XNStatusStartCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNStatusStartCallback_fct_##A == 0) {my_XNStatusStartCallback_fct_##A = (uintptr_t)fct; return my_XNStatusStartCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNStatusStartCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNStatusDoneCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNStatusDoneCallback_fct_##A = 0; \
|
||||
static void my_XNStatusDoneCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNStatusDoneCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNStatusDoneCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNStatusDoneCallback_fct_##A == (uintptr_t)fct) return my_XNStatusDoneCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNStatusDoneCallback_fct_##A == 0) {my_XNStatusDoneCallback_fct_##A = (uintptr_t)fct; return my_XNStatusDoneCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNStatusDoneCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNStatusDrawCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNStatusDrawCallback_fct_##A = 0; \
|
||||
static void my_XNStatusDrawCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNStatusDrawCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNStatusDrawCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNStatusDrawCallback_fct_##A == (uintptr_t)fct) return my_XNStatusDrawCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNStatusDrawCallback_fct_##A == 0) {my_XNStatusDrawCallback_fct_##A = (uintptr_t)fct; return my_XNStatusDrawCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNStatusDrawCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNR6PreeditCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNR6PreeditCallback_fct_##A = 0; \
|
||||
static void my_XNR6PreeditCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNR6PreeditCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNR6PreeditCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNR6PreeditCallback_fct_##A == (uintptr_t)fct) return my_XNR6PreeditCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNR6PreeditCallback_fct_##A == 0) {my_XNR6PreeditCallback_fct_##A = (uintptr_t)fct; return my_XNR6PreeditCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNR6PreeditCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// XNStringConversionCallback
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XNStringConversionCallback_fct_##A = 0; \
|
||||
static void my_XNStringConversionCallback_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
RunFunctionFmt(my_XNStringConversionCallback_fct_##A, "ppp", a, b); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findXNStringConversionCallbackFct(void* fct)
|
||||
{
|
||||
if(!fct) return NULL;
|
||||
void* p;
|
||||
if((p = GetNativeFnc((uintptr_t)fct))) return p;
|
||||
#define GO(A) if(my_XNStringConversionCallback_fct_##A == (uintptr_t)fct) return my_XNStringConversionCallback_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_XNStringConversionCallback_fct_##A == 0) {my_XNStringConversionCallback_fct_##A = (uintptr_t)fct; return my_XNStringConversionCallback_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for libX11 XNStringConversionCallback callback\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef SUPER
|
||||
|
||||
#define SUPER() \
|
||||
GO(XNGeometryCallback) \
|
||||
GO(XNDestroyCallback) \
|
||||
@@ -509,24 +796,6 @@ GO(XNStatusDrawCallback) \
|
||||
GO(XNR6PreeditCallback) \
|
||||
GO(XNStringConversionCallback)
|
||||
|
||||
#define GO(A) \
|
||||
static uintptr_t my_XICProc_fct_##A = 0; \
|
||||
static int my_XICProc_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
if (my_XICProc_fct_##A == 0) \
|
||||
printf_log(LOG_NONE, "%s cannot find XICProc callback\n", __func__); \
|
||||
return (int)RunFunctionFmt(my_XICProc_fct_##A, "ppp", a, b, c); \
|
||||
} \
|
||||
static uintptr_t my_XIMProc_fct_##A = 0; \
|
||||
static void my_XIMProc_##A(void* a, void* b, void* c) \
|
||||
{ \
|
||||
if (my_XIMProc_fct_##A == 0) \
|
||||
printf_log(LOG_NONE, "%s cannot find XIMProc callback\n", __func__); \
|
||||
RunFunctionFmt(my_XIMProc_fct_##A, "ppp", a, b, c); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
|
||||
#define VA_CALL(FUNC, FIRST_ARG, VAARGS, VAARGSZ, RESULT) \
|
||||
switch (VAARGSZ) \
|
||||
{ \
|
||||
@@ -565,14 +834,10 @@ default:
|
||||
break; \
|
||||
}
|
||||
|
||||
#define GO(A) \
|
||||
if (va[i] && strcmp((char*)va[i], A) == 0) { \
|
||||
XICCallback* origin = (XICCallback*)va[i+1]; \
|
||||
XICCallback* new = callbacks + i; \
|
||||
new->client_data = origin->client_data; \
|
||||
my_XICProc_fct_##A = (uintptr_t)origin->callback; \
|
||||
new->callback = my_XICProc_##A; \
|
||||
new_va[i+1] = new; \
|
||||
#define GO(A) \
|
||||
if (va[i] && strcmp((char*)va[i], A) == 0) { \
|
||||
XICCallback* origin = (XICCallback*)va[i+1]; \
|
||||
new_va[i+1] = find##A##Fct(origin); \
|
||||
}
|
||||
|
||||
EXPORT void* my_XVaCreateNestedList(x86emu_t* emu, int unused, void** va) {
|
||||
@@ -580,7 +845,6 @@ EXPORT void* my_XVaCreateNestedList(x86emu_t* emu, int unused, void** va) {
|
||||
(void)emu;
|
||||
while (va[n]) n+=2;
|
||||
void** new_va = alloca(sizeof(void*) * n);
|
||||
XICCallback* callbacks = (XICCallback*)alloca(sizeof(XIMCallback) * n);
|
||||
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
new_va[i] = va[i];
|
||||
@@ -598,7 +862,6 @@ EXPORT void* my_XCreateIC(x86emu_t* emu, void* xim, void** va) {
|
||||
(void)emu;
|
||||
while (va[n]) n+=2;
|
||||
void** new_va = alloca(sizeof(void*) * n);
|
||||
XICCallback* callbacks = (XICCallback*)alloca(sizeof(XIMCallback) * n);
|
||||
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
new_va[i] = va[i];
|
||||
@@ -616,7 +879,6 @@ EXPORT void* my_XSetICValues(x86emu_t* emu, void* xic, void** va) {
|
||||
(void)emu;
|
||||
while (va[n]) n+=2;
|
||||
void** new_va = alloca(sizeof(void*) * n);
|
||||
XICCallback* callbacks = (XICCallback*)alloca(sizeof(XIMCallback) * n);
|
||||
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
new_va[i] = va[i];
|
||||
@@ -635,16 +897,11 @@ EXPORT void* my_XSetIMValues(x86emu_t* emu, void* xim, void** va) {
|
||||
(void)emu;
|
||||
while (va[n]) n+=2;
|
||||
void** new_va = alloca(sizeof(void*) * n);
|
||||
XIMCallback* callbacks = (XIMCallback*)alloca(sizeof(XIMCallback) * n);
|
||||
|
||||
#define GO(A) \
|
||||
if (va[i] && strcmp((char*)va[i], A) == 0) { \
|
||||
XIMCallback* origin = (XIMCallback*)va[i+1]; \
|
||||
XIMCallback* new = callbacks + i; \
|
||||
new->client_data = origin->client_data; \
|
||||
my_XIMProc_fct_##A = (uintptr_t)origin->callback; \
|
||||
new->callback = my_XIMProc_##A; \
|
||||
new_va[i+1] = new; \
|
||||
#define GO(A) \
|
||||
if (va[i] && strcmp((char*)va[i], A) == 0) { \
|
||||
XIMCallback* origin = (XIMCallback*)va[i+1]; \
|
||||
new_va[i+1] = find##A##Fct(origin); \
|
||||
}
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
new_va[i] = va[i];
|
||||
|
||||
@@ -103,3 +103,7 @@ GO(png_set_shift, vFpp)
|
||||
GO(png_image_begin_read_from_memory, iFppL)
|
||||
GO(png_image_finish_read, iFpppip)
|
||||
GO(png_image_free, vFp)
|
||||
GO(png_set_flush, vFpi)
|
||||
GO(png_set_invert_alpha, vFp)
|
||||
GO(png_set_invert_mono, vFp)
|
||||
GO(png_get_mem_ptr, pFp)
|
||||
@@ -739,6 +739,8 @@ EXPORT void* my2_SDL_GL_GetProcAddress(x86emu_t* emu, void* name)
|
||||
{
|
||||
khint_t k;
|
||||
const char* rname = (const char*)name;
|
||||
void* ret = getGLProcAddress(emu, (glprocaddress_t)my->SDL_GL_GetProcAddress, rname);
|
||||
#ifndef GOA_CLONE
|
||||
static int lib_checked = 0;
|
||||
if(!lib_checked) {
|
||||
lib_checked = 1;
|
||||
@@ -747,7 +749,8 @@ EXPORT void* my2_SDL_GL_GetProcAddress(x86emu_t* emu, void* name)
|
||||
// use a my_dlopen to actually open that lib, like SDL2 is doing...
|
||||
my_glhandle = my_dlopen(emu, box86_libGL?box86_libGL:"libGL.so.1", RTLD_LAZY|RTLD_GLOBAL);
|
||||
}
|
||||
return getGLProcAddress(emu, (glprocaddress_t)my->SDL_GL_GetProcAddress, rname);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define nb_once 16
|
||||
|
||||
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user