mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-07 17:43:14 -10:00
Compare commits
58
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
157d368939 | ||
|
|
ea7eb6f866 | ||
|
|
c6cdde4b53 | ||
|
|
df71c7da43 | ||
|
|
ec8f7a6179 | ||
|
|
cbbe23606d | ||
|
|
1c4898754f | ||
|
|
bcb19dbe5d | ||
|
|
039c62f740 | ||
|
|
7663aacd1b | ||
|
|
fd5bf804ec | ||
|
|
70d18cfb7c | ||
|
|
1e32ccc9c7 | ||
|
|
23fa99d148 | ||
|
|
0e3ce6d8b1 | ||
|
|
970384559f | ||
|
|
2f8a939485 | ||
|
|
4f13c33628 | ||
|
|
4ef5da404c | ||
|
|
15fa9f687c | ||
|
|
331e5700a2 | ||
|
|
1411d44b51 | ||
|
|
bf53a76223 | ||
|
|
ecbc1e6642 | ||
|
|
7dc5b501f3 | ||
|
|
af67f69ee2 | ||
|
|
8f2a4ea880 | ||
|
|
eb44fd62fb | ||
|
|
46f015da9d | ||
|
|
705414a3d0 | ||
|
|
4591d337cb | ||
|
|
54e13be02a | ||
|
|
1524e883cd | ||
|
|
7a65bd60e9 | ||
|
|
8c1694e530 | ||
|
|
292d1455b6 | ||
|
|
9c69702011 | ||
|
|
3554d6decb | ||
|
|
7fb36acf85 | ||
|
|
ed3296978e | ||
|
|
4b212f91bf | ||
|
|
94f451c4b7 | ||
|
|
13bbf105ad | ||
|
|
3eb16fb7bd | ||
|
|
e85bcb671a | ||
|
|
1a0888ca51 | ||
|
|
3043f5066f | ||
|
|
b3b55d2d74 | ||
|
|
58426cbfb6 | ||
|
|
4a88ff38ea | ||
|
|
8d96ff02e3 | ||
|
|
eaa6ecb9cc | ||
|
|
027909bddc | ||
|
|
0eca6a8b94 | ||
|
|
24494ba143 | ||
|
|
a813321ad4 | ||
|
|
a43884ff66 | ||
|
|
27b269f53a |
No files matched your search
+56
-16
@@ -29,6 +29,9 @@ option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
|
||||
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
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 A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
@@ -297,9 +300,6 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX86_ROOT}/src/emu/x86emu.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run660f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x86syscall.c"
|
||||
"${BOX86_ROOT}/src/emu/x86primop.c"
|
||||
@@ -307,7 +307,6 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/emu/x86int3.c"
|
||||
"${BOX86_ROOT}/src/emu/x86tls.c"
|
||||
"${BOX86_ROOT}/src/emu/x87emu_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x87run.c"
|
||||
"${BOX86_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX86_ROOT}/src/libtools/myalign64.c"
|
||||
@@ -324,6 +323,33 @@ if(NOT ANDROID)
|
||||
list(APPEND ELFLOADER_SRC "${BOX86_ROOT}/src/libtools/obstack.c")
|
||||
endif()
|
||||
|
||||
set(INTERPRETER
|
||||
"${BOX86_ROOT}/src/emu/x86run.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run0f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run64.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run640f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run6466.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run6467.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run660f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66d9.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66dd.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run67.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run6766.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rund8.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rund9.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runda.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rundb.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rundc.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rundd.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runde.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rundf.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf0.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf066.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf20f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86runf30f.c"
|
||||
)
|
||||
|
||||
set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibpthread.c"
|
||||
@@ -492,6 +518,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpcap.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
)
|
||||
if(ANDROID)
|
||||
list(APPEND WRAPPEDS
|
||||
@@ -545,7 +572,9 @@ if(ARM_DYNAREC)
|
||||
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec_arm_jmpnext.c"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
|
||||
"${BOX86_ROOT}/src/emu/x86test.c"
|
||||
|
||||
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
|
||||
@@ -593,6 +622,8 @@ if(ARM_DYNAREC)
|
||||
set_target_properties(arm_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
|
||||
add_library(arm_pass3 OBJECT ${DYNAREC_PASS})
|
||||
set_target_properties(arm_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
|
||||
add_library(test_interpreter OBJECT ${INTERPRETER})
|
||||
set_target_properties(test_interpreter PROPERTIES COMPILE_FLAGS "-DTEST_INTERPRETER")
|
||||
add_dependencies(arm_pass0 WRAPPERS)
|
||||
add_dependencies(arm_pass1 WRAPPERS)
|
||||
add_dependencies(arm_pass2 WRAPPERS)
|
||||
@@ -604,6 +635,7 @@ if(ARM_DYNAREC)
|
||||
$<TARGET_OBJECTS:arm_pass1>
|
||||
$<TARGET_OBJECTS:arm_pass2>
|
||||
$<TARGET_OBJECTS:arm_pass3>
|
||||
$<TARGET_OBJECTS:test_interpreter>
|
||||
)
|
||||
|
||||
endif()
|
||||
@@ -613,16 +645,18 @@ if(ARM_DYNAREC)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
add_library(interpreter OBJECT ${INTERPRETER})
|
||||
|
||||
if(BOX86LIB)
|
||||
#build a static or dynamic lib...
|
||||
if(BOX86DYNAMIC)
|
||||
@@ -632,9 +666,9 @@ else()
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
if(ANDROID)
|
||||
target_link_libraries(${BOX86} dynarec m dl)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl)
|
||||
else()
|
||||
target_link_libraries(${BOX86} dynarec m dl rt pthread resolv)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl rt pthread resolv)
|
||||
endif()
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
@@ -660,7 +694,9 @@ else()
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
target_link_libraries(${BOX86} dynarec)
|
||||
target_link_libraries(${BOX86} dynarec interpreter)
|
||||
else()
|
||||
target_link_libraries(${BOX86} interpreter)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
@@ -679,13 +715,17 @@ endif()
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX86}
|
||||
RUNTIME DESTINATION bin)
|
||||
configure_file(system/box86.conf.cmake system/box86.conf)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
|
||||
if(NOT NO_CONF_INSTALL)
|
||||
configure_file(system/box86.conf.cmake system/box86.conf)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
|
||||
endif()
|
||||
if(NOT NO_LIB_INSTALL)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT TARGET uninstall)
|
||||
|
||||
Vendored
+2
-1
@@ -6,7 +6,8 @@
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DARM_DYNAREC=1
|
||||
-DARM_DYNAREC=1 \
|
||||
-DNOGIT=1
|
||||
|
||||
override_dh_shlibdeps:
|
||||
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
|
||||
+3
-3
@@ -6,7 +6,7 @@ You can use [@Itai-Nelken](https://github.com/Itai-Nelken)'s apt repository to i
|
||||
|
||||
```
|
||||
sudo wget https://itai-nelken.github.io/weekly-box86-debs/debian/box86.list -O /etc/apt/sources.list.d/box86.list
|
||||
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo apt-key add -
|
||||
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box86-debs-archive-keyring.gpg
|
||||
sudo apt update && sudo apt install box86 -y
|
||||
```
|
||||
|
||||
@@ -117,7 +117,7 @@ Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may hav
|
||||
|
||||
#### for Other ARM64 64bits Linux platform
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM64 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
`mkdir build; cd build; cmake .. -DARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
|
||||
|
||||
@@ -194,5 +194,5 @@ NVIDIA doesn't provide armhf libraries for their GPU drivers at this time. There
|
||||
|
||||
Debian Packaging
|
||||
----
|
||||
Box86 can also be packaged into a .deb file with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`.
|
||||
Box86 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you might want in `debian/rules`.
|
||||
|
||||
@@ -127,6 +127,11 @@ Enables/Disables trace for generated code.
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX86_DYNAREC_TEST *
|
||||
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
|
||||
* 0 : No comparison
|
||||
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different
|
||||
|
||||
#### BOX86_DYNAREC_BIGBLOCK *
|
||||
Enables/Disables Box86's Dynarec building BigBlock.
|
||||
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
|
||||
@@ -170,11 +175,21 @@ 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_BLEEDING_EDGE *
|
||||
Detect MonoBleedingEdge and apply conservative settings
|
||||
* 0 : Don't detect MonoBleedingEdge
|
||||
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
|
||||
|
||||
#### BOX86_DYNAREC_WAIT *
|
||||
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
|
||||
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
|
||||
* 1 : Dynarec will wait for FillBlock to be ready (Default)
|
||||
|
||||
#### BOX86_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
|
||||
+9
-2
@@ -28,14 +28,21 @@ export DBUS_FATAL_WARNINGS=0
|
||||
chmod +x steam
|
||||
sudo mv steam /usr/local/bin/
|
||||
|
||||
# detect if we're running on 64 bit Debian
|
||||
# detect if we're running on 64 bit Debian (maybe this can be moved in another script then mentioned in documentation for the people that don't use steam but don't want a headache)
|
||||
MACHINE_TYPE=`uname -m`
|
||||
if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
|
||||
echo "Detected 64 bit ARM Debian. Installing 32 bit libraries"
|
||||
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
|
||||
sudo apt update # update package lists with the newly added arch
|
||||
# install the libraries that Steam requires
|
||||
sudo apt install libc6:armhf libncurses5:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf
|
||||
sudo apt install libc6:armhf libncurses5:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf
|
||||
|
||||
# install mesa for armhf if already installed
|
||||
if dpkg-query -W libgl1-mesa-dri 2>/dev/null; then
|
||||
echo "Detected mesa driver for 64 bit ARM. Installing complementary 32 bit one"
|
||||
sudo apt install libgl1-mesa-dri:armhf
|
||||
fi
|
||||
|
||||
echo "Don't forget to compile/install Box64!"
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rk3399-git
|
||||
pkgver=r3858.5368285
|
||||
pkgname=box86-a64-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -9,21 +9,28 @@ url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
provides=("${pkgname%-git}" "${pkgname%-a64-git}-git" "${pkgname%-a64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-a64-git}-git" "${pkgname%-a64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}"
|
||||
cd "${srcdir}/${pkgname%-a64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-a64-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DA64=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-rk3399-git}" -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-a64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-a64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
+13
-6
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-arm-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-arm-git}"
|
||||
cd "${srcdir}/${pkgname%-arm-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-arm-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-arm-git}" -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-arm-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-arm-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-arm64-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DARM64=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-gameshell-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-gameshell-git}"
|
||||
cd "${srcdir}/${pkgname%-gameshell-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-gameshell-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DGAMESHELL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-gameshell-git}" -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-gameshell-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-gameshell-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-goaclone-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-goaclone-git}-git" "${pkgname%-goaclone-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-goaclone-git}-git" "${pkgname%-goaclone-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-goaclone-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-goaclone-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DGOA_CLONE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-goaclone-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-goaclone-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-lx2610a-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-lx2610a-git}-git" "${pkgname%-lx2610a-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-lx2610a-git}-git" "${pkgname%-lx2610a-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-lx2610a-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-lx2610a-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DLX2610A=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-lx2610a-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-lx2610a-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-odroid-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-odroid-git}"
|
||||
cd "${srcdir}/${pkgname%-odroid-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-odroid-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DODROID=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-odroid-git}" -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-odroid-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-odroid-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-odroidn2-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-odroidn2-git}-git" "${pkgname%-odroidn2-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-odroidn2-git}-git" "${pkgname%-odroidn2-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-odroidn2-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-odroidn2-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DODROID=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-odroidn2-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-odroidn2-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-pandora-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-pandora-git}"
|
||||
cd "${srcdir}/${pkgname%-pandora-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-pandora-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DPANDORA=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-pandora-git}" -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-pandora-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-pandora-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-phytium-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-phytium-git}"-git "${pkgname%-phytium-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-phytium-git}"-git "${pkgname%-phytium-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-phytium-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-phytium-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DPHYTIUM=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-phytium-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-phytium-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
+13
-6
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-pyra-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-pyra-git}"
|
||||
cd "${srcdir}/${pkgname%-pyra-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-pyra-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DPYRA=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-pyra-git}" -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-pyra-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-pyra-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rpi-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
@@ -16,11 +16,12 @@ md5sums=('SKIP')
|
||||
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}"
|
||||
cd "${srcdir}/${pkgname%-rpi-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
build() {
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rpi-git}"
|
||||
# Check for Pi version number
|
||||
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
|
||||
_piversion=4
|
||||
@@ -31,15 +32,20 @@ build() {
|
||||
else
|
||||
# This RPI is not supported or this device is not a pi.
|
||||
# We should cancel then the build.
|
||||
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 isn't supported yet).\033[00m"
|
||||
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 isn't supported).\033[00m"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DRPI${_piversion}=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
cmake -B build -S "${pkgname%-rpi-git}" -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-rpi-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
cd "${srcdir}/${pkgname%-rpi-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rk3xxx-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rk3xxx-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rk3xxx-git}"
|
||||
# Check for RockChip version number
|
||||
if [[ ${_rkmodel} =~ "rk3288"]]; then
|
||||
_rksuffix=3288
|
||||
elif [[ ${_rkmodel} =~ "rk3399" ]]; then
|
||||
_rksuffix=3399
|
||||
elif [[ ${_rkmodel} =~ "rk3588" ]]; then
|
||||
_rksuffix=3588
|
||||
else
|
||||
# This RKxxxx is not supported or this device is not RockChip based.
|
||||
# We should cancel then the build.
|
||||
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RockChip model 3399/3588.\033[00m"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected RockChip verion number is: \033[01;31m${_rksuffix}\033[01m.\033[00m"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DRK${_rksuffix}=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-sd845-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-sd845-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-sd845-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DSD845=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-sd845-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-sd845-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-tegra-git
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-tegra-git}"-git "${pkgname%-tegra-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}"-git "${pkgname%-tegra-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DTEGRAX1ARM32=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
+13
-6
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-x86-git
|
||||
pkgver=r3858.5368285
|
||||
pkgver=r4581.d698861
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('i386')
|
||||
@@ -14,15 +14,22 @@ source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-x86-git}"
|
||||
cd "${srcdir}/${pkgname%-x86-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-x86-git}"
|
||||
[[ ! -d ./build ]] && mkdir build
|
||||
cmake -B build -DLD80BITS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
}
|
||||
|
||||
build() {
|
||||
cmake -B build -S "${pkgname%-x86-git}" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make -C build
|
||||
cd "${srcdir}/${pkgname%-x86-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C build DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
cd "${srcdir}/${pkgname%-x86-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ This will copy the PKGBUILD for your platform (where you type your platform name
|
||||
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
|
||||
|
||||
### 2. What platforms are currently supported.
|
||||
All specified in [COMPILE.md](../docs/COMPILE.md).
|
||||
Most specified in [COMPILE.md](../docs/COMPILE.md). Except PowerPC based.
|
||||
|
||||
### 3. Any advantages with that sollution?
|
||||
This might give you some advantages like those:
|
||||
|
||||
+9
-2
@@ -23,6 +23,7 @@
|
||||
#include "custommem.h"
|
||||
#include "dictionnary.h"
|
||||
#include "rcfile.h"
|
||||
#include "gltools.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
@@ -146,6 +147,7 @@ static void init_mutexes(box86context_t* context)
|
||||
arm_lock_stored(&context->mutex_tls, 0);
|
||||
arm_lock_stored(&context->mutex_thread, 0);
|
||||
arm_lock_stored(&context->mutex_bridge, 0);
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
@@ -222,9 +224,12 @@ box86context_t *NewBox86Context(int argc)
|
||||
context->system = NewBridge();
|
||||
context->globaldefver = NewDefaultVersion();
|
||||
context->weakdefver = NewDefaultVersion();
|
||||
// Cannot use Bridge name as the map is not initialized yet
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
|
||||
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
|
||||
// create exit bridge
|
||||
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
|
||||
#ifdef BUILD_LIB
|
||||
context->box86lib = RTLD_DEFAULT; // not ideal
|
||||
#else
|
||||
@@ -250,7 +255,7 @@ box86context_t *NewBox86Context(int argc)
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void freeALProcWrapper(box86context_t* context);
|
||||
EXPORTDYN
|
||||
void FreeBox86Context(box86context_t** context)
|
||||
{
|
||||
@@ -359,7 +364,9 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifndef DYNAREC
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 3
|
||||
#define BOX86_REVISION 0
|
||||
#define BOX86_REVISION 1
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+536
-489
File diff suppressed because it is too large.
Load diff
@@ -390,6 +390,8 @@ Op is 20-27
|
||||
#define LDRD_IMM8(reg, addr, imm8) EMIT(c__ | 0b000<<25 | 1<<24 | (((imm8)<0)?0:1)<<23 | 1<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | ((abs(imm8))&0xf0)<<(8-4) | (0b1101<<4) | ((abs(imm8))&0x0f) )
|
||||
// ldrd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
|
||||
#define LDRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1101<<4 | (rm) )
|
||||
// ldr reg, [pc+imm]
|
||||
#define LDR_literal(reg, imm12) EMIT(c__ | 0b010<<25 | 1<<24 | (((imm12)>=0)?1:0)<<23 | 0<<21 | 1<<20 | 0b1111<<16 | (reg)<<12 | (abs(imm12)))
|
||||
|
||||
// str reg, [addr, #+/-imm9]
|
||||
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
.extern LinkNext
|
||||
|
||||
.global arm_next
|
||||
.4byte 0 // NULL pointer before arm64_next, for getDB
|
||||
arm_next:
|
||||
// emu is r0
|
||||
//stm r0, {r4-r12,r14} // don't put put back reg value in emu, faster but more tricky to debug
|
||||
|
||||
+187
-300
@@ -41,21 +41,37 @@ uint32_t X31_hash_code(void* addr, int len)
|
||||
return (uint32_t)h;
|
||||
}
|
||||
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(!textsz) {
|
||||
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
|
||||
return NULL;
|
||||
if(db) {
|
||||
if(db->gone)
|
||||
return NULL; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "InvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
// remove jumptable
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
dynablocklist_t* ret = (dynablocklist_t*)box_calloc(1, sizeof(dynablocklist_t));
|
||||
ret->text = text;
|
||||
ret->textsz = textsz;
|
||||
if(direct && textsz) {
|
||||
ret->direct = (dynablock_t**)box_calloc(textsz, sizeof(dynablock_t*));
|
||||
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
||||
return db;
|
||||
}
|
||||
|
||||
void FreeInvalidDynablock(dynablock_t* db, int need_lock)
|
||||
{
|
||||
if(db) {
|
||||
if(!db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeInvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
FreeDynarecMap((uintptr_t)db->actual_block);
|
||||
customFree(db);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
@@ -63,237 +79,100 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
if(db) {
|
||||
if(db->gone)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
// remove from direct if there
|
||||
uintptr_t startdb = db->parent->text;
|
||||
uintptr_t enddb = db->parent->text + db->parent->textsz;
|
||||
if(db->parent->direct) {
|
||||
uintptr_t addr = (uintptr_t)db->x86_addr;
|
||||
if(addr>=startdb && addr<enddb)
|
||||
db->parent->direct[addr-startdb] = NULL;
|
||||
}
|
||||
// remove jumptable
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
// remove and free the sons
|
||||
for (int i=0; i<db->sons_size; ++i) {
|
||||
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
|
||||
FreeDynablock(son, 0);
|
||||
}
|
||||
// only the father free the DynarecMap
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
box_free(db->sons);
|
||||
box_free(db->instsize);
|
||||
}
|
||||
box_free(db);
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, 0);
|
||||
FreeDynarecMap((uintptr_t)db->actual_block);
|
||||
customFree(db);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!*dynablocks)
|
||||
return;
|
||||
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
|
||||
if((*dynablocks)->direct) {
|
||||
for (int i=0; i<(*dynablocks)->textsz; ++i) {
|
||||
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
||||
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
|
||||
}
|
||||
box_free((*dynablocks)->direct);
|
||||
}
|
||||
(*dynablocks)->direct = NULL;
|
||||
|
||||
box_free(*dynablocks);
|
||||
*dynablocks = NULL;
|
||||
}
|
||||
|
||||
void MarkDynablock(dynablock_t* db)
|
||||
{
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father; // mark only father
|
||||
if(db->need_test)
|
||||
return; // already done
|
||||
db->need_test = 1;
|
||||
setJumpTableDefault(db->x86_addr);
|
||||
for(int i=0; i<db->sons_size; ++i)
|
||||
setJumpTableDefault(db->sons[i]->x86_addr);
|
||||
dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1);
|
||||
if(!setJumpTableIfRef(db->x86_addr, db->jmpnext, db->block)) {
|
||||
dynablock_t* old = db;
|
||||
db = getDB((uintptr_t)old->x86_addr);
|
||||
if(!old->gone && db!=old) {
|
||||
printf_log(LOG_INFO, "Warning, couldn't mark block as dirty for %p, block=%p, current_block=%p\n", old->x86_addr, old, db);
|
||||
// the block is lost, need to invalidate it...
|
||||
old->gone = 1;
|
||||
old->done = 0;
|
||||
if(!db || db->previous)
|
||||
FreeInvalidDynablock(old, 1);
|
||||
else
|
||||
db->previous = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t StartDynablockList(dynablocklist_t* db)
|
||||
{
|
||||
if(db)
|
||||
return db->text;
|
||||
return 0;
|
||||
}
|
||||
uintptr_t EndDynablockList(dynablocklist_t* db)
|
||||
{
|
||||
if(db)
|
||||
return db->text+db->textsz-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
{
|
||||
if(start1 > end2 || start2 > end1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
static int MarkedDynablock(dynablock_t* db)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!dynablocks->direct)
|
||||
return;
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz -1;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size-1;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
dynablock_t *db;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i)
|
||||
if((db=dynablocks->direct[i-startdb]))
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
|
||||
if(dynablocks->direct) {
|
||||
int need_lock = my_context?1:0;
|
||||
dynablock_t* db;
|
||||
int ret;
|
||||
khint_t k;
|
||||
kh_dynablocks_t *blocks = kh_init(dynablocks);
|
||||
// copy in a temporary list
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father;
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db, need_lock);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
if(db) {
|
||||
if(getNeedTest((uintptr_t)db->x86_addr))
|
||||
return 1; // already done
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
|
||||
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
// Mark will try to find *any* blocks that intersect the range to mark
|
||||
if(!db)
|
||||
return;
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t new_addr = addr - dynablocks->maxsz;
|
||||
uintptr_t new_size = size + dynablocks->maxsz;
|
||||
MarkDirectDynablock(dynablocks, new_addr, new_size);
|
||||
// the blocks check before
|
||||
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
MarkDirectDynablock(getDB(idx), new_addr, new_size);
|
||||
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x86_addr, (void*)db->x86_size);
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!db)
|
||||
return 1;
|
||||
|
||||
int need_lock = my_context?1:0;
|
||||
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1)) {
|
||||
FreeDynablock(db, need_lock);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
|
||||
dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return NULL;
|
||||
dynablock_t* db;
|
||||
kh_foreach_value(dynablocks, db,
|
||||
const uintptr_t s = (uintptr_t)db->block;
|
||||
const uintptr_t e = (uintptr_t)db->block+db->size;
|
||||
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
|
||||
return db->father?db->father:db;
|
||||
)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
|
||||
{
|
||||
const int idx = (addr>>DYNAMAP_SHIFT);
|
||||
return getDB(idx);
|
||||
}
|
||||
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
|
||||
{
|
||||
if(!dynablocks) {
|
||||
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
|
||||
*created = 0;
|
||||
dynablock_t* block;
|
||||
#if 0
|
||||
// check if memory as the correct flags
|
||||
int prot = getProtection(addr);
|
||||
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
|
||||
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
|
||||
return NULL;
|
||||
}
|
||||
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
|
||||
// this should be useless
|
||||
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
|
||||
//*created = 0;
|
||||
//return NULL;
|
||||
return AddNewDynablock(getDBFromAddress(addr), addr, created);
|
||||
}
|
||||
dynablock_t* block = NULL;
|
||||
// first, check if it exist in direct access mode
|
||||
if(dynablocks->direct) {
|
||||
block = dynablocks->direct[addr-dynablocks->text];
|
||||
if(block) {
|
||||
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*created)
|
||||
return block;
|
||||
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm_lock_storeifnull(&dynablocks->direct, p)!=NULL)
|
||||
box_free(p); // someone already create the direct array, too late...
|
||||
}
|
||||
|
||||
#endif
|
||||
// create and add new block
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], block, NULL);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
box_free(block);
|
||||
*created = 0;
|
||||
return tmp;
|
||||
}
|
||||
*created = 1;
|
||||
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -309,121 +188,120 @@ void cancelFillBlock()
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
|
||||
{
|
||||
if(hasAlternate((void*)addr))
|
||||
return NULL;
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
dynablock_t* block = NULL;
|
||||
if(current && current->done) {
|
||||
dynablocks = current->parent;
|
||||
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
|
||||
dynablocks = NULL;
|
||||
}
|
||||
// nope, lets do the long way
|
||||
if(!dynablocks) {
|
||||
dynablocks = getDBFromAddress(addr);
|
||||
if(!dynablocks) {
|
||||
dynablocks = GetDynablocksFromAddress(emu->context, addr);
|
||||
if(!dynablocks)
|
||||
dynablock_t* block = getDB(addr);
|
||||
if(block || !create)
|
||||
return block;
|
||||
|
||||
if(need_lock) {
|
||||
if(box86_dynarec_wait) {
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
} else {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// check direct first, without lock
|
||||
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
|
||||
if((block = dynablocks->direct[addr-dynablocks->text]))
|
||||
return block;
|
||||
|
||||
int created = create;
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
block = AddNewDynablock(dynablocks, addr, &created);
|
||||
if(!created) {
|
||||
if(need_lock)
|
||||
block = getDB(addr); // just in case
|
||||
if(block) {
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return block; // existing block...
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
block = AddNewDynablock(addr);
|
||||
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
FreeDynablock(block, 0);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock(block, filladdr);
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
if(old!=block && old) { // put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// Doing nothing else, the block has not been written
|
||||
}
|
||||
box_free(block);
|
||||
customFree(block);
|
||||
block = NULL;
|
||||
}
|
||||
// check size
|
||||
if(block && block->x86_size) {
|
||||
if(block) {
|
||||
int blocksz = block->x86_size;
|
||||
if(dynablocks->maxsz<blocksz) {
|
||||
dynablocks->maxsz = blocksz;
|
||||
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
dynablocklist_t* dblist;
|
||||
if((dblist = getDB(idx)))
|
||||
if(dblist->maxsz<blocksz)
|
||||
dblist->maxsz = blocksz;
|
||||
}
|
||||
}
|
||||
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
|
||||
// but check if it already need test
|
||||
if(block->need_test || (block->father && block->father->need_test))
|
||||
return NULL;
|
||||
if(blocksz>my_context->max_db_size)
|
||||
my_context->max_db_size = blocksz;
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault(block->x86_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i)
|
||||
addJumpTableIfDefault(block->sons[i]->x86_addr, block->sons[i]->block);
|
||||
if(!addJumpTableIfDefault(block->x86_addr, block->dirty?block->jmpnext:block->block)) {
|
||||
FreeDynablock(block, 0);
|
||||
block = getDB(addr);
|
||||
MarkDynablock(block); // just in case...
|
||||
} else {
|
||||
if(block->x86_size)
|
||||
block->done = 1; // don't validate the block if the size is null, but keep the block
|
||||
}
|
||||
}
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
|
||||
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x86_size:1)-1), (block)?block->block:0, (block)?block->size:0);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
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)) {
|
||||
dynarec_log(LOG_DEBUG, "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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// no more current if it gets invalidated too
|
||||
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
|
||||
*current = NULL;
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father, 0);
|
||||
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);
|
||||
// Free db, it's now invalid!
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
|
||||
db = internalDBGetBlock(emu, addr, addr, create, need_lock);
|
||||
if(db) {
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, need_lock);
|
||||
db->previous = old;
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
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);
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault(father->x86_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -431,27 +309,36 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father, 0);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
|
||||
if(db && db->done && db->block && getNeedTest(filladdr)) {
|
||||
if(db->always_test)
|
||||
sched_yield(); // just calm down...
|
||||
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
|
||||
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
|
||||
if(hash!=db->hash) {
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
dynablock_t* old = InvalidDynablock(db, need_lock);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, need_lock);
|
||||
if(db) {
|
||||
if(db->previous)
|
||||
FreeInvalidDynablock(db->previous, need_lock);
|
||||
db->previous = old;
|
||||
} else
|
||||
FreeInvalidDynablock(old, need_lock);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
protectDB((uintptr_t)db->x86_addr, db->x86_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault(father->x86_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
|
||||
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
if(!db || !db->block || !db->done)
|
||||
emu->test.test = 0;
|
||||
return db;
|
||||
}
|
||||
@@ -1,36 +1,26 @@
|
||||
#ifndef __DYNABLOCK_PRIVATE_H_
|
||||
#define __DYNABLOCK_PRIVATE_H_
|
||||
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
|
||||
typedef struct instsize_s {
|
||||
unsigned char x86:4;
|
||||
unsigned char nat:4;
|
||||
} instsize_t;
|
||||
|
||||
typedef struct dynablock_s {
|
||||
dynablocklist_t* parent;
|
||||
void* block;
|
||||
void* block; // block-sizeof(void*) == self
|
||||
void* actual_block; // the actual start of the block (so block-sizeof(void*))
|
||||
struct dynablock_s* previous; // a previous block that might need to be freed
|
||||
int size;
|
||||
void* x86_addr;
|
||||
uintptr_t x86_size;
|
||||
uint32_t hash;
|
||||
uint8_t need_test;
|
||||
uint8_t done;
|
||||
uint8_t gone;
|
||||
uint8_t dummy;
|
||||
uint8_t always_test;
|
||||
uint8_t dirty; // if need to be tested as soon as it's created
|
||||
int isize;
|
||||
dynablock_t** sons; // sons (kind-of dummy dynablock...)
|
||||
int sons_size;
|
||||
dynablock_t* father; // set only in the case of a son
|
||||
instsize_t* instsize;
|
||||
void* jmpnext; // a branch jmpnext code when block is marked
|
||||
} dynablock_t;
|
||||
|
||||
typedef struct dynablocklist_s {
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
int maxsz; // maxblock size (for this block or previous block)
|
||||
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
|
||||
} dynablocklist_t;
|
||||
|
||||
#endif //__DYNABLOCK_PRIVATE_H_
|
||||
+42
-19
@@ -20,6 +20,7 @@
|
||||
#include "dynablock.h"
|
||||
#include "dynablock_private.h"
|
||||
#include "bridge.h"
|
||||
void x86test_check(x86emu_t* ref, uintptr_t ip);
|
||||
#endif
|
||||
|
||||
#ifdef ARM
|
||||
@@ -44,9 +45,8 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
|
||||
}
|
||||
#endif
|
||||
dynablock_t* current = NULL;
|
||||
void * jblock;
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1);
|
||||
if(!block) {
|
||||
// no block, let link table as is...
|
||||
if(hasAlternate((void*)addr)) {
|
||||
@@ -54,12 +54,15 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
R_EIP = addr;
|
||||
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
|
||||
block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
block = DBGetBlock(emu, addr, 1);
|
||||
}
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
|
||||
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)");
|
||||
}
|
||||
#endif
|
||||
//tableupdate(arm_epilog, addr, table);
|
||||
return arm_epilog;
|
||||
@@ -84,18 +87,25 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
// prepare setjump for signal handling
|
||||
emu_jmpbuf_t *ejb = NULL;
|
||||
int jmpbuf_reset = 0;
|
||||
int skip = 0;
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
if(!ejb->jmpbuf_ok) {
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
int a;
|
||||
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
|
||||
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", skip, ejb->emu->segs[_FS]);
|
||||
addr = R_EIP; // not sure if it should still be inside DynaCall!
|
||||
if(a==2)
|
||||
Run(emu, 1); // "single step" next instruction that is doing auto-smc
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x86test_check(emu, R_EIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
if(skip!=2)
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,15 +127,18 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
|
||||
if(box86_dynarec_test)
|
||||
emu->test.clean = 0;
|
||||
Run(emu, 1);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,block->father, emu);
|
||||
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,emu);
|
||||
CHECK_FLAGS(emu);
|
||||
// block is here, let's run it!
|
||||
#ifdef ARM
|
||||
@@ -173,6 +186,7 @@ int DynaRun(x86emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
emu_jmpbuf_t *ejb = NULL;
|
||||
int skip = 0;
|
||||
#ifdef DYNAREC
|
||||
int jmpbuf_reset = 1;
|
||||
#endif
|
||||
@@ -185,11 +199,17 @@ int DynaRun(x86emu_t* emu)
|
||||
#ifdef DYNAREC
|
||||
jmpbuf_reset = 1;
|
||||
#endif
|
||||
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
|
||||
if(a==2)
|
||||
Run(emu, 1); // "single step" next instruction that is doing auto-smc
|
||||
|
||||
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", skip, ejb->emu->segs[_FS]);
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
x86test_check(emu, R_EIP);
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
if(skip!=2)
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,15 +222,18 @@ int DynaRun(x86emu_t* emu)
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
block = DBGetBlock(emu, R_EIP, 1, ¤t);
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
current = block;
|
||||
if(!block || !block->block || !block->done) {
|
||||
skip = 0;
|
||||
// no block, of block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
|
||||
if(box86_dynarec_test)
|
||||
emu->test.clean = 0;
|
||||
Run(emu, 1);
|
||||
} else {
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->father, emu);
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, emu);
|
||||
// block is here, let's run it!
|
||||
#ifdef ARM
|
||||
arm_prolog(emu, block->block);
|
||||
|
||||
+131
-122
@@ -73,8 +73,8 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
}
|
||||
// add slots
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 16;
|
||||
dyn->next = (uintptr_t*)box_realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
dyn->next_cap += 64;
|
||||
dyn->next = (uintptr_t*)customRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
}
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
@@ -83,11 +83,13 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
uintptr_t best = 0;
|
||||
int i = 0;
|
||||
while((i<dyn->next_sz) && (best!=addr)) {
|
||||
if(dyn->next[i]<addr) { // remove the address, it's before current address
|
||||
dyn->next[i] = 0;
|
||||
} else {
|
||||
if((dyn->next[i]<best) || !best)
|
||||
best = dyn->next[i];
|
||||
if(dyn->next[i]) {
|
||||
if(dyn->next[i]<addr) { // remove the address, it's before current address
|
||||
dyn->next[i] = 0;
|
||||
} else {
|
||||
if((dyn->next[i]<best) || !best)
|
||||
best = dyn->next[i];
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@@ -241,35 +243,31 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
return (i==n)?1:0;
|
||||
}
|
||||
|
||||
static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
|
||||
void addInst(instsize_t* insts, size_t* size, int x86_size, int native_size)
|
||||
{
|
||||
// x86 instruction is <16 bytes
|
||||
int toadd;
|
||||
if(x86_size>arm_size)
|
||||
if(x86_size>native_size)
|
||||
toadd = 1 + x86_size/15;
|
||||
else
|
||||
toadd = 1 + arm_size/15;
|
||||
if((*size)+toadd>(*cap)) {
|
||||
*cap = (*size)+toadd;
|
||||
insts = (instsize_t*)box_realloc(insts, (*cap)*sizeof(instsize_t));
|
||||
}
|
||||
toadd = 1 + native_size/15;
|
||||
while(toadd) {
|
||||
if(x86_size>15)
|
||||
insts[*size].x86 = 15;
|
||||
else
|
||||
insts[*size].x86 = x86_size;
|
||||
x86_size -= insts[*size].x86;
|
||||
if(arm_size>15)
|
||||
if(native_size>15)
|
||||
insts[*size].nat = 15;
|
||||
else
|
||||
insts[*size].nat = arm_size;
|
||||
arm_size -= insts[*size].nat;
|
||||
insts[*size].nat = native_size;
|
||||
native_size -= insts[*size].nat;
|
||||
++(*size);
|
||||
--toadd;
|
||||
}
|
||||
return insts;
|
||||
}
|
||||
|
||||
|
||||
static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
{
|
||||
int pred_sz = 1; // to be safe
|
||||
@@ -288,7 +286,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
++dyn->insts[i+1].pred_sz;
|
||||
}
|
||||
}
|
||||
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
|
||||
dyn->predecessor = (int*)customMalloc(pred_sz*sizeof(int));
|
||||
// fill pred pointer
|
||||
int* p = dyn->predecessor;
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
@@ -356,36 +354,70 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
return ninst;
|
||||
}
|
||||
|
||||
void* current_helper = NULL;
|
||||
|
||||
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) {
|
||||
customFree(helper->next);
|
||||
customFree(helper->insts);
|
||||
customFree(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->actual_block) {
|
||||
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
|
||||
helper->dynablock->actual_block = NULL;
|
||||
}
|
||||
}
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
|
||||
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
void* current_helper = NULL;
|
||||
|
||||
void CancelBlock()
|
||||
{
|
||||
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
return;
|
||||
box_free(helper->next);
|
||||
box_free(helper->insts);
|
||||
box_free(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
|
||||
}
|
||||
void arm_epilog();
|
||||
void arm_next();
|
||||
|
||||
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->isize = 0;
|
||||
block->done = 0;
|
||||
block->size = 0;
|
||||
block->block = NULL;
|
||||
block->need_test = 0;
|
||||
size_t sz = 8*sizeof(void*);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
block->size = sz;
|
||||
block->actual_block = actual_p;
|
||||
block->block = p;
|
||||
block->jmpnext = p;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
*(void**)(p+4*sizeof(void*)) = arm_epilog;
|
||||
CreateJmpNext(block->jmpnext, p+4*sizeof(void*));
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
return block;
|
||||
}
|
||||
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
/*
|
||||
A Block must have this layout:
|
||||
|
||||
0x0000..0x0003 : dynablock_t* : self
|
||||
0x0004..4+4*n : actual Native instructions, (n is the total number)
|
||||
B .. B+3 : dynablock_t* : self (as part of JmpNext, that simulate another block)
|
||||
B+4 .. B+15 : 3 Native code for jmpnext (or jmp epilog in case of empty block)
|
||||
B+16 .. B+19 : jmpnext (or jmp_epilog) address
|
||||
B+20 .. B+31 : empty (in case an architecture needs more than 3 opcodes)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x86 and native side)
|
||||
|
||||
*/
|
||||
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);
|
||||
@@ -395,10 +427,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(!isJumpTableDefault((void*)addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block at %p, but JumpTable is not default\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(current_helper) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
|
||||
return NULL;
|
||||
@@ -412,23 +440,23 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)box_calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
helper.insts = (instruction_arm_t*)customCalloc(helper.cap, sizeof(instruction_arm_t));
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
// no need for next anymore
|
||||
box_free(helper.next);
|
||||
customFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
CancelBlock();
|
||||
return (void*)block;
|
||||
CancelBlock(0);
|
||||
return CreateEmptyBlock(block, 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();
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
// already protect the block and compute hash signature
|
||||
@@ -441,6 +469,8 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(helper.insts[i].x86.jmp) {
|
||||
uintptr_t j = helper.insts[i].x86.jmp;
|
||||
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 {
|
||||
@@ -468,29 +498,68 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
int sz = helper.arm_size;
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
|
||||
CancelBlock();
|
||||
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
size_t arm_size = (helper.arm_size+7)&~7; // round the size...
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
size_t sz = sizeof(void*) + arm_size + 8*sizeof(void*) + insts_rsize;
|
||||
// dynablock_t* block (arm insts) jmpnext code instsize
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
|
||||
void* next = p + arm_size;
|
||||
void* instsize = next + 8*sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
block->actual_block = actual_p;
|
||||
helper.arm_start = (uintptr_t)p;
|
||||
if(helper.sons_size) {
|
||||
helper.sons_x86 = (uintptr_t*)alloca(helper.sons_size*sizeof(uintptr_t));
|
||||
helper.sons_arm = (void**)alloca(helper.sons_size*sizeof(void*));
|
||||
}
|
||||
// pass 3, emit (log emit arm opcode)
|
||||
helper.jmp_next = (uintptr_t)next+sizeof(void*);
|
||||
helper.insts_size = 0; // reset
|
||||
helper.instsize = (instsize_t*)instsize;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
// pass 3, emit (log emit native opcode)
|
||||
if(box86_dynarec_dump) {
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
printFunctionAddr(helper.start, " => ");
|
||||
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
size_t oldarmsize = helper.arm_size;
|
||||
helper.arm_size = 0;
|
||||
arm_pass3(&helper, addr);
|
||||
if(sz!=helper.arm_size) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
|
||||
// keep size of instructions for signal handling
|
||||
block->instsize = instsize;
|
||||
// ok, free the helper now
|
||||
customFree(helper.insts);
|
||||
helper.insts = NULL;
|
||||
helper.instsize = NULL;
|
||||
customFree(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->jmpnext = next+sizeof(void*);
|
||||
block->always_test = helper.always_test;
|
||||
block->dirty = block->always_test;
|
||||
*(dynablock_t**)next = block;
|
||||
*(void**)(next+5*sizeof(void*)) = arm_next;
|
||||
CreateJmpNext(block->jmpnext, next+5*sizeof(void*));
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start;
|
||||
// all done...
|
||||
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
|
||||
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||
// 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:%ld)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
if((oldarmsize!=helper.arm_size)) {
|
||||
printf_log(LOG_NONE, "BOx86: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.arm_size);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
@@ -500,76 +569,16 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
|
||||
}
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
}
|
||||
// all done...
|
||||
__clear_cache(p, p+sz); // need to clear the cache before execution...
|
||||
// keep size of instructions for signal handling
|
||||
{
|
||||
size_t cap = 1;
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
|
||||
size_t size = 0;
|
||||
block->instsize = (instsize_t*)box_calloc(cap, sizeof(instsize_t));
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
|
||||
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
|
||||
}
|
||||
// ok, free the helper now
|
||||
box_free(helper.insts);
|
||||
helper.insts = NULL;
|
||||
box_free(helper.next);
|
||||
helper.next = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->need_test = 0;
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start;
|
||||
if(box86_dynarec_largest<block->x86_size)
|
||||
box86_dynarec_largest = block->x86_size;
|
||||
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
CancelBlock();
|
||||
AddHotPage(addr);
|
||||
CancelBlock(0);
|
||||
return NULL;
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%zd, cancelling\n", block->x86_addr, block->x86_size);
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x86_addr, block->x86_size);
|
||||
AddHotPage(addr);
|
||||
block->need_test = 1;
|
||||
block->dirty = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
// fill sons if any
|
||||
dynablock_t** sons = NULL;
|
||||
int sons_size = 0;
|
||||
if(helper.sons_size) {
|
||||
sons = (dynablock_t**)box_calloc(helper.sons_size, sizeof(dynablock_t*));
|
||||
for (int i=0; i<helper.sons_size; ++i) {
|
||||
int created = 1;
|
||||
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
|
||||
if(created) { // avoid breaking a working block!
|
||||
son->block = helper.sons_arm[i];
|
||||
son->x86_addr = (void*)helper.sons_x86[i];
|
||||
son->x86_size = end-helper.sons_x86[i];
|
||||
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
|
||||
son->father = block;
|
||||
son->done = 1;
|
||||
sons[sons_size++] = son;
|
||||
if(!son->parent)
|
||||
son->parent = block->parent;
|
||||
}
|
||||
}
|
||||
if(sons_size) {
|
||||
block->sons = sons;
|
||||
block->sons_size = sons_size;
|
||||
} else
|
||||
box_free(sons);
|
||||
}
|
||||
box_free(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
current_helper = NULL;
|
||||
block->done = 1;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
@@ -1663,6 +1663,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
|
||||
{
|
||||
addr+=4;
|
||||
SKIPTEST(x14);
|
||||
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
|
||||
MOV32(x14, ip+1+2);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
@@ -1672,6 +1673,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
*need_epilog = 1;
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
|
||||
SKIPTEST(x14);
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if((box86_log<2) && !cycle_log) { // call the wrapper directly
|
||||
uintptr_t ncall[2]; // to avoid BUSERROR!!!
|
||||
@@ -1715,10 +1717,11 @@ 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...)
|
||||
SKIPTEST(x14);
|
||||
SMEND();
|
||||
if(PK(0)==0x80) {
|
||||
u8 = F8;
|
||||
if(u8==0x80) {
|
||||
INST_NAME("Syscall");
|
||||
u8 = F8;
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
MOV32(xEIP, ip+2);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
@@ -1734,7 +1737,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
} else {
|
||||
INST_NAME("INT Ib");
|
||||
DEFAULT;
|
||||
if(box86_wine && u8==0x2D) {
|
||||
MESSAGE(LOG_DEBUG, "Hack for wine/int 2d\n");
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2158,8 +2165,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
tmp = dyn->insts[ninst].pass2choice = 1;
|
||||
else if ((getProtection(u32)&PROT_READ) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
|
||||
tmp = dyn->insts[ninst].pass2choice = 2;
|
||||
/*else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;*/
|
||||
else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;
|
||||
else
|
||||
tmp = dyn->insts[ninst].pass2choice = 0;
|
||||
#else
|
||||
@@ -2169,18 +2176,19 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
//SETFLAGS(X_ALL, SF_SET); // 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
|
||||
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
|
||||
SKIPTEST(x14);
|
||||
u8 = PK(i32+1);
|
||||
gd = xEAX+((u8&0x38)>>3);
|
||||
MOV32(gd, addr);
|
||||
break;
|
||||
// disabling this to avoid fetching data outside current block (in case this part changed, this block will not been marck as dirty)
|
||||
/*case 3:
|
||||
case 3:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
BARRIER(BARRIER_FULL);
|
||||
BARRIER_NEXT(BARRIER_FULL);
|
||||
@@ -2219,16 +2227,22 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_NEXT(cNE); // not quitting, so lets continue
|
||||
MARK;
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
break;*/
|
||||
break;
|
||||
default:
|
||||
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); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
// regular call
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
//BARRIER_NEXT(BARRIER_FULL);
|
||||
if(/*box86_dynarec_callret &&*/ box86_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
MOV32(x2, addr);
|
||||
@@ -2823,10 +2837,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags), 1) {
|
||||
PASS2IF((box86_dynarec_safeflags>1) ||
|
||||
((ninst && dyn->insts[ninst-1].x86.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x86.set_flags)), 1)
|
||||
{
|
||||
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); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDH(xEIP);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
|
||||
@@ -90,6 +90,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
//CALL(arm_ud, -1, 0);
|
||||
SKIPTEST(x14);
|
||||
UDF(0);
|
||||
break;
|
||||
|
||||
@@ -421,6 +422,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x31:
|
||||
INST_NAME("RDTSC");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SKIPTEST(x14);
|
||||
CALL(ReadTSC, xEAX, 0); // will return the u64 in x1:xEAX
|
||||
MOV_REG(xEDX, x1);
|
||||
break;
|
||||
@@ -656,6 +658,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
@@ -695,6 +698,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
@@ -703,6 +707,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
SKIPTEST(x1);
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
@@ -791,7 +796,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0);
|
||||
// VMIN/VMAX wll put default NaN if any input is NaN
|
||||
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
|
||||
if(!box86_dynarec_fastnan) {
|
||||
if(v0==v1) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else
|
||||
q1 = v1;
|
||||
}
|
||||
VMINQ_F32(v0, v0, v1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VCEQQ_F32(q0, v0, v0); // 0 is NaN, -1 is not NaN
|
||||
VANDQ(v0, v0, q0);
|
||||
VBICQ(q0, q1, q0);
|
||||
VORRQ(v0, v0, q0);
|
||||
}
|
||||
break;
|
||||
case 0x5E:
|
||||
INST_NAME("DIVPS Gx, Ex");
|
||||
@@ -815,7 +836,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0);
|
||||
// VMIN/VMAX wll put default NaN if any input is NaN
|
||||
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
|
||||
if(!box86_dynarec_fastnan) {
|
||||
if(v0==v1) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else
|
||||
q1 = v1;
|
||||
}
|
||||
VMAXQ_F32(v0, v0, v1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VCEQQ_F32(q0, v0, v0); // 0 is NaN, -1 is not NaN
|
||||
VANDQ(v0, v0, q0);
|
||||
VBICQ(q0, q1, q0);
|
||||
VORRQ(v0, v0, q0);
|
||||
}
|
||||
break;
|
||||
case 0x60:
|
||||
INST_NAME("PUNPCKLBW Gm,Em");
|
||||
|
||||
@@ -313,7 +313,10 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL FS:Ed");
|
||||
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
|
||||
PASS2IF((box86_dynarec_safeflags>1) ||
|
||||
((ninst && dyn->insts[ninst-1].x86.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x86.set_flags)), 1)
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
|
||||
@@ -230,7 +230,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1Q_32(v0, ed);
|
||||
VLD1Q_64(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
@@ -244,7 +244,23 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_32(v0, ed);
|
||||
VST1Q_64(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("MOVNTPD Ex, Gx");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_64(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
@@ -2295,7 +2311,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VPADDLQ_U32(q0, q0);
|
||||
break;
|
||||
case 0xF7:
|
||||
INST_NAME("MASKMOVDQU Gx, Ex")
|
||||
INST_NAME("MASKMOVDQU Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
|
||||
@@ -194,7 +194,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +204,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +216,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +228,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +240,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +252,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 +264,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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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 {
|
||||
@@ -309,7 +309,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FPTAN");
|
||||
v2 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
v2 = x87_do_push(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);
|
||||
VMOV_64(0, v1); // prepare call to tan
|
||||
CALL_1D(tan, 0);
|
||||
@@ -589,7 +589,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else {
|
||||
@@ -608,7 +608,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FSTP float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else {
|
||||
|
||||
@@ -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, NEON_CACHE_ST_F);
|
||||
v1 = x87_do_push(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)) {
|
||||
@@ -175,7 +175,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -202,7 +202,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
@@ -224,7 +224,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "bridge.h"
|
||||
#include "arm_printer.h"
|
||||
#include "custommem.h"
|
||||
|
||||
void arm_fstp(x86emu_t* emu, void* p)
|
||||
{
|
||||
@@ -109,7 +111,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
memcpy(ed, &STll(0).sq, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = fpu_round(emu, ST0.d);
|
||||
@@ -120,7 +122,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
int64_t arm_fist64_0(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = nearbyint(d);
|
||||
@@ -129,7 +131,7 @@ int64_t arm_fist64_0(double d)
|
||||
int64_t arm_fist64_1(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = floor(d);
|
||||
@@ -138,7 +140,7 @@ int64_t arm_fist64_1(double d)
|
||||
int64_t arm_fist64_2(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = ceil(d);
|
||||
@@ -147,7 +149,7 @@ int64_t arm_fist64_2(double d)
|
||||
int64_t arm_fist64_3(double d)
|
||||
{
|
||||
int64_t tmp;
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
tmp = trunc(d);
|
||||
@@ -170,6 +172,7 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
|
||||
|
||||
void arm_ud(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
}
|
||||
|
||||
@@ -608,6 +611,7 @@ void neoncacheUnwind(neoncache_t* cache)
|
||||
case NEON_CACHE_XMMW:
|
||||
cache->ssecache[cache->neoncache[i].n].reg = i+FPUFIRST;
|
||||
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
|
||||
cache->neoncache[i] = cache->neoncache[i+1];
|
||||
++cache->fpu_reg;
|
||||
++i; // next next
|
||||
break;
|
||||
@@ -702,13 +706,13 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(uint32_t*)(addr+a)
|
||||
|
||||
if(!addr)
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
|
||||
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = (uintptr_t)getAlternate(*(void**)a1);
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
if(addr<0x10000 || !getProtection(addr)) // too low, that is suspicious
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
|
||||
@@ -737,24 +741,6 @@ const char* getCacheName(int t, int n)
|
||||
return buff;
|
||||
}
|
||||
|
||||
// is inst clean for a son branch?
|
||||
int isInstClean(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
// check flags cache
|
||||
if(dyn->insts[ninst].f_entry.dfnone || dyn->insts[ninst].f_entry.pending)
|
||||
return 0;
|
||||
if(dyn->insts[ninst].x86.state_flags)
|
||||
return 0;
|
||||
// check neoncache
|
||||
neoncache_t* n = &dyn->insts[ninst].n;
|
||||
if(n->news || n->stack || n->stack_next)
|
||||
return 0;
|
||||
for(int i=0; i<24; ++i)
|
||||
if(n->neoncache[i].v)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
int jmp = dyn->insts[ninst].x86.jmp_insts;
|
||||
if(jmp<0)
|
||||
@@ -795,4 +781,58 @@ int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
|
||||
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void inst_name_pass3(dynarec_arm_t* dyn, int ninst, const char* name)
|
||||
{
|
||||
if(box86_dynarec_dump) {
|
||||
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name);
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X sm=%d/%d",
|
||||
(box86_dynarec_dump>1)?"\e[32m":"",
|
||||
(void*)(dyn->arm_start+dyn->insts[ninst].address),
|
||||
dyn->insts[ninst].size/4,
|
||||
ninst,
|
||||
dyn->insts[ninst].x86.barrier,
|
||||
dyn->insts[ninst].x86.state_flags,
|
||||
dyn->f.pending,
|
||||
dyn->f.dfnone,
|
||||
dyn->insts[ninst].x86.may_set?"may":"set",
|
||||
dyn->insts[ninst].x86.set_flags,
|
||||
dyn->insts[ninst].x86.gen_flags,
|
||||
dyn->insts[ninst].x86.use_flags,
|
||||
dyn->insts[ninst].x86.need_before,
|
||||
dyn->insts[ninst].x86.need_after,
|
||||
dyn->smread, dyn->smwrite);
|
||||
if(dyn->insts[ninst].pred_sz) {
|
||||
dynarec_log(LOG_NONE, ", pred=");
|
||||
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
|
||||
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);
|
||||
}
|
||||
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)
|
||||
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);
|
||||
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)
|
||||
dynarec_log(LOG_NONE, ", jmp=out");
|
||||
for(int ii=0; ii<24; ++ii) {
|
||||
switch(dyn->insts[ninst].n.neoncache[ii].t) {
|
||||
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
|
||||
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
|
||||
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
|
||||
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break;
|
||||
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break;
|
||||
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
|
||||
case NEON_CACHE_NONE:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack)
|
||||
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
|
||||
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
|
||||
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -71,9 +71,6 @@ int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
|
||||
// Undo the changes of a neoncache to get the status before the instruction
|
||||
void neoncacheUnwind(neoncache_t* cache);
|
||||
|
||||
// is inst clean for a son branch?
|
||||
int isInstClean(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
// predecessor access
|
||||
int isPred(dynarec_arm_t* dyn, int ninst, int pred);
|
||||
int getNominalPred(dynarec_arm_t* dyn, int ninst);
|
||||
@@ -88,4 +85,7 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
|
||||
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);
|
||||
|
||||
#endif //__DYNAREC_ARM_FUNCTIONS_H__
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -185,7 +186,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
case 1: offset = F8S; break;
|
||||
case 2: offset = F16S; break;
|
||||
}
|
||||
if(offset && (abs(offset)>absmax || (offset&mask))) {
|
||||
if(offset && (abs(offset)<=absmax && !(offset&mask))) {
|
||||
*fixaddress = offset;
|
||||
offset = 0;
|
||||
}
|
||||
@@ -861,10 +862,29 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
|
||||
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
// Synch top & stack counter
|
||||
int a = dyn->n.x87stack;
|
||||
if(a) {
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s2, s2, a);
|
||||
} else {
|
||||
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));
|
||||
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));
|
||||
}
|
||||
int ret = 0;
|
||||
for (int i=0; (i<8) && (!ret); ++i)
|
||||
if(dyn->n.x87cache[i] != -1)
|
||||
@@ -872,13 +892,20 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
if(!ret) // nothing to do
|
||||
return;
|
||||
// Get top
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
if(!a) {
|
||||
// already there
|
||||
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
|
||||
}
|
||||
// loop all cache entries
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->n.x87cache[i]!=-1) {
|
||||
ADD_IMM8(s3, s2, dyn->n.x87cache[i]);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + i)&7
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
if(dyn->n.x87cache[i]) {
|
||||
ADD_IMM8(s3, s2, dyn->n.x87cache[i]);
|
||||
AND_IMM8(s3, s3, 7); // (emu->top + i)&7
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
} else {
|
||||
ADD_REG_LSL_IMM5(s3, xEmu, s2, 3);
|
||||
}
|
||||
if(ST_IS_F(dyn->n.x87cache[i])) {
|
||||
VCVT_F64_F32(0, dyn->n.x87reg[i]*2); // use D0 as scratch...
|
||||
VSTR_64(0, s3, offsetof(x86emu_t, x87));
|
||||
@@ -887,7 +914,31 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
// go back with the top & stack counter
|
||||
int a = dyn->n.x87stack;
|
||||
if(a) {
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
SUB_IMM8(s1, s1, a);
|
||||
} else {
|
||||
ADD_IMM8(s1, s1, -a);
|
||||
}
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
if(a>0) {
|
||||
ADD_IMM8(s1, s1, a);
|
||||
} else {
|
||||
SUB_IMM8(s1, s1, -a);
|
||||
}
|
||||
AND_IMM8(s1, s1, 7);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
|
||||
}
|
||||
}
|
||||
|
||||
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
|
||||
{
|
||||
@@ -1223,7 +1274,6 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
int old = -1;
|
||||
@@ -1241,7 +1291,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VST1_32_W(dyn->n.mmxcache[i], s1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// SSE / SSE2 helpers
|
||||
@@ -1321,7 +1370,6 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
int old = -1;
|
||||
@@ -1345,7 +1393,6 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VST1Q_32_W(dyn->n.ssecache[i].reg, s1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
@@ -1446,8 +1493,10 @@ static void swapCache(dynarec_arm_t* dyn, int ninst, int i, int j, neoncache_t *
|
||||
quad =1;
|
||||
if(cache->neoncache[j].t==NEON_CACHE_XMMR || cache->neoncache[j].t==NEON_CACHE_XMMW)
|
||||
quad =1;
|
||||
if(quad) // if quad, we need to swap the whole quad!
|
||||
if(quad) { // if quad, we need to swap the whole quad!
|
||||
i&=~1;
|
||||
j&=~1;
|
||||
}
|
||||
if(!cache->neoncache[i].v && ((quad && !cache->neoncache[i+1].v) || !quad)) {
|
||||
// a mov is enough, no need to swap
|
||||
MESSAGE(LOG_DUMP, "\t - Moving %d <- %d\n", i, j);
|
||||
@@ -1717,7 +1766,7 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
stack_cnt = cache_i2.stack;
|
||||
}
|
||||
neoncache_t cache = dyn->n;
|
||||
// sanitize XMM regs alocation
|
||||
// sanitize XMM regs alocation, cache_i2 has been sanitized in neoncacheUnwind already
|
||||
for(int i=0; i<24; i+=2) {
|
||||
if(cache.neoncache[i].t == NEON_CACHE_XMMR || cache.neoncache[i].t == NEON_CACHE_XMMW)
|
||||
cache.neoncache[i+1] = cache.neoncache[i];
|
||||
@@ -1825,11 +1874,11 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->f.pending!=SF_PENDING) {
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
j32 = (GETMARK3)-(dyn->arm_size+8);
|
||||
j32 = (GETMARKF2)-(dyn->arm_size+8);
|
||||
Bcond(cEQ, j32);
|
||||
}
|
||||
CALL_(UpdateFlags, -1, 0);
|
||||
MARK3;
|
||||
MARKF2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1841,16 +1890,17 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2,
|
||||
flagsCacheTransform(dyn, ninst, s1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_reflectcache(dyn, ninst, s1, s2, s3);
|
||||
if(trace_emm)
|
||||
mmx_reflectcache(dyn, ninst, s1);
|
||||
if(trace_xmm)
|
||||
sse_reflectcache(dyn, ninst, s1);
|
||||
mmx_reflectcache(dyn, ninst, s1);
|
||||
sse_reflectcache(dyn, ninst, s1);
|
||||
}
|
||||
|
||||
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_unreflectcache(dyn, ninst, s1, s2, s3);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_reset(dynarec_arm_t* dyn)
|
||||
{
|
||||
@@ -1887,3 +1937,64 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MVN_REG_LSR_REG(s4, s4, s3);
|
||||
BFI(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
|
||||
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
|
||||
{
|
||||
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",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;
|
||||
neoncacheUnwind(&dyn->n);
|
||||
#ifdef HAVE_TRACE
|
||||
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=");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[reset_n].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
|
||||
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
|
||||
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " ==> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
|
||||
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " -> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
|
||||
if(dyn->n.combined1 || dyn->n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
|
||||
if(dyn->n.stack_push || dyn->n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
|
||||
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
|
||||
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
if(dyn->n.stack_pop) {
|
||||
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)) {
|
||||
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
|
||||
dyn->n.neoncache[j].v = 0;
|
||||
else
|
||||
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
|
||||
}
|
||||
dyn->n.stack_pop = 0;
|
||||
}
|
||||
dyn->n.stack = dyn->n.stack_next;
|
||||
dyn->n.news = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
}
|
||||
@@ -260,17 +260,19 @@
|
||||
// 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);
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKF2 if(dyn->insts) {dyn->insts[ninst].markf2 = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKF2 ((dyn->insts)?dyn->insts[ninst].markf2:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
|
||||
// Branch to MARK if cond (use j32)
|
||||
@@ -547,12 +549,13 @@ 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)
|
||||
#define x87_purgecache STEPNAME(x87_purgecache)
|
||||
#define mmx_purgecache STEPNAME(mmx_purgecache)
|
||||
#ifdef HAVE_TRACE
|
||||
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
|
||||
#endif
|
||||
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
|
||||
|
||||
// get the single reg that from the double "reg" (so Dx[idx])
|
||||
#define fpu_get_single_reg STEPNAME(fpu_get_single_reg)
|
||||
@@ -741,13 +744,16 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// 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
|
||||
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst);
|
||||
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
#endif
|
||||
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
@@ -794,4 +800,21 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
#define MAYUSE(A)
|
||||
#endif
|
||||
|
||||
#define NOTEST(s1) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s1, 0); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.test)); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
|
||||
}
|
||||
#define SKIPTEST(s1) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s1, 0); \
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
|
||||
}
|
||||
#define GOTEST(s1, s2) \
|
||||
if(box86_dynarec_test) { \
|
||||
MOVW(s2, 1); \
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, test.test)); \
|
||||
}
|
||||
|
||||
#endif //__DYNAREC_ARM_HELPER_H__
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "arm_emitter.h"
|
||||
|
||||
#define EMIT(A) *block = (A); ++block
|
||||
void CreateJmpNext(void* addr, void* next)
|
||||
{
|
||||
uint32_t* block = (uint32_t*)addr;
|
||||
LDR_literal(x2, ((intptr_t)next - (intptr_t)addr)-8);
|
||||
BX(x2);
|
||||
}
|
||||
@@ -36,7 +36,6 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
uintptr_t init_addr = addr;
|
||||
MAYUSE(init_addr);
|
||||
int need_epilog = 1;
|
||||
dyn->sons_size = 0;
|
||||
// Clean up (because there are multiple passes)
|
||||
dyn->f.pending = 0;
|
||||
dyn->f.dfnone = 0;
|
||||
@@ -57,44 +56,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->f.pending = 0;
|
||||
fpu_reset(dyn);
|
||||
} else {
|
||||
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",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;
|
||||
neoncacheUnwind(&dyn->n);
|
||||
#ifdef HAVE_TRACE
|
||||
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=");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[reset_n].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
|
||||
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
|
||||
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " ==> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->insts[ninst].n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
|
||||
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, " -> ");
|
||||
for(int i=0; i<24; ++i)
|
||||
if(dyn->n.neoncache[i].v)
|
||||
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
|
||||
if(dyn->n.combined1 || dyn->n.combined2)
|
||||
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
|
||||
if(dyn->n.stack_push || dyn->n.stack_pop)
|
||||
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
|
||||
MESSAGE(LOG_DEBUG, "\n");
|
||||
}
|
||||
#endif //HAVE_TRACE
|
||||
#else
|
||||
dyn->n = dyn->insts[reset_n].n;
|
||||
#endif
|
||||
fpu_reset_cache(dyn, ninst, reset_n);
|
||||
dyn->f = dyn->insts[reset_n].f_exit;
|
||||
if(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT) {
|
||||
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
|
||||
@@ -108,29 +70,29 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
reset_n = -1;
|
||||
}
|
||||
// propagate ST stack state, especial stack pop that are defered
|
||||
if(dyn->n.stack_pop) {
|
||||
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)) {
|
||||
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
|
||||
dyn->n.neoncache[j].v = 0;
|
||||
else
|
||||
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
|
||||
}
|
||||
dyn->n.stack_pop = 0;
|
||||
}
|
||||
dyn->n.stack = dyn->n.stack_next;
|
||||
dyn->n.news = 0;
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
NEW_INST;
|
||||
if(!ninst) {
|
||||
GOTEST(x1, x2);
|
||||
}
|
||||
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
|
||||
fpu_reset_scratch(dyn);
|
||||
if((dyn->insts[ninst].x86.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
|
||||
READFLAGS(dyn->insts[ninst].x86.need_before&~X_PEND);
|
||||
}
|
||||
if(box86_dynarec_test) {
|
||||
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
MOV32(x1, ip);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
MOVW(x2, 1);
|
||||
CALL(x86test_init, -1, 0);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(my_context->dec && box86_dynarec_trace) {
|
||||
else if(my_context->dec && box86_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) {
|
||||
MESSAGE(LOG_DUMP, "TRACE ----\n");
|
||||
@@ -140,6 +102,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
MOVW(x2, 1);
|
||||
CALL(PrintTrace, -1, 0);
|
||||
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
}
|
||||
@@ -162,13 +125,26 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->f.dfnone = 0;
|
||||
}
|
||||
}
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
#if STEP != 0
|
||||
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
// we use the 1st predecessor here
|
||||
int ii = ninst+1;
|
||||
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
|
||||
++ii;
|
||||
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))) {
|
||||
// may need to skip opcodes to advance
|
||||
++ninst;
|
||||
NEW_INST;
|
||||
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
|
||||
INST_NAME("Skipped opcode");
|
||||
INST_EPILOG;
|
||||
addr += dyn->insts[ii].x86.size;
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
if((dyn->insts[ii].x86.barrier&BARRIER_FULL)==BARRIER_FULL)
|
||||
reset_n = -2; // hack to say Barrier!
|
||||
else {
|
||||
@@ -180,20 +156,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr) {
|
||||
if(dyn->forward_to == addr && !need_epilog) {
|
||||
// we made it!
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
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);
|
||||
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) {
|
||||
// something when wrong! rollback
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
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;
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst;
|
||||
@@ -204,12 +178,12 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
// else just continue
|
||||
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
|
||||
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||
/*&& box86_dynarec_bigblock*/))
|
||||
/*||(((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
|
||||
@@ -220,30 +194,56 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
ii=ninst;
|
||||
}
|
||||
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);
|
||||
} else if(next && (next-addr<box86_dynarec_forward)
|
||||
&& (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=forwardblock*/) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
if(ok<0) {
|
||||
ok = 0; need_epilog=1;
|
||||
#if STEP == 0
|
||||
if(ninst) {
|
||||
--ninst;
|
||||
if(!dyn->insts[ninst].x86.barrier) {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
}
|
||||
dyn->insts[ninst].x86.need_after |= X_PEND;
|
||||
++ninst;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
|
||||
/*|| (dyn->size >= 2000)*/)) // is this still needed? maybe it should be a parameter?
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)))
|
||||
#else
|
||||
if(ok && (ninst==dyn->size))
|
||||
#endif
|
||||
{
|
||||
#if STEP == 0
|
||||
if(dyn->forward) {
|
||||
// stopping too soon
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst+1;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
#endif
|
||||
int j32;
|
||||
MAYUSE(j32);
|
||||
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
if(!box86_dynarec_dump && addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
|
||||
dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
|
||||
--ninst;
|
||||
if(!dyn->insts[ninst].x86.barrier) {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
@@ -252,16 +252,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
dyn->insts[ninst].x86.need_after |= X_PEND;
|
||||
#endif
|
||||
++ninst;
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_next(dyn, addr, 0, ninst);
|
||||
ok=0; need_epilog=0;
|
||||
}
|
||||
}
|
||||
if(need_epilog) {
|
||||
NOTEST(x3);
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
|
||||
}
|
||||
FINI;
|
||||
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
|
||||
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
|
||||
return addr;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
dyn->isize = addr-sav_addr;\
|
||||
dyn->insts[ninst].x86.addr = addr;\
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define MAYSETFLAGS() dyn->insts[ninst].x86.may_set = 1
|
||||
#define READFLAGS(A) \
|
||||
@@ -15,13 +16,13 @@
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)(A)); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#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 NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm_t*)box_realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
|
||||
dyn->insts = (instruction_arm_t*)customRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define FINI
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A)
|
||||
|
||||
#define NEW_INST \
|
||||
dyn->insts[ninst].f_entry = dyn->f; \
|
||||
dyn->n.combined1 = dyn->n.combined2 = 0;\
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#define INIT dyn->arm_size = 0
|
||||
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
|
||||
#define FINI \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst].x86.size>dyn->insts[ninst].size)?dyn->insts[ninst].x86.size:dyn->insts[ninst].size)/15; \
|
||||
}
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
|
||||
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->arm_size+=4;}while(0)
|
||||
#define NEW_INST \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
if(ninst && isInstClean(dyn, ninst)) \
|
||||
++dyn->sons_size; \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst-1].x86.size>dyn->insts[ninst-1].size)?dyn->insts[ninst-1].x86.size:dyn->insts[ninst-1].size)/15; \
|
||||
}
|
||||
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
|
||||
#define INST_NAME(name)
|
||||
@@ -1,65 +1,20 @@
|
||||
#define INIT
|
||||
#define FINI
|
||||
#define EMIT(A) \
|
||||
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
|
||||
*(uint32_t*)(dyn->block) = A; \
|
||||
dyn->block += 4; dyn->arm_size += 4;\
|
||||
dyn->insts[ninst].size2 += 4
|
||||
#define FINI \
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x86.size, dyn->insts[ninst].size/4); \
|
||||
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
|
||||
#define EMIT(A) \
|
||||
do{ \
|
||||
if(box86_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
|
||||
if((uintptr_t)dyn->block<(uintptr_t)dyn->next-sizeof(void*))\
|
||||
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
|
||||
dyn->block += 4; dyn->arm_size += 4; \
|
||||
dyn->insts[ninst].size2 += 4; \
|
||||
}while(0)
|
||||
|
||||
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
|
||||
#define NEW_INST \
|
||||
if(ninst && isInstClean(dyn, ninst)) { \
|
||||
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
|
||||
dyn->sons_arm[dyn->sons_size] = dyn->block; \
|
||||
MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block); \
|
||||
++dyn->sons_size; \
|
||||
}
|
||||
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x86.size, dyn->insts[ninst-1].size/4);
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name) \
|
||||
if(box86_dynarec_dump) {\
|
||||
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X sm=%d/%d", \
|
||||
(box86_dynarec_dump>1)?"\e[32m":"", \
|
||||
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
|
||||
dyn->insts[ninst].size/4, \
|
||||
ninst, \
|
||||
dyn->insts[ninst].x86.barrier, \
|
||||
dyn->insts[ninst].x86.state_flags, \
|
||||
dyn->f.pending, \
|
||||
dyn->f.dfnone, \
|
||||
dyn->insts[ninst].x86.may_set?"may":"set", \
|
||||
dyn->insts[ninst].x86.set_flags, \
|
||||
dyn->insts[ninst].x86.gen_flags, \
|
||||
dyn->insts[ninst].x86.use_flags, \
|
||||
dyn->insts[ninst].x86.need_before, \
|
||||
dyn->insts[ninst].x86.need_after, \
|
||||
dyn->smread, dyn->smwrite); \
|
||||
if(dyn->insts[ninst].pred_sz) { \
|
||||
dynarec_log(LOG_NONE, ", pred="); \
|
||||
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
|
||||
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);\
|
||||
} \
|
||||
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)\
|
||||
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);\
|
||||
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)\
|
||||
dynarec_log(LOG_NONE, ", jmp=out");\
|
||||
for(int ii=0; ii<24; ++ii) { \
|
||||
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
|
||||
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
|
||||
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
|
||||
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
|
||||
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
|
||||
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
|
||||
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
|
||||
case NEON_CACHE_NONE: \
|
||||
default: break; \
|
||||
} \
|
||||
} \
|
||||
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) \
|
||||
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack); \
|
||||
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
|
||||
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
|
||||
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
|
||||
}
|
||||
|
||||
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name)
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
#define BARRIER_MAYBE 8
|
||||
|
||||
@@ -68,7 +69,7 @@ typedef struct instruction_arm_s {
|
||||
int pred_sz; // size of predecessor list
|
||||
int *pred; // predecessor array
|
||||
uintptr_t mark, mark2, mark3;
|
||||
uintptr_t markf;
|
||||
uintptr_t markf, markf2;
|
||||
uintptr_t markseg;
|
||||
uintptr_t marklock;
|
||||
int pass2choice;// value for choices that are fixed on pass2 for pass3
|
||||
@@ -90,22 +91,23 @@ typedef struct dynarec_arm_s {
|
||||
void* block; // memory pointer where next instruction is emited
|
||||
uintptr_t arm_start; // start of the arm code
|
||||
int arm_size; // size of emitted arm code
|
||||
uintptr_t jmp_next; // address of the jump_next address
|
||||
flagcache_t f;
|
||||
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
int next_sz;
|
||||
int next_cap;
|
||||
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
|
||||
void** sons_arm; // the arm address of potential dynablock sons
|
||||
int sons_size; // number of potential dynablock sons
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
int32_t forward_size; // size at the forward point
|
||||
int forward_ninst; // ninst at the forward point
|
||||
uint8_t always_test;
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
@@ -113,4 +115,6 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
void CreateJmpNext(void* addr, void* next);
|
||||
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
@@ -1607,16 +1607,12 @@ void* ElfSetBrk(void* newbrk)
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
|
||||
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
|
||||
{
|
||||
// if we are here, the there is not block in standard "space"
|
||||
/*dynablocklist_t* ret = getDBFromAddress(addr);
|
||||
if(ret) {
|
||||
return ret;
|
||||
}*/
|
||||
(void)context;
|
||||
if(box86_dynarec_forced) {
|
||||
addDBFromAddressRange(addr, 1);
|
||||
return getDB(addr>>DYNAMAP_SHIFT);
|
||||
return getDB(addr);
|
||||
}
|
||||
//check if address is in an elf... if yes, grant a block (should I warn)
|
||||
Dl_info info;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#ifndef __ELFLOADER_PRIVATE_H_
|
||||
#define __ELFLOADER_PRIVATE_H_
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
#endif
|
||||
|
||||
typedef struct library_s library_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
#include <string.h>
|
||||
|
||||
#define F8 *(uint8_t*)(addr++)
|
||||
#define F8S *(int8_t*)(addr++)
|
||||
#define F16 *(uint16_t*)(addr+=2, addr-2)
|
||||
#define F16S *(int16_t*)(addr+=2, addr-2)
|
||||
#define F32 *(uint32_t*)(addr+=4, addr-4)
|
||||
#define F32S *(int32_t*)(addr+=4, addr-4)
|
||||
#define F32S64 (uint64_t)(int64_t)F32S
|
||||
#define F64 *(uint64_t*)(addr+=8, addr-8)
|
||||
#define F64S *(int64_t*)(addr+=8, addr-8)
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#ifdef DYNAREC
|
||||
#define STEP if(step) return 0;
|
||||
#define STEP2 if(step) {R_EIP = addr; return 0;}
|
||||
#define STEP3 if(*step) (*step)++;
|
||||
#else
|
||||
#define STEP
|
||||
#define STEP2
|
||||
#define STEP3
|
||||
#endif
|
||||
|
||||
// ModRM utilities macros
|
||||
#define getecommon(A, T) \
|
||||
if(!(nextop&0xC0)) { \
|
||||
@@ -97,6 +119,17 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else getecommon(A, reg32_t)
|
||||
#define testeb(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
getecommono(ret, reg32_t, O);\
|
||||
test->memsize = 1; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
test->mem[0] = ret->byte[0];\
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getebo(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
@@ -109,14 +142,47 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommono(A, reg32_t, O)
|
||||
#define tested(A, SZ, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else {\
|
||||
reg32_t* ret; \
|
||||
getecommono(ret, reg32_t, O);\
|
||||
test->memsize = SZ; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->dword, SZ);\
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else getecommon(A, mmx87_regs_t)
|
||||
#define testem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else {\
|
||||
mmx87_regs_t* ret; \
|
||||
getecommon(ret, mmx87_regs_t) \
|
||||
test->memsize = 8; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->ub, 8);\
|
||||
A = (mmx87_regs_t*)test->mem;\
|
||||
}
|
||||
#define getex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else getecommon(A, sse_regs_t)
|
||||
#define testex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else {\
|
||||
sse_regs_t* ret; \
|
||||
getecommon(ret, sse_regs_t);\
|
||||
test->memsize = 16; \
|
||||
test->memaddr = (uintptr_t)ret;\
|
||||
memcpy(test->mem, ret->ub, 16);\
|
||||
A = (sse_regs_t*)test->mem;\
|
||||
}
|
||||
#define getew16(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
@@ -125,16 +191,44 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16o(A, reg32_t, O)
|
||||
#define testtew16(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
getecommon16o(A, reg32_t, O); \
|
||||
test->memsize = 2; \
|
||||
test->memaddr = (uintptr_t)ret; \
|
||||
*(uint16_t*)test->mem = ret->word[0];\
|
||||
A = (reg32_t*)test->mem; \
|
||||
}
|
||||
|
||||
// Macros for ModR/M gets
|
||||
#ifdef TEST_INTERPRETER
|
||||
#define GET_EB testeb(oped, 0)
|
||||
#define GET_ED tested(oped, 4, 0)
|
||||
#define GET_ED8 tested(oped, 8, 0)
|
||||
#define GET_EDT tested(oped, 10, 0)
|
||||
#define GET_ED_OFFS(o) tested(oped, 4, o)
|
||||
#define GET_EB_OFFS(o) testeb(oped, o)
|
||||
#define GET_EM testem(opem)
|
||||
#define GET_EX testex(opex)
|
||||
#define GET_EW16 testew16(oped, 0)
|
||||
#define GET_EW16_OFFS(o) testtew16(oped, o)
|
||||
#else
|
||||
#define GET_EB geteb(oped)
|
||||
#define GET_ED geted(oped)
|
||||
#define GET_ED8 geted(oped)
|
||||
#define GET_EDT geted(oped)
|
||||
#define GET_ED_OFFS(o) getedo(oped, o)
|
||||
#define GET_EB_OFFS(o) getebo(oped, o)
|
||||
#define GET_EM getem(opem)
|
||||
#define GET_EX getex(opex)
|
||||
#define GET_EW16 getew16(oped)
|
||||
#define GET_EW16_OFFS(o) getew16o(oped, o)
|
||||
#endif
|
||||
#define GET_ED_ geted(oped)
|
||||
#define GET_EW16_ getew16(oped)
|
||||
#define EB oped
|
||||
#define ED oped
|
||||
#define EM opem
|
||||
|
||||
-555
@@ -1,555 +0,0 @@
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
|
||||
#define GO(B, OP) \
|
||||
_66_##B##_0: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
NEXT; \
|
||||
_66_##B##_1: \
|
||||
nextop = F8; \
|
||||
GET_EW; \
|
||||
EW->word[0] = OP##16(emu, EW->word[0], GW.word[0]); \
|
||||
NEXT; \
|
||||
_66_##B##_2: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
NEXT; \
|
||||
_66_##B##_3: \
|
||||
nextop = F8; \
|
||||
GET_EW; \
|
||||
GW.word[0] = OP##16(emu, GW.word[0], EW->word[0]); \
|
||||
NEXT; \
|
||||
_66_##B##_4: \
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
NEXT; \
|
||||
_66_##B##_5: \
|
||||
R_AX = OP##16(emu, R_AX, F16); \
|
||||
NEXT;
|
||||
|
||||
GO(0x00, add) /* ADD 0x01 ~> 0x05 */
|
||||
GO(0x08, or) /* OR 0x09 ~> 0x0D */
|
||||
GO(0x10, adc) /* ADC 0x11 ~> 0x15 */
|
||||
GO(0x18, sbb) /* SBB 0x19 ~> 0x1D */
|
||||
GO(0x20, and) /* AND 0x21 ~> 0x25 */
|
||||
GO(0x28, sub) /* SUB 0x29 ~> 0x2D */
|
||||
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
|
||||
//GO(0x38, cmp) /* CMP 0x39 ~> 0x3D */
|
||||
#undef GO
|
||||
_66_0x06: /* PUSH ES */
|
||||
Push16(emu, emu->segs[_ES]);
|
||||
NEXT;
|
||||
_66_0x07: /* POP ES */
|
||||
emu->segs[_ES] = Pop16(emu); // no check, no use....
|
||||
emu->segs_serial[_ES] = 0;
|
||||
NEXT;
|
||||
|
||||
_66_0x0F: /* 66 0f prefix */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-2; // don't count 66 0F yet
|
||||
Run660F(emu); // implemented in Run660f.c
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP
|
||||
NEXT;
|
||||
|
||||
_66_0x1E: /* PUSH DS */
|
||||
Push16(emu, emu->segs[_DS]);
|
||||
NEXT;
|
||||
_66_0x1F: /* POP DS */
|
||||
emu->segs[_DS] = Pop16(emu); // no check, no use....
|
||||
emu->segs_serial[_DS] = 0;
|
||||
NEXT;
|
||||
|
||||
_66_0x26: /* ES: */
|
||||
// ignored
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
_66_0x2E: /* CS: */
|
||||
// ignored
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
_66_0x36: /* SS: */
|
||||
// ignored
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
|
||||
_66_0x39:
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
cmp16(emu, EW->word[0], GW.word[0]);
|
||||
NEXT;
|
||||
_66_0x3B:
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
cmp16(emu, GW.word[0], EW->word[0]);
|
||||
NEXT;
|
||||
_66_0x3D:
|
||||
cmp16(emu, R_AX, F16);
|
||||
NEXT;
|
||||
_66_0x3E: /* DS: */
|
||||
// ignored
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
|
||||
_66_0x40:
|
||||
_66_0x41:
|
||||
_66_0x42:
|
||||
_66_0x43:
|
||||
_66_0x44:
|
||||
_66_0x45:
|
||||
_66_0x46:
|
||||
_66_0x47: /* INC Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].word[0] = inc16(emu, emu->regs[tmp8u].word[0]);
|
||||
NEXT;
|
||||
_66_0x48:
|
||||
_66_0x49:
|
||||
_66_0x4A:
|
||||
_66_0x4B:
|
||||
_66_0x4C:
|
||||
_66_0x4D:
|
||||
_66_0x4E:
|
||||
_66_0x4F: /* DEC Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].word[0] = dec16(emu, emu->regs[tmp8u].word[0]);
|
||||
NEXT;
|
||||
_66_0x50:
|
||||
_66_0x51:
|
||||
_66_0x52:
|
||||
_66_0x53:
|
||||
_66_0x54:
|
||||
_66_0x55:
|
||||
_66_0x56:
|
||||
_66_0x57: /* PUSH Reg */
|
||||
tmp8u = opcode&7;
|
||||
Push16(emu, emu->regs[tmp8u].word[0]);
|
||||
NEXT;
|
||||
_66_0x58:
|
||||
_66_0x59:
|
||||
_66_0x5A:
|
||||
_66_0x5B:
|
||||
_66_0x5C:
|
||||
_66_0x5D:
|
||||
_66_0x5E:
|
||||
_66_0x5F: /* POP Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].word[0] = Pop16(emu);
|
||||
NEXT;
|
||||
_66_0x60: /* PUSHA */
|
||||
tmp16u = R_SP;
|
||||
Push16(emu, R_AX);
|
||||
Push16(emu, R_CX);
|
||||
Push16(emu, R_DX);
|
||||
Push16(emu, R_BX);
|
||||
Push16(emu, tmp16u);
|
||||
Push16(emu, R_BP);
|
||||
Push16(emu, R_SI);
|
||||
Push16(emu, R_DI);
|
||||
NEXT;
|
||||
_66_0x61: /* POPA */
|
||||
R_DI = Pop16(emu);
|
||||
R_SI = Pop16(emu);
|
||||
R_BP = Pop16(emu);
|
||||
R_ESP+=2; // POP ESP
|
||||
R_BX = Pop16(emu);
|
||||
R_DX = Pop16(emu);
|
||||
R_CX = Pop16(emu);
|
||||
R_AX = Pop16(emu);
|
||||
NEXT;
|
||||
|
||||
_66_0x64:
|
||||
R_EIP = ip-2;
|
||||
RunFS66(emu, GetFSBaseEmu(emu));
|
||||
ip = R_EIP;
|
||||
STEP;
|
||||
NEXT;
|
||||
|
||||
_66_0x66:
|
||||
goto _0x66; // 0x66 0x66 => can remove one 0x66
|
||||
|
||||
_66_0x68: /* PUSH u16 */
|
||||
tmp16u = F16;
|
||||
Push16(emu, tmp16u);
|
||||
NEXT;
|
||||
_66_0x69: /* IMUL Gw,Ew,Iw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp16u = F16;
|
||||
GW.word[0] = imul16(emu, EW->word[0], tmp16u);
|
||||
NEXT;
|
||||
_66_0x6A: /* PUSH Ib (as signed word) */
|
||||
tmp16s = F8S;
|
||||
Push16(emu, (uint16_t)tmp16s);
|
||||
NEXT;
|
||||
_66_0x6B: /* IMUL Gw,Ew,Ib */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp16s = F8S;
|
||||
GW.word[0] = imul16(emu, EW->word[0], (uint16_t)tmp16s);
|
||||
NEXT;
|
||||
|
||||
_66_0x81: /* GRP3 Ew,Iw */
|
||||
_66_0x83: /* GRP3 Ew,Ib */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
if(opcode==0x81)
|
||||
tmp16u = F16;
|
||||
else {
|
||||
tmp16s = F8S;
|
||||
tmp16u = (uint16_t)tmp16s;
|
||||
}
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EW->word[0] = add16(emu, EW->word[0], tmp16u); break;
|
||||
case 1: EW->word[0] = or16(emu, EW->word[0], tmp16u); break;
|
||||
case 2: EW->word[0] = adc16(emu, EW->word[0], tmp16u); break;
|
||||
case 3: EW->word[0] = sbb16(emu, EW->word[0], tmp16u); break;
|
||||
case 4: EW->word[0] = and16(emu, EW->word[0], tmp16u); break;
|
||||
case 5: EW->word[0] = sub16(emu, EW->word[0], tmp16u); break;
|
||||
case 6: EW->word[0] = xor16(emu, EW->word[0], tmp16u); break;
|
||||
case 7: cmp16(emu, EW->word[0], tmp16u); break;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_66_0x85: /* TEST Ew,Gw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
test16(emu, EW->word[0], GW.word[0]);
|
||||
NEXT;
|
||||
|
||||
_66_0x87: /* XCHG Ew,Gw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp16u = GW.word[0];
|
||||
GW.word[0] = EW->word[0];
|
||||
EW->word[0] = tmp16u;
|
||||
NEXT;
|
||||
|
||||
_66_0x89: /* MOV Ew,Gw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
EW->word[0] = GW.word[0];
|
||||
NEXT;
|
||||
|
||||
_66_0x8B: /* MOV Gw,Ew */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
GW.word[0] = EW->word[0];
|
||||
NEXT;
|
||||
_66_0x8C: /* MOV Ew,Seg */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
EW->word[0] = emu->segs[(nextop&0x38)>>3];
|
||||
NEXT;
|
||||
|
||||
_66_0x8E: /* MOV Seg,Ew */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
|
||||
emu->segs_serial[((nextop&0x38)>>3)] = 0;
|
||||
NEXT;
|
||||
_66_0x8F: /* POP Ew */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
EW->word[0] = Pop16(emu);
|
||||
NEXT;
|
||||
_66_0x90: /* NOP */
|
||||
NEXT;
|
||||
|
||||
_66_0x91:
|
||||
_66_0x92:
|
||||
_66_0x93:
|
||||
_66_0x94:
|
||||
_66_0x95:
|
||||
_66_0x96:
|
||||
_66_0x97: /* XCHG reg,EAX */
|
||||
tmp16u = R_AX;
|
||||
R_AX = emu->regs[opcode&7].word[0];
|
||||
emu->regs[opcode&7].word[0] = tmp16u;
|
||||
NEXT;
|
||||
|
||||
_66_0x98: /* CBW */
|
||||
emu->regs[_AX].sword[0] = emu->regs[_AX].sbyte[0];
|
||||
NEXT;
|
||||
_66_0x99: /* CWD */
|
||||
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
|
||||
NEXT;
|
||||
|
||||
_66_0x9C: /* PUSHFW */
|
||||
CHECK_FLAGS(emu);
|
||||
Push16(emu, (uint16_t)emu->eflags.x32);
|
||||
NEXT;
|
||||
_66_0x9D: /* POPFW */
|
||||
CHECK_FLAGS(emu);
|
||||
emu->eflags.x32 &=0xffff0000;
|
||||
emu->eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
|
||||
NEXT;
|
||||
|
||||
_66_0xA1: /* MOV AX,Ow */
|
||||
R_AX = *(uint16_t*)F32;
|
||||
NEXT;
|
||||
_66_0xA3: /* MOV Ow,AX */
|
||||
*(uint16_t*)F32 = R_AX;
|
||||
NEXT;
|
||||
_66_0xA5: /* MOVSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
*(uint16_t*)R_EDI = *(uint16_t*)R_ESI;
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
NEXT;
|
||||
|
||||
_66_0xA7: /* CMPSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
tmp16u = *(uint16_t*)R_EDI;
|
||||
tmp16u2 = *(uint16_t*)R_ESI;
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
cmp16(emu, tmp16u2, tmp16u);
|
||||
NEXT;
|
||||
|
||||
_66_0xA9: /* TEST AX,Iw */
|
||||
test16(emu, R_AX, F16);
|
||||
NEXT;
|
||||
|
||||
_66_0xAB: /* STOSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
*(uint16_t*)R_EDI = R_AX;
|
||||
R_EDI += tmp8s;
|
||||
NEXT;
|
||||
_66_0xAD: /* LODSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
R_AX = *(uint16_t*)R_ESI;
|
||||
R_ESI += tmp8s;
|
||||
NEXT;
|
||||
_66_0xAF: /* SCASW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
cmp16(emu, R_AX, *(uint16_t*)R_EDI);
|
||||
R_EDI += tmp8s;
|
||||
NEXT;
|
||||
|
||||
_66_0xB8: /* MOV AX,Iw */
|
||||
_66_0xB9: /* MOV CX,Iw */
|
||||
_66_0xBA: /* MOV DX,Iw */
|
||||
_66_0xBB: /* MOV BX,Iw */
|
||||
_66_0xBC: /* ... */
|
||||
_66_0xBD:
|
||||
_66_0xBE:
|
||||
_66_0xBF:
|
||||
emu->regs[opcode&7].word[0] = F16;
|
||||
NEXT;
|
||||
|
||||
_66_0xC1: /* GRP2 Ew,Ib */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp8u = F8 /*& 0x1f*/;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;
|
||||
case 1: EW->word[0] = ror16(emu, EW->word[0], tmp8u); break;
|
||||
case 2: EW->word[0] = rcl16(emu, EW->word[0], tmp8u); break;
|
||||
case 3: EW->word[0] = rcr16(emu, EW->word[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: EW->word[0] = shl16(emu, EW->word[0], tmp8u); break;
|
||||
case 5: EW->word[0] = shr16(emu, EW->word[0], tmp8u); break;
|
||||
case 7: EW->word[0] = sar16(emu, EW->word[0], tmp8u); break;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_66_0xC7: /* MOV Ew,Iw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
EW->word[0] = F16;
|
||||
NEXT;
|
||||
|
||||
_66_0xCB: /* FAR RET */
|
||||
ip = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu); // no check, no use....
|
||||
emu->segs_serial[_CS] = 0;
|
||||
// need to check status of CS register!
|
||||
STEP
|
||||
NEXT;
|
||||
_66_0xCC: /* INT3 */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-1;
|
||||
if(my_context->signals[SIGTRAP])
|
||||
raise(SIGTRAP);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP
|
||||
NEXT;
|
||||
_66_0xD1: /* GRP2 Ew,1 */
|
||||
_66_0xD3: /* GRP2 Ew,CL */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp8u=(opcode==0xD3)?R_CL:1;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;
|
||||
case 1: EW->word[0] = ror16(emu, EW->word[0], tmp8u); break;
|
||||
case 2: EW->word[0] = rcl16(emu, EW->word[0], tmp8u); break;
|
||||
case 3: EW->word[0] = rcr16(emu, EW->word[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: EW->word[0] = shl16(emu, EW->word[0], tmp8u); break;
|
||||
case 5: EW->word[0] = shr16(emu, EW->word[0], tmp8u); break;
|
||||
case 7: EW->word[0] = sar16(emu, EW->word[0], tmp8u); break;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_66_0xD9:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
Run66D9(emu);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP
|
||||
NEXT;
|
||||
|
||||
_66_0xDD:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
Run66DD(emu);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP
|
||||
NEXT;
|
||||
|
||||
_66_0xF0: /* LOCK prefix */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip - 2;
|
||||
RunLock66(emu);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP
|
||||
NEXT;
|
||||
|
||||
_66_0xF2: /* REPNZ prefix */
|
||||
_66_0xF3: /* REPZ prefix */
|
||||
nextop = F8;
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
|
||||
tmp32u = R_ECX;
|
||||
switch(nextop) {
|
||||
case 0xA4: /* REP MOVSB */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
break;
|
||||
case 0xA5: /* REP MOVSW */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
*(uint16_t*)R_EDI = *(uint16_t*)R_ESI;
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
break;
|
||||
case 0xA7: /* REP(N)Z CMPSW */
|
||||
tmp16u = 0;
|
||||
tmp16u2 = 0;
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
tmp16u = *(uint16_t*)R_EDI;
|
||||
tmp16u2 = *(uint16_t*)R_ESI;
|
||||
R_EDI += tmp8s;
|
||||
R_ESI += tmp8s;
|
||||
if((tmp16u==tmp16u2)==(opcode==0xF2))
|
||||
break;
|
||||
}
|
||||
if(R_ECX) cmp16(emu, tmp16u2, tmp16u);
|
||||
break;
|
||||
case 0xAB: /* REP STOSW */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
*(uint16_t*)R_EDI = R_AX;
|
||||
R_EDI += tmp8s;
|
||||
}
|
||||
break;
|
||||
case 0xAD: /* REP LODSW */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
R_AX = *(uint16_t*)R_ESI;
|
||||
R_ESI += tmp8s;
|
||||
}
|
||||
break;
|
||||
case 0xAF: /* REP(N)Z SCASW */
|
||||
tmp16u = 0;
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
tmp16u = *(uint16_t*)R_EDI;
|
||||
R_EDI += tmp8s;
|
||||
if((R_AX==tmp16u)==(opcode==0xF2))
|
||||
break;
|
||||
}
|
||||
if(R_ECX) cmp16(emu, R_AX, tmp16u);
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
R_ECX = tmp32u;
|
||||
NEXT;
|
||||
|
||||
_66_0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
|
||||
NEXT;
|
||||
|
||||
_66_0xF7: /* GRP3 Ew(,Iw) */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
case 1: /* TEST Ew,Iw */
|
||||
test16(emu, EW->word[0], F16);
|
||||
break;
|
||||
case 2: /* NOT Ew */
|
||||
EW->word[0] = not16(emu, EW->word[0]);
|
||||
break;
|
||||
case 3: /* NEG Ew */
|
||||
EW->word[0] = neg16(emu, EW->word[0]);
|
||||
break;
|
||||
case 4: /* MUL AX,Ew */
|
||||
mul16(emu, EW->word[0]);
|
||||
break;
|
||||
case 5: /* IMUL AX,Ew */
|
||||
imul16_eax(emu, EW->word[0]);
|
||||
break;
|
||||
case 6: /* DIV Ew */
|
||||
div16(emu, EW->word[0]);
|
||||
break;
|
||||
case 7: /* IDIV Ew */
|
||||
idiv16(emu, EW->word[0]);
|
||||
break;
|
||||
}
|
||||
NEXT;
|
||||
_66_0xF8: /* CLC */
|
||||
CHECK_FLAGS(emu);
|
||||
CLEAR_FLAG(F_CF);
|
||||
NEXT;
|
||||
_66_0xF9: /* STC */
|
||||
CHECK_FLAGS(emu);
|
||||
SET_FLAG(F_CF);
|
||||
NEXT;
|
||||
|
||||
_66_0xFF: /* GRP 5 Ew */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
EW->word[0] = inc16(emu, EW->word[0]);
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
EW->word[0] = dec16(emu, EW->word[0]);
|
||||
break;
|
||||
case 6:
|
||||
Push16(emu, EW->word[0]);
|
||||
break;
|
||||
default:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode 66 %02X %02X\n", opcode, nextop);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
}
|
||||
NEXT;
|
||||
+38
-12
@@ -54,17 +54,6 @@ uint32_t* GetParityTab()
|
||||
return x86emu_parity_tab;
|
||||
}
|
||||
|
||||
void PushExit(x86emu_t* emu)
|
||||
{
|
||||
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
Push(emu, endMarker);
|
||||
}
|
||||
|
||||
void* GetExit()
|
||||
{
|
||||
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
|
||||
}
|
||||
|
||||
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||
{
|
||||
emu->context = context;
|
||||
@@ -198,6 +187,11 @@ void FreeX86Emu(x86emu_t **emu)
|
||||
return;
|
||||
printf_log(LOG_DEBUG, "%04d|Free a X86 Emu (%p)\n", GetTID(), *emu);
|
||||
|
||||
if((*emu)->test.emu) {
|
||||
internalFreeX86((*emu)->test.emu);
|
||||
box_free((*emu)->test.emu);
|
||||
(*emu)->test.emu = NULL;
|
||||
}
|
||||
internalFreeX86(*emu);
|
||||
|
||||
box_free(*emu);
|
||||
@@ -231,6 +225,10 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
newemu->df = emu->df;
|
||||
newemu->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
@@ -240,6 +238,34 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
|
||||
}
|
||||
|
||||
void CopyEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
{
|
||||
memcpy(newemu->regs, emu->regs, sizeof(emu->regs));
|
||||
memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip));
|
||||
memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags));
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memcpy(newemu->segs_serial, emu->segs_serial, sizeof(emu->segs_serial));
|
||||
memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
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->cw = emu->cw;
|
||||
newemu->sw = emu->sw;
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
newemu->df = emu->df;
|
||||
newemu->op1 = emu->op1;
|
||||
newemu->op2 = emu->op2;
|
||||
newemu->res = emu->res;
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
newemu->error = emu->error;
|
||||
}
|
||||
|
||||
box86context_t* GetEmuContext(x86emu_t* emu)
|
||||
{
|
||||
return emu->context;
|
||||
@@ -311,7 +337,7 @@ void ResetFlags(x86emu_t *emu)
|
||||
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
|
||||
{
|
||||
static char buff[800];
|
||||
char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
static const char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
char tmp[80];
|
||||
buff[0] = '\0';
|
||||
if(trace_emm) {
|
||||
|
||||
@@ -23,6 +23,17 @@ typedef struct forkpty_s {
|
||||
void* f; // forkpty function
|
||||
} forkpty_t;
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef struct x86test_s {
|
||||
x86emu_t* emu;
|
||||
uintptr_t memaddr;
|
||||
int memsize;
|
||||
int test;
|
||||
int clean;
|
||||
uint8_t mem[16];
|
||||
} x86test_t;
|
||||
|
||||
typedef struct x86emu_s {
|
||||
// cpu
|
||||
reg32_t regs[8];
|
||||
@@ -63,6 +74,7 @@ typedef struct x86emu_s {
|
||||
int exit;
|
||||
int quitonlongjmp; // quit if longjmp is called
|
||||
int longjmp; // if quit because of longjmp
|
||||
x86test_t test; // used for dynarec testing
|
||||
// parent context
|
||||
box86context_t *context;
|
||||
// cpu helpers
|
||||
|
||||
+967
-1011
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,459 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uintptr_t tlsdata = (seg==_FS)?GetFSBaseEmu(emu):GetGSBaseEmu(emu);
|
||||
switch(opcode) {
|
||||
case 0x01: /* ADD GS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x03: /* ADD Gd, GS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x06: /* PUSH ES */
|
||||
Push(emu, emu->segs[_ES]);
|
||||
break;
|
||||
case 0x07: /* POP ES */
|
||||
emu->segs[_ES] = Pop(emu);
|
||||
emu->segs_serial[_ES] = 0;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test640F(test, tlsdata, addr);
|
||||
#else
|
||||
return Run640F(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x11: /* ADC GS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x13: /* ADC Gd, GS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = adc32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x21: /* AND Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = and32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x23: /* AND Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = and32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x29: /* SUB GS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = sub32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x2B: /* SUB Gd, GS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x31: /* XOR Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = xor32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x33: /* XOR Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x39: /* CMP Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
cmp32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x3B: /* CMP Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
cmp32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x43:
|
||||
case 0x44:
|
||||
case 0x45:
|
||||
case 0x46:
|
||||
case 0x47: /* INC Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].dword[0] = inc32(emu, emu->regs[tmp8u].dword[0]);
|
||||
break;
|
||||
case 0x48:
|
||||
case 0x49:
|
||||
case 0x4A:
|
||||
case 0x4B:
|
||||
case 0x4C:
|
||||
case 0x4D:
|
||||
case 0x4E:
|
||||
case 0x4F: /* DEC Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].dword[0] = dec32(emu, emu->regs[tmp8u].dword[0]);
|
||||
break;
|
||||
case 0x50: /* PUSH Reg */
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x54: /* PUSH ESP */
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
case 0x58: /* POP Reg */
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C: /* POP ESP */
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
// Segment override if for memory loc, no stack segment
|
||||
return addr-1;
|
||||
|
||||
case 0x64: /* FS: */
|
||||
// so just ignore that GS: prefix then
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test64(test, _FS, addr-1); // put FS back
|
||||
#else
|
||||
return Run64(emu, _FS, addr-1); // put FS back
|
||||
#endif
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6466(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6466(emu, tlsdata, addr);
|
||||
#endif
|
||||
case 0x67:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6467(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6467(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x69: /* IMUL Gd,Ed,Id */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
tmp32u = F32;
|
||||
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0x74:
|
||||
case 0x75:
|
||||
case 0x76:
|
||||
case 0x77:
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
case 0x7A:
|
||||
case 0x7B:
|
||||
case 0x7C:
|
||||
case 0x7D:
|
||||
case 0x7E:
|
||||
case 0x7F:
|
||||
// just ignore the prefix
|
||||
return addr-1;
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
tmp8u = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
|
||||
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if(opcode==0x83) {
|
||||
tmp32s = F8S;
|
||||
tmp32u = (uint32_t)tmp32s;
|
||||
} else
|
||||
tmp32u = F32;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
|
||||
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
|
||||
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
|
||||
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
|
||||
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
|
||||
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
|
||||
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
break;
|
||||
case 0x87:
|
||||
nextop = F8;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
} else {
|
||||
if(((uintptr_t)ED)&3)
|
||||
{
|
||||
// not aligned, dont't try to "LOCK"
|
||||
tmp32u = ED->dword[0];
|
||||
ED->dword[0] = GD.dword[0];
|
||||
GD.dword[0] = tmp32u;
|
||||
} else {
|
||||
// XCHG is supposed to automaticaly LOCK memory bus
|
||||
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = GD.dword[0];
|
||||
break;
|
||||
case 0x8A: /* MOV Gb,GS:Eb */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
GB = EB->byte[0];
|
||||
break;
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
break;
|
||||
case 0x8C: /* MOV Seg:Ed, Seg */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
break;
|
||||
case 0x8E: /* MOV Seg,Seg:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
emu->segs[((nextop&0x38)>>3)] = ED->word[0];
|
||||
emu->segs_serial[((nextop&0x38)>>3)] = 0;
|
||||
break;
|
||||
case 0x8F: /* POP Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = Pop(emu);
|
||||
break;
|
||||
|
||||
case 0x9C: /* PUSHFD */
|
||||
// Segment override if for memory loc, no stack segment
|
||||
return addr-1; // so ignore prefix and continue
|
||||
|
||||
case 0xA0: /* MOV AL,Ob */
|
||||
tmp32s = F32S;
|
||||
R_AL = *(uint8_t*)((tlsdata) + tmp32s);
|
||||
break;
|
||||
case 0xA1: /* MOV EAX,Ov */
|
||||
tmp32s = F32S;
|
||||
R_EAX = *(uint32_t*)((tlsdata) + tmp32s);
|
||||
break;
|
||||
case 0xA2: /* MOV Ob,AL */
|
||||
tmp32s = F32S;
|
||||
*(uint8_t*)((tlsdata) + tmp32s) = R_AL;
|
||||
break;
|
||||
case 0xA3: /* MOV Od,EAX */
|
||||
tmp32s = F32S;
|
||||
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
|
||||
break;
|
||||
|
||||
case 0xA8: /* TEST AL, Ib */
|
||||
test8(emu, R_AL, F8);
|
||||
break;
|
||||
|
||||
case 0xC0: /* GRP2 Eb,Ib */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
tmp8u = F8/* & 0x1f*/; // masking done in each functions
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC6: /* MOV Eb,Ib */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
EB->byte[0] = F8;
|
||||
break;
|
||||
case 0xC7: /* MOV Ed,Id */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
case 0xD0: /* GRP2 Eb,1 */
|
||||
case 0xD2: /* GRP2 Eb,CL */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
tmp8u = (opcode==0xD0)?1:R_CL;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
case 0xD1: /* GRP2 Ed,1 */
|
||||
case 0xD3: /* GRP2 Ed,CL */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
tmp8u = (opcode==0xD1)?1:R_CL;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
|
||||
case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
|
||||
case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
return addr-1; // ignore FS: to execute regular opcode
|
||||
break;
|
||||
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
ED->dword[0] = inc32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
R_EIP = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
Push(emu, addr);
|
||||
addr = R_EIP;
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, addr);
|
||||
addr = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
addr = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
case 6: /* Push Ed */
|
||||
Push(emu, ED->dword[0]);
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run640F(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xAF: /* IMUL Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = imul32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gd,GS:Eb */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
GD.dword[0] = EB->byte[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03: /* ADD Gw, FS:Ew */
|
||||
nextop = F8;
|
||||
GET_EW_OFFS(tlsdata);
|
||||
GW.word[0] = add16(emu, GW.word[0], EW->word[0]);
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gw,FS:Ew */
|
||||
nextop = F8;
|
||||
GET_EW_OFFS(tlsdata);
|
||||
GW.word[0] = EW->word[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x3B: /* CMP GD, FS:Ed16 */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
cmp32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV ED16,Gd */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = GD.dword[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed16 */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8F: /* POP FS:Ed */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = Pop(emu);
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Ov16 */
|
||||
tmp32u = F16;
|
||||
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
|
||||
break;
|
||||
case 0xA3: /* MOV Ov16,EAX */
|
||||
tmp32u = F16;
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr = tlsdata + tmp32u;
|
||||
test->memsize = 4;
|
||||
*(uint32_t*)(test->mem) = R_EAX;
|
||||
#else
|
||||
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
|
||||
#endif
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: /* Push Ed */
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
Push(emu, ED->dword[0]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
+520
-1634
File diff suppressed because it is too large.
Load diff
+119
-102
@@ -14,19 +14,14 @@
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#define F8 *(uint8_t*)(ip++)
|
||||
#define F8S *(int8_t*)(ip++)
|
||||
#define F16 *(uint16_t*)(ip+=2, ip-2)
|
||||
#define F16S *(int16_t*)(ip+=2, ip-2)
|
||||
#define F32 *(uint32_t*)(ip+=4, ip-4)
|
||||
#define F32S *(int32_t*)(ip+=4, ip-4)
|
||||
#define PK(a) *(uint8_t*)(ip+a)
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
void Run660F(x86emu_t *emu)
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test660F(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uintptr_t ip = R_EIP+2; //skip 66 0F
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
@@ -43,6 +38,9 @@ void Run660F(x86emu_t *emu)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
@@ -144,8 +142,7 @@ void Run660F(x86emu_t *emu)
|
||||
EW->word[0] = 0; // dummy operation. Should be CR0 -> Ew
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x10: /* MOVUPD Gx, Ex */
|
||||
@@ -160,7 +157,7 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
case 0x12: /* MOVLPD Gx, Eq */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 7)
|
||||
memcpy(&GX.q[0], ED, 8);
|
||||
else
|
||||
@@ -168,7 +165,7 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
case 0x13: /* MOVLPD Eq, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 7)
|
||||
memcpy(ED, &GX.q[0], 8);
|
||||
else
|
||||
@@ -187,18 +184,18 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
case 0x16: /* MOVHPD Gx, Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
GX.q[1] = *(uint64_t*)ED;
|
||||
break;
|
||||
case 0x17: /* MOVHPD Ed, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
*(uint64_t*)ED = GX.q[1];
|
||||
break;
|
||||
|
||||
case 0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
break;
|
||||
|
||||
case 0x28: /* MOVAPD Gx, Ex */
|
||||
@@ -219,16 +216,20 @@ void Run660F(x86emu_t *emu)
|
||||
GX.d[0] = EM->sd[0];
|
||||
GX.d[1] = EM->sd[1];
|
||||
break;
|
||||
|
||||
|
||||
case 0x2B: /* MOVNTPD Ex, Gx */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
EX->q[0] = GX.q[0]; // Address needs to ba aligned for MOVNTPD
|
||||
EX->q[1] = GX.q[1];
|
||||
break;
|
||||
case 0x2C: /* CVTTPD2PI Gm, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
|
||||
GM.ud[0] = 0x80000000;
|
||||
else
|
||||
GM.sd[0] = EX->d[0];
|
||||
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
|
||||
if(!isfinite(EX->d[1]) || EX->d[1]>(double)0x7fffffff || EX->d[1]<-(double)0x80000000U)
|
||||
GM.ud[1] = 0x80000000;
|
||||
else
|
||||
GM.sd[1] = EX->d[1];
|
||||
@@ -237,7 +238,7 @@ void Run660F(x86emu_t *emu)
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<2; ++i)
|
||||
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
|
||||
if(!isfinite(EX->d[i]) || EX->d[i]>(double)0x7fffffff || EX->d[i]<-(double)0x80000000U)
|
||||
GM.ud[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
@@ -347,7 +348,34 @@ void Run660F(x86emu_t *emu)
|
||||
GX.sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: /* PHSUBD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<2; ++i)
|
||||
GX.sd[i] = GX.sd[i*2+0] - GX.sd[i*2+1];
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for (int i=0; i<2; ++i)
|
||||
GX.sd[2+i] = EX->sd[i*2+0] - EX->sd[i*2+1];
|
||||
}
|
||||
break;
|
||||
case 0x07: /* PHSUBSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = GX.sw[i*2+0]-GX.sw[i*2+1];
|
||||
GX.sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = EX->sw[i*2+0] - EX->sw[i*2+1];
|
||||
GX.sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x08: /* PSIGNB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -513,8 +541,7 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -528,28 +555,28 @@ void Run660F(x86emu_t *emu)
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.f[0] = nearbyint(EX->f[0]);
|
||||
GX.f[1] = nearbyint(EX->f[1]);
|
||||
GX.f[2] = nearbyint(EX->f[2]);
|
||||
GX.f[3] = nearbyint(EX->f[3]);
|
||||
GX.f[0] = nearbyintf(EX->f[0]);
|
||||
GX.f[1] = nearbyintf(EX->f[1]);
|
||||
GX.f[2] = nearbyintf(EX->f[2]);
|
||||
GX.f[3] = nearbyintf(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.f[0] = floor(EX->f[0]);
|
||||
GX.f[1] = floor(EX->f[1]);
|
||||
GX.f[2] = floor(EX->f[2]);
|
||||
GX.f[3] = floor(EX->f[3]);
|
||||
GX.f[0] = floorf(EX->f[0]);
|
||||
GX.f[1] = floorf(EX->f[1]);
|
||||
GX.f[2] = floorf(EX->f[2]);
|
||||
GX.f[3] = floorf(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.f[0] = ceil(EX->f[0]);
|
||||
GX.f[1] = ceil(EX->f[1]);
|
||||
GX.f[2] = ceil(EX->f[2]);
|
||||
GX.f[3] = ceil(EX->f[3]);
|
||||
GX.f[0] = ceilf(EX->f[0]);
|
||||
GX.f[1] = ceilf(EX->f[1]);
|
||||
GX.f[2] = ceilf(EX->f[2]);
|
||||
GX.f[3] = ceilf(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.f[0] = trunc(EX->f[0]);
|
||||
GX.f[1] = trunc(EX->f[1]);
|
||||
GX.f[2] = trunc(EX->f[2]);
|
||||
GX.f[3] = trunc(EX->f[3]);
|
||||
GX.f[0] = truncf(EX->f[0]);
|
||||
GX.f[1] = truncf(EX->f[1]);
|
||||
GX.f[2] = truncf(EX->f[2]);
|
||||
GX.f[3] = truncf(EX->f[3]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -584,16 +611,16 @@ void Run660F(x86emu_t *emu)
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.f[0] = nearbyint(EX->f[0]);
|
||||
GX.f[0] = nearbyintf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.f[0] = floor(EX->f[0]);
|
||||
GX.f[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.f[0] = ceil(EX->f[0]);
|
||||
GX.f[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.f[0] = trunc(EX->f[0]);
|
||||
GX.f[0] = truncf(EX->f[0]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -634,35 +661,12 @@ void Run660F(x86emu_t *emu)
|
||||
if(tmp8u>31)
|
||||
{GX.q[0] = GX.q[1] = 0;}
|
||||
else
|
||||
#if 0
|
||||
if(tmp8u>15) {
|
||||
tmp8u=(tmp8u-16)*8;
|
||||
if (tmp8u < 64) {
|
||||
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (GX.q[1] >> tmp8u);
|
||||
} else {
|
||||
GX.q[0] = GX.q[1] >> (tmp8u - 64);
|
||||
GX.q[1] = 0;
|
||||
}
|
||||
} else {
|
||||
tmp8u*=8;
|
||||
if (tmp8u < 64) {
|
||||
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64-tmp8u));
|
||||
} else {
|
||||
tmp8u -= 64;
|
||||
GX.q[0] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64 - tmp8u));
|
||||
GX.q[1] = (GX.q[0] >> tmp8u) | (GX.q[1] >> (64 - tmp8u));
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
for (int i=0; i<16; ++i, ++tmp8u)
|
||||
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX.ub[tmp8u-16]):EX->ub[tmp8u];
|
||||
GX.q[0] = eax1.q[0];
|
||||
GX.q[1] = eax1.q[1];
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x16: // PEXTRD ED, GX, u8
|
||||
@@ -696,8 +700,7 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -782,23 +785,24 @@ void Run660F(x86emu_t *emu)
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
|
||||
// note, converting 0x7fffffff to float gives 0x80000000 basicaly, because of the loss or precision in the mantice. So uing >= here...
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>=(float)0x80000000U || EX->f[i]<-(float)0x80000000U)
|
||||
GX.sd[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GX.sd[i] = nearbyintf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.sd[i] = floorf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.sd[i] = ceilf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.sd[i] = EX->f[i];
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GX.sd[i] = nearbyintf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.sd[i] = floorf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.sd[i] = ceilf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.sd[i] = EX->f[i];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x5C: /* SUBPD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -1016,8 +1020,7 @@ void Run660F(x86emu_t *emu)
|
||||
for (int i=0; i<8; ++i) EX->uw[i] <<= tmp8u;
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x72: /* GRP */
|
||||
@@ -1043,8 +1046,7 @@ void Run660F(x86emu_t *emu)
|
||||
for (int i=0; i<4; ++i) EX->ud[i] <<= tmp8u;
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x73: /* GRP */
|
||||
@@ -1096,8 +1098,7 @@ void Run660F(x86emu_t *emu)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x74: /* PCMPEQB Gx,Ex */
|
||||
@@ -1190,7 +1191,12 @@ void Run660F(x86emu_t *emu)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -1217,7 +1223,12 @@ void Run660F(x86emu_t *emu)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -1263,7 +1274,12 @@ void Run660F(x86emu_t *emu)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
@@ -1332,8 +1348,7 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0xBB: /* BTC Ew,Gw */
|
||||
@@ -1345,7 +1360,12 @@ void Run660F(x86emu_t *emu)
|
||||
GET_EW;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+tmp32s*2);
|
||||
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
|
||||
#else
|
||||
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
|
||||
#endif
|
||||
}
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
@@ -1512,8 +1532,7 @@ void Run660F(x86emu_t *emu)
|
||||
if(EX->ub[i]&0x80)
|
||||
GD.dword[0] |= (1<<i);
|
||||
} else {
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0xD8: /* PSUBUSB Gx,Ex */
|
||||
@@ -1617,11 +1636,11 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xE6: /* CVTTPD2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
|
||||
GX.sd[0] = 0x80000000;
|
||||
else
|
||||
GX.sd[0] = EX->d[0];
|
||||
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
|
||||
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>(double)0x7fffffff || EX->d[1]<-(double)0x80000000U)
|
||||
GX.sd[1] = 0x80000000;
|
||||
else
|
||||
GX.sd[1] = EX->d[1];
|
||||
@@ -1799,10 +1818,8 @@ void Run660F(x86emu_t *emu)
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_EIP = ip;
|
||||
return;
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66D9(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xE0:
|
||||
case 0xE5:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xFC:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* FLDENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
#endif
|
||||
break;
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66DD(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xE0:
|
||||
case 0xE5:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xFC:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* FRSTOR m94byte */
|
||||
GET_EW;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
// get the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
LD2D(p, &ST(i).d);
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 6: /* FNSAVE m94byte */
|
||||
GET_EW;
|
||||
// ENV first...
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
// save the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
D2LD(&ST(i).d, p);
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "my_cpuid.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test67(x86test_t *test, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run67(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u, tmp8u2;
|
||||
int8_t tmp8s;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int16_t tmp16s;
|
||||
uint32_t tmp32u, tmp32u2, tmp32u3;
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint64_t tmp64u;
|
||||
int64_t tmp64s;
|
||||
double d;
|
||||
float f;
|
||||
int64_t ll;
|
||||
sse_regs_t *opex, eax1;
|
||||
mmx87_regs_t *opem, eam1;
|
||||
uintptr_t tlsdata;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t *emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
while(opcode==0x67)
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x64:
|
||||
tlsdata = GetFSBaseEmu(emu);
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6467(test, tlsdata, addr);
|
||||
#else
|
||||
return Run6467(emu, tlsdata, addr);
|
||||
#endif
|
||||
|
||||
case 0x66: /* MoooRE opcodes */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6766(test, rep, addr);
|
||||
#else
|
||||
return Run6766(emu, rep, addr);
|
||||
#endif
|
||||
|
||||
case 0x6C: /* INSB */
|
||||
tmp32u = rep?R_CX:1;
|
||||
while(tmp32u--) {
|
||||
#ifdef TEST_INTERPRETER
|
||||
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
|
||||
#endif
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_DI-=1;
|
||||
else
|
||||
R_DI+=1;
|
||||
}
|
||||
if(rep) R_CX = 0;
|
||||
break;
|
||||
|
||||
case 0xAC: /* LODSB */
|
||||
tmp32u = rep?R_CX:1;
|
||||
while(tmp32u--) {
|
||||
R_AL = *(int8_t*)(R_SI+GetDSBaseEmu(emu));
|
||||
if(ACCESS_FLAG(F_DF))
|
||||
R_SI-=1;
|
||||
else
|
||||
R_SI+=1;
|
||||
}
|
||||
if(rep) R_CX = 0;
|
||||
break;
|
||||
|
||||
case 0xE0: /* LOOPNZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX && !ACCESS_FLAG(F_ZF))
|
||||
addr += tmp8s;
|
||||
break;
|
||||
case 0xE1: /* LOOPZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX && ACCESS_FLAG(F_ZF))
|
||||
addr += tmp8s;
|
||||
break;
|
||||
case 0xE2: /* LOOP */
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX)
|
||||
addr += tmp8s;
|
||||
break;
|
||||
case 0xE3: /* JCXZ */
|
||||
tmp8s = F8S;
|
||||
if(!R_CX)
|
||||
addr += tmp8s;
|
||||
break;
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, addr);
|
||||
addr += tmp32s;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test6766(x86test_t *test, int rep, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
uint8_t opcode = F8;
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x8D: /* LEA Gw,Ew */
|
||||
nextop = F8;
|
||||
GET_EW16_;
|
||||
GW.word[0] = (uint16_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
+70
-13
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include "regs.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "box86context.h"
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
static inline uint8_t Fetch8(x86emu_t *emu) {return *(uint8_t*)(R_EIP++);}
|
||||
@@ -41,15 +42,25 @@ static inline uint32_t Pop(x86emu_t *emu)
|
||||
return *st;
|
||||
}
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
#define Push(E, V) do{E->regs[_SP].dword[0] -=4; test->memsize = 4; *(uint64_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
|
||||
#define Push16(E, V) do{E->regs[_SP].dword[0] -=2; test->memsize = 2; *(uint16_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
|
||||
#else
|
||||
static inline void Push(x86emu_t *emu, uint32_t v)
|
||||
{
|
||||
R_ESP -= 4;
|
||||
*((uint32_t*)R_ESP) = v;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void PushExit(x86emu_t* emu)
|
||||
{
|
||||
R_ESP -= 4;
|
||||
*((uint32_t*)R_ESP) = my_context->exit_bridge;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
|
||||
|
||||
static inline reg32_t* GetECommon(x86emu_t* emu, uint32_t m)
|
||||
{
|
||||
if (m<=7) {
|
||||
@@ -188,23 +199,69 @@ static inline sse_regs_t* GetGx(x86emu_t *emu, uint32_t v)
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
return &emu->xmm[m&7];
|
||||
}
|
||||
|
||||
#endif
|
||||
void UpdateFlags(x86emu_t *emu);
|
||||
|
||||
#define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
|
||||
#define RESET_FLAGS(emu) emu->df = d_none
|
||||
|
||||
void Run67(x86emu_t *emu);
|
||||
void Run0F(x86emu_t *emu);
|
||||
void Run660F(x86emu_t *emu);
|
||||
void Run66D9(x86emu_t *emu); // x87
|
||||
void Run6766(x86emu_t *emu);
|
||||
void RunGS(x86emu_t *emu);
|
||||
void RunGS0F(x86emu_t *emu, uintptr_t tlsdata);
|
||||
void RunFS(x86emu_t *emu);
|
||||
void RunFS66(x86emu_t *emu, uintptr_t tlsdata);
|
||||
void RunLock(x86emu_t *emu);
|
||||
void RunLock66(x86emu_t *emu);
|
||||
uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step);
|
||||
uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr);
|
||||
uintptr_t Run640F(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr);
|
||||
uintptr_t Run660F(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t Run6664(x86emu_t *emu, int seg, uintptr_t addr);
|
||||
uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t Run66F0(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t Run67(x86emu_t *emu, int rep, uintptr_t addr);
|
||||
uintptr_t Run670F(x86emu_t *emu, int rep, uintptr_t addr);
|
||||
uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr);
|
||||
uintptr_t Run67660F(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunD8(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunD9(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDA(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDB(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDC(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDD(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDE(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunDF(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunF0(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunF066(x86emu_t *emu, uintptr_t addr);
|
||||
uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step);
|
||||
uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr);
|
||||
|
||||
#ifdef DYNAREC
|
||||
uintptr_t Test0F(x86test_t *test, uintptr_t addr, int *step);
|
||||
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr);
|
||||
uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
|
||||
uintptr_t Test66(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test660F(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test6664(x86test_t *test, int seg, uintptr_t addr);
|
||||
uintptr_t Test66D9(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test66DD(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test66F0(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t Test67(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test670F(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test6766(x86test_t *test, int rep, uintptr_t addr);
|
||||
uintptr_t Test67660F(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestD8(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestD9(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDA(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDB(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDC(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDD(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDE(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestDF(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF0(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF066(x86test_t *test, uintptr_t addr);
|
||||
uintptr_t TestF20F(x86test_t *test, uintptr_t addr, int *step);
|
||||
uintptr_t TestF30F(x86test_t *test, uintptr_t addr);
|
||||
#endif
|
||||
|
||||
void x86Syscall(x86emu_t *emu);
|
||||
void x86Int3(x86emu_t* emu);
|
||||
|
||||
@@ -1,7 +1,40 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestD8(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
float f;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
@@ -159,7 +192,9 @@
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -1,3 +1,38 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestD9(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
float f;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
@@ -206,7 +241,7 @@
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
case 0xEF:
|
||||
goto _default;
|
||||
return 0;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FLD ST0, Ed float */
|
||||
@@ -241,7 +276,9 @@
|
||||
case 4: /* FLDENV m */
|
||||
// warning, incomplete
|
||||
GET_ED;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
break;
|
||||
case 5: /* FLDCW Ew */
|
||||
GET_EW;
|
||||
@@ -251,7 +288,9 @@
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GET_ED;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
// intruction pointer: 48bits
|
||||
// data (operand) pointer: 48bits
|
||||
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
|
||||
@@ -261,6 +300,8 @@
|
||||
EW->word[0] = emu->cw.x16;
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDA(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
float f;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
@@ -66,8 +100,7 @@
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFD:
|
||||
UnimpOpcode(emu);
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ed int */
|
||||
@@ -105,3 +138,5 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDB(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDB(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
float f;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0: /* FCMOVNB ST(0), ST(i) */
|
||||
@@ -93,7 +127,7 @@
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
goto _default;
|
||||
return 0;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FILD ST0, Ed */
|
||||
@@ -103,15 +137,16 @@
|
||||
break;
|
||||
case 1: /* FISTTP Ed, ST0 */
|
||||
GET_ED;
|
||||
tmp32s = ST0.d; // TODO: Handling of FPU Exception
|
||||
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
|
||||
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
|
||||
tmp32s = 0x80000000;
|
||||
else
|
||||
tmp32s = ST0.d; // TODO: Handling of FPU Exception
|
||||
fpu_do_pop(emu);
|
||||
ED->sdword[0] = tmp32s;
|
||||
break;
|
||||
case 2: /* FIST Ed, ST0 */
|
||||
GET_ED;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
@@ -120,7 +155,7 @@
|
||||
break;
|
||||
case 3: /* FISTP Ed, ST0 */
|
||||
GET_ED;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
@@ -129,14 +164,14 @@
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 5: /* FLD ST0, Et */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
LD2D(&STld(0).ld, &ST(0).d);
|
||||
STld(0).uref = ST0.q;
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, ED);
|
||||
else
|
||||
@@ -144,6 +179,8 @@
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDC(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
double d;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -82,7 +116,7 @@
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
break;
|
||||
default:
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, double */
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
@@ -150,7 +184,8 @@
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDD(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
double d;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
@@ -79,12 +113,12 @@
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
goto _default;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FLD double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
fpu_do_push(emu);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED;
|
||||
@@ -93,17 +127,32 @@
|
||||
}
|
||||
break;
|
||||
case 1: /* FISTTP ED qword */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(int64_t*)ED = ST0.d;
|
||||
else {
|
||||
int64_t i64 = ST0.d;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7)) {
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
*(int64_t*)ED = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
*(uint64_t*)ED = 0x8000000000000000LL;
|
||||
else
|
||||
*(int64_t*)ED = ST0.d;
|
||||
}
|
||||
} else {
|
||||
int64_t i64;
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
i64 = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
i64 = 0x8000000000000000LL;
|
||||
else
|
||||
i64 = ST0.d;
|
||||
}
|
||||
memcpy(ED, &i64, sizeof(int64_t));
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FST double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
@@ -111,7 +160,7 @@
|
||||
}
|
||||
break;
|
||||
case 3: /* FSTP double */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
@@ -120,8 +169,10 @@
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FRSTOR m108byte */
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_loadenv(emu, (char*)ED, 0);
|
||||
#endif
|
||||
// get the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
@@ -133,9 +184,10 @@
|
||||
}
|
||||
break;
|
||||
case 6: /* FNSAVE m108byte */
|
||||
GET_ED;
|
||||
GET_ED_;
|
||||
// ENV first...
|
||||
// warning, incomplete
|
||||
#ifndef TEST_INTERPRETER
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
// save the STx
|
||||
{
|
||||
@@ -146,6 +198,7 @@
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
case 7: /* FNSTSW m2byte */
|
||||
@@ -154,6 +207,8 @@
|
||||
*(uint16_t*)ED = emu->sw.x16;
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDE(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int32_t tmp32s;
|
||||
int64_t ll;
|
||||
double d;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0: /* FADDP STx, ST0 */
|
||||
@@ -95,7 +129,7 @@
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
goto _default;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -124,6 +158,8 @@
|
||||
ST0.d = (double)EW->sword[0] / ST0.d;
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestDF(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunDF(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t nextop;
|
||||
int16_t tmp16s;
|
||||
int64_t tmp64s;
|
||||
double d;
|
||||
reg32_t *oped;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0: /* FFREEP STx */
|
||||
@@ -25,8 +59,11 @@
|
||||
break;
|
||||
|
||||
case 0xE0: /* FNSTSW AX */
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
R_AX = emu->sw.x16;
|
||||
{
|
||||
x87flags_t sw = emu->sw;
|
||||
sw.f.F87_TOP = emu->top&7;
|
||||
R_AX = sw.x16;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE8: /* FUCOMIP ST0, STx */
|
||||
@@ -84,7 +121,7 @@
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
goto _default;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -96,32 +133,35 @@
|
||||
break;
|
||||
case 1: /* FISTTP Ew, ST0 */
|
||||
GET_EW;
|
||||
tmp16s = ST0.d;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
|
||||
tmp16s = 0x8000;
|
||||
else
|
||||
tmp16s = ST0.d;
|
||||
EW->sword[0] = tmp16s;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FIST Ew, ST0 */
|
||||
GET_EW;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
|
||||
EW->sword[0] = 0x8000;
|
||||
else
|
||||
EW->sword[0] = fpu_round(emu, ST0.d);
|
||||
break;
|
||||
case 3: /* FISTP Ew, ST0 */
|
||||
GET_EW;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
|
||||
EW->sword[0] = 0x8000;
|
||||
else
|
||||
EW->sword[0] = fpu_round(emu, ST0.d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FBLD ST0, tbytes */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_do_push(emu);
|
||||
fpu_fbld(emu, (uint8_t*)ED);
|
||||
break;
|
||||
case 5: /* FILD ST0, Gq */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
tmp64s = *(int64_t*)ED;
|
||||
fpu_do_push(emu);
|
||||
ST0.d = tmp64s;
|
||||
@@ -129,19 +169,19 @@
|
||||
STll(0).sref = ST0.sq;
|
||||
break;
|
||||
case 6: /* FBSTP tbytes, ST0 */
|
||||
GET_ED;
|
||||
GET_EDT;
|
||||
fpu_fbst(emu, (uint8_t*)ED);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 7: /* FISTP i64 */
|
||||
GET_ED;
|
||||
GET_ED8;
|
||||
if((uintptr_t)ED & 0x7) {
|
||||
// un-aligned!
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
memcpy(ED, &STll(0).sq, sizeof(int64_t));
|
||||
else {
|
||||
int64_t i64;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
i64 = 0x8000000000000000LL;
|
||||
else
|
||||
i64 = fpu_round(emu, ST0.d);
|
||||
@@ -151,7 +191,7 @@
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
*(int64_t*)ED = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
*(int64_t*)ED = 0x8000000000000000LL;
|
||||
else
|
||||
*(int64_t*)ED = fpu_round(emu, ST0.d);
|
||||
@@ -160,6 +200,8 @@
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,625 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "my_cpuid.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF0(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u, tmp8u2;
|
||||
int8_t tmp8s;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int16_t tmp16s;
|
||||
uint32_t tmp32u, tmp32u2, tmp32u3;
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint64_t tmp64u;
|
||||
int64_t tmp64s;
|
||||
double d;
|
||||
float f;
|
||||
int64_t ll;
|
||||
sse_regs_t *opex, eax1;
|
||||
mmx87_regs_t *opem, eam1;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t *emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
do { \
|
||||
tmp8u = arm_lock_read_b(EB); \
|
||||
tmp8u = OP##8(emu, tmp8u, GB); \
|
||||
} while (arm_lock_write_b(EB, tmp8u)); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
do { \
|
||||
tmp32u = arm_lock_read_d(ED); \
|
||||
tmp32u = OP##32(emu, tmp32u, GD.dword[0]); \
|
||||
} while (arm_lock_write_d(ED, tmp32u)); \
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
|
||||
break; \
|
||||
case B+4: \
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
break; \
|
||||
case B+5: \
|
||||
R_EAX = OP##32(emu, R_EAX, F32); \
|
||||
break;
|
||||
#else
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+4: \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+5: \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
R_EAX = OP##32(emu, R_EAX, F32); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break;
|
||||
#endif
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or) /* OR 0x08 -> 0x0D */
|
||||
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
|
||||
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
|
||||
GO(0x20, and) /* AND 0x20 -> 0x25 */
|
||||
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x0f:
|
||||
opcode = F8;
|
||||
switch (opcode) {
|
||||
case 0xB0: /* CMPXCHG Eb,Gb */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
cmp8(emu, R_AL, tmp8u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_b(EB, GB);
|
||||
} else {
|
||||
R_AL = tmp8u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp8(emu, R_AL, EB->byte[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EB->byte[0] = GB;
|
||||
} else {
|
||||
R_AL = EB->byte[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xB1: /* CMPXCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(((uintptr_t)ED)&3) {
|
||||
do {
|
||||
tmp32u = ED->dword[0] & ~0xff;
|
||||
tmp32u |= arm_lock_read_b(ED);
|
||||
cmp32(emu, R_EAX, tmp32u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_b(ED, GD.dword[0] & 0xff);
|
||||
if(!tmp32s)
|
||||
ED->dword[0] = GD.dword[0];
|
||||
} else {
|
||||
R_EAX = tmp32u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
cmp32(emu, R_EAX, tmp32u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_d(ED, GD.dword[0]);
|
||||
} else {
|
||||
R_EAX = tmp32u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp32(emu, R_EAX, ED->dword[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
ED->dword[0] = GD.dword[0];
|
||||
} else {
|
||||
R_EAX = ED->dword[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xB3: /* BTR Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm_lock_write_d(ED, tmp32u);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* BT Ed,Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(arm_lock_read_d(ED) & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 5: /* BTS Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm_lock_write_d(ED, tmp32u);
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 6: /* BTR Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm_lock_write_d(ED, tmp32u);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return addr-3; //unfetchall 0F BA nextop but not F0, continue normal without LOCK
|
||||
}
|
||||
break;
|
||||
case 0xBB: /* BTC Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = GD.byte[0];
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
#ifdef TEST_INTERPRETER
|
||||
test->memaddr=((test->memaddr)+(tmp8u>>5));
|
||||
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
|
||||
#else
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
#endif
|
||||
}
|
||||
tmp8u&=31;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
} while(arm_lock_write_d(ED, tmp32u));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC0: /* XADD Gb,Eb */
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
tmp8u2 = add8(emu, tmp8u, GB);
|
||||
} while (arm_lock_write_b(EB, tmp8u2));
|
||||
GB = tmp8u;
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp8u = add8(emu, EB->byte[0], GB);
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC1: /* XADD Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(((uintptr_t)ED)&3) {
|
||||
do {
|
||||
tmp32u = ED->dword[0] & ~0xff;
|
||||
tmp32u |= arm_lock_read_b(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
|
||||
} while(arm_lock_write_b(ED, tmp32u2&0xff));
|
||||
ED->dword[0] = tmp32u2;
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
|
||||
} while(arm_lock_write_d(ED, tmp32u2));
|
||||
}
|
||||
GD.dword[0] = tmp32u;
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp32u = add32(emu, ED->dword[0], GD.dword[0]);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC7: /* CMPXCHG8B Gq */
|
||||
nextop = F8;
|
||||
GET_ED8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
CHECK_FLAGS(emu);
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned!!!
|
||||
uint64_t ref = R_EDX;
|
||||
ref = ref<<32 | R_EAX;
|
||||
void* p = (void*)(((uintptr_t)ED + 3)&~3);
|
||||
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
|
||||
do {
|
||||
uint64_t m = *(uint64_t*)ED;
|
||||
m&=~((0xffffffffLL)<<d);
|
||||
tmp32u = arm_lock_read_d(p);
|
||||
m|=((uint64_t)tmp32u)<<d;
|
||||
if(ref == m) {
|
||||
SET_FLAG(F_ZF);
|
||||
m = ((uint64_t)R_ECX)<<32 | R_EBX;
|
||||
tmp32u2 = m>>d;
|
||||
tmp32s = arm_lock_write_d(p, tmp32u2);
|
||||
if(!tmp32s)
|
||||
*(uint64_t*)ED = m;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = m&0xffffffff;
|
||||
R_EDX = m>>32;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else
|
||||
do {
|
||||
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u2= ED->dword[1];
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
ED->dword[0] = R_EBX;
|
||||
ED->dword[1] = R_ECX;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xC7 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// trigger invalid lock?
|
||||
return addr-2; // unfetch 0F and nextop but not F0
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return TestF066(test, addr);
|
||||
#else
|
||||
return RunF066(emu, addr);
|
||||
#endif
|
||||
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
if(opcode==0x83) {
|
||||
tmp32s = F8S;
|
||||
tmp32u = (uint32_t)tmp32s;
|
||||
} else
|
||||
tmp32u = F32;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, add32(emu, tmp32u2, tmp32u))); break;
|
||||
case 1: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, or32(emu, tmp32u2, tmp32u))); break;
|
||||
case 2: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, adc32(emu, tmp32u2, tmp32u))); break;
|
||||
case 3: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sbb32(emu, tmp32u2, tmp32u))); break;
|
||||
case 4: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, and32(emu, tmp32u2, tmp32u))); break;
|
||||
case 5: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sub32(emu, tmp32u2, tmp32u))); break;
|
||||
case 6: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, xor32(emu, tmp32u2, tmp32u))); break;
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
|
||||
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
|
||||
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
|
||||
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
|
||||
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
|
||||
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
|
||||
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0x86: /* XCHG Eb,Gb */
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
return addr-1; // let the normal XCHG execute, it have integrated LOCK
|
||||
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
return addr-1;
|
||||
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if((uintptr_t)ED&3) {
|
||||
//meh.
|
||||
do {
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u &=~0xff;
|
||||
tmp32u |= arm_lock_read_b(ED);
|
||||
tmp32u = inc32(emu, tmp32u);
|
||||
} while(arm_lock_write_b(ED, tmp32u&0xff));
|
||||
ED->dword[0] = tmp32u;
|
||||
} else
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
} while(arm_lock_write_d(ED, inc32(emu, tmp32u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = inc32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
if((uintptr_t)ED&3) {
|
||||
//meh.
|
||||
do {
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u &=~0xff;
|
||||
tmp32u |= arm_lock_read_b(ED);
|
||||
tmp32u = dec32(emu, tmp32u);
|
||||
} while(arm_lock_write_b(ED, tmp32u&0xff));
|
||||
ED->dword[0] = tmp32u;
|
||||
} else
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
} while(arm_lock_write_d(ED, dec32(emu, tmp32u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "my_cpuid.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF066(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunF066(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u, tmp8u2;
|
||||
int8_t tmp8s;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int16_t tmp16s;
|
||||
uint32_t tmp32u, tmp32u2, tmp32u3;
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint64_t tmp64u;
|
||||
int64_t tmp64s;
|
||||
double d;
|
||||
float f;
|
||||
int64_t ll;
|
||||
sse_regs_t *opex, eax1;
|
||||
mmx87_regs_t *opem, eam1;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t *emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0f:
|
||||
opcode = F8;
|
||||
switch (opcode) {
|
||||
case 0xB1: /* CMPXCHG Ew,Gw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp16u = arm_lock_read_h(ED);
|
||||
cmp16(emu, R_AX, tmp16u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_h(ED, GW.word[0]);
|
||||
} else {
|
||||
R_AX = tmp16u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
GET_EW;
|
||||
cmp16(emu, R_AX, EW->word[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EW->word[0] = GW.word[0];
|
||||
} else {
|
||||
R_AX = EW->word[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x81: /* GRP Ed,Iw */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
if(opcode==0x83) {
|
||||
tmp16s = F8S;
|
||||
tmp16u = (uint32_t)tmp16s;
|
||||
} else
|
||||
tmp16u = F16;
|
||||
#ifdef DYNAREC
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, add16(emu, tmp16u2, tmp16u))); break;
|
||||
case 1: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, or16(emu, tmp16u2, tmp16u))); break;
|
||||
case 2: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, adc16(emu, tmp16u2, tmp16u))); break;
|
||||
case 3: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, sbb16(emu, tmp16u2, tmp16u))); break;
|
||||
case 4: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, and16(emu, tmp16u2, tmp16u))); break;
|
||||
case 5: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, sub16(emu, tmp16u2, tmp16u))); break;
|
||||
case 6: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, xor16(emu, tmp16u2, tmp16u))); break;
|
||||
case 7: cmp16(emu, ED->dword[0], tmp16u); break;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EW->word[0] = add16(emu, EW->word[0], tmp16u); break;
|
||||
case 1: EW->word[0] = or16(emu, EW->word[0], tmp16u); break;
|
||||
case 2: EW->word[0] = adc16(emu, EW->word[0], tmp16u); break;
|
||||
case 3: EW->word[0] = sbb16(emu, EW->word[0], tmp16u); break;
|
||||
case 4: EW->word[0] = and16(emu, EW->word[0], tmp16u); break;
|
||||
case 5: EW->word[0] = sub16(emu, EW->word[0], tmp16u); break;
|
||||
case 6: EW->word[0] = xor16(emu, EW->word[0], tmp16u); break;
|
||||
case 7: cmp16(emu, EW->word[0], tmp16u); break;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
if((uintptr_t)ED&1) {
|
||||
//meh.
|
||||
do {
|
||||
tmp16u = ED->dword[0];
|
||||
tmp16u &=~0xff;
|
||||
tmp16u |= arm_lock_read_b(ED);
|
||||
tmp16u = inc16(emu, tmp16u);
|
||||
} while(arm_lock_write_b(ED, tmp16u&0xff));
|
||||
ED->dword[0] = tmp16u;
|
||||
} else
|
||||
do {
|
||||
tmp16u = arm_lock_read_h(ED);
|
||||
} while(arm_lock_write_h(ED, inc16(emu, tmp16u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = inc32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
if((uintptr_t)ED&1) {
|
||||
//meh.
|
||||
do {
|
||||
tmp16u = ED->dword[0];
|
||||
tmp16u &=~0xff;
|
||||
tmp16u |= arm_lock_read_b(ED);
|
||||
tmp16u = dec16(emu, tmp16u);
|
||||
} while(arm_lock_write_b(ED, tmp16u&0xff));
|
||||
ED->dword[0] = tmp16u;
|
||||
} else
|
||||
do {
|
||||
tmp16u = arm_lock_read_h(ED);
|
||||
} while(arm_lock_write_h(ED, dec16(emu, tmp16u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -1,4 +1,51 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF20F(x86test_t *test, uintptr_t addr, int *step)
|
||||
#else
|
||||
uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u;
|
||||
int32_t tmp32s;
|
||||
int64_t tmp64s0, tmp64s1;
|
||||
reg32_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opgm;
|
||||
#ifndef NOALIGN
|
||||
int is_nan;
|
||||
#endif
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10: /* MOVSD Gx, Ex */
|
||||
@@ -30,7 +77,7 @@
|
||||
case 0x2C: /* CVTTSD2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
|
||||
GD.dword[0] = 0x80000000;
|
||||
else
|
||||
GD.sdword[0] = EX->d[0];
|
||||
@@ -38,7 +85,7 @@
|
||||
case 0x2D: /* CVTSD2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
|
||||
GD.dword[0] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
@@ -255,7 +302,7 @@
|
||||
|
||||
GOCOND(0x80
|
||||
, tmp32s = F32S; CHECK_FLAGS(emu);
|
||||
, ip += tmp32s;
|
||||
, addr += tmp32s; STEP3;
|
||||
) /* 0x80 -> 0x8F Jxx */
|
||||
|
||||
case 0xC2: /* CMPSD Gx, Ex, Ib */
|
||||
@@ -295,7 +342,7 @@
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<2; ++i)
|
||||
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
|
||||
if(!isfinite(EX->d[i]) || EX->d[i]>(double)0x7fffffff || EX->d[i]<-(double)0x80000000U)
|
||||
GX.ud[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
@@ -322,6 +369,7 @@
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -1,4 +1,49 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t TestF30F(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u;
|
||||
reg32_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem;
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10: /* MOVSS Gx Ex */
|
||||
@@ -47,7 +92,7 @@
|
||||
case 0x2C: /* CVTTSS2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[0]<-(float)0x80000000U)
|
||||
GD.dword[0] = 0x80000000;
|
||||
else
|
||||
GD.sdword[0] = EX->f[0];
|
||||
@@ -55,7 +100,7 @@
|
||||
case 0x2D: /* CVTSS2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[0]<-(float)0x80000000U)
|
||||
GD.dword[0] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
@@ -109,7 +154,7 @@
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>=(float)0x80000000U || EX->f[i]<-(float)0x80000000U)
|
||||
GX.ud[i] = 0x80000000;
|
||||
else
|
||||
GX.sd[i] = EX->f[i];
|
||||
@@ -123,7 +168,7 @@
|
||||
case 0x5D: /* MINSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(GX.f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
|
||||
if(isnanf(GX.f[0]) || isnanf(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
|
||||
GX.f[0] = EX->f[0];
|
||||
break;
|
||||
case 0x5E: /* DIVSS Gx, Ex */
|
||||
@@ -134,7 +179,7 @@
|
||||
case 0x5F: /* MAXSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
|
||||
if (isnanf(GX.f[0]) || isnanf(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
|
||||
GX.f[0] = EX->f[0];
|
||||
break;
|
||||
|
||||
@@ -240,5 +285,7 @@
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
return 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
+41
-34
@@ -75,6 +75,39 @@ int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot);
|
||||
void* ElfSetBrk(void* newbrk);
|
||||
int my_vfork(x86emu_t* emu);
|
||||
|
||||
#ifndef __NR_socketcall
|
||||
int my_socketcall(x86emu_t* emu, int n, unsigned long *args) {
|
||||
int ret = 0;
|
||||
switch(n) {
|
||||
case SYS_SOCKET: ret = socket(args[0], args[1], args[2]); break;
|
||||
case SYS_BIND: ret = bind(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_CONNECT: ret = connect(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_LISTEN: ret = listen(args[0], args[1]); break;
|
||||
case SYS_ACCEPT: ret = accept(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_GETSOCKNAME: ret = getsockname(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_GETPEERNAME: ret = getpeername(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_SOCKETPAIR: ret = socketpair(args[0], args[1], args[2], (int*)args[3]); break;
|
||||
case SYS_SEND: ret = send(args[0], (void*)args[1], args[2], args[3]); break;
|
||||
case SYS_RECV: ret = recv(args[0], (void*)args[1], args[2], args[3]); break;
|
||||
case SYS_SENDTO: ret = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break;
|
||||
case SYS_RECVFROM: ret = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break;
|
||||
case SYS_SHUTDOWN: ret = shutdown(args[0], args[1]); break;
|
||||
case SYS_SETSOCKOPT: ret = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break;
|
||||
case SYS_GETSOCKOPT: ret = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break;
|
||||
case SYS_SENDMSG: ret = sendmsg(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_RECVMSG: ret = recvmsg(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_ACCEPT4: ret = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break;
|
||||
#ifdef SYS_RECVMMSG
|
||||
case SYS_RECVMMSG: ret = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break;
|
||||
case SYS_SENDMMSG: ret = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", n);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 04000
|
||||
@@ -491,39 +524,10 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_socketcall
|
||||
case 102: {
|
||||
unsigned long *args = (unsigned long *)R_ECX;
|
||||
// need to do all call "by hand"
|
||||
switch(R_EBX) {
|
||||
case SYS_SOCKET: R_EAX = socket(args[0], args[1], args[2]); break;
|
||||
case SYS_BIND: R_EAX = bind(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_CONNECT: R_EAX = connect(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_LISTEN: R_EAX = listen(args[0], args[1]); break;
|
||||
case SYS_ACCEPT: R_EAX = accept(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_GETSOCKNAME: R_EAX = getsockname(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_GETPEERNAME: R_EAX = getpeername(args[0], (void*)args[1], (void*)args[2]); break;
|
||||
case SYS_SOCKETPAIR: R_EAX = socketpair(args[0], args[1], args[2], (int*)args[3]); break;
|
||||
case SYS_SEND: R_EAX = send(args[0], (void*)args[1], args[2], args[3]); break;
|
||||
case SYS_RECV: R_EAX = recv(args[0], (void*)args[1], args[2], args[3]); break;
|
||||
case SYS_SENDTO: R_EAX = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break;
|
||||
case SYS_RECVFROM: R_EAX = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break;
|
||||
case SYS_SHUTDOWN: R_EAX = shutdown(args[0], args[1]); break;
|
||||
case SYS_SETSOCKOPT: R_EAX = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break;
|
||||
case SYS_GETSOCKOPT: R_EAX = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break;
|
||||
case SYS_SENDMSG: R_EAX = sendmsg(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_RECVMSG: R_EAX = recvmsg(args[0], (void*)args[1], args[2]); break;
|
||||
case SYS_ACCEPT4: R_EAX = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break;
|
||||
#ifdef SYS_RECVMMSG
|
||||
case SYS_RECVMMSG: R_EAX = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break;
|
||||
case SYS_SENDMMSG: R_EAX = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX);
|
||||
R_EAX = -EINVAL;
|
||||
}
|
||||
case 102:
|
||||
R_EAX = my_socketcall(emu, R_EBX, (unsigned long *)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_olduname
|
||||
@@ -748,9 +752,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
printf_log(LOG_INFO, "Warning: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
R_EAX = (uint32_t)-ENOSYS;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
@@ -804,6 +807,10 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
return (uintptr_t)ElfSetBrk(p(4));
|
||||
case 91: // munmap
|
||||
return (uint32_t)my_munmap(emu, p(4), u32(8));
|
||||
#ifndef __NR_socketcall
|
||||
case 102:
|
||||
return my_socketcall(emu, i32(4), (unsigned long *)p(8));
|
||||
#endif
|
||||
#ifndef __NR_ipc
|
||||
case 117: // ipc
|
||||
return (uint32_t)my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
|
||||
void print_banner(x86emu_t* ref)
|
||||
{
|
||||
printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p (%02x %02x %02x %02x %02x %02x %02x %02x)\n"\
|
||||
"=======================================\n",
|
||||
(void*)ref->old_ip,
|
||||
((uint8_t*)ref->old_ip)[0], ((uint8_t*)ref->old_ip)[1], ((uint8_t*)ref->old_ip)[2], ((uint8_t*)ref->old_ip)[3],
|
||||
((uint8_t*)ref->old_ip)[4], ((uint8_t*)ref->old_ip)[5], ((uint8_t*)ref->old_ip)[6], ((uint8_t*)ref->old_ip)[7]
|
||||
);
|
||||
printf_log(LOG_NONE, "DIFF: Dynarec | Interpreter\n----------------------\n");
|
||||
}
|
||||
#define BANNER if(!banner) {banner=1; print_banner(ref);}
|
||||
void x86test_check(x86emu_t* ref, uintptr_t ip)
|
||||
{
|
||||
int banner = 0;
|
||||
x86test_t* test = &ref->test;
|
||||
x86emu_t* emu = test->emu;
|
||||
if(memcmp(ref->regs, emu->regs, sizeof(emu->regs))) {
|
||||
static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI"};
|
||||
BANNER;
|
||||
for(int i=0; i<8; ++i) {
|
||||
if(ref->regs[i].dword[0]!=emu->regs[i].dword[0]) {
|
||||
printf_log(LOG_NONE, "%s: %08x | %08x\n", regname[i], ref->regs[i].dword[0], emu->regs[i].dword[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ip!=emu->ip.dword[0]) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "RIP: %08x | %08x\n", ip, emu->ip.dword[0]);
|
||||
}
|
||||
// flags are volatile, so don't test them
|
||||
//memcpy(&ref->eflags, &emu->eflags, sizeof(emu->eflags));
|
||||
if(memcmp(ref->segs, emu->segs, sizeof(emu->segs))) {
|
||||
static const char* segname[] = {"CS", "DS", "ES", "SS", "FS", "GS"};
|
||||
BANNER;
|
||||
for(int i=0; i<6; ++i) {
|
||||
if(ref->segs[i]!=emu->segs[i]) {
|
||||
printf_log(LOG_NONE, "%s: %04x | %04x\n", segname[i], ref->segs[i], emu->segs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ref->top != emu->top) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 TOP: %d | %d\n", ref->top, emu->top);
|
||||
}
|
||||
if(ref->fpu_stack != emu->fpu_stack) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 STACK: %d | %d\n", ref->fpu_stack, emu->fpu_stack);
|
||||
}
|
||||
if(ref->fpu_stack && memcmp(ref->x87, emu->x87, sizeof(emu->x87))) {
|
||||
// need to check each regs, unused one might have different left over value
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
//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) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
|
||||
}*/
|
||||
if(ref->cw.x16 != emu->cw.x16) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
|
||||
}
|
||||
if(ref->sw.x16 != emu->sw.x16) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "X87 SW: %x | %x\n", ref->sw.x16, emu->sw.x16);
|
||||
}
|
||||
if(memcmp(ref->mmx, emu->mmx, sizeof(emu->mmx))) {
|
||||
BANNER;
|
||||
for(int i=0; i<8; ++i) {
|
||||
if(ref->mmx[i].q!=emu->mmx[i].q) {
|
||||
printf_log(LOG_NONE, "EMM[%d]: %016llx | %016llx\n", i, ref->mmx[i].q, emu->mmx[i].q);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ref->mxcsr.x32 != emu->mxcsr.x32) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "MXCSR: %x | %x\n", ref->mxcsr.x32, emu->mxcsr.x32);
|
||||
}
|
||||
if(memcmp(ref->xmm, emu->xmm, sizeof(emu->xmm))) {
|
||||
BANNER;
|
||||
for(int i=0; i<8; ++i) {
|
||||
if(ref->xmm[i].q[0]!=emu->xmm[i].q[0] || ref->xmm[i].q[1]!=emu->xmm[i].q[1] ) {
|
||||
printf_log(LOG_NONE, "XMM[%02d]: %016llx-%016llx | %016llx-%016llx\n", i, ref->xmm[i].q[1], ref->xmm[i].q[0], emu->xmm[i].q[1], emu->xmm[i].q[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(test->memsize) {
|
||||
if(memcmp(test->mem, (void*)test->memaddr, test->memsize)) {
|
||||
BANNER;
|
||||
printf_log(LOG_NONE, "MEM: @%p :", (void*)test->memaddr);
|
||||
for(int i=0; i<test->memsize; ++i)
|
||||
printf_log(LOG_NONE, " %02x", test->mem[i]);
|
||||
printf_log(LOG_NONE, " |");
|
||||
for(int i=0; i<test->memsize; ++i)
|
||||
printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]);
|
||||
printf_log(LOG_NONE, "\n");
|
||||
}
|
||||
}
|
||||
if(banner) // there was an error, re-sync!
|
||||
CopyEmu(emu, ref);
|
||||
}
|
||||
#undef BANNER
|
||||
|
||||
void x86test_init(x86emu_t* ref, uintptr_t ip)
|
||||
{
|
||||
x86test_t* test = &ref->test;
|
||||
if(!test->test) {
|
||||
test->clean = 0;
|
||||
return;
|
||||
}
|
||||
// check if test as a valid emu struct
|
||||
if(!test->emu) {
|
||||
test->emu = NewX86Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0);
|
||||
CopyEmu(test->emu, ref);
|
||||
} else {
|
||||
// check if IP is same, else, sync
|
||||
uintptr_t prev_ip = test->emu->ip.dword[0];
|
||||
if(test->clean)
|
||||
x86test_check(ref, ip);
|
||||
if(ip != prev_ip || !test->test || !test->clean) {
|
||||
CopyEmu(test->emu, ref);
|
||||
}
|
||||
}
|
||||
// Do a Dry single Step
|
||||
test->memsize = 0;
|
||||
test->clean = 1;
|
||||
ref->old_ip = ip;
|
||||
RunTest(test);
|
||||
// this will be anakyzed next step
|
||||
}
|
||||
@@ -304,6 +304,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
p->MxCsr = emu->mxcsr.x32;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
|
||||
@@ -313,8 +314,6 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
p->ErrorSelector = 0;
|
||||
p->DataOffset = 0;
|
||||
p->DataSelector = 0;
|
||||
p->MxCsr = 0;
|
||||
p->MxCsr_Mask = 0;
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
|
||||
@@ -327,6 +326,7 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
xsave_t *p = (xsave_t*)ed;
|
||||
emu->cw.x16 = p->ControlWord;
|
||||
emu->sw.x16 = p->StatusWord;
|
||||
emu->mxcsr.x32 = p->MxCsr;
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
|
||||
@@ -14,10 +14,6 @@ typedef struct x86emu_s x86emu_t;
|
||||
#define LN2 0.69314718055994531
|
||||
#define LG2 0.3010299956639812
|
||||
|
||||
void Run66D9(x86emu_t *emu);
|
||||
void Run66DD(x86emu_t *emu);
|
||||
void RunDF(x86emu_t *emu);
|
||||
|
||||
#define ST0 emu->x87[emu->top]
|
||||
#define ST1 emu->x87[(emu->top+1)&7]
|
||||
#define ST(a) emu->x87[(emu->top+(a))&7]
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "x86run.h"
|
||||
|
||||
#define F8 *(uint8_t*)(ip++)
|
||||
#define F8S *(int8_t*)(ip++)
|
||||
#define F16 *(uint16_t*)(ip+=2, ip-2)
|
||||
#define F16S *(int16_t*)(ip+=2, ip-2)
|
||||
#define F32 *(uint32_t*)(ip+=4, ip-4)
|
||||
#define F32S *(int32_t*)(ip+=4, ip-4)
|
||||
#define PK(a) *(uint8_t*)(ip+a)
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
void Run66D9(x86emu_t *emu)
|
||||
{
|
||||
uintptr_t ip = R_EIP;
|
||||
uint8_t nextop = F8;
|
||||
reg32_t *oped;
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xE0:
|
||||
case 0xE5:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xFC:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
ip = R_EIP-2;
|
||||
UnimpOpcode(emu);
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* FLDENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
break;
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
GET_EW;
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP-2;
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
}
|
||||
R_EIP = ip;
|
||||
}
|
||||
|
||||
void Run66DD(x86emu_t *emu)
|
||||
{
|
||||
uintptr_t ip = R_EIP;
|
||||
uint8_t nextop = F8;
|
||||
reg32_t *oped;
|
||||
switch(nextop) {
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xE0:
|
||||
case 0xE5:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xFC:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
ip = R_EIP-2;
|
||||
UnimpOpcode(emu);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* FRSTOR m94byte */
|
||||
GET_EW;
|
||||
fpu_loadenv(emu, (char*)ED, 1);
|
||||
// get the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
LD2D(p, &ST(i).d);
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: /* FNSAVE m94byte */
|
||||
GET_EW;
|
||||
// ENV first...
|
||||
fpu_savenv(emu, (char*)ED, 1);
|
||||
// save the STx
|
||||
{
|
||||
char* p =(char*)ED;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
D2LD(&ST(i).d, p);
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
reset_fpu(emu);
|
||||
break;
|
||||
default:
|
||||
ip = R_EIP-2; // unfetch
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
}
|
||||
R_EIP = ip;
|
||||
}
|
||||
@@ -30,7 +30,6 @@ typedef struct atfork_fnc_s {
|
||||
} atfork_fnc_t;
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct mmaplist_s mmaplist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#endif
|
||||
@@ -38,9 +37,10 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#define DYNAMAP_SIZE (1<<(32-DYNAMAP_SHIFT))
|
||||
#define JMPTABL_SHIFT 16
|
||||
#define JMPTABL_SIZE (1<<(32-JMPTABL_SHIFT))
|
||||
#define JMPTABLE_MASK ((1<<JMPTABL_SHIFT)-1)
|
||||
|
||||
typedef void* (*procaddess_t)(const char* name);
|
||||
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
|
||||
typedef void* (*procaddress_t)(const char* name);
|
||||
typedef void* (*vkprocaddress_t)(void* instance, const char* name);
|
||||
|
||||
#define MAX_SIGNAL 64
|
||||
|
||||
@@ -113,18 +113,16 @@ typedef struct box86context_s {
|
||||
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
uintptr_t exit_bridge; // exit bridge value
|
||||
uintptr_t vsyscall; // vsyscall bridge value
|
||||
dlprivate_t *dlprivate; // dlopen library map
|
||||
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
|
||||
kh_symbolmap_t *glmymap; // link to the mysymbolmap of libGL
|
||||
procaddess_t glxprocaddress;
|
||||
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
|
||||
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
|
||||
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
|
||||
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
|
||||
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
|
||||
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
|
||||
vkprocaddess_t vkprocaddress;
|
||||
vkprocaddress_t vkprocaddress;
|
||||
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_t mutex_once;
|
||||
@@ -142,7 +140,9 @@ typedef struct box86context_s {
|
||||
uint32_t mutex_thread;
|
||||
uint32_t mutex_bridge;
|
||||
uint32_t mutex_dyndump;
|
||||
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
|
||||
int trace_dynarec;
|
||||
pthread_mutex_t mutex_lock; // this is for the Test interpreter
|
||||
#endif
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
@@ -208,7 +208,7 @@ typedef struct box86context_s {
|
||||
#else
|
||||
int GetTID();
|
||||
#define mutex_lock(A) {int tid = GetTID(); while(arm_lock_storeifnull(A, (void*)tid)) sched_yield();}
|
||||
#define mutex_trylock(A) arm_lock_storeifnull(A, (void*)GetTID())
|
||||
#define mutex_trylock(A) (uintptr_t)arm_lock_storeifnull(A, (void*)GetTID())
|
||||
#define mutex_unlock(A) arm_lock_storeifref(A, NULL, (void*)GetTID())
|
||||
#endif
|
||||
|
||||
|
||||
+22
-14
@@ -18,35 +18,43 @@ void customFree(void* p);
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
||||
uintptr_t AllocDynarecMap(size_t size);
|
||||
void FreeDynarecMap(uintptr_t addr);
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy);
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx);
|
||||
void addJumpTableIfDefault(void* addr, void* jmp);
|
||||
dynablock_t* getDB(uintptr_t idx);
|
||||
int getNeedTest(uintptr_t idx);
|
||||
int addJumpTableIfDefault(void* addr, void* jmp); // return 1 if write was succesfull
|
||||
int setJumpTableIfRef(void* addr, void* jmp, void* ref); // return 1 if write was succesfull
|
||||
void setJumpTableDefault(void* addr);
|
||||
void setJumpTableDefaultRef(void* addr, void* jmp);
|
||||
int isJumpTableDefault(void* addr);
|
||||
uintptr_t getJumpTable();
|
||||
uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
uintptr_t getJumpAddress(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R)
|
||||
#define PROT_NOPROT 0x20
|
||||
#define PROT_MMAP 0x10
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP | PROT_NOPROT)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
void refreshProtection(uintptr_t addr);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, uintptr_t size);
|
||||
int getMmapped(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
|
||||
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);
|
||||
|
||||
@@ -24,7 +24,10 @@ extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
|
||||
extern int box86_dynarec_fastnan;
|
||||
extern int box86_dynarec_fastround;
|
||||
extern int box86_dynarec_hotpage;
|
||||
extern int box86_dynarec_wait;
|
||||
extern int box86_dynarec_fastpage;
|
||||
extern int box86_dynarec_bleeding_edge;
|
||||
extern int box86_dynarec_test;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
|
||||
+7
-16
@@ -3,31 +3,22 @@
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
|
||||
uint32_t X31_hash_code(void* addr, int len);
|
||||
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
void FreeInvalidDynablock(dynablock_t* db, int need_lock);
|
||||
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock);
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box86context.h
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
|
||||
|
||||
uintptr_t StartDynablockList(dynablocklist_t* db);
|
||||
uintptr_t EndDynablockList(dynablocklist_t* db);
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x64 translated code)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr);
|
||||
|
||||
// Create and Add an new dynablock in the list, handling direct/map
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
|
||||
|
||||
// for use in signal handler
|
||||
void cancelFillBlock();
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
void DynaCall(x86emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available
|
||||
void x86test_init(x86emu_t* ref, uintptr_t ip);
|
||||
|
||||
#endif // __DYNAREC_H_
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
void addInst(instsize_t* insts, size_t* size, int x86_size, int arm_size);
|
||||
|
||||
void CancelBlock();
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
@@ -10,7 +10,7 @@ typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
#endif
|
||||
|
||||
elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
|
||||
@@ -49,8 +49,7 @@ uint32_t GetTLSSize(elfheader_t* h);
|
||||
void* GetTLSPointer(box86context_t* context, elfheader_t* h);
|
||||
void* GetDTatOffset(box86context_t* context, int index, int offset);
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr);
|
||||
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
|
||||
dynablock_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr);
|
||||
#endif
|
||||
void ResetSpecialCaseMainElf(elfheader_t* h);
|
||||
void CreateMemorymapFile(box86context_t* context, int fd);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __GL_TOOLS_H__
|
||||
#define __GL_TOOLS_H__
|
||||
|
||||
typedef struct box86context_s box86context_t;
|
||||
|
||||
typedef void* (*glprocaddress_t)(const char* name);
|
||||
|
||||
void freeGLProcWrapper(box86context_t* context);
|
||||
|
||||
void* getGLProcAddress(x86emu_t* emu, glprocaddress_t procaddr, const char* rname);
|
||||
|
||||
#endif //__GL_TOOLS_H__
|
||||
@@ -457,6 +457,19 @@ typedef struct my_GDBusObjectManagerClientClass_s
|
||||
void* padding[8];
|
||||
} my_GDBusObjectManagerClientClass_t;
|
||||
|
||||
typedef struct my_GstObjectClass_s {
|
||||
my_GInitiallyUnownedClass_t parent;
|
||||
const char* path_string_separator;
|
||||
void (*deep_notify) (void* object, void* orig, void* pspec);
|
||||
void* _gst_reserved[4];
|
||||
} my_GstObjectClass_t;
|
||||
|
||||
typedef struct my_GstAllocatorClass_s {
|
||||
my_GstObjectClass_t parent;
|
||||
void* (*alloc) (void *allocator, size_t size, void *params);
|
||||
void (*free) (void *allocator, void *memory);
|
||||
void* _gst_reserved[4];
|
||||
} my_GstAllocatorClass_t;
|
||||
|
||||
// GTypeValueTable
|
||||
typedef struct my_GTypeValueTable_s {
|
||||
@@ -540,6 +553,8 @@ GTKCLASS(GtkMenuShell2) \
|
||||
GTKCLASS(GtkMenuBar2) \
|
||||
GTKCLASS(MetaFrames2) \
|
||||
GTKCLASS(GDBusObjectManagerClient) \
|
||||
GTKCLASS(GstObject) \
|
||||
GTKCLASS(GstAllocator) \
|
||||
|
||||
#define GTKCLASS(A) void Set##A##ID(int id);
|
||||
GTKCLASSES()
|
||||
|
||||
@@ -27,10 +27,6 @@ int IsSameLib(library_t* lib, const char* path); // check if lib is same (pat
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
void fillGLProcWrapper(box86context_t* context);
|
||||
void freeGLProcWrapper(box86context_t* context);
|
||||
void fillALProcWrapper(box86context_t* context);
|
||||
void freeALProcWrapper(box86context_t* context);
|
||||
needed_libs_t* GetNeededLibs(library_t* lib);
|
||||
int GetNeededLibN(library_t* lib);
|
||||
library_t* GetNeededLib(library_t* lib, int idx);
|
||||
|
||||
@@ -23,6 +23,7 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack);
|
||||
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack);
|
||||
void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack);
|
||||
|
||||
void AlignStat64(const void* source, void* dest);
|
||||
void UnalignStat64(const void* source, void* dest);
|
||||
|
||||
void UnalignStatFS64(const void* source, void* dest);
|
||||
|
||||
@@ -10,6 +10,7 @@ void SetupX86Emu(x86emu_t *emu);
|
||||
void FreeX86Emu(x86emu_t **x86emu);
|
||||
void FreeX86EmuFromStack(x86emu_t **emu);
|
||||
void CloneEmu(x86emu_t *newemu, const x86emu_t* emu);
|
||||
void CopyEmu(x86emu_t *newemu, const x86emu_t* emu);
|
||||
void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end);
|
||||
|
||||
box86context_t* GetEmuContext(x86emu_t* emu);
|
||||
@@ -34,8 +35,6 @@ void ResetSegmentsCache(x86emu_t *emu);
|
||||
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip);
|
||||
|
||||
void StopEmu(x86emu_t* emu, const char* reason);
|
||||
void PushExit(x86emu_t* emu);
|
||||
void* GetExit();
|
||||
void EmuCall(x86emu_t* emu, uintptr_t addr);
|
||||
void AddCleanup(x86emu_t *emu, void *p);
|
||||
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a);
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct x86test_s x86test_t;
|
||||
int Run(x86emu_t *emu, int step); // 0 if run was successfull, 1 if error in x86 world
|
||||
int RunTest(x86test_t *test);
|
||||
int DynaRun(x86emu_t *emu);
|
||||
|
||||
uint32_t LibSyscall(x86emu_t *emu);
|
||||
|
||||
@@ -173,6 +173,7 @@ GO("libcap.so.2", cap)
|
||||
GO("libpcap.so.0", pcap)
|
||||
GO("libFAudio.so.0", faudio)
|
||||
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
|
||||
GO("libfuse.so.2", libfuse)
|
||||
|
||||
#ifdef ANDROID
|
||||
GO("libc.so", libc)
|
||||
|
||||
@@ -43,6 +43,35 @@ void UnalignStat64(const void* source, void* dest)
|
||||
i386st->st_ino = st->st_ino;
|
||||
}
|
||||
|
||||
void AlignStat64(const void* source, void* dest)
|
||||
{
|
||||
struct stat64 *st = (struct stat64*) dest;
|
||||
struct i386_stat64 *i386st = (struct i386_stat64*)source;
|
||||
|
||||
st->st_dev = i386st->st_dev;
|
||||
#ifndef POWERPCLE
|
||||
st->__st_ino = i386st->__st_ino;
|
||||
#else
|
||||
st->st_ino = i386st->__st_ino; // Separate __st_ino doesn't
|
||||
// exist on powerpc
|
||||
#endif
|
||||
st->st_mode = i386st->st_mode;
|
||||
st->st_nlink = i386st->st_nlink;
|
||||
st->st_uid = i386st->st_uid;
|
||||
st->st_gid = i386st->st_gid;
|
||||
st->st_rdev = i386st->st_rdev;
|
||||
st->st_size = i386st->st_size;
|
||||
st->st_blksize = i386st->st_blksize;
|
||||
st->st_blocks = i386st->st_blocks;
|
||||
st->st_atime = i386st->st_atime;
|
||||
st->st_atime_nsec = i386st->st_atime_nsec;
|
||||
st->st_mtime = i386st->st_mtime;
|
||||
st->st_mtime_nsec = i386st->st_mtime_nsec;
|
||||
st->st_ctime = i386st->st_ctime;
|
||||
st->st_ctime_nsec = i386st->st_ctime_nsec;
|
||||
st->st_ino = i386st->st_ino;
|
||||
}
|
||||
|
||||
struct native_fsid {
|
||||
int val[2];
|
||||
};
|
||||
|
||||
+54
-17
@@ -277,6 +277,10 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
//trace_start = 0; trace_end = 1; // disabling trace, globably for now...
|
||||
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test)
|
||||
emu->test.test = 0;
|
||||
#endif
|
||||
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_ESP);
|
||||
|
||||
@@ -308,6 +312,12 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
uint32_t ret = R_EAX;
|
||||
emu->quitonlongjmp = oldquitonlongjmp;
|
||||
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test)
|
||||
emu->test.test = 0;
|
||||
emu->test.clean = 0;
|
||||
#endif
|
||||
|
||||
if(emu->longjmp) {
|
||||
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
|
||||
emu->longjmp = 0;
|
||||
@@ -676,7 +686,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
//relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled
|
||||
#ifdef DYNAREC
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock();
|
||||
CancelBlock(1);
|
||||
#endif
|
||||
siglongjmp(ejb->jmpbuf, 1);
|
||||
}
|
||||
@@ -718,6 +728,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
}
|
||||
|
||||
extern void* current_helper;
|
||||
#ifdef DYNAREC
|
||||
static uint32_t mutex_dynarec_prot = 0;
|
||||
#endif
|
||||
|
||||
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
{
|
||||
@@ -749,18 +762,20 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
#endif
|
||||
#ifdef DYNAREC
|
||||
if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) {
|
||||
relockMutex(Locks);
|
||||
CancelBlock();
|
||||
CancelBlock(0);
|
||||
cancelFillBlock(); // Segfault inside a Fillblock
|
||||
relockMutex(Locks);
|
||||
}
|
||||
dynablock_t* db = NULL;
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) {
|
||||
mutex_lock(&mutex_dynarec_prot);
|
||||
// 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;
|
||||
static int repeated_count = 0;
|
||||
@@ -772,7 +787,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
repeated_page = (uintptr_t)addr&~0xfff;
|
||||
repeated_count = 0;
|
||||
}
|
||||
if(db && ((addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) || db->need_test)) {
|
||||
if(db && ((addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) || db_need_test)) {
|
||||
// dynablock got auto-dirty! need to get out of it!!!
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
if(ejb->jmpbuf_ok) {
|
||||
@@ -799,40 +814,46 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
dynarec_log(LOG_INFO, "Dynablock %p(%p) unprotected, getting out (arm pc=%p, x86_pc=%p, special=%d)!\n", db, db->x86_addr, pc, (void*)ejb->emu->ip.dword[0], special);
|
||||
}
|
||||
//relockMutex(Locks); // do not relock because of he siglongjmp
|
||||
#ifdef DYNAREC
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock();
|
||||
#endif
|
||||
CancelBlock(1);
|
||||
ejb->emu->test.clean = 0;
|
||||
siglongjmp(ejb->jmpbuf, 2);
|
||||
}
|
||||
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x86_addr);
|
||||
}
|
||||
// done
|
||||
if(prot&PROT_WRITE) {
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
// if there is no write permission, don't return and continue to program signal handling
|
||||
relockMutex(Locks);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
|
||||
mutex_lock(&mutex_dynarec_prot);
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
|
||||
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
|
||||
}
|
||||
if(addr && pc && db) {
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
// mark stuff as unclean
|
||||
cleanDBFromAddressRange(((uintptr_t)addr)&~(box86_pagesize-1), box86_pagesize, 0);
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
if(addr && pc /*&& db*/) {
|
||||
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x, retrying\n", pc, addr, db, prot);
|
||||
glitch_pc = pc;
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
relockMutex(Locks);
|
||||
sched_yield(); // give time to the other process
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
return; // try again
|
||||
}
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot);
|
||||
glitch_pc = NULL;
|
||||
glitch_addr = NULL;
|
||||
glitch_prot = 0;
|
||||
@@ -848,16 +869,23 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
glitch2_addr = addr;
|
||||
glitch2_prot = prot;
|
||||
sched_yield(); // give time to the other process
|
||||
forceProtection((uintptr_t)addr, 1, prot); // force the protection
|
||||
refreshProtection((uintptr_t)addr);
|
||||
relockMutex(Locks);
|
||||
sched_yield(); // give time to the other process
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
return; // try again
|
||||
}
|
||||
glitch2_pc = NULL;
|
||||
glitch2_addr = NULL;
|
||||
glitch2_prot = 0;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC_R)) {
|
||||
// unprotect and continue to signal handler, because Write is not there on purpose
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
}
|
||||
if(!db_searched)
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
#else
|
||||
void* db = NULL;
|
||||
#endif
|
||||
@@ -928,7 +956,7 @@ exit(-1);
|
||||
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_EBP,
|
||||
addr, info->si_code, prot, db, db?db->block:0, db?(db->block+db->size):0,
|
||||
db?db->x86_addr:0, db?(db->x86_addr+db->x86_size):0,
|
||||
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?getNeedTest((uintptr_t)db->x86_addr):0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
#if defined(ARM)
|
||||
static const char* reg_name[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
|
||||
if(db)
|
||||
@@ -1309,7 +1337,7 @@ EXPORT int my_makecontext(x86emu_t* emu, void* ucp, void* fnc, int32_t argc, int
|
||||
}
|
||||
// push the return value
|
||||
--esp;
|
||||
*esp = (uintptr_t)GetExit();
|
||||
*esp = my_context->exit_bridge;
|
||||
u->uc_mcontext.gregs[REG_ESP] = (uintptr_t)esp;
|
||||
|
||||
return 0;
|
||||
@@ -1324,7 +1352,12 @@ EXPORT int my_swapcontext(x86emu_t* emu, void* ucp1, void* ucp2)
|
||||
my_setcontext(emu, ucp2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
static void atfork_child_dynarec_prot(void)
|
||||
{
|
||||
arm_lock_stored(&mutex_dynarec_prot, 0);
|
||||
}
|
||||
#endif
|
||||
void init_signal_helper(box86context_t* context)
|
||||
{
|
||||
// setup signal handling
|
||||
@@ -1343,6 +1376,10 @@ void init_signal_helper(box86context_t* context)
|
||||
sigaction(SIGILL, &action, NULL);
|
||||
|
||||
pthread_once(&sigstack_key_once, sigstack_key_alloc);
|
||||
#ifdef DYNAREC
|
||||
atfork_child_dynarec_prot();
|
||||
pthread_atfork(NULL, NULL, atfork_child_dynarec_prot);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fini_signal_helper()
|
||||
|
||||
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user