mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-08 02:08:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f191228318 | ||
|
|
7c3730f4e6 | ||
|
|
772aca08b8 | ||
|
|
0f19b73dfe | ||
|
|
b7dccd065f | ||
|
|
57c1ed7118 | ||
|
|
5a348e1de9 | ||
|
|
76a5f3b7c9 | ||
|
|
c317bf94c8 | ||
|
|
cbe0ef830b | ||
|
|
5c54463c32 | ||
|
|
531ccfaf6a | ||
|
|
339af4a13e | ||
|
|
d4f7ec6ee4 | ||
|
|
2de4ce82f3 | ||
|
|
d2f033e97a | ||
|
|
c2375d030b | ||
|
|
786680a288 | ||
|
|
0883cdc9ac | ||
|
|
e35d6d22a4 | ||
|
|
14a53affc0 | ||
|
|
18e8b06dfb | ||
|
|
ac8ae8f0ec | ||
|
|
274fe75017 | ||
|
|
278d8fe8d9 | ||
|
|
dcf89339b8 | ||
|
|
1c3c3a209a | ||
|
|
d91ac13592 | ||
|
|
aafa791f4a | ||
|
|
3b08ace904 | ||
|
|
fefa13f655 | ||
|
|
949e7b7809 | ||
|
|
7fe38de5f6 | ||
|
|
9803591643 | ||
|
|
d87033837b | ||
|
|
507b68358f | ||
|
|
1b721a536e | ||
|
|
77706f8142 | ||
|
|
8a71575487 | ||
|
|
dd0a57ab30 | ||
|
|
07b0f6673a | ||
|
|
88e84a6c1c | ||
|
|
767e94aae1 | ||
|
|
0c211a0164 | ||
|
|
be6e2fe1da | ||
|
|
d94dce18c5 | ||
|
|
a0f180e86b | ||
|
|
8f2fe64afc | ||
|
|
d64248b1f8 | ||
|
|
cc67b01aa8 | ||
|
|
90a18265b9 | ||
|
|
08f8d8d721 | ||
|
|
df2504f976 | ||
|
|
117fe48b5e | ||
|
|
e02844fb93 | ||
|
|
ca1f0d0cf2 | ||
|
|
2e6bc42a49 | ||
|
|
cf2e754447 | ||
|
|
708986a3c6 | ||
|
|
e8fabe23ec | ||
|
|
fa2374a7a7 | ||
|
|
a70e5d7aa7 | ||
|
|
e87915bcfb | ||
|
|
c540942294 | ||
|
|
3869cc2bc0 | ||
|
|
f3ddb6bcf4 | ||
|
|
26f30a3c09 | ||
|
|
b831475d1b | ||
|
|
431eb604e4 | ||
|
|
0d2bf2fe30 | ||
|
|
94f9f5d0b5 | ||
|
|
8349acb93a | ||
|
|
8c00a1100f | ||
|
|
0cdd36bac6 | ||
|
|
fd3dcf3873 | ||
|
|
72d3098ba4 | ||
|
|
177abf2e44 | ||
|
|
077764251d | ||
|
|
90fbf7237f | ||
|
|
d9ec366ce4 | ||
|
|
c854b23d35 | ||
|
|
fd137915b6 | ||
|
|
dad0e5ef2f | ||
|
|
5abf1fa24e | ||
|
|
b5bc46e13a | ||
|
|
c39a8ebd51 | ||
|
|
38d35cbef0 | ||
|
|
3058fefe93 | ||
|
|
f03d09b949 | ||
|
|
2343533b41 | ||
|
|
fa2f3c0577 | ||
|
|
6c28b3584e | ||
|
|
8fa5ec74ec | ||
|
|
868ad666ed | ||
|
|
150b035a1b | ||
|
|
fdd775790a | ||
|
|
68ff10a18e | ||
|
|
3f072c8aa8 | ||
|
|
7b0c1689bb | ||
|
|
6946198045 | ||
|
|
8f76973fcf | ||
|
|
b9ded7320a | ||
|
|
fc14382a07 | ||
|
|
35cc9af4ff | ||
|
|
0c2d9acd99 | ||
|
|
9c0ecf0427 | ||
|
|
10529d007c | ||
|
|
ac356fc146 | ||
|
|
0b584bbb48 | ||
|
|
c10b105f5f | ||
|
|
236de084ea | ||
|
|
72e917bb06 | ||
|
|
0d64ab09bb | ||
|
|
ff0b7683e7 | ||
|
|
d210f12f25 | ||
|
|
87d346230c | ||
|
|
47c65e1e3a | ||
|
|
57440bd102 | ||
|
|
389c803929 | ||
|
|
08d8407056 | ||
|
|
3f12bde9ff | ||
|
|
a47a9d95d7 | ||
|
|
f2a4125ab8 | ||
|
|
2d3f244935 | ||
|
|
2a1342c5b3 | ||
|
|
82bf0a99d2 | ||
|
|
c6275bcb62 | ||
|
|
7a175a9733 | ||
|
|
75759f9ba7 | ||
|
|
6f966fe468 | ||
|
|
f716212932 | ||
|
|
4b1b214663 | ||
|
|
5e7a7db60d | ||
|
|
968da3a4d4 | ||
|
|
347c645e95 | ||
|
|
e50f152355 | ||
|
|
59f85c8fbb | ||
|
|
9fbab85232 | ||
|
|
a0a3389651 | ||
|
|
6e51e73a1e | ||
|
|
35e64fd56c | ||
|
|
402496c93e | ||
|
|
84d415c211 | ||
|
|
020b2ba8d0 | ||
|
|
2890c05fba | ||
|
|
829d39f8a3 | ||
|
|
197cdafa22 | ||
|
|
aa75d5a434 | ||
|
|
38b8d9b8a5 | ||
|
|
a1091a9a72 | ||
|
|
8d1561f6e5 | ||
|
|
375bc45b51 | ||
|
|
334b891364 | ||
|
|
a8f3d57afb | ||
|
|
3023c8262d | ||
|
|
bc166ae3b3 | ||
|
|
4e29df8a56 | ||
|
|
e24c1f048b | ||
|
|
daef5cbdc9 | ||
|
|
699af54183 | ||
|
|
731d9a249d | ||
|
|
3e67c4573b | ||
|
|
ef25a75b86 | ||
|
|
c4b182048c | ||
|
|
6079f39655 | ||
|
|
2dcd2741c7 | ||
|
|
399b2c7f8a | ||
|
|
7ae3200c6f | ||
|
|
299ddb22a5 | ||
|
|
df8930a78a | ||
|
|
a37cd0bd91 | ||
|
|
ee10226614 | ||
|
|
ad934455c1 | ||
|
|
c0e7062b03 | ||
|
|
04d03af8ac |
No files matched your search
@@ -23,6 +23,9 @@ on:
|
||||
- RPI4
|
||||
- RPI4ARM64
|
||||
- SD845
|
||||
- SD888
|
||||
- ADLINK
|
||||
- PHYTIUM
|
||||
build_type:
|
||||
description: 'Build type'
|
||||
required: true
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
|
||||
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, SD888, ADLINK, PHYTIUM, ANDROID]
|
||||
type: [Release, Trace]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
|
||||
unzip android-ndk-r23b-linux.zip
|
||||
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
|
||||
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DNOLOADADDR=1" >> $GITHUB_ENV
|
||||
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DNOLOADADDR=1" >> $GITHUB_ENV
|
||||
else
|
||||
sudo apt-get -y install gcc-arm-linux-gnueabihf
|
||||
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
|
||||
|
||||
+130
-21
@@ -19,11 +19,14 @@ option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
|
||||
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
|
||||
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
|
||||
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
|
||||
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
|
||||
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
|
||||
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
|
||||
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
|
||||
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
|
||||
option(TERMUX "Set to ON if targeting an Android device with Termux" ${TERMUX})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
|
||||
@@ -32,7 +35,7 @@ option(NOGIT "Set to ON if not building from a git clone repo (like when buildin
|
||||
option(NO_LIB_INSTALL "Set ON to not install a few x86 libs that are used by many program" ${NO_LIB_INSTALL})
|
||||
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
|
||||
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -40,8 +43,13 @@ if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE O
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
endif()
|
||||
if(TERMUX)
|
||||
set(ANDROID ON CACHE BOOL "")
|
||||
set(TERMUX_PATH "/data/data/com.termux/files")
|
||||
endif()
|
||||
if(ANDROID)
|
||||
set(NOLOADADDR ON CACHE BOOL "")
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
|
||||
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
|
||||
@@ -70,8 +78,10 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "arm" _arm)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armv8l" _armv8l)
|
||||
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR RK3588 OR ARM64))
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
|
||||
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
|
||||
@@ -137,6 +147,14 @@ elseif(SD845)
|
||||
add_definitions(-DSD845)
|
||||
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(SD888)
|
||||
add_definitions(-DSD888)
|
||||
add_definitions(-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ADLINK)
|
||||
add_definitions(-DADLINK)
|
||||
add_definitions(-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(A64)
|
||||
add_definitions(-DA64)
|
||||
add_definitions(-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
@@ -178,13 +196,18 @@ elseif(LX2160A)
|
||||
add_definitions(-DLX2160A)
|
||||
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ANDROID)
|
||||
add_definitions(-DANDROID)
|
||||
elseif(ARM_DYNAREC)
|
||||
#if DYNAREC is selected alone, without any arch
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
|
||||
if(NOT ANDROID)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
|
||||
endif()
|
||||
endif()
|
||||
if(ANDROID)
|
||||
add_definitions(-DANDROID)
|
||||
endif()
|
||||
if(TERMUX)
|
||||
add_definitions(-DTERMUX)
|
||||
endif()
|
||||
|
||||
if(BAD_SIGNAL)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
endif()
|
||||
@@ -299,6 +322,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/librarian/dictionnary.c"
|
||||
"${BOX86_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX86_ROOT}/src/emu/x86compstrings.c"
|
||||
"${BOX86_ROOT}/src/emu/x86emu.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x86syscall.c"
|
||||
@@ -334,6 +358,7 @@ set(INTERPRETER
|
||||
"${BOX86_ROOT}/src/emu/x86run660f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66d9.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66dd.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66f20f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run67.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run6766.c"
|
||||
"${BOX86_ROOT}/src/emu/x86rund8.c"
|
||||
@@ -354,6 +379,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibpthread.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibrt.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibbsd.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibx11.c"
|
||||
@@ -413,6 +439,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedalure.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedopencl.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
|
||||
@@ -467,6 +494,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedappindicator3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedayatanaappindicator3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatkbridge.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
@@ -519,6 +547,8 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatomic.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibpcre.c"
|
||||
)
|
||||
if(ANDROID)
|
||||
list(APPEND WRAPPEDS
|
||||
@@ -548,7 +578,7 @@ add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX86_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "--"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "TERMUX" "--"
|
||||
${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
@@ -666,7 +696,11 @@ else()
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
if(ANDROID)
|
||||
if(TERMUX)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl android-sysv-semaphore android-spawn)
|
||||
else()
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl rt pthread resolv)
|
||||
endif()
|
||||
@@ -688,6 +722,11 @@ add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head
|
||||
add_dependencies(${BOX86} WRAPPERS)
|
||||
add_dependencies(${BOX86} PRINTER)
|
||||
if(ANDROID)
|
||||
if(TERMUX)
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl android-complex-math android-sysv-semaphore android-spawn )
|
||||
else()
|
||||
target_link_libraries(${BOX86} dynarec interpreter m dl)
|
||||
endif()
|
||||
target_link_libraries(${BOX86} c m dl)
|
||||
else()
|
||||
#target_link_libraries(${BOX86} c m dl rt pthread resolv)
|
||||
@@ -701,30 +740,58 @@ endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,--image-base,${BOX86_ELF_ADDRESS}")
|
||||
else()
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
|
||||
endif()
|
||||
else()
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
|
||||
endif()
|
||||
else()
|
||||
target_link_options(${BOX86} PUBLIC -rdynamic)
|
||||
if(NOT NOLOADADDR)
|
||||
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_options(${BOX86} PUBLIC -Wl,--image-base,${BOX86_ELF_ADDRESS})
|
||||
else()
|
||||
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX86}
|
||||
if(NOT TERMUX)
|
||||
install(TARGETS ${BOX86}
|
||||
RUNTIME DESTINATION bin)
|
||||
else()
|
||||
install(TARGETS ${BOX86}
|
||||
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
|
||||
endif()
|
||||
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/)
|
||||
if(NOT TERMUX)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
|
||||
else()
|
||||
#install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION ${TERMUX_PATH}/usr/etc/)
|
||||
endif()
|
||||
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/)
|
||||
if(NOT TERMUX)
|
||||
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}/x86lib/libunwind.so.8 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
else()
|
||||
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -742,7 +809,11 @@ set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
|
||||
set(CPACK_PACKAGE_CONTACT "[email protected]")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Box86 - Linux Userspace x86 Emulator with a twist")
|
||||
if(TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libandroid-sysv-semaphore, libandroid-spawn")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
endif()
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
|
||||
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MAJOR\\s*")
|
||||
string(REGEX REPLACE "BOX86_MAJOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
@@ -756,16 +827,29 @@ string(REGEX MATCH "[0-9]" BOX86_REVISION ${TEMP_STRING})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX86_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${BOX86_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${BOX86_REVISION})
|
||||
if(NOT TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
|
||||
if(_aarch64 OR _armhf)
|
||||
endif()
|
||||
if(_aarch64 OR _armhf OR _arm OR _armv8l)
|
||||
if(TERMUX)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
|
||||
endif()
|
||||
elseif(_x86_64 OR _x86)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
|
||||
else()
|
||||
#probably wrong...
|
||||
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||
endif()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
if(TERMUX)
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "${TERMUX_PATH}/usr")
|
||||
endif()
|
||||
if(NOT TERMUX)
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_${CMAKE_SYSTEM_NAME}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
else()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Termux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
endif()
|
||||
INCLUDE(CPack)
|
||||
|
||||
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
@@ -872,20 +956,45 @@ add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
add_test(NAME multiple_dlopen COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME aes COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
foreach(file ${extension_tests})
|
||||
get_filename_component(testname "${file}" NAME_WE)
|
||||
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
|
||||
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
|
||||
|
||||
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23 -D TEST_OUTPUT=tmpfile23.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
#add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
|
||||
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
|
||||
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
endif(BOX86LIB)
|
||||
Vendored
+35
@@ -1,3 +1,38 @@
|
||||
box86 (0.3.4) unstable; urgency=low
|
||||
|
||||
* X86Libs: Updated libstdc++ & libgcc_s
|
||||
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
|
||||
* Dynarec: Fixed some flags propagation issues inside blocks
|
||||
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
|
||||
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
|
||||
* CPU: Added full support for SSE4.2
|
||||
* ElfLoader: rework how elf memory is handled
|
||||
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
|
||||
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
|
||||
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
|
||||
* Wrapping: Removed faked libunwind wrapping
|
||||
* Hardware: Added more profile, with support for ADLink Ampere Altra
|
||||
* OS: Added profile to build for Android and Termux.
|
||||
* => Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
|
||||
* => Some work also to reduce the memory footprint
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 15 Dec 2023 17:30:33 -0100
|
||||
|
||||
box86 (0.3.2) unstable; urgency=low
|
||||
|
||||
* Better syscall handling
|
||||
* Fixed some wrapped functions, added some others
|
||||
* Introduced another wrapper helper
|
||||
* Added some more opcodes
|
||||
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
|
||||
* Added support of FASTNAN for some more opcodes
|
||||
* Reduced memory footprint
|
||||
* Added BOX86_NOSANDBOX (adds an argument to the command line)
|
||||
* Added an ukrainian translation
|
||||
* => Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
|
||||
|
||||
box86 (0.3.0) unstable; urgency=low
|
||||
|
||||
* Added rcfile handling: box86 now read "/etc/box86.box86rc" and "~/.box86rc" and apply per process parameters
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
v0.3.4
|
||||
======
|
||||
* X86Libs: Updated libstdc++ & libgcc_s
|
||||
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
|
||||
* Dynarec: Fixed some flags propagation issues inside blocks
|
||||
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
|
||||
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
|
||||
* CPU: Added full support for SSE4.2
|
||||
* ElfLoader: rework how elf memory is handled
|
||||
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
|
||||
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
|
||||
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
|
||||
* Wrapping: Removed faked libunwind wrapping
|
||||
* Hardware: Added more profile, with support for ADLink Ampere Altra
|
||||
* OS: Added profile to build for Android and Termux.
|
||||
=> Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
|
||||
=> Some work also to reduce the memory footprint
|
||||
|
||||
v0.3.2
|
||||
======
|
||||
* Better syscall handling
|
||||
|
||||
+10
-2
@@ -100,11 +100,13 @@ As most Allwinner A64 devices run an AARCH64 OS, you'll need an `armhf` multiarc
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for Snapdragon 845
|
||||
#### for Snapdragon
|
||||
|
||||
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
or
|
||||
`mkdir build; cd build; cmake .. -DSD888=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
Depending how old/recent you SD is. As most Snapdragon devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Phytium
|
||||
|
||||
@@ -115,6 +117,12 @@ As most Phytium (D2000 or FT2000/4) devices run an AARCH64 OS, you'll need an `a
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for ADLink AmpereAltra
|
||||
|
||||
`mkdir build; cd build; cmake .. -DADLINK=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j`
|
||||
|
||||
As ADLINK AmpereAltra computers run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Other ARM64 64bits Linux platform
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
+6
-6
@@ -28,8 +28,8 @@ Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86
|
||||
----
|
||||
Compiling/Installation
|
||||
----
|
||||
> Compilation instructions can be found [here](COMPILE.md)
|
||||
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
|
||||
> Compilation instructions can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md)
|
||||
> Instructions for installing Wine for Box86 can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/X86WINE.md)
|
||||
|
||||
----
|
||||
|
||||
@@ -80,8 +80,8 @@ Notes about Box86 configuration
|
||||
----
|
||||
|
||||
Box86 now have configurations files. There are 2 files loaded. `/etc/box4.box86rc` and `~/.box86rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box86 comes with a default file that should be installed for better stability. The file in in `system/box86.box86rc` and should be installed to `/etc/box86.box86rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box86rc` or some game may not function correctly.
|
||||
Note that the priority is: `~/.bashrc` > `/etc/box86.box86rc` > command line
|
||||
So, your settings in `~/.bashrc` may override the setting from your command line...
|
||||
Note that the priority is: `~/.box86rc` > `/etc/box86.box86rc` > command line
|
||||
So, your settings in `~/.box86rc` may override the setting from your command line...
|
||||
|
||||
----
|
||||
|
||||
@@ -134,8 +134,8 @@ I want to thank everyone who has contributed to box86 development.
|
||||
There are many ways to contribute: code, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin, icecream95, M-HT
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
|
||||
* For their hardware contribution: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/), [AYN](https://www.ayntec.com/)
|
||||
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
And I also thank the many other people who participated even once in the project.
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序
|
||||
以下感谢不分先后:
|
||||
* 代码贡献:rajdakin, icecream95, M-HT
|
||||
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* 硬件捐赠:[ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
我还要感谢很多人,即使他们只参与了一次本项目。
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ Box86 вже використовує Vulkan. Якщо у вашій систе
|
||||
Отже, без особливого порядку, я хочу подякувати:
|
||||
* За основний внесок у код: rajdakin, icecream95, M-HT
|
||||
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* За внесок у апаратне забезпечення: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
|
||||
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
|
||||
* За постійну рекламу Box86: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[Команда TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
І я також дякую багатьом іншим людям, які хоч раз брали участь у проекті.
|
||||
|
||||
+24
-2
@@ -146,8 +146,9 @@ Define Box86's Dynarec max allowed forward value when building Block.
|
||||
#### BOX86_DYNAREC_STRONGMEM *
|
||||
Enable/Disable simulation of Strong Memory model
|
||||
* 0 : Don't try anything special (Default.)
|
||||
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
|
||||
* 1 : Enable some Memory Barrier when writting to memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : All 1. plus a memory barrier on every write to memory using MOV
|
||||
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
|
||||
|
||||
#### BOX86_DYNAREC_X87DOUBLE *
|
||||
Force the use of Double for x87 emulation
|
||||
@@ -195,6 +196,11 @@ Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is n
|
||||
* 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_DYNAREC_MISSING *
|
||||
Dynarec print the missing opcodes
|
||||
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
|
||||
* 1 : Will print the missing opcodes
|
||||
|
||||
#### BOX86_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
@@ -210,6 +216,16 @@ Detect libcef and apply malloc_hack settings
|
||||
* 0 : Don't detect libcef
|
||||
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
|
||||
|
||||
#### BOX86_SDL2_JGUID *
|
||||
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
|
||||
* 0 : Don't use any workaround
|
||||
* 1 : Use a workaround for program that use the private SDL_GetJoystickGUIDInfo function with 1 missing argument
|
||||
|
||||
#### BOX86_MUTEX_ALIGNED *
|
||||
Will mutex are used as-is or wrapped to handle unaligned used
|
||||
* 0 : Mutex will be wrapped in case unaligned mutexes are used (Default)
|
||||
* 1 : Do no wrap mutex and use them as-is (faster, but might crash with SEGBUS error)
|
||||
|
||||
#### BOX86_LIBGL *
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
@@ -259,6 +275,11 @@ Disables the load of vulkan libraries.
|
||||
* 0 : Load vulkan libraries if found.
|
||||
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
|
||||
|
||||
#### BOX86_FUTEX_WAITV *
|
||||
Use of the new fuext_waitc syscall
|
||||
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
|
||||
* 1 : let program use the syscall if the host system support it (Default for other build)
|
||||
|
||||
#### BOX86_ENV
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var.
|
||||
@@ -303,6 +324,7 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
|
||||
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
|
||||
Use `gdb /PATH/TO/box86` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX86_JITGDB=1`.
|
||||
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
|
||||
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
|
||||
|
||||
#### BOX86_NORCFILES
|
||||
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
|
||||
|
||||
+4
-2
@@ -22,7 +22,7 @@ echo "#!/bin/bash
|
||||
export STEAMOS=1
|
||||
export STEAM_RUNTIME=1
|
||||
export DBUS_FATAL_WARNINGS=0
|
||||
~/steam/bin/steam steam://open/minigameslist $@" > steam
|
||||
~/steam/bin/steam $@" > steam
|
||||
|
||||
# make script executable and move
|
||||
chmod +x steam
|
||||
@@ -35,7 +35,9 @@ if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
|
||||
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 libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf
|
||||
sudo apt install libc6: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
|
||||
# this one is not there all the time, so just try it...
|
||||
sudo apt install libncurses5:armhf
|
||||
|
||||
# install mesa for armhf if already installed
|
||||
if dpkg-query -W libgl1-mesa-dri 2>/dev/null; then
|
||||
|
||||
@@ -751,6 +751,8 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
|
||||
or match("gstinterfaces010","gstaudio")\
|
||||
or match("gstreamer010","gstreamer") \
|
||||
or match("appindicator","appindicator3")\
|
||||
or match("appindicator","ayatanaappindicator3")\
|
||||
or match("appindicator3","ayatanaappindicator3")\
|
||||
\
|
||||
or match("libc", "tcmallocminimal") \
|
||||
or match("libc", "ldlinux") \
|
||||
|
||||
+22
-7
@@ -79,13 +79,15 @@ void free_tlsdatasize(void* p)
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)p;
|
||||
box_free(data->ptr);
|
||||
box_free(p);
|
||||
if(my_context)
|
||||
pthread_setspecific(my_context->tlskey, NULL);
|
||||
}
|
||||
|
||||
int unlockMutex()
|
||||
{
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
void* tid = (void*)GetTID();
|
||||
#define GO(A, B) \
|
||||
i = (arm_lock_storeifref2(&A, NULL, tid)==tid); \
|
||||
@@ -140,6 +142,7 @@ static void init_mutexes(box86context_t* context)
|
||||
{
|
||||
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
arm_lock_stored(&context->mutex_dyndump, 0);
|
||||
arm_lock_stored(&context->mutex_once, 0);
|
||||
arm_lock_stored(&context->mutex_once2, 0);
|
||||
@@ -147,6 +150,20 @@ 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);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
@@ -241,7 +258,7 @@ box86context_t *NewBox86Context(int argc)
|
||||
init_mutexes(context);
|
||||
pthread_atfork(NULL, NULL, atfork_child_box64context);
|
||||
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
pthread_key_create(&context->tlskey, NULL/*free_tlsdatasize*/);
|
||||
|
||||
InitFTSMap(context);
|
||||
|
||||
@@ -271,6 +288,7 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
box86context_t* ctx = *context; // local copy to do the cleanning
|
||||
|
||||
//clean_current_emuthread(); // cleaning main thread seems a bad idea
|
||||
if(ctx->local_maplib)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
@@ -341,7 +359,6 @@ void FreeBox86Context(box86context_t** context)
|
||||
void* ptr;
|
||||
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
|
||||
free_tlsdatasize(ptr);
|
||||
pthread_setspecific(ctx->tlskey, NULL);
|
||||
}
|
||||
pthread_key_delete(ctx->tlskey);
|
||||
|
||||
@@ -365,17 +382,15 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
#ifndef USE_CUSTOM_MUTEX
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
|
||||
freeCycleLog(ctx);
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 3
|
||||
#define BOX86_REVISION 2
|
||||
#define BOX86_REVISION 4
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+112
-42
@@ -44,6 +44,8 @@ static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
|
||||
// lock addresses
|
||||
KHASH_SET_INIT_INT(lockaddress)
|
||||
static kh_lockaddress_t *lockaddress = NULL;
|
||||
#endif
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
static uint32_t mutex_prot;
|
||||
static uint32_t mutex_blocks;
|
||||
#else
|
||||
@@ -67,7 +69,8 @@ typedef struct mapmem_s {
|
||||
struct mapmem_s *next;
|
||||
} mapmem_t;
|
||||
|
||||
static mapmem_t *mapmem = NULL;
|
||||
static mapmem_t *mapallmem = NULL;
|
||||
static mapmem_t *mmapmem = NULL;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
void* block;
|
||||
@@ -76,7 +79,7 @@ typedef struct blocklist_s {
|
||||
void* first;
|
||||
} blocklist_t;
|
||||
|
||||
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
|
||||
#define MMAPSIZE (64*1024) // allocate 64kb sized blocks
|
||||
|
||||
static int n_blocks = 0; // number of blocks for custom malloc
|
||||
static int c_blocks = 0; // capacity of blocks for custom malloc
|
||||
@@ -797,16 +800,15 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
uint32_t dyn = prot&PROT_DYN;
|
||||
uint32_t mapped = prot&PROT_MMAP;
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
|
||||
prot&=~PROT_CUSTOM;
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
if(prot&PROT_WRITE) {
|
||||
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
memprot[i] = prot|mapped|PROT_DYNAREC; // need to use atomic exchange?
|
||||
memprot[i] = prot|PROT_DYNAREC; // need to use atomic exchange?
|
||||
} else
|
||||
memprot[i] = prot|mapped|PROT_DYNAREC_R;
|
||||
memprot[i] = prot|PROT_DYNAREC_R;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
@@ -827,7 +829,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
|
||||
prot&=~PROT_DYN;
|
||||
if(mark)
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
|
||||
memprot[i] = prot; // need to use atomic exchange?
|
||||
} else if(prot&PROT_DYNAREC_R)
|
||||
memprot[i] = prot&~PROT_CUSTOM;
|
||||
@@ -854,7 +856,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
|
||||
|
||||
#endif
|
||||
|
||||
void printMapMem()
|
||||
void printMapMem(mapmem_t* mapmem)
|
||||
{
|
||||
mapmem_t* m = mapmem;
|
||||
while(m) {
|
||||
@@ -863,10 +865,12 @@ void printMapMem()
|
||||
}
|
||||
}
|
||||
|
||||
void addMapMem(uintptr_t begin, uintptr_t end)
|
||||
void addMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
if(begin<box86_pagesize)
|
||||
begin = box86_pagesize;
|
||||
begin &=~(box86_pagesize-1);
|
||||
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
|
||||
// sanitize values
|
||||
@@ -902,10 +906,12 @@ void addMapMem(uintptr_t begin, uintptr_t end)
|
||||
}
|
||||
// all done!
|
||||
}
|
||||
void removeMapMem(uintptr_t begin, uintptr_t end)
|
||||
void removeMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
if(begin<box86_pagesize)
|
||||
begin = box86_pagesize;
|
||||
begin &=~(box86_pagesize-1);
|
||||
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
|
||||
// sanitize values
|
||||
@@ -952,13 +958,12 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(addr, addr+size-1);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t old_prot = memprot[i];
|
||||
uint32_t dyn=(old_prot&PROT_DYN);
|
||||
uint32_t mapped=(old_prot&PROT_MMAP);
|
||||
if(!(dyn&PROT_NOPROT)) {
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
dyn = PROT_DYNAREC;
|
||||
@@ -967,7 +972,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
dyn = PROT_DYNAREC_R;
|
||||
}
|
||||
}
|
||||
memprot[i] = prot|dyn|mapped;
|
||||
memprot[i] = prot|dyn;
|
||||
}
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -976,7 +981,7 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(addr, addr+size-1);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
@@ -987,11 +992,28 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
|
||||
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
if(!size)
|
||||
return;
|
||||
size = (size+box86_pagesize-1)&~(box86_pagesize-1); // round size
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mmapmem, addr, addr+size-1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
if(prot)
|
||||
setProtection(addr, size, prot|PROT_MMAP);
|
||||
setProtection(addr, size, prot);
|
||||
else {
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(addr, addr+size-1);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
}
|
||||
|
||||
void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
if(prot)
|
||||
setProtection(addr, size, prot);
|
||||
else {
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
}
|
||||
@@ -1014,7 +1036,7 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
mutex_lock(&mutex_prot);
|
||||
addMapMem(addr, addr+size-1);
|
||||
addMapMem(mapallmem, addr, addr+size-1);
|
||||
mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
@@ -1077,7 +1099,8 @@ void loadProtectionFromMap()
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
mutex_lock(&mutex_prot);
|
||||
removeMapMem(addr, addr+size-1);
|
||||
removeMapMem(mmapmem, addr, addr+size-1);
|
||||
removeMapMem(mapallmem, addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
@@ -1092,56 +1115,92 @@ uint32_t getProtection(uintptr_t addr)
|
||||
mutex_lock(&mutex_prot);
|
||||
uint32_t ret = memprot[idx];
|
||||
mutex_unlock(&mutex_prot);
|
||||
return ret&~PROT_MMAP;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getMmapped(uintptr_t addr)
|
||||
{
|
||||
mutex_lock(&mutex_prot);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uint32_t ret = memprot[idx];
|
||||
mutex_unlock(&mutex_prot);
|
||||
return (ret&PROT_MMAP)?1:0;
|
||||
mapmem_t* m = mmapmem;
|
||||
if(addr<box86_pagesize) return 0;
|
||||
while(m) {
|
||||
uintptr_t begin = m->begin;
|
||||
uintptr_t end = m->end;
|
||||
if(addr>=begin && addr<=end)
|
||||
return 1;
|
||||
if(addr<begin)
|
||||
return 0;
|
||||
m = m->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define LOWEST (void*)0x10000
|
||||
#define MEDIAN (void*)0x40000000
|
||||
static void* findBlockHinted(void* hint, size_t size)
|
||||
static void* findBlockHinted(void* hint, size_t size, uintptr_t mask)
|
||||
{
|
||||
mapmem_t* m = mapmem;
|
||||
mapmem_t* m = mapallmem;
|
||||
uintptr_t h = (uintptr_t)hint;
|
||||
if(!mask) mask = 0xffff;
|
||||
while(m) {
|
||||
// granularity 0x10000
|
||||
uintptr_t addr = (m->end+1+0xffff)&~0xffff;
|
||||
uintptr_t addr = m->end+1;
|
||||
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
|
||||
// check hint and available size
|
||||
if(addr<=h && end>=h && end-h+1>=size)
|
||||
return hint;
|
||||
if(addr>=h && end-addr+1>=size)
|
||||
return (void*)addr;
|
||||
uintptr_t aaddr = (addr+mask)&~mask;
|
||||
if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
|
||||
return (void*)aaddr;
|
||||
if(end>=0xc0000000 && h<0xc0000000)
|
||||
return NULL;
|
||||
m = m->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
{ void* ret = findBlockHinted(hint, size);
|
||||
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask)
|
||||
{ void* ret = findBlockHinted(hint, size, mask);
|
||||
return ret?ret:hint;
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
void* ret = findBlockHinted(MEDIAN, size);
|
||||
if(!ret) ret = findBlockHinted(LOWEST, size);
|
||||
void* ret = findBlockHinted(MEDIAN, size, 0);
|
||||
if(!ret) ret = findBlockHinted(LOWEST, size, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask)
|
||||
{
|
||||
static void* startingpoint = (void*)0x60000000;
|
||||
void* mainaddr = (void*)0x30000000;
|
||||
void* ret = findBlockHinted(mainbin?mainaddr:startingpoint, size, mask);
|
||||
if(!ret) ret = findBlockHinted(LOWEST, size, mask);
|
||||
if(!mainbin)
|
||||
startingpoint = (void*)(((uintptr_t)startingpoint+size+0x200000)&~0xfffff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int isBlockFree(void* hint, size_t size)
|
||||
{
|
||||
mapmem_t* m = mapallmem;
|
||||
uintptr_t h = (uintptr_t)hint;
|
||||
while(m) {
|
||||
uintptr_t addr = m->end+1;
|
||||
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
|
||||
if(addr<=h && end>=h && end-h+1>=size)
|
||||
return 1;
|
||||
if(addr>h)
|
||||
return 0;
|
||||
m = m->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unlockCustommemMutex()
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
void* tid = (void*)GetTID();
|
||||
#define GO(A, B) \
|
||||
i = (arm_lock_storeifref2(&A, NULL, (void*)tid)==tid); \
|
||||
@@ -1174,7 +1233,7 @@ void relockCustommemMutex(int locks)
|
||||
|
||||
static void init_mutexes(void)
|
||||
{
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
arm_lock_stored(&mutex_blocks, 0);
|
||||
arm_lock_stored(&mutex_prot, 0);
|
||||
#else
|
||||
@@ -1182,6 +1241,7 @@ static void init_mutexes(void)
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
pthread_mutex_init(&mutex_prot, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
@@ -1212,10 +1272,14 @@ void init_custommem_helper(box86context_t* ctx)
|
||||
lockaddress = kh_init(lockaddress);
|
||||
#endif
|
||||
pthread_atfork(NULL, NULL, atfork_child_custommem);
|
||||
// init mapmem list
|
||||
mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mapmem->begin = 0x0;
|
||||
mapmem->end = (uintptr_t)LOWEST - 1;
|
||||
// init mapallmem list
|
||||
mapallmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mapallmem->begin = 0x0;
|
||||
mapallmem->end = (uintptr_t)LOWEST - 1;
|
||||
// init mmapmem list
|
||||
mmapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mmapmem->begin = 0x0;
|
||||
mmapmem->end = (uintptr_t)box86_pagesize - 1;
|
||||
loadProtectionFromMap();
|
||||
}
|
||||
|
||||
@@ -1276,12 +1340,18 @@ void fini_custommem_helper(box86context_t *ctx)
|
||||
box_free(p_blocks[i].block);
|
||||
#endif
|
||||
box_free(p_blocks);
|
||||
#ifndef DYNAREC
|
||||
#ifndef USE_CUSTOM_MUTEX
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
pthread_mutex_destroy(&mutex_prot);
|
||||
#endif
|
||||
while(mapmem) {
|
||||
mapmem_t *tmp = mapmem;
|
||||
mapmem = mapmem->next;
|
||||
while(mapallmem) {
|
||||
mapmem_t *tmp = mapallmem;
|
||||
mapallmem = mapallmem->next;
|
||||
box_free(tmp);
|
||||
}
|
||||
while(mmapmem) {
|
||||
mapmem_t *tmp = mmapmem;
|
||||
mmapmem = mmapmem->next;
|
||||
box_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +222,8 @@ Op is 20-27
|
||||
// add dst, src1, src2, lsr #imm
|
||||
#define ADD_REG_LSR_IMM5(dst, src1, src2, imm5) \
|
||||
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
|
||||
#define ADD_REG_LSR_IMM5_COND(cond, dst, src1, src2, imm5) \
|
||||
EMIT((cond) | 0x00800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
|
||||
#define ADC_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2a00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// add.s dst, src, #(imm8)
|
||||
@@ -591,8 +593,12 @@ Op is 20-27
|
||||
|
||||
// Count leading 0 bit of Rm, store result in Rd
|
||||
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
|
||||
// Count leading 0 bit of Rm, store result in Rd with cond
|
||||
#define CLZ_COND(cond, Rd, Rm) EMIT(cond | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
|
||||
// Reverse bits of Rm, store result in Rd
|
||||
#define RBIT(Rd, Rm) EMIT(c__ | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
|
||||
// Reverse bits of Rm, store result in Rd with cond
|
||||
#define RBIT_COND(cond, Rd, Rm) EMIT(cond | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
|
||||
|
||||
#define PLD_gen(U, R, Rn, Imm5, type, Rm) (0b1111<<28 | 0b0111<<24 | (U)<<23 | (R)<<22 | 0b01<<20 | (Rn)<<16 | 0b1111<<12 | (Imm5)<<7 | (type)<<5 | (Rm))
|
||||
// Preload Cache Rn+Rm
|
||||
@@ -602,7 +608,21 @@ Op is 20-27
|
||||
|
||||
#define DMB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0101<<4 | (opt))
|
||||
// Data memory barrier Inner Sharable
|
||||
#ifdef PANDORA
|
||||
// The Pandora is single core and ordered, DMB is not usefull here so just emit nothing
|
||||
#define DMB_ISH()
|
||||
#else
|
||||
#define DMB_ISH() EMIT(DMB_gen(0b1011))
|
||||
#endif
|
||||
|
||||
#define DSB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0100<<4 | (opt))
|
||||
// Data memory barrier Inner Sharable
|
||||
#ifdef PANDORA
|
||||
// The Pandora is single core and ordered, DSB is not usefull here so just emit nothing
|
||||
#define DSB_ISH()
|
||||
#else
|
||||
#define DSB_ISH() EMIT(DSB_gen(0b1011))
|
||||
#endif
|
||||
|
||||
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
|
||||
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
|
||||
@@ -628,11 +648,15 @@ Op is 20-27
|
||||
#define VMRS(Rt) EMIT(c__ | (0b1110<<24) | (0b1111<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
|
||||
// Move to FPSCR from Arm register
|
||||
#define VMSR(Rt) EMIT(c__ | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
|
||||
// Move to FPSCR from Arm register with cond
|
||||
#define VMSR_cond(cond, Rt) EMIT(cond | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
|
||||
// Move to FPSCR from Arm flags APSR
|
||||
#define VMRS_APSR() VMRS(15)
|
||||
|
||||
// Move between Rt to Sm
|
||||
#define VMOVtoV(Sm, Rt) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
|
||||
// Move between Rt to Sm with condition
|
||||
#define VMOVtoVcond(cond, Sm, Rt) EMIT(cond | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
|
||||
// Move between Sm to Rt
|
||||
#define VMOVfrV(Rt, Sm) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (1<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
|
||||
|
||||
@@ -1095,6 +1119,7 @@ Op is 20-27
|
||||
#define VMULL_U32_U16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMULL_S64_S32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMULL_U64_U32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMULL_P64(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 1, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VMUL_NEON_gen(op, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (op)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1001<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
|
||||
#define VMULQ_32(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
@@ -1392,4 +1417,17 @@ Op is 20-27
|
||||
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
// AES
|
||||
#define AESD_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 1<<6 | (M)<<5 | (Vm))
|
||||
#define AESD(Dd, Dm) EMIT(AESD_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define AESE_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 0<<6 | (M)<<5 | (Vm))
|
||||
#define AESE(Dd, Dm) EMIT(AESE_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define AESIMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 1<<6 | (M)<<5 | (Vm))
|
||||
#define AESIMC(Dd, Dm) EMIT(AESIMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define AESMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 0<<6 | (M)<<5 | (Vm))
|
||||
#define AESMC(Dd, Dm) EMIT(AESMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#endif //__ARM_EMITTER_H__
|
||||
@@ -131,6 +131,7 @@ arm_lock_storeifref_loop:
|
||||
beq arm_lock_storeifref_loop
|
||||
mov r0, r1
|
||||
arm_lock_storeifref_exit:
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_decifnot0b:
|
||||
@@ -174,13 +175,11 @@ arm_lock_incif0b_0:
|
||||
bx lr
|
||||
|
||||
arm_lock_stored:
|
||||
dmb ish
|
||||
str r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeb:
|
||||
dmb ish
|
||||
strb r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
+13
-3
@@ -177,11 +177,21 @@ dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
}
|
||||
|
||||
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
|
||||
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
|
||||
#ifdef ANDROID
|
||||
#define JUMPBUFF sigjmp_buf
|
||||
#else
|
||||
#define JUMPBUFF struct __jmp_buf_tag
|
||||
#endif
|
||||
static __thread JUMPBUFF dynarec_jmpbuf;
|
||||
#ifdef ANDROID
|
||||
#define DYN_JMPBUF dynarec_jmpbuf
|
||||
#else
|
||||
#define DYN_JMPBUF &dynarec_jmpbuf
|
||||
#endif
|
||||
|
||||
void cancelFillBlock()
|
||||
{
|
||||
longjmp(&dynarec_jmpbuf, 1);
|
||||
longjmp(DYN_JMPBUF, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -214,7 +224,7 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
if(sigsetjmp(DYN_JMPBUF, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
FreeDynablock(block, 0);
|
||||
if(need_lock)
|
||||
|
||||
+76
-140
@@ -81,125 +81,75 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#define JUMPBUFF sigjmp_buf
|
||||
#else
|
||||
#define JUMPBUFF struct __jmp_buf_tag
|
||||
#endif
|
||||
|
||||
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;
|
||||
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!
|
||||
#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;
|
||||
}
|
||||
}
|
||||
uint32_t old_esp = R_ESP;
|
||||
uint32_t old_ebx = R_EBX;
|
||||
uint32_t old_edi = R_EDI;
|
||||
uint32_t old_esi = R_ESI;
|
||||
uint32_t old_ebp = R_EBP;
|
||||
uint32_t old_eip = R_EIP;
|
||||
// save defered flags
|
||||
defered_flags_t old_df = emu->df;
|
||||
uint32_t old_op1 = emu->op1;
|
||||
uint32_t old_op2 = emu->op2;
|
||||
uint32_t old_res = emu->res;
|
||||
// uc_link
|
||||
i386_ucontext_t* old_uc_link = emu->uc_link;
|
||||
emu->uc_link = NULL;
|
||||
|
||||
PushExit(emu);
|
||||
R_EIP = addr;
|
||||
emu->df = d_none;
|
||||
DynaRun(emu);
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
emu->uc_link = old_uc_link;
|
||||
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
|
||||
if(emu->flags.quitonlongjmp==1)
|
||||
emu->flags.longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
// restore defered flags
|
||||
emu->df = old_df;
|
||||
emu->op1 = old_op1;
|
||||
emu->op2 = old_op2;
|
||||
emu->res = old_res;
|
||||
// and the old registers
|
||||
R_EBX = old_ebx;
|
||||
R_EDI = old_edi;
|
||||
R_ESI = old_esi;
|
||||
R_EBP = old_ebp;
|
||||
R_ESP = old_esp;
|
||||
R_EIP = old_eip; // and set back instruction pointer
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box86_dynarec)
|
||||
#endif
|
||||
EmuCall(emu, addr);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
uint32_t old_esp = R_ESP;
|
||||
uint32_t old_ebx = R_EBX;
|
||||
uint32_t old_edi = R_EDI;
|
||||
uint32_t old_esi = R_ESI;
|
||||
uint32_t old_ebp = R_EBP;
|
||||
uint32_t old_eip = R_EIP;
|
||||
PushExit(emu);
|
||||
R_EIP = addr;
|
||||
emu->df = d_none;
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
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 emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,emu);
|
||||
CHECK_FLAGS(emu);
|
||||
// block is here, let's run it!
|
||||
#ifdef ARM
|
||||
arm_prolog(emu, block->block);
|
||||
#endif
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x86emu_fork(emu, forktype);
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_EIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_EBX = old_ebx;
|
||||
R_EDI = old_edi;
|
||||
R_ESI = old_esi;
|
||||
R_EBP = old_ebp;
|
||||
R_ESP = old_esp;
|
||||
R_EIP = old_eip; // and set back instruction pointer
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// clear the setjmp
|
||||
if(ejb && jmpbuf_reset)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
}
|
||||
|
||||
int my_setcontext(x86emu_t* emu, void* ucp);
|
||||
int DynaRun(x86emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
emu_jmpbuf_t *ejb = NULL;
|
||||
JUMPBUFF jmpbuf[1] = {0};
|
||||
int skip = 0;
|
||||
#ifdef DYNAREC
|
||||
int jmpbuf_reset = 1;
|
||||
#endif
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
if(!ejb->jmpbuf_ok) {
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
int a;
|
||||
#ifdef DYNAREC
|
||||
jmpbuf_reset = 1;
|
||||
#endif
|
||||
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]);
|
||||
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 0;
|
||||
|
||||
while(!(emu->quit)) {
|
||||
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
|
||||
emu->jmpbuf = jmpbuf;
|
||||
emu->flags.jmpbuf_ready = 1;
|
||||
#ifdef ANDROID
|
||||
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
|
||||
#else
|
||||
if((skip=sigsetjmp(emu->jmpbuf, 1)))
|
||||
#endif
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun\n");
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test) {
|
||||
if(emu->test.clean)
|
||||
@@ -207,60 +157,46 @@ int DynaRun(x86emu_t* emu)
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
if(skip!=2)
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box86_dynarec)
|
||||
#endif
|
||||
return Run(emu, 0);
|
||||
#ifdef DYNAREC
|
||||
else {
|
||||
dynablock_t* block = NULL;
|
||||
dynablock_t* current = NULL;
|
||||
while(!emu->quit) {
|
||||
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
current = block;
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->flags.need_jmpbuf = 0;
|
||||
|
||||
#ifndef DYNAREC
|
||||
Run(emu, 0);
|
||||
#else
|
||||
if(!box86_dynarec)
|
||||
Run(emu, 0);
|
||||
else {
|
||||
dynablock_t* block = (skip || ACCESS_FLAG(F_TF))?NULL:DBGetBlock(emu, R_EIP, 1);
|
||||
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);
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%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 emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, emu);
|
||||
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->hash, emu);
|
||||
// block is here, let's run it!
|
||||
#ifdef ARM
|
||||
arm_prolog(emu, block->block);
|
||||
#endif
|
||||
}
|
||||
if(emu->fork) {
|
||||
int forktype = emu->fork;
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x86emu_fork(emu, forktype);
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
else if(emu->quit && emu->uc_link) {
|
||||
if(emu->quit && emu->uc_link) {
|
||||
emu->quit = 0;
|
||||
my_setcontext(emu, emu->uc_link);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->quit = 0;
|
||||
}
|
||||
// clear the setjmp
|
||||
if(ejb && jmpbuf_reset)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
return 0;
|
||||
#endif
|
||||
emu->jmpbuf = old_jmpbuf;
|
||||
}
|
||||
+65
-24
@@ -95,6 +95,21 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
}
|
||||
return best;
|
||||
}
|
||||
void add_jump(dynarec_arm_t *dyn, int ninst) {
|
||||
// add slots
|
||||
if(dyn->jmp_sz == dyn->jmp_cap) {
|
||||
dyn->jmp_cap += 64;
|
||||
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
|
||||
}
|
||||
dyn->jmps[dyn->jmp_sz++] = ninst;
|
||||
}
|
||||
int get_first_jump(dynarec_arm_t *dyn, int next) {
|
||||
for(int i=0; i<dyn->jmp_sz; ++i)
|
||||
if(dyn->insts[dyn->jmps[i]].x86.jmp == next)
|
||||
return i;
|
||||
return -2;
|
||||
}
|
||||
|
||||
#define PK(A) (*((uint8_t*)(addr+(A))))
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
{
|
||||
@@ -335,9 +350,8 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
|
||||
if(dyn->insts[ninst].x86.may_set)
|
||||
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
|
||||
// Consume X_PEND if relevant
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
|
||||
need &=~X_PEND;
|
||||
else if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
|
||||
need &=~X_PEND; // Consume X_PEND if relevant
|
||||
need |= dyn->insts[ninst].x86.use_flags;
|
||||
if(dyn->insts[ninst].x86.need_before == need)
|
||||
return ninst - 1;
|
||||
@@ -448,10 +462,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.insts = (instruction_arm_t*)dynaCalloc(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
|
||||
dynaFree(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);
|
||||
@@ -470,26 +480,57 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// calculate barriers
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
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 {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
for(int i2=0; i2<helper.size && k==-1; ++i2) {
|
||||
if(helper.insts[i2].x86.addr==j)
|
||||
k=i2;
|
||||
for(int ii=0; ii<helper.jmp_sz; ++ii) {
|
||||
int i = helper.jmps[ii];
|
||||
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 {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
int search = ((j>=helper.insts[0].x86.addr) && j<helper.insts[0].x86.addr+helper.isize)?1:0;
|
||||
int imin = 0;
|
||||
int imax = helper.size-1;
|
||||
int i2 = helper.size/2;
|
||||
// dichotomy search
|
||||
while(search) {
|
||||
if(helper.insts[i2].x86.addr == j) {
|
||||
k = i2;
|
||||
search = 0;
|
||||
} else if(helper.insts[i2].x86.addr>j) {
|
||||
imax = i2;
|
||||
i2 = (imax+imin)/2;
|
||||
} else {
|
||||
imin = i2;
|
||||
i2 = (imax+imin)/2;
|
||||
}
|
||||
if(search && (imax-imin)<2) {
|
||||
search = 0;
|
||||
if(helper.insts[imin].x86.addr==j)
|
||||
k = imin;
|
||||
else if(helper.insts[imax].x86.addr==j)
|
||||
k = imax;
|
||||
}
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x86.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x86.jmp_insts = k;
|
||||
}
|
||||
/*for(int i2=0; i2<helper.size && k==-1; ++i2) {
|
||||
if(helper.insts[i2].x86.addr==j)
|
||||
k=i2;
|
||||
}*/
|
||||
if(k!=-1 && !helper.insts[i].barrier_maybe)
|
||||
helper.insts[k].x86.barrier |= BARRIER_FULL;
|
||||
helper.insts[i].x86.jmp_insts = k;
|
||||
}
|
||||
}
|
||||
// no need for next and jmps anymore
|
||||
dynaFree(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
dynaFree(helper.jmps);
|
||||
helper.jmp_sz = helper.jmp_cap = 0;
|
||||
helper.jmps = NULL;
|
||||
// fill predecessors with the jump address
|
||||
fillPredecessors(&helper);
|
||||
|
||||
|
||||
+266
-161
@@ -28,6 +28,8 @@
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
int isRetX87Wrapper(wrapper_t fun);
|
||||
void emit_signal(x86emu_t* emu, int sig, void* addr, int code);
|
||||
void emit_div0(x86emu_t* emu, void* addr, int code);
|
||||
|
||||
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
@@ -1002,7 +1004,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("(LOCK)XCHG Eb, Gb");
|
||||
// Do the swap
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGB(x14);
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3);
|
||||
@@ -1029,7 +1031,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x87:
|
||||
INST_NAME("(LOCK)XCHG Ed, Gd");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGD;
|
||||
GETED;
|
||||
if(gd!=ed) {
|
||||
@@ -1079,7 +1081,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
gd = gb1; // no need to extract
|
||||
}
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = ((ed&4)>>2); // L or H
|
||||
@@ -1094,7 +1096,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
@@ -1108,7 +1110,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
gd = (nextop&0x38)>>3;
|
||||
gb1 = xEAX+(gd&3);
|
||||
gb2 = ((gd&4)>>2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -1119,10 +1121,6 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = wback;
|
||||
}
|
||||
} else {
|
||||
if(box86_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
|
||||
SMDMB();
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
|
||||
SMREADLOCK(lock);
|
||||
LDRB_IMM9(x14, wback, fixedaddress);
|
||||
@@ -1134,7 +1132,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
@@ -1146,7 +1144,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Ed, Seg");
|
||||
nextop=F8;
|
||||
MOV32(x3, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
if((nextop&0xC0)==0xC0) { // reg <= seg
|
||||
if(MODREG) { // reg <= seg
|
||||
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
|
||||
} else { // mem <= seg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -1159,7 +1157,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg? that's an invalid operation
|
||||
if(MODREG) { // reg <= reg? that's an invalid operation
|
||||
DEFAULT;
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -1171,7 +1169,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x8E:
|
||||
INST_NAME("MOV Seg,Ew");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
@@ -1191,7 +1189,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1(xEAX+(nextop&7));
|
||||
} else {
|
||||
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
|
||||
@@ -1247,14 +1245,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
|
||||
ORR_IMM8(xFlags, xFlags, 2, 0);
|
||||
SET_DFNONE(x1);
|
||||
if(box86_wine) { // should this be done all the time?
|
||||
if(box86_wine || 1) { // should this be done all the time?
|
||||
TSTS_IMM8_ROR(xFlags, 0x1, 12); // 0x100 == F_TF
|
||||
B_NEXT(cEQ);
|
||||
MOV32(x1, addr);
|
||||
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));
|
||||
CALL(arm_singlestep, -1, 0);
|
||||
BFC(xFlags, F_TF, 1); // should not be needed
|
||||
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
|
||||
jump_to_epilog(dyn, addr, 0, ninst);
|
||||
}
|
||||
break;
|
||||
case 0x9E:
|
||||
@@ -1275,6 +1270,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV AL, Ob");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
SMREADLOCK(lock);
|
||||
LDRB_IMM9(x2, x2, 0);
|
||||
BFI(xEAX, x2, 0, 8);
|
||||
break;
|
||||
@@ -1282,33 +1279,41 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV EAX, Od");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
SMREADLOCK(lock);
|
||||
LDR_IMM9(xEAX, x2, 0);
|
||||
break;
|
||||
case 0xA2:
|
||||
INST_NAME("MOV Ob, AL");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
STRB_IMM9(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
SMWRITELOCK(lock);
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od, EAX");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
STR_IMM9(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
SMWRITELOCK(lock);
|
||||
break;
|
||||
case 0xA4:
|
||||
INST_NAME("MOVSB");
|
||||
GETDIR(x3, 1);
|
||||
SMREAD();
|
||||
LDRBAI_REG_LSL_IMM5(x1, xESI, x3, 0);
|
||||
STRBAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA5:
|
||||
INST_NAME("MOVSD");
|
||||
GETDIR(x3, 4);
|
||||
SMREAD();
|
||||
LDRAI_REG_LSL_IMM5(x1, xESI, x3, 0);
|
||||
STRAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA6:
|
||||
INST_NAME("CMPSB");
|
||||
@@ -1345,11 +1350,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("STOSB");
|
||||
GETDIR(x3, 1);
|
||||
STRBAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAB:
|
||||
INST_NAME("STOSD");
|
||||
GETDIR(x3, 4);
|
||||
STRAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAC:
|
||||
INST_NAME("LODSB");
|
||||
@@ -1455,49 +1462,42 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32(x14, u8); UFLAG_OP2(x14)
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
MOV_REG_LSL_IMM5(ed, ed, u8);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl8);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_shl8c(dyn, ninst, ed, u8, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32(x14, u8); UFLAG_OP2(x14)
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
MOV_REG_LSR_IMM5(ed, ed, u8);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_shr8c(dyn, ninst, ed, u8, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr8);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32(x14, u8); UFLAG_OP2(x14)
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
MOV_REG_ASR_IMM5(ed, ed, u8);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETSEB(x1);
|
||||
u8 = (F8)&0x1f;
|
||||
emit_sar8c(dyn, ninst, ed, u8, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1628,7 +1628,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC6:
|
||||
INST_NAME("MOV Eb, Ib");
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= u8
|
||||
if(MODREG) { // reg <= u8
|
||||
u8 = F8;
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
@@ -1646,7 +1646,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC7:
|
||||
INST_NAME("MOV Ed, Id");
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= i32
|
||||
if(MODREG) { // reg <= i32
|
||||
i32 = F32S;
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
@@ -1677,6 +1677,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SKIPTEST(x14);
|
||||
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
|
||||
MOV32(x14, ip+1+2);
|
||||
SMEND();
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
MOVW(x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
|
||||
@@ -1685,6 +1686,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
|
||||
SKIPTEST(x14);
|
||||
SMEND();
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if((box86_log<2) && !cycle_log) { // call the wrapper directly
|
||||
uintptr_t ncall[2]; // to avoid BUSERROR!!!
|
||||
@@ -1720,9 +1722,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, offsetof(box86context_t, signals[SIGTRAP]));
|
||||
LDR_REG_LSL_IMM5(x3, x1, x2, 0);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_NEXT(cNE);
|
||||
B_NEXT(cEQ);
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
MOV32(xEIP, addr);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
MOV32(x1, SIGTRAP);
|
||||
CALL_(raise, -1, 0);
|
||||
MOV32(x2, addr);
|
||||
MOV32(x3, 128);
|
||||
CALL(emit_signal, -1, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1748,7 +1755,7 @@ 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");
|
||||
if(box86_wine && u8==0x2D) {
|
||||
if(box86_wine && u8==0x2D && 0) {
|
||||
MESSAGE(LOG_DEBUG, "Hack for wine/int 2d\n");
|
||||
} else {
|
||||
DEFAULT;
|
||||
@@ -1765,115 +1772,68 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
*ok = 0;
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD2:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
if(opcode==0xD0) {
|
||||
INST_NAME("ROL Eb, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEB(x1);
|
||||
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
INST_NAME("ROL Eb, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
MESSAGE(LOG_DUMP, "Need Optimization ROL 8b\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEB(x1);
|
||||
CALL_(rol8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
}
|
||||
INST_NAME("ROL Eb, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEB(x1);
|
||||
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
break;
|
||||
case 1:
|
||||
if(opcode==0xD0) {
|
||||
INST_NAME("ROR Eb, 1");
|
||||
MOVW(x2, 1);
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEB(x1);
|
||||
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
} else {
|
||||
INST_NAME("ROR Eb, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MESSAGE(LOG_DUMP, "Need Optimization ROR 8b\n");
|
||||
GETEB(x1);
|
||||
CALL_(ror8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
}
|
||||
INST_NAME("ROR Eb, 1");
|
||||
MOVW(x2, 1);
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEB(x1);
|
||||
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
break;
|
||||
case 2:
|
||||
if(opcode==0xD0) {INST_NAME("RCL Eb, 1");} else {INST_NAME("RCL Eb, CL");}
|
||||
INST_NAME("RCL Eb, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
|
||||
MOVW(x2, 1);
|
||||
GETEB(x1);
|
||||
CALL_(rcl8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
break;
|
||||
case 3:
|
||||
if(opcode==0xD0) {INST_NAME("RCR Eb, 1");} else {INST_NAME("RCR Eb, CL");}
|
||||
INST_NAME("RCR Eb, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
|
||||
MOVW(x2, 1);
|
||||
GETEB(x1);
|
||||
CALL_(rcr8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
if(opcode==0xD0) {
|
||||
INST_NAME("SHL Eb, 1");
|
||||
MOVW(x2, 1);
|
||||
} else {
|
||||
INST_NAME("SHL Eb, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHL Eb, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEB(x1);
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_LSL_REG(ed, ed, x2);
|
||||
emit_shl8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl8);
|
||||
break;
|
||||
case 5:
|
||||
if(opcode==0xD0) {
|
||||
INST_NAME("SHR Eb, 1");
|
||||
MOVW(x2, 1);
|
||||
} else {
|
||||
INST_NAME("SHR Eb, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHR Eb, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEB(x1);
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
emit_shr8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr8);
|
||||
break;
|
||||
case 7:
|
||||
if(opcode==0xD0) {
|
||||
INST_NAME("SAR Eb, 1");
|
||||
MOVW(x2, 1);
|
||||
} else {
|
||||
INST_NAME("SAR Eb, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SAR Eb, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETSEB(x1);
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_ASR_REG(ed, ed, x2);
|
||||
emit_sar8c(dyn, ninst, ed, 1, x2, x14);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD1:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -1954,6 +1914,125 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xD2:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Eb, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTS_IMM8(xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
AND_IMM8(x2, xECX, 0x7);
|
||||
RSB_IMM8(x2, x2, 8);
|
||||
GETEB(x1);
|
||||
BFI(ed, ed, 8, 8);
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
EBBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x2, 7);
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, x3, ed, 7);
|
||||
ADD_REG_LSL_IMM5_COND(cEQ, x3, x3, ed, 0);
|
||||
BFI_COND(cEQ, xFlags, x3, F_OF, 1);
|
||||
BFI(xFlags, ed, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Eb, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTS_IMM8(xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
AND_IMM8(x2, xECX, 0x7);
|
||||
GETEB(x1);
|
||||
BFI(ed, ed, 8, 8);
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
EBBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x2, 1);
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, x2, ed, 6); // x2 = d>>30
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
|
||||
BFI_COND(cEQ, xFlags, x2, F_OF, 1);
|
||||
MOV_REG_LSR_IMM5(x2, ed, 7);
|
||||
BFI(xFlags, x2, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Eb, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEB(x1);
|
||||
CALL_(rcl8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Eb, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEB(x1);
|
||||
CALL_(rcr8, x1, (1<<x3));
|
||||
EBBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Eb, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETEB(x1);
|
||||
emit_shl8(dyn, ninst, ed, x2, x2, x14);
|
||||
EBBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Eb, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETEB(x1);
|
||||
emit_shr8(dyn, ninst, ed, x2, x2, x14);
|
||||
EBBACK;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Eb, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETSEB(x1);
|
||||
emit_sar8(dyn, ninst, ed, x2, x2, x14);
|
||||
EBBACK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -2206,6 +2285,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, addr);
|
||||
PUSH1(x2);
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
|
||||
SKIPTEST(x14);
|
||||
// calling a native function
|
||||
if(isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
|
||||
// return value will be on the stack, so the stack depth needs to be updated
|
||||
@@ -2306,6 +2386,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
MOV32(xEIP, ip);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_priv, -1, 0);
|
||||
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
@@ -2335,11 +2416,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3, 2);
|
||||
SMREAD();
|
||||
MARK;
|
||||
LDRHAI_REG_LSL_IMM5(x1, xESI, x3);
|
||||
STRHAI_REG_LSL_IMM5(x1, xEDI, x3);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAB:
|
||||
INST_NAME("REP STOSW");
|
||||
@@ -2350,6 +2433,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STRHAI_REG_LSL_IMM5(xEAX, xEDI, x3);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAF:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
|
||||
@@ -2428,11 +2512,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,1);
|
||||
SMREAD();
|
||||
MARK;
|
||||
LDRBAI_REG_LSL_IMM5(x1, xESI, x3, 0);
|
||||
STRBAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
// done
|
||||
break;
|
||||
case 0xA5:
|
||||
@@ -2440,11 +2526,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,4);
|
||||
SMREAD();
|
||||
MARK;
|
||||
LDRAI_REG_LSL_IMM5(x1, xESI, x3, 0);
|
||||
STRAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
// done
|
||||
break;
|
||||
case 0xA6:
|
||||
@@ -2506,6 +2594,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STRBAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAB:
|
||||
INST_NAME("REP STOSD");
|
||||
@@ -2516,6 +2605,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STRAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
|
||||
SUBS_IMM8(xECX, xECX, 1);
|
||||
B_MARK(cNE);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xAC:
|
||||
INST_NAME("REP LODSB");
|
||||
@@ -2614,7 +2704,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Eb");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -2635,12 +2725,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4:
|
||||
INST_NAME("MUL AL, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, d_mul8);
|
||||
GETEB(x1);
|
||||
UBFX(x2, xEAX, 0, 8);
|
||||
MUL(x1, x1, x2);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
UFLAG_RES(x1);
|
||||
UFLAG_DF(x2, d_mul8);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL AL, Eb");
|
||||
@@ -2699,52 +2789,66 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4:
|
||||
INST_NAME("MUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, d_mul32);
|
||||
GETED;
|
||||
UMULL(xEDX, xEAX, xEAX, ed);
|
||||
UFLAG_RES(xEAX);
|
||||
UFLAG_OP1(xEDX);
|
||||
UFLAG_DF(x2, d_mul32);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, d_imul32);
|
||||
GETED;
|
||||
SMULL(xEDX, xEAX, xEAX, ed);
|
||||
UFLAG_RES(xEAX);
|
||||
UFLAG_OP1(xEDX);
|
||||
UFLAG_DF(x2, d_imul32);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if(arm_div && ninst && dyn->insts
|
||||
if(ninst && dyn->insts && (nextop==0xF0)
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|
||||
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
|
||||
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
|
||||
SET_DFNONE(x2); // flags are undefined
|
||||
GETED;
|
||||
UDIV(x2, xEAX, ed); // x1 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x1*ed)
|
||||
MOV_REG(xEAX, x2);
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0xB8
|
||||
&& *(uint32_t*)(dyn->insts[ninst-1].x86.addr+1)==0) {
|
||||
// hack for some protection that check a divide by zero actualy trigger a div0 exception
|
||||
MESSAGE(LOG_INFO, "Divide by 0 hack\n");
|
||||
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
|
||||
MOV32(xEIP, addr);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
MOV_REG(x1, xEIP);
|
||||
MOV32(x2, 0);
|
||||
CALL(emit_div0, -1, 0);
|
||||
} else {
|
||||
GETEDH(x1);
|
||||
if(arm_div) {
|
||||
CMPS_IMM8(xEDX, 0);
|
||||
B_MARK(cEQ);
|
||||
}
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(div32, -1, 0);
|
||||
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
if(arm_div) {
|
||||
B_NEXT(c__);
|
||||
MARK;
|
||||
UDIV(x2, xEAX, ed); // x2 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x2*ed)
|
||||
MOV_REG(xEAX, x2);
|
||||
if(arm_div && ninst && dyn->insts
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|
||||
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
|
||||
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
|
||||
SET_DFNONE(x2); // flags are undefined
|
||||
GETED;
|
||||
UDIV(x2, xEAX, ed); // x1 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x1*ed)
|
||||
MOV_REG(xEAX, x2);
|
||||
} else {
|
||||
GETEDH(x1);
|
||||
if(arm_div) {
|
||||
CMPS_IMM8(xEDX, 0);
|
||||
B_MARK(cEQ);
|
||||
}
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(div32, -1, 0);
|
||||
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
if(arm_div) {
|
||||
B_NEXT(c__);
|
||||
MARK;
|
||||
UDIV(x2, xEAX, ed); // x2 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x2*ed)
|
||||
MOV_REG(xEAX, x2);
|
||||
SET_DFNONE(x2); // flags are undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2806,6 +2910,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME(opcode==0xFA?"STI":"CLI");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
|
||||
MOV32(xEIP, ip);
|
||||
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
CALL(arm_priv, -1, 0);
|
||||
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
#define GETEX(a, w) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
@@ -40,7 +40,7 @@
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
|
||||
#define GETEM(a) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
@@ -111,7 +111,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVUPS Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -133,7 +133,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -150,7 +150,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x12:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
INST_NAME("MOVHLPS Gx,Ex");
|
||||
GETGX(v0, 1);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
@@ -169,7 +169,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
INST_NAME("MOVLPS Ex,Gx");
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
VMOVD(v1, v0);
|
||||
} else {
|
||||
@@ -192,7 +192,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, q0);
|
||||
} else q1 = q0;
|
||||
@@ -203,7 +203,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, q0);
|
||||
} else q1 = q0;
|
||||
@@ -212,7 +212,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x16:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
INST_NAME("MOVLHPS Gx,Ex");
|
||||
GETGX(v0, 1);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
@@ -229,7 +229,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
INST_NAME("MOVHPS Ex,Gx");
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
VMOVD(v1, v0+1);
|
||||
} else {
|
||||
@@ -249,7 +249,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x18:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
INST_NAME("NOP (multibyte)");
|
||||
} else
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -282,7 +282,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVAPS Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -298,7 +298,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -312,7 +312,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -327,7 +327,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -340,7 +340,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -355,7 +355,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -388,7 +388,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v1<16)
|
||||
d0 = v1;
|
||||
@@ -466,7 +466,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVBE Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
REV(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
@@ -479,12 +479,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVBE Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
REV(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
REV(x1, gd);
|
||||
STR_IMM9(gd, ed, fixedaddress);
|
||||
STR_IMM9(x1, ed, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
@@ -523,7 +523,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETFLAGS; \
|
||||
nextop=F8; \
|
||||
GETGD; \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
ed = xEAX+(nextop&7); \
|
||||
MOV_REG_COND(YES, gd, ed); \
|
||||
} else { \
|
||||
@@ -625,7 +625,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
XOR_REG_LSL_IMM5(gd, gd, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// EX is an xmm reg
|
||||
GETEX(q0, 0);
|
||||
VMOVfrV_D(x1, x2, q0);
|
||||
@@ -663,6 +663,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEX(q0, 0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
#if 0
|
||||
// the approximate is not precise enough and and some incorrect behavior
|
||||
v2 = fpu_get_scratch_quad(dyn);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
// Newton-Raphson: Xn+1 = Xn*(3-d*Xn²)/2 converge to 1/sqrt(d) with X0 = result of VSQRTE
|
||||
@@ -695,6 +697,33 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
VMULQ_F32(v0, v2, q0); // v0 = X2*d ~ SQRT(d)
|
||||
}
|
||||
#else
|
||||
if((q0<15) && (v0<15)) {
|
||||
d0 = q0;
|
||||
d1 = v0;
|
||||
} else {
|
||||
s0 = fpu_get_scratch_quad(dyn);
|
||||
// source ok or not
|
||||
if(q0<15) {
|
||||
d0 = q0;
|
||||
} else {
|
||||
VMOVQ(s0, q0);
|
||||
d0 = s0;
|
||||
}
|
||||
if(v0<15)
|
||||
d1 = v0;
|
||||
else
|
||||
d1 = s0;
|
||||
}
|
||||
for(int i=0; i<4; ++i) {
|
||||
VSQRT_F32(d1*2+i, d0*2+i);
|
||||
}
|
||||
if(v0<15) {
|
||||
//done
|
||||
} else {
|
||||
VMOVQ(v0, d1);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
@@ -880,7 +909,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -891,7 +920,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -902,7 +931,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -944,7 +973,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
VMOVD(q0+1, d1);
|
||||
} else {
|
||||
@@ -959,7 +988,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -971,7 +1000,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -983,7 +1012,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOVD(v0, d1);
|
||||
} else v0 = d1;
|
||||
@@ -1018,7 +1047,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
VMOVD(v0, v1);
|
||||
@@ -1034,7 +1063,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
gd = (nextop&0x38)>>3;
|
||||
i32 = -1;
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
u8 = F8;
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
// use stack as temporary storage
|
||||
@@ -1079,7 +1108,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLW Em, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1102,7 +1131,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAW Em, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1121,7 +1150,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLW Em, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1249,7 +1278,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVD Ed, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX + (nextop&7);
|
||||
VMOVfrDx_32(ed, v0, 0);
|
||||
} else {
|
||||
@@ -1263,7 +1292,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVQ Em, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
VMOVD(v1, v0);
|
||||
} else {
|
||||
@@ -1402,7 +1431,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop=F8; \
|
||||
MOVW_COND(NO, x3, 0); \
|
||||
MOVW_COND(YES, x3, 1); \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
ed = (nextop&7); \
|
||||
eb1 = xEAX+(ed&3); \
|
||||
eb2 = ((ed&4)>>2); \
|
||||
@@ -1529,7 +1558,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1585,7 +1614,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1652,7 +1681,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
// A purge is probably not needed, just a full refresh
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -1664,7 +1693,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FXRSTOR Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -1685,7 +1714,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("STMXCSR Md");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
LDR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
} else {
|
||||
@@ -1781,7 +1810,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1813,7 +1842,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVZX Gd, Eb");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
@@ -1828,7 +1857,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVZX Gd, Ew");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
UXTH(gd, ed, 0);
|
||||
} else {
|
||||
@@ -1846,7 +1875,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1866,7 +1895,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("BTS Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1898,7 +1927,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1930,7 +1959,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("BTC Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1970,7 +1999,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -2042,7 +2071,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVSX Gd, Eb");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
@@ -2057,7 +2086,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVSX Gd, Ew");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
SXTH(gd, ed, 0);
|
||||
} else {
|
||||
@@ -2082,11 +2111,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED;
|
||||
MOV_REG(x1, gd);
|
||||
if(gd!=ed) {
|
||||
MOV_REG(gd, ed);
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
|
||||
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
|
||||
}
|
||||
emit_add32(dyn, ninst, ed, x1, x3, x14);
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xC2:
|
||||
@@ -2125,7 +2155,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
// ignoring "NTI"
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd); // doesn't exist
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
@@ -2136,7 +2166,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("PINSRW Gm,Ed,Ib");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
u8 = (F8)&3;
|
||||
ed = xEAX+(nextop&7);
|
||||
VMOVtoDx_16(d0, u8, ed);
|
||||
@@ -2151,7 +2181,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("PEXTRW Gd,Em,Ib");
|
||||
nextop = F8;
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETEM(d0);
|
||||
u8 = (F8)&3;
|
||||
VMOVfrDx_U16(gd, d0, u8);
|
||||
@@ -2414,7 +2444,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
INST_NAME("PMOVMSKB Gd, Em");
|
||||
GETEM(d0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
@@ -2558,7 +2588,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVNTQ Em, Gm");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
|
||||
|
||||
@@ -29,7 +29,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, u8;
|
||||
uint8_t wback, u8, wb1, wb2;
|
||||
uint8_t gb1, gb2, eb1, eb2;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(j32);
|
||||
@@ -46,6 +47,17 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_add32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
INST_NAME("AND Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
GETEBO(x14);
|
||||
emit_and8(dyn, ninst, x1, x2, x14, x2);
|
||||
EBBACK;
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
@@ -86,6 +98,13 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
case 0x65:
|
||||
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
// reduced EA size...
|
||||
opcode = F8;
|
||||
@@ -95,7 +114,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
GETGD; // don't need GETGW here
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(ed, gd, 0, 16);
|
||||
@@ -112,7 +131,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
@@ -125,7 +144,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("POP FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1(xEAX+(nextop&7)); // 67 ignored
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
@@ -165,7 +184,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ew");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
if(MODREG) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
@@ -182,13 +201,36 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x88:
|
||||
INST_NAME("MOV Eb, Gb");
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
gb2 = ((gd&4)>>2);
|
||||
gb1 = xEAX+(gd&3);
|
||||
if(gb2) {
|
||||
gd = x3;
|
||||
UXTB(gd, gb1, gb2);
|
||||
} else {
|
||||
gd = gb1; // no need to extract
|
||||
}
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = ((ed&4)<<1); // L or H
|
||||
BFI(eb1, gd, eb2, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
STRB_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ed, Gd");
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -202,7 +244,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
@@ -215,7 +257,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("POP FS:Ed");
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1(xEAX+(nextop&7));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -224,6 +266,9 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
INST_NAME("NOP");
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
INST_NAME("MOV AL, FS:Id");
|
||||
@@ -288,7 +333,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV FS:Ed, Id");
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= i32
|
||||
if(MODREG) { // reg <= i32
|
||||
i32 = F32S;
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
@@ -321,7 +366,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
}
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
if(MODREG) { // reg
|
||||
MOV_REG(xEIP, xEAX+(nextop&7));
|
||||
} else { // mem
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -336,7 +381,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ed");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
if(MODREG) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
|
||||
@@ -172,6 +172,13 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
case 0x65:
|
||||
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x69:
|
||||
INST_NAME("IMUL Gd, GS:Ed, Id");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
@@ -369,7 +376,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -383,7 +390,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
@@ -396,7 +403,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("POP GS:Ed");
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1((xEAX+(nextop&7)));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
@@ -405,6 +412,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
INST_NAME("NOP");
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX, GS:Id");
|
||||
@@ -444,7 +454,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV GS:Eb, Ib");
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= u8
|
||||
if(MODREG) { // reg <= u8
|
||||
u8 = F8;
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
@@ -463,7 +473,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV GS:Ed, Id");
|
||||
grab_tlsdata(dyn, addr, ninst, x14);
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= i32
|
||||
if(MODREG) { // reg <= i32
|
||||
i32 = F32S;
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
@@ -650,7 +660,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH GS:Ed");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
if(MODREG) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
|
||||
+229
-133
@@ -18,6 +18,7 @@
|
||||
#include "dynarec_arm.h"
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "arm_printer.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "dynarec_arm_helper.h"
|
||||
#include "dynarec_arm_functions.h"
|
||||
@@ -47,8 +48,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
emit_add16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -56,16 +57,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
emit_add16(dyn, ninst, x1, x2, x3, x14, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("ADD AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
emit_add16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -123,8 +124,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
emit_adc16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -133,8 +134,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
emit_adc16(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
@@ -142,8 +143,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -153,8 +154,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
emit_sbb16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -164,7 +165,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
GETSEW(x2);
|
||||
emit_sbb16(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
@@ -172,9 +173,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
emit_sbb16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
case 0x1E:
|
||||
@@ -219,8 +220,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SUB Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1);
|
||||
GETSGW(x2);
|
||||
GETSEW(x1);
|
||||
emit_sub16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -228,16 +229,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SUB Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2);
|
||||
GETSGW(x1);
|
||||
GETSEW(x2);
|
||||
emit_sub16(dyn, ninst, x1, x2, x3, x14, 0);
|
||||
GWBACK;
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("SUB AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
i32 = F16S;
|
||||
SXTH(x1, xEAX, 0);
|
||||
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -388,13 +389,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("IMUL Gw,Ew,Iw");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETEW(x1);
|
||||
i16 = F16S;
|
||||
MOVW(x2, i16);
|
||||
SMULBB(x2, ed, x2);
|
||||
UFLAG_RES(x2);
|
||||
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
case 0x6A:
|
||||
INST_NAME("PUSH Ib");
|
||||
@@ -406,13 +407,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("IMUL Gw,Ew,Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETEW(x1);
|
||||
i16 = F8S;
|
||||
MOVW(x2, i16);
|
||||
SMULBB(x2, ed, x2);
|
||||
UFLAG_RES(x2);
|
||||
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
@@ -507,7 +508,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x87:
|
||||
INST_NAME("(LOCK) XCHG Ew, Gw");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGD;
|
||||
UXTH(x14, gd, 0);
|
||||
ed = xEAX + (nextop&7);
|
||||
@@ -541,7 +542,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Ew, Gw");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW here
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(ed, gd, 0, 16);
|
||||
@@ -556,7 +557,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Gw, Ew");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW neither
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(gd, ed, 0, 16);
|
||||
@@ -573,7 +574,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
LDRH_REG(x1, xEmu, x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
BFI(ed, x1, 0, 16);
|
||||
} else {
|
||||
@@ -586,7 +587,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x8E:
|
||||
INST_NAME("MOV Seg,Ew");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(ed, xEmu, x2);
|
||||
@@ -649,7 +650,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV, AX, Od");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
SMREAD();
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
SMREADLOCK(lock);
|
||||
LDRH_IMM8(x2, x2, 0);
|
||||
BFI(xEAX, x2, 0, 16);
|
||||
break;
|
||||
@@ -657,8 +659,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV Od, AX");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
if(isLockAddress(u32)) lock=1; else lock = 0;
|
||||
STRH_IMM8(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
SMWRITELOCK(lock);
|
||||
break;
|
||||
case 0xA5:
|
||||
INST_NAME("MOVSW");
|
||||
@@ -723,21 +726,29 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, Ib");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
CALL_(rol16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_rol16c(dyn, ninst, x1, u8&15, x2, x14);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, Ib");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
CALL_(ror16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_ror16c(dyn, ninst, x1, u8&15, x2, x14);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, Ib");
|
||||
@@ -762,39 +773,42 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_LSL_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_shl16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
u8 = F8;
|
||||
emit_shr16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEW(x1);
|
||||
u8 = F8;
|
||||
MOVW(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
MOV_REG_ASR_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar16);
|
||||
if(geted_ib(dyn, addr, ninst, nextop)&31) {
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETSEW(x1);
|
||||
u8 = F8;
|
||||
emit_sar16c(dyn, ninst, x1, u8&31, x2, x14);
|
||||
EWBACK;
|
||||
} else {
|
||||
FAKEED;
|
||||
F8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -802,7 +816,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC7:
|
||||
INST_NAME("MOV Ew, Iw");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u16 = F16;
|
||||
MOVW(x1, u16);
|
||||
@@ -816,101 +830,178 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
case 0xD1:
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("ROL Ew, 1");
|
||||
MOVW(x2, 1);
|
||||
} else {
|
||||
INST_NAME("ROL Ew, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
INST_NAME("ROL Ew, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
CALL_(rol16, x1, (1<<x3));
|
||||
emit_rol16c(dyn, ninst, x1, 1, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 1:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("ROR Ew, 1");
|
||||
MOVW(x2, 1);
|
||||
} else {
|
||||
INST_NAME("ROR Ew, CL");
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
INST_NAME("ROR Ew, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEW(x1);
|
||||
CALL_(ror16, x1, (1<<x3));
|
||||
emit_ror16c(dyn, ninst, x1, 1, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 2:
|
||||
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
|
||||
INST_NAME("RCL Ew, 1");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
|
||||
MOVW(x2, 1);
|
||||
GETEW(x1);
|
||||
CALL_(rcl16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
break;
|
||||
case 3:
|
||||
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
|
||||
INST_NAME("RCR Ew, 1");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
|
||||
MOVW(x2, 1);
|
||||
GETEW(x1);
|
||||
CALL_(rcr16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SHL Ew, 1");
|
||||
MOVW(x14, 1);
|
||||
} else {
|
||||
INST_NAME("SHL Ew, CL");
|
||||
AND_IMM8(x14, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHL Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1);
|
||||
UFLAG_OP12(ed, x14)
|
||||
MOV_REG_LSL_REG(ed, ed, x14);
|
||||
emit_shl16c(dyn, ninst, x1, 1, x2, x14);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
break;
|
||||
case 5:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SHR Ew, 1");
|
||||
MOVW(x14, 1);
|
||||
} else {
|
||||
INST_NAME("SHR Ew, CL");
|
||||
AND_IMM8(x14, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SHR Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEW(x1);
|
||||
UFLAG_OP12(ed, x14)
|
||||
MOV_REG_LSR_REG(ed, ed, x14);
|
||||
emit_shr16c(dyn, ninst, x1, 1, x2, x14);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
break;
|
||||
case 7:
|
||||
if(opcode==0xD1) {
|
||||
INST_NAME("SAR Ew, 1");
|
||||
MOVW(x14, 1);
|
||||
} else {
|
||||
INST_NAME("SAR Ew, CL");
|
||||
AND_IMM8(x14, xECX, 0x1f);
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
INST_NAME("SAR Ew, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETSEW(x1);
|
||||
UFLAG_OP12(ed, x14)
|
||||
MOV_REG_ASR_REG(ed, ed, x14);
|
||||
emit_sar16c(dyn, ninst, x1, 1, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTS_IMM8(xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
AND_IMM8(x2, xECX, 0x0f);
|
||||
RSB_IMM8(x2, x2, 16);
|
||||
GETEW(x1);
|
||||
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x2, 15);
|
||||
ADD_REG_LSR_IMM5_COND(cEQ, x3, ed, ed, 15);
|
||||
BFI_COND(cEQ, xFlags, x3, F_OF, 1);
|
||||
BFI(xFlags, ed, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
TSTS_IMM8(xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
AND_IMM8(x2, xECX, 0x0f);
|
||||
GETEW(x1);
|
||||
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
|
||||
MOV_REG_LSR_REG(ed, ed, x2);
|
||||
EWBACK;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x2, 1);
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, x2, ed, 14); // x2 = d>>14
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
|
||||
BFI_COND(cEQ, xFlags, x2, F_OF, 1);
|
||||
MOV_REG_LSR_IMM5(x2, ed, 15);
|
||||
BFI(xFlags, x2, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, CL");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEW(x1);
|
||||
CALL_(rcl16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, CL");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
GETEW(x1);
|
||||
CALL_(rcr16, x1, (1<<x3));
|
||||
EWBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETEW(x1);
|
||||
emit_shl16(dyn, ninst, x1, x2, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETEW(x1);
|
||||
emit_shr16(dyn, ninst, x1, x2, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ew, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(box86_dynarec_safeflags>1)
|
||||
MAYSETFLAGS();
|
||||
UFLAG_IF {
|
||||
ANDS_IMM8(x2, xECX, 0x1f);
|
||||
B_NEXT(cEQ);
|
||||
} else {
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
}
|
||||
GETSEW(x1);
|
||||
emit_sar16(dyn, ninst, x1, x2, x2, x14);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1058,13 +1149,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 5:
|
||||
INST_NAME("IMUL AX, Ew");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
GETEW(x1);
|
||||
SMULBB(x2, xEAX, ed);
|
||||
UFLAG_RES(x2);
|
||||
BFI(xEAX, x2, 0, 16);
|
||||
MOV_REG_LSR_IMM5(x2, x2, 16);
|
||||
BFI(xEDX, x2, 0, 16);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ew");
|
||||
@@ -1128,6 +1219,11 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_dec16(dyn, ninst, x1, x2, x14);
|
||||
EWBACK;
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PUSH Ew");
|
||||
GETEW(x1);
|
||||
PUSH16(x1, xESP);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
+332
-56
@@ -21,10 +21,11 @@
|
||||
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
#include "emu/x86compstrings.h"
|
||||
|
||||
// Get EX as a quad
|
||||
#define GETEX(a, w) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
@@ -35,12 +36,18 @@
|
||||
#define GETGX(a, w) \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
#define GETGX_empty(a) \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETG gd = (nextop&0x38)>>3
|
||||
|
||||
uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
uint8_t eb1, eb2;
|
||||
@@ -66,7 +73,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVUPD Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -87,7 +94,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -105,7 +112,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVLPD Gx, Eq");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
@@ -126,7 +133,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVLPD Eq, Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
@@ -147,7 +154,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("UNPCKLPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1);
|
||||
} else {
|
||||
@@ -161,7 +168,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
VMOVD(v0, v0+1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1+1);
|
||||
} else {
|
||||
@@ -174,7 +181,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVHPD Gx, Ed");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
@@ -195,7 +202,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVHPD Ed, Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
@@ -223,7 +230,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVAPD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -239,7 +246,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -255,7 +262,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -286,7 +293,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -460,6 +467,108 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VABSQ_S32(q0, q1);
|
||||
break;
|
||||
|
||||
case 0xDB:
|
||||
INST_NAME("AESIMC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
AESIMC(q0, q1);
|
||||
} else {
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
if(q0!=q1) {
|
||||
VMOVQ(q0, q1);
|
||||
}
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd);
|
||||
CALL(arm_aesimc, -1, 0);
|
||||
}
|
||||
break;
|
||||
case 0xDC:
|
||||
INST_NAME("AESENC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESE(v0, q1);
|
||||
AESMC(v0, v0);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd);
|
||||
CALL(arm_aese, -1, 0);
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDD:
|
||||
INST_NAME("AESENCLAST Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESE(v0, q1);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd);
|
||||
CALL(arm_aeselast, -1, 0);
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDE:
|
||||
INST_NAME("AESDEC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESD(v0, q1);
|
||||
AESIMC(v0, v0);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd);
|
||||
CALL(arm_aesd, -1, 0);
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDF:
|
||||
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESD(v0, q1);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd);
|
||||
CALL(arm_aesdlast, -1, 0);
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -484,6 +593,163 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VEXTQ_8(q0, q1, q0, u8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x16:
|
||||
INST_NAME("PEXTRD Ed, Gx, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 0);
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
VMOVfrDx_32(ed, q0+((u8&2)>>1), u8&1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
VST1LANE_32(q0+((u8&2)>>1), wback, u8&1);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
INST_NAME("PINSRB Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
VMOVtoDx_8(q0+((u8&8)>>3), u8&7, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
VLD1LANE_8(q0+((u8&8)>>3), wback, u8&7);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
INST_NAME("PINSRD Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
VMOVtoDx_32(q0+((u8&2)>>1), u8&1, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
VLD1LANE_32(q0+((u8&2)>>1), wback, u8&1);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
if(arm_pmull) {
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
u8 = F8;
|
||||
switch (u8&0b00010001) {
|
||||
case 0b00000000:
|
||||
VMULL_P64(q0, q0, q1);
|
||||
break;
|
||||
case 0b00010001:
|
||||
VMULL_P64(q0, q0+1, q1+1);
|
||||
break;
|
||||
case 0b00000001:
|
||||
VMULL_P64(q0, q0+1, q1);
|
||||
break;
|
||||
case 0b00010000:
|
||||
VMULL_P64(q0, q0, q1+1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
if(MODREG) {
|
||||
ed = nextop&7;
|
||||
sse_forget_reg(dyn, ninst, ed, x1);
|
||||
MOV32(x2, ed);
|
||||
} else {
|
||||
MOV32(x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x2) {
|
||||
MOV_REG(x2, ed);
|
||||
}
|
||||
}
|
||||
MOV32(x1, gd); // gx
|
||||
u8 = F8;
|
||||
MOV32(x3, u8);
|
||||
CALL(arm_pclmul, -1, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x63:
|
||||
INST_NAME("PCMPISTRI Gx, Ex, Ib");
|
||||
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(!sse_reflect_reg(dyn, ninst, gd, x2)) {
|
||||
u32 = offsetof(x86emu_t, xmm[gd]);
|
||||
if(!(u32&3) && (u32>>2)<256) {
|
||||
ADD_IMM8_ROR(x2, xEmu, u32>>2, 15);
|
||||
} else {
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
|
||||
}
|
||||
}
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
if(!sse_reflect_reg(dyn, ninst, ed, x1)) {
|
||||
u32 = offsetof(x86emu_t, xmm[ed]);
|
||||
if(!(u32&3) && (u32>>2)<256) {
|
||||
ADD_IMM8_ROR(x1, xEmu, u32>>2, 15);
|
||||
} else {
|
||||
MOV32(x1, u32);
|
||||
ADD_REG_LSL_IMM5(x1, xEmu, x1, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
}
|
||||
u8 = F8;
|
||||
MOV32(x3, u8);
|
||||
CALL(sse42_compare_string_implicit_len, x1, 0);
|
||||
CMPS_IMM8(x1, 0);
|
||||
MOVW_COND(cEQ, xECX, (u8&1)?8:16);
|
||||
if(u8&0b1000000) {
|
||||
CLZ_COND(cNE, xECX, x1);
|
||||
RSB_COND_IMM8(cNE, xECX, xECX, 31);
|
||||
} else {
|
||||
RBIT_COND(cNE, xECX, x1);
|
||||
CLZ_COND(cNE, xECX, xECX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDF:
|
||||
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
|
||||
nextop = F8;
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd, x1);
|
||||
MOV32(x1, gd); // gx
|
||||
if(MODREG) {
|
||||
ed = nextop&7;
|
||||
sse_forget_reg(dyn, ninst, ed, x2);
|
||||
MOV32(x2, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x2) {
|
||||
MOV_REG(x2, ed);
|
||||
}
|
||||
}
|
||||
u8 = F8;
|
||||
MOV32(x3, u8);
|
||||
CALL(arm_aeskeygenassist, -1, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -494,7 +760,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETFLAGS; \
|
||||
nextop=F8; \
|
||||
GETGD; \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
ed = xEAX+(nextop&7); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
@@ -602,7 +868,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
q1 = q0;
|
||||
@@ -727,11 +993,21 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
q1 = v1;
|
||||
// need rounding!
|
||||
//VCVTQ_S32_F32(v0, v1);
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
VCVTR_S32_F32(q0*2+0, q1*2+0);
|
||||
VCVTR_S32_F32(q0*2+1, q1*2+1);
|
||||
VCVTR_S32_F32(q0*2+2, q1*2+2);
|
||||
VCVTR_S32_F32(q0*2+3, q1*2+3);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
else
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
for(int i=0; i<4; ++i) {
|
||||
VCVTR_S32_F32(q0*2+i, q1*2+i);
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, x1, 0b10, 1); // 0x80000000
|
||||
VMOVtoVcond(cNE, q0*2+i, x1);
|
||||
BIC_IMM8_COND(cNE, x3, x3, 1, 0); // reset FPU
|
||||
VMSR_cond(cNE, x3);
|
||||
}
|
||||
}
|
||||
if(q0!=v0) {
|
||||
VMOVQ(v0, q0);
|
||||
}
|
||||
@@ -936,7 +1212,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1);
|
||||
} else {
|
||||
@@ -950,7 +1226,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
VMOVD(q0, q0+1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(q0+1, q1+1);
|
||||
} else {
|
||||
@@ -972,7 +1248,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDQA Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -988,7 +1264,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
i32 = -1;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
u8 = F8;
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
@@ -1119,7 +1395,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLW Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1142,7 +1418,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAW Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1161,7 +1437,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLW Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1192,7 +1468,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLD Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1215,7 +1491,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAD Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1234,7 +1510,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLD Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1264,7 +1540,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLQ Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1287,7 +1563,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("PSRLDQ Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1312,7 +1588,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLQ Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1335,7 +1611,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("PSLLDQ Ex, Ib");
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1389,7 +1665,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX + (nextop&7);
|
||||
VMOVfrDx_32(ed, v0, 0);
|
||||
} else {
|
||||
@@ -1403,7 +1679,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDQA Ex,Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -1419,7 +1695,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD; // there is an AND below, so 32bits is the same (no need for GETGW)
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7); // no need for extract
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1461,7 +1737,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD; // there is an AND below, to 32bits is the same
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
@@ -1511,8 +1787,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("IMUL Gw,Ew");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
@@ -1523,6 +1798,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
SMULBB(x2, gd, ed);
|
||||
UFLAG_RES(x2);
|
||||
BFI((xEAX+((nextop&0x38)>>3)), x2, 0, 16);
|
||||
UFLAG_DF(x1, d_imul16);
|
||||
break;
|
||||
|
||||
case 0xB3:
|
||||
@@ -1531,7 +1807,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD; // there is an AND below, to 32bits is the same
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
@@ -1560,7 +1836,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVZX Gw, Eb");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
@@ -1576,7 +1852,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVZX Gw, Ew");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX + (nextop&7);
|
||||
UXTH(x1, ed, 0);
|
||||
} else {
|
||||
@@ -1594,7 +1870,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("BT Ew, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -1614,7 +1890,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("BTS Ew, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1645,7 +1921,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("BTR Ew, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1676,7 +1952,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("BTC Ew, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -1712,7 +1988,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD; // there is an AND below, to 32bits is the same
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
@@ -1771,7 +2047,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSX Gw, Eb");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
@@ -1844,7 +2120,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PINSRW Gx,Ed,Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
u8 = (F8)&7;
|
||||
ed = xEAX+(nextop&7);
|
||||
VMOVtoDx_16(v0+(u8/4), u8&3, ed);
|
||||
@@ -1859,7 +2135,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PEXTRW Gd,Ex,Ib");
|
||||
nextop = F8;
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETEX(v0, 0);
|
||||
u8 = (F8)&7;
|
||||
VMOVfrDx_U16(gd, v0+(u8/4), (u8&3));
|
||||
@@ -1973,7 +2249,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVQ Ex,Gx");
|
||||
nextop = F8;
|
||||
GETGX(q0, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVD(q1, q0);
|
||||
VEOR(q1+1, q1+1, q1+1);
|
||||
@@ -1994,7 +2270,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
break;
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
INST_NAME("PMOVMSKB Gd, Ex");
|
||||
GETEX(q0, 0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
@@ -2165,7 +2441,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -2280,7 +2556,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q0, v0);
|
||||
VTRN_32(q0, q0+1); // transpose GX
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else {
|
||||
@@ -2317,7 +2593,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_8(v0, xEDI); // hopefully it's always aligned?
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
v1 = fpu_get_scratch_quad(dyn); // need to preserve the register
|
||||
else
|
||||
v1 = q1;
|
||||
|
||||
@@ -41,7 +41,6 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -50,8 +49,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("LOCK ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add16c(dyn, ninst, ed, i16, x3, x14);
|
||||
@@ -69,9 +67,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
STREXH(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
|
||||
@@ -84,8 +82,8 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STRH_IMM8(x1, wback, 0); // put the whole value
|
||||
SMDMB();
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -101,7 +99,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0: // INC Ew
|
||||
INST_NAME("INC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETEW(x1);
|
||||
emit_inc16(dyn, ninst, ed, x3, x14);
|
||||
EWBACK(x1);
|
||||
@@ -118,9 +116,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
STREXH(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
|
||||
@@ -133,13 +131,14 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STRH_IMM8(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ew
|
||||
INST_NAME("DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETEW(x1);
|
||||
emit_dec32(dyn, ninst, ed, x3, x14);
|
||||
EWBACK(x1);
|
||||
@@ -156,9 +155,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
STREXH(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -171,6 +170,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STRH_IMM8(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -50,7 +50,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
GETGD; // don't need GETGW here
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(ed, gd, 0, 16);
|
||||
@@ -67,7 +67,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
if(MODREG) { // reg <= reg
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(gd, ed, 0, 16);
|
||||
@@ -83,7 +83,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("POP FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1(xEAX+(nextop&7)); // 67 ignored
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
@@ -123,7 +123,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ew");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
if(MODREG) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
|
||||
@@ -319,15 +319,21 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
BFC(x1, 9, 2); //C1 C2 = 0 0
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
|
||||
// and want 1.0 = 0x3ff0000000000000
|
||||
// so 00111111 11110000 00000000 00000000....
|
||||
// a = 0, b = 1, c = 1, d = 1, efgh=0
|
||||
// 0b01110000
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_i_32(v2, 0b01110000);
|
||||
if(PK(0)==0xdd && PK(1)==0xd8) {
|
||||
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
|
||||
u8 = F8;
|
||||
u8 = F8;
|
||||
} else {
|
||||
VMOV_i_64(v2, 0b01110000);
|
||||
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
|
||||
// and want 1.0 = 0x3ff0000000000000
|
||||
// so 00111111 11110000 00000000 00000000....
|
||||
// a = 0, b = 1, c = 1, d = 1, efgh=0
|
||||
// 0b01110000
|
||||
if(ST_IS_F(0)) {
|
||||
VMOV_i_32(v2, 0b01110000);
|
||||
} else {
|
||||
VMOV_i_64(v2, 0b01110000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
|
||||
@@ -923,7 +923,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
SET_DF(s3, d_dec8);
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
SET_DFNONE(s3);
|
||||
|
||||
@@ -154,7 +154,17 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
B_NEXT(cEQ);
|
||||
}
|
||||
IFX(X_ZF|X_CF) {
|
||||
IFX(X_CF) {
|
||||
SUB_IMM8(s4, s2, 1);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1); // if s2==1
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOVS_REG_LSR_REG(s1, s1, s2);
|
||||
} else {
|
||||
MOV_REG_LSR_REG(s1, s1, s2);
|
||||
@@ -162,25 +172,14 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF|X_CF) {
|
||||
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
|
||||
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1);
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -203,7 +202,21 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_ZF|X_CF) {
|
||||
IFX(X_CF) {
|
||||
if(c==1) {
|
||||
BFI(xFlags, s1, F_CF, 1);
|
||||
} else {
|
||||
MOV_REG_LSR_IMM5(s3, s1, c-1);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOVS_REG_LSR_IMM5(s1, s1, c);
|
||||
} else {
|
||||
MOV_REG_LSR_IMM5(s1, s1, c);
|
||||
@@ -211,26 +224,14 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF|X_CF) {
|
||||
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
|
||||
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 31);
|
||||
BFI(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 30);
|
||||
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -274,6 +275,565 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
MOV_REG_LSR_IMM5(s3, s1, 31);
|
||||
BFI(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF)
|
||||
if(c==1) {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHL8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
|
||||
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shl8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF | X_OF) {
|
||||
RSB_IMM8(s4, s2, 8);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
MOV_REG_LSL_REG(s1, s1, s2);
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
} else IFX(X_PEND) {
|
||||
AND_IMM8(s1, s1, 0xff);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOV32(s4, 1);
|
||||
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1); // if s2==1
|
||||
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);}
|
||||
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shl8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c<8) {
|
||||
IFX(X_CF|X_OF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 8-c);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
MOV_REG_LSL_IMM5(s1, s1, c);
|
||||
|
||||
IFX(X_PEND) {
|
||||
AND_IMM8(s1, s1, 0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_IMM8(s1, 0xff);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 7);}
|
||||
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
} else {
|
||||
IFX(X_CF) {
|
||||
MOV_REG_LSL_IMM5(s3, s1, c-1);
|
||||
MOV_REG_LSR_IMM5(s4, s3, 7);
|
||||
BFI(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
MOVW(s1, 0);
|
||||
IFX(X_OF) {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
BFC(xFlags, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF | X_ZF) {
|
||||
MOVW(s3, 1);
|
||||
IFX(X_ZF) {
|
||||
BFI(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
BFI(xFlags, s3, F_PF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shr8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SUB_IMM8(s4, s2, 1);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, 0, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1); // if s2==1
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
MOV_REG_LSR_REG(s1, s1, s2);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_IMM8(s1, 0xff);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shr8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c==1) {
|
||||
BFI(xFlags, s1, 0, 1);
|
||||
} else {
|
||||
MOV_REG_LSR_IMM5(s3, s1, c-1);
|
||||
BFI(xFlags, s3, 0, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
MOV_REG_LSR_IMM5(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_IMM8(s1, 0xff);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SAR8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_sar8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SUB_IMM8(s4, s2, 1);
|
||||
MOV_REG_ASR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, 0, 1);
|
||||
}
|
||||
MOV_REG_ASR_REG(s1, s1, s2);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_IMM8(s1, 0xff);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1);
|
||||
BFC_COND(cEQ, xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SAR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_sar8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOV_REG_ASR_IMM5(s3, s1, c-1);
|
||||
BFI(xFlags, s3, 0, 1);
|
||||
}
|
||||
MOV_REG_ASR_IMM5(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_IMM8(s1, 0xff);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 7);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF)
|
||||
if(c==1) {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
|
||||
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shl16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF | X_OF) {
|
||||
RSB_IMM8(s4, s2, 16);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
MOV_REG_LSL_REG(s1, s1, s2);
|
||||
UBFX(s1, s1, 0, 16);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOV32(s4, 1);
|
||||
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1); // if s2==1
|
||||
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 15);}
|
||||
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shl16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c<16) {
|
||||
IFX(X_CF|X_OF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 16-c);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
MOV_REG_LSL_IMM5(s1, s1, c);
|
||||
|
||||
UBFX(s1, s1, 0, 16);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 15);}
|
||||
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
} else {
|
||||
IFX(X_CF) {
|
||||
MOV_REG_LSL_IMM5(s3, s1, c-1);
|
||||
MOV_REG_LSR_IMM5(s4, s3, 15);
|
||||
BFI(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
MOVW(s1, 0);
|
||||
IFX(X_OF) {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
BFC(xFlags, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF | X_ZF) {
|
||||
MOVW(s3, 1);
|
||||
IFX(X_ZF) {
|
||||
BFI(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
BFI(xFlags, s3, F_PF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shr16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SUB_IMM8(s4, s2, 1);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, 0, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1); // if s2==1
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 16);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
MOV_REG_LSR_REG(s1, s1, s2);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SHR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_shr16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c==1) {
|
||||
BFI(xFlags, s1, 0, 1);
|
||||
} else {
|
||||
MOV_REG_LSR_IMM5(s3, s1, c-1);
|
||||
BFI(xFlags, s3, 0, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
MOV_REG_LSR_IMM5(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SAR16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_sar16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
SUB_IMM8(s4, s2, 1);
|
||||
MOV_REG_ASR_REG(s4, s1, s4);
|
||||
BFI(xFlags, s4, 0, 1);
|
||||
}
|
||||
MOV_REG_ASR_REG(s1, s1, s2);
|
||||
UBFX(s1, s1, 0, 16);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s2, 1);
|
||||
BFC_COND(cEQ, xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(!c)
|
||||
return;
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_sar16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOV_REG_ASR_IMM5(s3, s1, c-1);
|
||||
BFI(xFlags, s3, 0, 1);
|
||||
}
|
||||
MOV_REG_ASR_IMM5(s1, s1, c);
|
||||
IFX(X_PEND | X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
BFI(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 15);
|
||||
BFI(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF)
|
||||
if(c==1) {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
@@ -366,6 +926,12 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_OF, 1); // store sign for later use
|
||||
}
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOVS_REG_LSR_IMM5(s1, s1, c);
|
||||
} else {
|
||||
@@ -394,9 +960,11 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 30);
|
||||
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
@@ -425,6 +993,12 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_OF, 1); // store sign for later use
|
||||
}
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 32-c);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
@@ -436,9 +1010,9 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
UBFX(s3, s1, (31-c), 1);
|
||||
XOR_IMM8_COND(cCS, s3, s3, 1);
|
||||
BFI(xFlags, s3, F_OF, 1);
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
BFC(xFlags, F_OF, 1);
|
||||
}
|
||||
@@ -474,7 +1048,7 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
// same flags calc as shr32
|
||||
SET_DF(s4, d_shr32);
|
||||
SET_DF(s4, d_shrd32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
@@ -484,6 +1058,10 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
B_NEXT(cEQ);
|
||||
|
||||
IFX(X_OF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_OF, 1); // store sign for later use
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOVS_REG_LSR_REG(s1, s1, s3);
|
||||
} else {
|
||||
@@ -513,8 +1091,8 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
IFX(X_OF) {
|
||||
CMPS_IMM8(s3, 31); // 32-c
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
@@ -531,7 +1109,7 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
// same flags calc as shl32
|
||||
SET_DF(s4, d_shl32);
|
||||
SET_DF(s4, d_shld32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
@@ -544,6 +1122,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
B_NEXT(cEQ);
|
||||
|
||||
IFX(X_OF) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 31);
|
||||
BFI(xFlags, s4, F_OF, 1); // store sign for later use
|
||||
}
|
||||
IFX(X_CF) {
|
||||
RSB_IMM8(s4, s3, 32);
|
||||
MOV_REG_LSR_REG(s4, s1, s4);
|
||||
@@ -555,13 +1137,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MOV_REG_LSL_REG(s1, s1, s3);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
MOVW_COND(cCS, s4, 1);
|
||||
MOVW_COND(cCC, s4, 0);
|
||||
CMPS_IMM8(s3, 1);
|
||||
ORR_REG_LSR_IMM5_COND(cEQ, s4, s4, s1, 30);
|
||||
CMPS_IMM8(s3, 31); // 32-c
|
||||
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
|
||||
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
|
||||
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
|
||||
//else
|
||||
BFC_COND(cNE, xFlags, F_OF, 1);
|
||||
}
|
||||
RSB_IMM8(s3, s3, 32);
|
||||
IFX(X_ZF) {
|
||||
@@ -602,8 +1181,8 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
return;
|
||||
}
|
||||
if(c&7) {
|
||||
BFI(s1, s1, 24, 8); // duplicate the value for rotate left
|
||||
MOV_REG_ROR_IMM5(s1, s1, 32-(c&7));
|
||||
BFI(s1, s1, 8, 8);
|
||||
MOV_REG_LSR_IMM5(s1, s1, 8-(c&7));
|
||||
}
|
||||
//AND_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
@@ -614,7 +1193,7 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
ADD_REG_LSR_IMM5(s3, s1, s1, 7);
|
||||
XOR_REG_LSR_IMM8(s3, s1, s1, 7);
|
||||
BFI(xFlags, s3, F_OF, 1);
|
||||
}
|
||||
}
|
||||
@@ -638,7 +1217,7 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
if(c&7) {
|
||||
BFI(s1, s1, 8, 8); // duplicate the value for Rotate right
|
||||
MOV_REG_ROR_IMM5(s1, s1, c&7);
|
||||
MOV_REG_LSR_IMM5(s1, s1, c&7);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
AND_IMM8(s1, s1, 0xff);
|
||||
@@ -656,3 +1235,75 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit ROL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_rol16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(c&15) {
|
||||
BFI(s1, s1, 16, 16);
|
||||
MOV_REG_LSR_IMM5(s1, s1, 16-(c&15));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
UBFX(s1, s1, 0, 16);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
BFI(xFlags, s1, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
XOR_REG_LSR_IMM8(s3, s1, s1, 15);
|
||||
BFI(xFlags, s3, F_OF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit ROR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_ror16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(c&15) {
|
||||
BFI(s1, s1, 16, 16); // duplicate the value for Rotate right
|
||||
MOV_REG_LSR_IMM5(s1, s1, c&15);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
UBFX(s1, s1, 0, 16);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_CF) {
|
||||
MOV_REG_LSR_IMM5(s3, s1, 15);
|
||||
BFI(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
MOV_REG_LSR_IMM5(s4, s1, 14);
|
||||
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
|
||||
BFI(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
-104
@@ -42,8 +42,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -66,8 +65,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -85,8 +83,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK OR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -111,8 +108,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -132,8 +128,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -157,8 +152,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -178,8 +172,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -203,8 +196,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -222,8 +214,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK AND Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -248,8 +239,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -268,8 +258,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -292,8 +281,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -311,8 +299,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK XOR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -337,8 +324,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
@@ -368,8 +354,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add32c(dyn, ninst, ed, i32, x3, x14);
|
||||
@@ -409,8 +394,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32c(dyn, ninst, ed, i32, x3, x14);
|
||||
@@ -430,8 +414,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
|
||||
@@ -451,8 +434,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
|
||||
@@ -471,8 +453,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32c(dyn, ninst, ed, i32, x3, x14);
|
||||
@@ -491,12 +472,11 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
if(!fixedaddress) {
|
||||
@@ -532,12 +512,11 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
@@ -552,7 +531,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
GETEDH(x1);
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -566,7 +544,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
|
||||
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed by a locked write)
|
||||
#define GO(A) \
|
||||
case A+0x02: \
|
||||
case A+0x03: \
|
||||
@@ -585,17 +563,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SMDMB();
|
||||
--addr;
|
||||
break;
|
||||
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:
|
||||
SMDMB();
|
||||
--addr;
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
nextop = F8;
|
||||
@@ -603,9 +570,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xB0:
|
||||
INST_NAME("LOCK CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -649,8 +615,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
// same as no lock, all in regs...
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
@@ -721,8 +686,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -736,30 +700,26 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x14, ed, x2);
|
||||
ANDS_IMM8(x14, x14, 1);
|
||||
BFI(xFlags, x14, F_CF, 1);
|
||||
B_MARK3(cEQ); // bit already clear, jump to end of instruction
|
||||
MOVW(x14, 1);
|
||||
XOR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
BIC_REG_LSL_REG(ed, ed, x14, x2);
|
||||
if(wback) {
|
||||
STREX(x14, ed, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
MARK3;
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 4:
|
||||
INST_NAME("(LOCK) BT Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0, LOCK_LOCK);
|
||||
@@ -778,26 +738,21 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK BTS Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8&0x1f);
|
||||
u8 = F8&0x1f;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
u8 = F8;
|
||||
u8 = F8&0x1f;
|
||||
ed = x1;
|
||||
MOVW(gd, u8&0x1f);
|
||||
MARKLOCK;
|
||||
LDREX(ed, wback);
|
||||
}
|
||||
MOV_REG_LSR_REG(x14, ed, x2);
|
||||
ANDS_IMM8(x14, x14, 1);
|
||||
MOV_REG_LSR_IMM5(x14, ed, u8);
|
||||
BFI(xFlags, x14, F_CF, 1);
|
||||
B_MARK3(cNE); // bit already set, jump to next instruction
|
||||
MOVW(x14, 1);
|
||||
XOR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
BFI(ed, x14, u8, 1);
|
||||
if(wback) {
|
||||
STREX(x14, ed, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
@@ -809,26 +764,46 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8&0x1f);
|
||||
u8 = F8&0x1f;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
u8 = F8;
|
||||
u8 = F8&0x1f;
|
||||
ed = x1;
|
||||
MOVW(gd, u8&0x1f);
|
||||
MARKLOCK;
|
||||
LDREX(ed, wback);
|
||||
}
|
||||
MOV_REG_LSR_REG(x14, ed, x2);
|
||||
ANDS_IMM8(x14, x14, 1);
|
||||
MOV_REG_LSR_IMM5(x14, ed, u8);
|
||||
BFI(xFlags, x14, F_CF, 1);
|
||||
B_MARK3(cEQ); // bit already clear, jump to next instruction
|
||||
//MOVW(x14, 1); // already 0x01
|
||||
XOR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
BFC(ed, u8, 1);
|
||||
if(wback) {
|
||||
STREX(x14, ed, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("LOCK BTC Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8&0x1f;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
u8 = F8&0x1f;
|
||||
ed = x1;
|
||||
MARKLOCK;
|
||||
LDREX(ed, wback);
|
||||
}
|
||||
MOV_REG_LSR_IMM5(x14, ed, u8);
|
||||
BFI(xFlags, x14, F_CF, 1);
|
||||
MOV32(x14, 1);
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STREX(x14, ed, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
@@ -847,8 +822,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
@@ -879,7 +853,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
GETGB(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
@@ -909,8 +883,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(gd!=ed) {
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
|
||||
@@ -964,7 +937,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
|
||||
@@ -1010,8 +982,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
default:
|
||||
// dafault to NO LOCK
|
||||
addr-=2;
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1023,7 +994,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0: // INC Ed
|
||||
INST_NAME("INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_inc32(dyn, ninst, ed, x3, x14);
|
||||
} else {
|
||||
@@ -1039,9 +1010,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -1054,13 +1025,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_dec32(dyn, ninst, ed, x3, x14);
|
||||
} else {
|
||||
@@ -1076,9 +1048,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -1091,19 +1063,18 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// default to NO LOCK
|
||||
addr-=2;
|
||||
DEFAULT;
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
default:
|
||||
// default to NO LOCK
|
||||
--addr;
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
return addr;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
|
||||
#define GETEX(a, w) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7,w);\
|
||||
} else { \
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3); \
|
||||
@@ -68,7 +68,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0, d0);
|
||||
@@ -87,7 +87,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
VMOVD(d0, v0);
|
||||
} else {
|
||||
@@ -102,7 +102,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, d0);
|
||||
@@ -133,7 +133,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -165,7 +165,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -328,7 +328,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -364,7 +364,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -434,7 +434,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -460,7 +460,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("LDDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
// Get Ex as a single, not a quad, with b a intermediary double
|
||||
#define GETEX(a, b) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
b = sse_get_reg(dyn, ninst, x1, nextop&7,0);\
|
||||
if(b<16) \
|
||||
a = b; \
|
||||
@@ -81,7 +81,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSS Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
@@ -121,7 +121,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
@@ -156,7 +156,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSLDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -173,7 +173,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVSHDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -223,7 +223,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
@@ -268,7 +268,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v0<16)
|
||||
d0 = v0;
|
||||
@@ -420,7 +420,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0x5B:
|
||||
INST_NAME("CVTTPS2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -523,7 +523,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
@@ -543,7 +543,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PSHUFHW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
@@ -579,7 +579,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVQ Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, v1);
|
||||
@@ -596,7 +596,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
@@ -666,7 +666,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVQ2DQ Gx, Em");
|
||||
nextop = F8;
|
||||
GETGX_empty(v0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
|
||||
VEORQ(v0, v0, v0); // usefull?
|
||||
VMOV_64(v0, v1);
|
||||
@@ -688,7 +688,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
case 0xE6:
|
||||
INST_NAME("CVTDQ2PD Gx, Ex");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
if(v1<16)
|
||||
v0 = v1;
|
||||
|
||||
@@ -69,12 +69,24 @@ void arm_fxtract(x86emu_t* emu)
|
||||
}
|
||||
void arm_fprem(x86emu_t* emu)
|
||||
{
|
||||
int64_t tmp64s = ST0.d / ST1.d;
|
||||
ST0.d -= ST1.d * tmp64s;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (tmp64s&1);
|
||||
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
|
||||
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
|
||||
int e0, e1;
|
||||
int64_t ll;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
int32_t tmp32s = e0 - e1;
|
||||
if(tmp32s<64)
|
||||
{
|
||||
ll = (int64_t)floor(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
}
|
||||
void arm_frndint(x86emu_t* emu)
|
||||
{
|
||||
@@ -179,13 +191,13 @@ void arm_ud(x86emu_t* emu)
|
||||
void arm_priv(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
}
|
||||
|
||||
void arm_singlestep(x86emu_t* emu)
|
||||
{
|
||||
emu->test.test = 0;
|
||||
emit_signal(emu, SIGTRAP, (void*)R_EIP, 1);
|
||||
emit_signal(emu, SIGTRAP, (void*)R_EIP, 2);
|
||||
}
|
||||
|
||||
void arm_fsave(x86emu_t* emu, uint8_t* ed)
|
||||
@@ -214,13 +226,179 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
|
||||
|
||||
void arm_fprem1(x86emu_t* emu)
|
||||
{
|
||||
// simplified version
|
||||
int64_t tmp64s = lrint(ST0.d / ST1.d);
|
||||
ST0.d -= ST1.d*tmp64s;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (tmp64s&1);
|
||||
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
|
||||
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
|
||||
int e0, e1;
|
||||
int64_t ll;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
int32_t tmp32s = e0 - e1;
|
||||
if(tmp32s<64)
|
||||
{
|
||||
ll = (int64_t)round(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if((b & 1) == 1)
|
||||
retval ^= a;
|
||||
|
||||
if((a & 0x80)) {
|
||||
a <<= 1;
|
||||
a ^= 0x1b;
|
||||
} else {
|
||||
a <<= 1;
|
||||
}
|
||||
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void arm_aesimc(x86emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesmc(x86emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesdlast(x86emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A N K H E B O L I F C P M J G D
|
||||
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
|
||||
const uint8_t invsubbytes[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
|
||||
|
||||
}
|
||||
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
|
||||
static const uint8_t subbytes[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
void arm_aeselast(x86emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A F K P E J O D I N C H M B G L
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
|
||||
}
|
||||
void arm_aesd(x86emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aesdlast(emu, xmm);
|
||||
arm_aesimc(emu, xmm);
|
||||
}
|
||||
void arm_aese(x86emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aeselast(emu, xmm);
|
||||
arm_aesmc(emu, xmm);
|
||||
}
|
||||
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8)
|
||||
{
|
||||
sse_regs_t *EX = ((uintptr_t)p>8)?((sse_regs_t*)p):&emu->xmm[(uintptr_t)p];
|
||||
sse_regs_t *GX = &emu->xmm[gx];
|
||||
for (int i = 4; i < 8; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
for (int i = 12; i < 16; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
GX->ud[0] = GX->ud[1];
|
||||
uint8_t tmp8u = GX->ub[4];
|
||||
GX->ud[1] = GX->ud[1] >> 8;
|
||||
GX->ub[7] = tmp8u;
|
||||
GX->ud[1] ^= u8;
|
||||
GX->ud[2] = GX->ud[3];
|
||||
tmp8u = GX->ub[12];
|
||||
GX->ud[3] = GX->ud[3] >> 8;
|
||||
GX->ub[15] = tmp8u;
|
||||
GX->ud[3] ^= u8;
|
||||
}
|
||||
|
||||
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8)
|
||||
{
|
||||
int ex = (((uintptr_t)p)<8)?((uintptr_t)p):-1;
|
||||
sse_regs_t *EX = (ex==-1)?((sse_regs_t*)p):&emu->xmm[ex];
|
||||
sse_regs_t *GX = &emu->xmm[gx];
|
||||
int g = (u8&1)?1:0;
|
||||
int e = (u8&0b10000)?1:0;
|
||||
uint64_t result[2] = {0};
|
||||
uint64_t op2 = EX->q[e];
|
||||
for (int i=0; i<64; ++i)
|
||||
if(GX->q[g]&(1LL<<i)) {
|
||||
result[0] ^= (EX->q[e]<<i);
|
||||
if(i)
|
||||
result[1] ^= (EX->q[e]>>(64-i));
|
||||
|
||||
}
|
||||
GX->q[0] = result[0];
|
||||
GX->q[1] = result[1];
|
||||
}
|
||||
|
||||
void arm_clflush(x86emu_t* emu, void* p)
|
||||
@@ -714,6 +892,12 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
// return Ib on a mod/rm opcode without emiting anything
|
||||
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
{
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
return F8;
|
||||
}
|
||||
#undef F8
|
||||
#undef F32
|
||||
|
||||
@@ -763,35 +947,27 @@ static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
return 0;
|
||||
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
|
||||
return 0;
|
||||
/* if((dyn->f.pending!=SF_SET)
|
||||
&& (dyn->f.pending!=SF_SET_PENDING)) {
|
||||
if(dyn->f.pending!=SF_PENDING) {*/
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: return 0;
|
||||
case SF_SET:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
case SF_SET_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
case SF_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
|
||||
return 1;
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: return 0;
|
||||
case SF_SET:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
case SF_SET_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
|
||||
return 0;
|
||||
return 1;
|
||||
case SF_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending==SF_PENDING || dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
|
||||
return 0;
|
||||
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
int ret = 0;
|
||||
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
|
||||
|
||||
@@ -23,6 +23,14 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_frstor(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fprem1(x86emu_t* emu);
|
||||
|
||||
void arm_aesd(x86emu_t* emu, int xmm);
|
||||
void arm_aese(x86emu_t* emu, int xmm);
|
||||
void arm_aesdlast(x86emu_t* emu, int xmm);
|
||||
void arm_aeselast(x86emu_t* emu, int xmm);
|
||||
void arm_aesimc(x86emu_t* emu, int xmm);
|
||||
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8);
|
||||
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8);
|
||||
|
||||
void arm_clflush(x86emu_t* emu, void* p);
|
||||
|
||||
int64_t arm_fist64_0(double d);
|
||||
@@ -83,6 +91,7 @@ int getNominalPred(dynarec_arm_t* dyn, int ninst);
|
||||
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
|
||||
// Do the GETED, but don't emit anything...
|
||||
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
|
||||
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
|
||||
|
||||
// Is what pointed at addr a native call? And if yes, to what function?
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
|
||||
|
||||
@@ -40,6 +40,9 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
if(hint>0 && hint<xEAX) scratch = hint;
|
||||
if(hint==xEIP) scratch = hint; // allow this one as a scratch and return register
|
||||
MAYUSE(scratch);
|
||||
|
||||
if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
|
||||
|
||||
if(!(nextop&0xC0)) {
|
||||
if((nextop&7)==4) {
|
||||
uint8_t sib = F8;
|
||||
@@ -1049,8 +1052,10 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
if(ret==-1) // nothing to do
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
|
||||
int reg = dyn->n.x87reg[ret];
|
||||
#if STEP == 1
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F)
|
||||
neoncache_promote_double(dyn, ninst, st);
|
||||
#endif
|
||||
// prepare offset to fpu => s1
|
||||
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
|
||||
@@ -1062,11 +1067,17 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
|
||||
}
|
||||
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
|
||||
VSTR_64(dyn->n.x87reg[ret], s2, 0); // save the value
|
||||
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
|
||||
// this should not happens
|
||||
VCVT_F64_F32(0, reg*2); // use D0 as scratch...
|
||||
VSTR_64(0, s2, 0);
|
||||
} else {
|
||||
VSTR_64(reg, s2, 0); // save the value
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t--------Forget x87 Cache for ST%d\n", st);
|
||||
// and forget that cache
|
||||
fpu_free_reg_double(dyn, dyn->n.x87reg[ret]);
|
||||
dyn->n.neoncache[dyn->n.x87reg[ret]].v = 0;
|
||||
fpu_free_reg_double(dyn, reg);
|
||||
dyn->n.neoncache[reg].v = 0;
|
||||
dyn->n.x87cache[ret] = -1;
|
||||
dyn->n.x87reg[ret] = -1;
|
||||
}
|
||||
@@ -1336,6 +1347,26 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
dyn->n.ssecache[a].write = 1; // it will be write...
|
||||
return dyn->n.ssecache[a].reg;
|
||||
}
|
||||
// forget neon register for a SSE reg
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1)
|
||||
{
|
||||
if(dyn->n.ssecache[a].v==-1)
|
||||
return;
|
||||
if(dyn->n.neoncache[dyn->n.ssecache[a].reg+0-FPUFIRST].t == NEON_CACHE_XMMW) {
|
||||
int offs = offsetof(x86emu_t, xmm[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
VST1Q_64(dyn->n.ssecache[a].reg, s1);
|
||||
}
|
||||
fpu_free_reg_quad(dyn, dyn->n.ssecache[a].reg);
|
||||
dyn->n.ssecache[a].v = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// purge the SSE cache only(needs 1 scratch registers)
|
||||
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
|
||||
{
|
||||
@@ -1394,6 +1425,24 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
}
|
||||
}
|
||||
|
||||
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1)
|
||||
{
|
||||
if(dyn->n.ssecache[a].v==-1)
|
||||
return 0;
|
||||
if(dyn->n.ssecache[a].write) {
|
||||
int offs = offsetof(x86emu_t, xmm[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
VST1Q_32(dyn->n.ssecache[a].reg, s1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
// only need to push 16-31...
|
||||
@@ -1846,7 +1895,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
|
||||
int go = 0;
|
||||
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: break;
|
||||
case SF_SET:
|
||||
@@ -1864,12 +1913,10 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
&& dyn->f.pending!=SF_SET_PENDING
|
||||
&& dyn->f.pending!=SF_PENDING)
|
||||
go = 1;
|
||||
else
|
||||
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
|
||||
else if(dyn->insts[jmp].f_entry.dfnone!=dyn->f.dfnone)
|
||||
go = 1;
|
||||
break;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
|
||||
go = 1;
|
||||
if(go) {
|
||||
if(dyn->f.pending!=SF_PENDING) {
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
|
||||
|
||||
@@ -27,29 +27,34 @@
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
#define PKa(a) *(uint8_t*)(a)
|
||||
|
||||
#define MODREG ((nextop&0xC0)==0xC0)
|
||||
|
||||
// Strong mem emulation helpers
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
|
||||
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
|
||||
#define SMREAD_MIN 2
|
||||
#define SMWRITE_MIN 1
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
|
||||
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
|
||||
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
|
||||
// Opcode will read
|
||||
#define SMREAD() if(!dyn->smread && box86_dynarec_strongmem>1) {SMDMB();}
|
||||
#define SMREAD() if((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
|
||||
// Opcode will read with option forced lock
|
||||
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box86_dynarec_strongmem>1)) {SMDMB();}
|
||||
// Opcode migh read (depend on nextop)
|
||||
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
|
||||
// Opcode might read (depend on nextop)
|
||||
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
|
||||
// Opcode has wrote
|
||||
#define SMWRITE() dyn->smwrite=1
|
||||
// Opcode has wrote (strongmem>1 only)
|
||||
#define SMWRITE2() if(box86_dynarec_strongmem>1) dyn->smwrite=1
|
||||
#define SMWRITE2() if(box86_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
|
||||
// Opcode has wrote with option forced lock
|
||||
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode migh have wrote (depend on nextop)
|
||||
#define SMWRITELOCK(lock) if(lock || (box86_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode might have wrote (depend on nextop)
|
||||
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
|
||||
// Start of sequence
|
||||
#define SMSTART() SMEND()
|
||||
// End of sequence
|
||||
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
|
||||
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
|
||||
// Force a Data memory barrier (for LOCK: prefix)
|
||||
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
|
||||
#define SMDMB() if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
|
||||
|
||||
//LOCK_* define
|
||||
#define LOCK_LOCK (int*)1
|
||||
@@ -120,6 +125,8 @@
|
||||
}
|
||||
// GETGW extract x86 register in gd, that is i
|
||||
#define GETGW(i) gd = xEAX+((nextop&0x38)>>3); UXTH(i, gd, 0); gd = i;
|
||||
// GETSGW extract x86 signed register in gd, that is i
|
||||
#define GETSGW(i) gd = xEAX+((nextop&0x38)>>3); SXTH(i, gd, 0); gd = i;
|
||||
//GETEWW will use i for ed, and can use w for wback.
|
||||
#define GETEWW(w, i) if((nextop&0xC0)==0xC0) { \
|
||||
wback = xEAX+(nextop&7);\
|
||||
@@ -335,7 +342,17 @@
|
||||
|
||||
|
||||
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
|
||||
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
|
||||
#define SET_DF(S, N) \
|
||||
if(N) { \
|
||||
MOVW(S, N);\
|
||||
STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); \
|
||||
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x86.need_after && !(dyn->insts[ninst].x86.need_after&X_PEND)) { \
|
||||
CALL_(UpdateFlags, -1, 0); \
|
||||
dyn->f.pending = SF_SET; \
|
||||
SET_NODF(); \
|
||||
} \
|
||||
dyn->f.dfnone=0;\
|
||||
} else SET_DFNONE(S)
|
||||
#define SET_NODF() dyn->f.dfnone = 0
|
||||
#define SET_DFOK() dyn->f.dfnone = 1
|
||||
|
||||
@@ -377,7 +394,7 @@
|
||||
} else dyn->f.pending = SF_SET
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
#define JUMP(A, C)
|
||||
#define JUMP(A, C) SMEND()
|
||||
#endif
|
||||
#ifndef BARRIER
|
||||
#define BARRIER(A)
|
||||
@@ -512,10 +529,24 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define emit_shr32 STEPNAME(emit_shr32)
|
||||
#define emit_shr32c STEPNAME(emit_shr32c)
|
||||
#define emit_sar32c STEPNAME(emit_sar32c)
|
||||
#define emit_shl8 STEPNAME(emit_shl8)
|
||||
#define emit_shl8c STEPNAME(emit_shl8c)
|
||||
#define emit_shr8 STEPNAME(emit_shr8)
|
||||
#define emit_shr8c STEPNAME(emit_shr8c)
|
||||
#define emit_sar8 STEPNAME(emit_sar8)
|
||||
#define emit_sar8c STEPNAME(emit_sar8c)
|
||||
#define emit_shl16 STEPNAME(emit_shl16)
|
||||
#define emit_shl16c STEPNAME(emit_shl16c)
|
||||
#define emit_shr16 STEPNAME(emit_shr16)
|
||||
#define emit_shr16c STEPNAME(emit_shr16c)
|
||||
#define emit_sar16 STEPNAME(emit_sar16)
|
||||
#define emit_sar16c STEPNAME(emit_sar16c)
|
||||
#define emit_rol32c STEPNAME(emit_rol32c)
|
||||
#define emit_rol8c STEPNAME(emit_rol8c)
|
||||
#define emit_ror32c STEPNAME(emit_ror32c)
|
||||
#define emit_ror8c STEPNAME(emit_ror8c)
|
||||
#define emit_rol16c STEPNAME(emit_rol16c)
|
||||
#define emit_ror16c STEPNAME(emit_ror16c)
|
||||
#define emit_shrd32c STEPNAME(emit_shrd32c)
|
||||
#define emit_shld32c STEPNAME(emit_shld32c)
|
||||
#define emit_shrd32 STEPNAME(emit_shrd32)
|
||||
@@ -545,6 +576,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
|
||||
#define sse_get_reg STEPNAME(sse_get_reg)
|
||||
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
|
||||
#define sse_forget_reg STEPNAME(sse_forget_reg)
|
||||
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
@@ -648,10 +681,24 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
@@ -740,6 +787,10 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// forget an SSE reg
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
|
||||
// sync reg with emu for sse reg (return 1 if reflect was done, s1 = &xmm[a] then)
|
||||
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
|
||||
|
||||
// common coproc helpers
|
||||
// reset the cache
|
||||
|
||||
@@ -187,12 +187,8 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
{
|
||||
ok = 1;
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
reset_n = -2;
|
||||
for(int ii=0; ii<ninst; ++ii)
|
||||
if(dyn->insts[ii].x86.jmp == next) {
|
||||
reset_n = ii;
|
||||
ii=ninst;
|
||||
}
|
||||
// and pred table is not ready yet
|
||||
reset_n = get_first_jump(dyn, next);
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
|
||||
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#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 \
|
||||
@@ -40,7 +40,7 @@
|
||||
#define DEFAULT \
|
||||
--dyn->size; \
|
||||
*ok = -1; \
|
||||
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
|
||||
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump || box86_dynarec_missing) {\
|
||||
dynarec_log(LOG_NONE, "%p: Dynarec stopped @ %s (%s:%u) because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
|
||||
(void*)ip, __FUNCTION__, __FILE__, __LINE__, PKip(0), \
|
||||
PKip(1), PKip(2), PKip(3), \
|
||||
|
||||
@@ -97,6 +97,9 @@ typedef struct dynarec_arm_s {
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
int next_sz;
|
||||
int next_cap;
|
||||
int* jmps; // variable array of jump instructions
|
||||
int jmp_sz;
|
||||
int jmp_cap;
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
@@ -112,6 +115,8 @@ typedef struct dynarec_arm_s {
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
void add_jump(dynarec_arm_t *dyn, int ninst);
|
||||
int get_first_jump(dynarec_arm_t *dyn, int next);
|
||||
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
|
||||
@@ -45,7 +45,9 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
|
||||
GO(SHT_GNU_ATTRIBUTES);
|
||||
GO(SHT_GNU_HASH);
|
||||
GO(SHT_GNU_LIBLIST);
|
||||
GO(SHT_CHECKSUM);
|
||||
#ifndef TERMUX
|
||||
GO(SHT_CHECKSUM);
|
||||
#endif
|
||||
GO(SHT_LOSUNW);
|
||||
//GO(SHT_SUNW_move);
|
||||
GO(SHT_SUNW_COMDAT);
|
||||
|
||||
+182
-214
@@ -67,6 +67,9 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
|
||||
h->globaldefver = NewDefaultVersion();
|
||||
h->weakdefver = NewDefaultVersion();
|
||||
h->refcnt = 1;
|
||||
|
||||
h->file = f;
|
||||
h->fileno = fileno(f);
|
||||
|
||||
return h;
|
||||
}
|
||||
@@ -98,6 +101,8 @@ void FreeElfHeader(elfheader_t** head)
|
||||
|
||||
box_free(h->name);
|
||||
box_free(h->path);
|
||||
if(h->file)
|
||||
fclose(h->file);
|
||||
box_free(h);
|
||||
|
||||
*head = NULL;
|
||||
@@ -167,196 +172,159 @@ const char* ElfPath(elfheader_t* head)
|
||||
return NULL;
|
||||
return head->path;
|
||||
}
|
||||
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
#define ALIGN(p) (((p)+box86_pagesize-1)&~(box86_pagesize-1))
|
||||
int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
{
|
||||
uintptr_t offs = 0;
|
||||
loadProtectionFromMap();
|
||||
int log_level = box86_load_addr?LOG_INFO:LOG_DEBUG;
|
||||
|
||||
head->multiblock_n = 0; // count PHEntrie with LOAD
|
||||
uintptr_t max_align = (box86_pagesize-1);
|
||||
for (size_t i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
|
||||
if(max_align < head->PHEntries[i].p_align-1)
|
||||
max_align = head->PHEntries[i].p_align-1;
|
||||
++head->multiblock_n;
|
||||
}
|
||||
|
||||
if(!head->vaddr && box86_load_addr) {
|
||||
offs = (uintptr_t)findBlockNearHint((void*)box86_load_addr, head->memsz);
|
||||
box86_load_addr += head->memsz*(1+mainbin);
|
||||
box86_load_addr = (box86_load_addr+0xffffffLL)&~0xffffffLL;
|
||||
offs = (uintptr_t)findBlockNearHint((void*)box86_load_addr, head->memsz, max_align);
|
||||
box86_load_addr = offs + head->memsz;
|
||||
box86_load_addr = (box86_load_addr+0x10ffffff)&~0xffffff;
|
||||
}
|
||||
int log_level = box86_load_addr?LOG_INFO:LOG_NEVER;
|
||||
if(!offs)
|
||||
offs = head->vaddr;
|
||||
if(head->vaddr) {
|
||||
head->multiblock_n = 0; // count PHEntrie with LOAD
|
||||
for (int i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
|
||||
++head->multiblock_n;
|
||||
head->multiblock_size = (uint32_t*)box_calloc(head->multiblock_n, sizeof(uint32_t));
|
||||
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
|
||||
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
|
||||
// and now, create all individual blocks
|
||||
head->memory = (char*)0xffffffff;
|
||||
int n = 0;
|
||||
for (int i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
uintptr_t bstart = e->p_vaddr;
|
||||
uint32_t bsize = e->p_memsz;
|
||||
uintptr_t balign = e->p_align;
|
||||
if (balign) balign = balign-1; else balign = 1;
|
||||
if(balign<4095) balign = 4095;
|
||||
uintptr_t bend = (bstart + bsize + balign)&(~balign);
|
||||
bstart &= ~balign;
|
||||
int ok = 0;
|
||||
for (int j=0; !ok && j<n; ++j) {
|
||||
uintptr_t start = head->multiblock_offs[j];
|
||||
uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
|
||||
start &= ~balign;
|
||||
if( (head->e_type == ET_DYN) ||
|
||||
(((bstart>=start) && (bstart<=end)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
|
||||
{
|
||||
// merge
|
||||
ok = 1;
|
||||
if(bstart<start)
|
||||
head->multiblock_offs[j] = bstart;
|
||||
head->multiblock_size[j] = ((bend>end)?bend:end) - head->multiblock_offs[j];
|
||||
--head->multiblock_n;
|
||||
}
|
||||
}
|
||||
if(!ok) {
|
||||
head->multiblock_offs[n] = bstart;
|
||||
head->multiblock_size[n] = bend - head->multiblock_offs[n];
|
||||
++n;
|
||||
}
|
||||
}
|
||||
head->multiblock_n = n; // might be less in fact
|
||||
for (int i=0; i<head->multiblock_n; ++i) {
|
||||
if(!offs && !head->vaddr)
|
||||
offs = (uintptr_t)find32bitBlockElf(head->memsz, mainbin, max_align);
|
||||
|
||||
uintptr_t sz = head->multiblock_size[i];
|
||||
if(my_context->elfsize==1) {
|
||||
if(head->multiblock_n==1)
|
||||
head->reserve = 2*1024*1024; // reserve 2Mb after bss
|
||||
sz+=head->reserve;
|
||||
}
|
||||
printf_dump(log_level, "Allocating 0x%x memory %p for Elf \"%s\"\n", sz, (void*)head->multiblock_offs[i], head->name);
|
||||
void* p = mmap((void*)head->multiblock_offs[i], sz
|
||||
, PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
, MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
|
||||
, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
|
||||
return 1;
|
||||
}
|
||||
if(head->multiblock_offs[i] &&( p!=(void*)head->multiblock_offs[i])) {
|
||||
if((head->e_type!=ET_DYN)) {
|
||||
printf_log(LOG_NONE, "Error, memory map (%p 0x%zx/0x%zx) for elf \"%s\" allocated %p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p);
|
||||
return 1;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Allocated memory is not at hinted %p but %p (size %p) \"%s\"\n", (void*)head->multiblock_offs[i], p, (void*)head->multiblock_size[i], head->name);
|
||||
// need to adjust vaddr!
|
||||
for (int i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
if(e->p_vaddr>=head->multiblock_offs[i] && e->p_vaddr<(head->multiblock_offs[i]+head->multiblock_size[i])) {
|
||||
e->p_vaddr = e->p_vaddr - head->multiblock_offs[i] + (uintptr_t)p;
|
||||
if(!head->delta) head->delta = (intptr_t)p - (intptr_t)head->multiblock_offs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setProtection((uintptr_t)p, head->multiblock_size[i], PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
head->multiblock[i] = p;
|
||||
if(p<(void*)head->memory)
|
||||
head->memory = (char*)p;
|
||||
}
|
||||
} else {
|
||||
// vaddr is 0, load everything has a One block
|
||||
printf_dump(log_level, "Allocating 0x%zx memory %p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
|
||||
void* p = mmap((void*)offs, head->memsz
|
||||
, PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
|
||||
, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
|
||||
return 1;
|
||||
}
|
||||
if(offs && (p!=(void*)offs) && (head->e_type!=ET_DYN)) {
|
||||
printf_log(LOG_NONE, "Error, memory map (%p 0x%zx/0x%zx) for elf \"%s\" allocated %p\n", (void*)offs, head->memsz, head->align, head->name, p);
|
||||
return 1;
|
||||
}
|
||||
setProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
head->memory = p;
|
||||
memset(p, 0, head->memsz);
|
||||
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
|
||||
printf_dump(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta);
|
||||
|
||||
head->multiblock_n = 1;
|
||||
head->multiblock_size = (uint32_t*)box_calloc(head->multiblock_n, sizeof(uint32_t));
|
||||
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
|
||||
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
|
||||
head->multiblock_size[0] = head->memsz;
|
||||
head->multiblock_offs[0] = (uintptr_t)p;
|
||||
head->multiblock[0] = p;
|
||||
// prereserve the whole elf image, without populating
|
||||
void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
if(image!=MAP_FAILED && head->vaddr && image!=(void*)offs && (((uintptr_t)image)&max_align)) {
|
||||
munmap(image, head->memsz);
|
||||
image = mmap64(find32bitBlockElf(head->memsz, mainbin, max_align), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
|
||||
}
|
||||
if(image!=MAP_FAILED && !head->vaddr && image!=(void*)offs) {
|
||||
offs = (uintptr_t)image;
|
||||
printf_log(LOG_INFO, "Mamp64 for (@%p 0x%zx) for elf \"%s\" returned %p instead", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image);
|
||||
}
|
||||
if(image==MAP_FAILED || image!=(void*)(head->vaddr?head->vaddr:offs)) {
|
||||
printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name);
|
||||
if(image==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
|
||||
} else {
|
||||
printf_log(LOG_NONE, " got %p\n", image);
|
||||
}
|
||||
if(image==MAP_FAILED)
|
||||
return 1;
|
||||
offs = (uintptr_t)image-head->vaddr;
|
||||
}
|
||||
printf_log(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
|
||||
head->delta = offs;
|
||||
printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\" (0x%zx bytes)\n", (void*)offs, (void*)head->vaddr, head->name, head->memsz);
|
||||
|
||||
head->image = image;
|
||||
setProtection_elf((uintptr_t)image, head->memsz, 0);
|
||||
|
||||
head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
|
||||
head->tlsbase = AddTLSPartition(context, head->tlssize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FreeElfMemory(elfheader_t* head)
|
||||
{
|
||||
if(head->multiblock_n) {
|
||||
if(head->multiblock_n==1)
|
||||
munmap(head->multiblock[0], head->multiblock_size[0]+head->reserve);
|
||||
else
|
||||
for(int i=0; i<head->multiblock_n; ++i)
|
||||
munmap(head->multiblock[i], head->multiblock_size[i]);
|
||||
#ifdef DYNAREC
|
||||
for(int i=0; i<head->multiblock_n; ++i) {
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
|
||||
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
|
||||
}
|
||||
#endif
|
||||
box_free(head->multiblock);
|
||||
box_free(head->multiblock_size);
|
||||
box_free(head->multiblock_offs);
|
||||
}
|
||||
}
|
||||
|
||||
int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
{
|
||||
for (int i=0; i<head->numPHEntries; ++i) {
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
// and now, create all individual blocks
|
||||
head->memory = (char*)0xffffffff;
|
||||
int n = 0;
|
||||
for (size_t i=0; i<head->numPHEntries; ++i) {
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
void* p = (void*)-1;
|
||||
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
|
||||
printf_dump(LOG_NEVER, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
|
||||
p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
|
||||
|
||||
head->multiblocks[n].flags = e->p_flags;
|
||||
head->multiblocks[n].offs = e->p_offset;
|
||||
head->multiblocks[n].paddr = e->p_paddr + offs;
|
||||
head->multiblocks[n].size = e->p_filesz;
|
||||
head->multiblocks[n].align = e->p_align;
|
||||
uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0);
|
||||
// check if alignment is correct
|
||||
uintptr_t balign = head->multiblocks[n].align-1;
|
||||
if(balign<(box86_pagesize-1)) balign = (box86_pagesize-1);
|
||||
head->multiblocks[n].asize = ALIGN(e->p_memsz+(e->p_paddr&balign));
|
||||
int try_mmap = 1;
|
||||
if(e->p_paddr&balign)
|
||||
try_mmap = 0;
|
||||
if(e->p_offset&(box86_pagesize-1))
|
||||
try_mmap = 0;
|
||||
if(e->p_memsz-e->p_filesz>(box86_pagesize-1))
|
||||
try_mmap = 0;
|
||||
if(!e->p_filesz)
|
||||
try_mmap = 0;
|
||||
if(try_mmap) {
|
||||
printf_log(log_level, "Mmaping 0x%zx memory @%p for Elf \"%s\"\n", head->multiblocks[n].size, (void*)head->multiblocks[n].paddr, head->name);
|
||||
void* p = mmap64(
|
||||
(void*)head->multiblocks[n].paddr,
|
||||
head->multiblocks[n].size,
|
||||
prot,
|
||||
MAP_PRIVATE|MAP_FIXED,
|
||||
head->fileno,
|
||||
e->p_offset
|
||||
);
|
||||
if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) {
|
||||
try_mmap = 0;
|
||||
printf_log(log_level, "Mapping failed, using regular mmap+read");
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(log_level, " err=%d/%s\n", errno, strerror(errno));
|
||||
} else {
|
||||
printf_log(log_level, " got %p instead\n", p);
|
||||
}
|
||||
} else {
|
||||
setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot);
|
||||
head->multiblocks[n].p = p;
|
||||
|
||||
}
|
||||
}
|
||||
if(p!=dest) {
|
||||
printf_dump(LOG_NEVER, "Loading block #%d %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(!try_mmap) {
|
||||
uintptr_t paddr = head->multiblocks[n].paddr&~balign;
|
||||
size_t asize = head->multiblocks[n].asize;
|
||||
printf_log(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
|
||||
void* p = mmap64(
|
||||
(void*)paddr,
|
||||
asize,
|
||||
prot,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
if(p==MAP_FAILED || p!=(void*)paddr) {
|
||||
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name);
|
||||
if(p==MAP_FAILED) {
|
||||
printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
|
||||
} else {
|
||||
printf_log(LOG_NONE, " got %p\n", p);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
setProtection_elf((uintptr_t)p, asize, prot);
|
||||
head->multiblocks[n].p = p;
|
||||
if(e->p_filesz) {
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%zd)\n", i, e->p_filesz);
|
||||
fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET);
|
||||
if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) {
|
||||
printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec && (e->p_flags & PF_X)) {
|
||||
printf_dump(LOG_NEVER, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
|
||||
addDBFromAddressRange((uintptr_t)dest, e->p_memsz);
|
||||
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", head->multiblocks[n].p, (void*)head->multiblocks[n].asize);
|
||||
addDBFromAddressRange((uintptr_t)head->multiblocks[n].p, head->multiblocks[n].asize);
|
||||
}
|
||||
#endif
|
||||
|
||||
// zero'd difference between filesz and memsz
|
||||
/*if(e->p_filesz != e->p_memsz)
|
||||
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation
|
||||
if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p)
|
||||
head->memory = (char*)head->multiblocks[n].p;
|
||||
++n;
|
||||
}
|
||||
if(head->PHEntries[i].p_type == PT_TLS) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase);
|
||||
printf_dump(LOG_NEVER, "Loading TLS block #%i %p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
if(e->p_filesz) {
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_TLS part #%d (size=%zd)\n", i, e->p_filesz);
|
||||
fseeko64(head->file, e->p_offset, SEEK_SET);
|
||||
if(fread(dest, e->p_filesz, 1, head->file)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -365,9 +333,34 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
// can close the elf file now!
|
||||
fclose(head->file);
|
||||
head->file = NULL;
|
||||
head->fileno = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FreeElfMemory(elfheader_t* head)
|
||||
{
|
||||
if(head->multiblock_n) {
|
||||
#ifdef DYNAREC
|
||||
for(int i=0; i<head->multiblock_n; ++i) {
|
||||
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
|
||||
if(box86_dynarec)
|
||||
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1);
|
||||
freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize);
|
||||
}
|
||||
#endif
|
||||
box_free(head->multiblocks);
|
||||
}
|
||||
// we only need to free the overall mmap, no need to free individual part as they are inside the big one
|
||||
if(head->image && head->memsz)
|
||||
munmap(head->image, head->memsz);
|
||||
freeProtection((uintptr_t)head->image, head->memsz);
|
||||
}
|
||||
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
|
||||
{
|
||||
if(!verneeded || !head)
|
||||
@@ -385,37 +378,6 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
{
|
||||
(void)context;
|
||||
for (int i=0; i<head->numPHEntries; ++i) {
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
printf_log(LOG_DEBUG, "Re-loading block #%i %p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
int ret = fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(ret==-1) {printf_log(LOG_NONE, "Fail to (re)seek PT_LOAD part #%d (offset=%zd, errno=%d/%s)\n", i, e->p_offset, errno, strerror(errno)); return 1;}
|
||||
#ifdef DYNAREC
|
||||
cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
|
||||
#endif
|
||||
uint32_t page_offset = (uintptr_t)dest & (box86_pagesize - 1);
|
||||
mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
if(e->p_filesz) {
|
||||
ssize_t r = -1;
|
||||
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
|
||||
printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%d (dest=%p, size=%zd, return=%zd, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// zero'd difference between filesz and memsz
|
||||
if(e->p_filesz != e->p_memsz)
|
||||
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
|
||||
}
|
||||
}
|
||||
// TLS data are just a copy, no need to re-load it
|
||||
return 0;
|
||||
}
|
||||
int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t** p, size_t size, int version, const char* vername)
|
||||
{
|
||||
if(!h)
|
||||
@@ -496,7 +458,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
weakdefver = old_weakdefver;
|
||||
} else {
|
||||
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
}
|
||||
if(bind==STB_LOCAL) {
|
||||
if(!symname || !symname[0]) {
|
||||
@@ -526,9 +488,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end)
|
||||
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
} else {
|
||||
if(old_version==version && old_bind==bind && old_symname==symname) {
|
||||
@@ -607,13 +570,15 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}
|
||||
}*/
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
|
||||
printf_log((bind==STB_GLOBAL)?LOG_NONE:LOG_INFO, "%s: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", (bind==STB_GLOBAL)?"Error":"Warning", symname, p, *(void**)p, head->name);
|
||||
if(bind==STB_GLOBAL) ret_ok=1;
|
||||
}
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
*p = offs/* + rela[i].r_addend*/; // not addend it seems
|
||||
@@ -700,8 +665,8 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)(-(int32_t)offs + h_tls->tlsbase);
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, (int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)((int32_t)offs - h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
@@ -785,7 +750,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
weakdefver = old_weakdefver;
|
||||
} else {
|
||||
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
|
||||
}
|
||||
if(bind==STB_LOCAL) {
|
||||
if(!symname || !symname[0]) {
|
||||
@@ -824,9 +789,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
offs = old_offs;
|
||||
end = old_end;
|
||||
} else {
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end && local_maplib)
|
||||
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
if(!offs && !end)
|
||||
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -895,10 +861,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
*p = globoffs;
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
|
||||
offs = globoffs;
|
||||
end = globend;
|
||||
}
|
||||
}*/
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
@@ -986,8 +952,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int32_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)(-(int32_t)offs + rela[i].r_addend + h_tls->tlsbase);
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, (int32_t)offs, end-offs);
|
||||
*p = (uintptr_t)((int32_t)offs + rela[i].r_addend - h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
|
||||
}
|
||||
@@ -1103,7 +1069,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CalcStack(elfheader_t* elf, uint32_t* stacksz, uint32_t* stackalign)
|
||||
void CalcStack(elfheader_t* elf, uint32_t* stacksz, size_t* stackalign)
|
||||
{
|
||||
if(*stacksz < elf->stacksz)
|
||||
*stacksz = elf->stacksz;
|
||||
@@ -1557,8 +1523,8 @@ int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
|
||||
if(!h)
|
||||
return 0;
|
||||
for(int i=0; i<h->multiblock_n; ++i) {
|
||||
uintptr_t base = h->multiblock_offs[i];
|
||||
uintptr_t end = h->multiblock_offs[i] + h->multiblock_size[i] - 1;
|
||||
uintptr_t base = (uintptr_t)h->multiblocks[i].p;
|
||||
uintptr_t end = (uintptr_t)h->multiblocks[i].p + h->multiblocks[i].asize - 1;
|
||||
if(addr>=base && addr<=end)
|
||||
return 1;
|
||||
|
||||
@@ -1582,6 +1548,8 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
const char* ret = NULL;
|
||||
uintptr_t s = 0;
|
||||
uint32_t size = 0;
|
||||
if((uintptr_t)p<0x10000)
|
||||
return ret;
|
||||
#ifdef HAVE_TRACE
|
||||
if(!h) {
|
||||
if(getProtection((uintptr_t)p)&(PROT_READ)) {
|
||||
|
||||
@@ -8,7 +8,18 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
#include <elf.h>
|
||||
#include "elfloader.h"
|
||||
|
||||
struct elfheader_s {
|
||||
|
||||
typedef struct multiblock_s {
|
||||
void* p;
|
||||
uintptr_t offs;
|
||||
uintptr_t paddr;
|
||||
uintptr_t align;
|
||||
size_t size;
|
||||
size_t asize;
|
||||
uint8_t flags;
|
||||
} multiblock_t;
|
||||
|
||||
typedef struct elfheader_s {
|
||||
char* name;
|
||||
char* path; // Resolved path to file
|
||||
char* soname; // soname of the elf
|
||||
@@ -38,6 +49,7 @@ struct elfheader_s {
|
||||
uint32_t flags;
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
void* image;
|
||||
|
||||
uintptr_t entrypoint;
|
||||
uintptr_t initentry;
|
||||
@@ -92,20 +104,21 @@ struct elfheader_s {
|
||||
int malloc_hook_2; // this elf hook malloc, hacking it
|
||||
|
||||
char* memory; // char* and not void* to allow math on memory pointer
|
||||
void** multiblock;
|
||||
uintptr_t* multiblock_offs;
|
||||
uint32_t* multiblock_size;
|
||||
multiblock_t* multiblocks;
|
||||
int multiblock_n;
|
||||
|
||||
library_t *lib;
|
||||
needed_libs_t *needed;
|
||||
|
||||
FILE* file;
|
||||
int fileno;
|
||||
|
||||
kh_mapsymbols_t *mapsymbols;
|
||||
kh_mapsymbols_t *weaksymbols;
|
||||
kh_mapsymbols_t *localsymbols;
|
||||
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)
|
||||
};
|
||||
} elfheader_t;
|
||||
|
||||
#define R_386_NONE 0
|
||||
#define R_386_32 1
|
||||
|
||||
+19
-2
@@ -242,8 +242,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
|
||||
break;
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
if(val)
|
||||
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
|
||||
#ifndef ANDROID
|
||||
if(val)
|
||||
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
|
||||
#endif
|
||||
break;
|
||||
case DT_FINI: // Exit hook
|
||||
h->finientry = ptr;
|
||||
@@ -469,4 +471,19 @@ const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
|
||||
{
|
||||
if(!libname || !ver)
|
||||
return 0;
|
||||
int n = GetNeededVersionCnt(h, libname);
|
||||
if(!n)
|
||||
return 0;
|
||||
for(int i=0; i<n; ++i) {
|
||||
const char* vername = GetNeededVersionString(h, libname, i);
|
||||
if(vername && !strcmp(ver, vername))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+14
-13
@@ -21,6 +21,7 @@
|
||||
#endif
|
||||
|
||||
// ModRM utilities macros
|
||||
#define MODREG ((nextop&0xC0)==0xC0)
|
||||
#define getecommon(A, T) \
|
||||
if(!(nextop&0xC0)) { \
|
||||
if((nextop&7)==4) { \
|
||||
@@ -116,11 +117,11 @@
|
||||
|
||||
|
||||
#define geteb(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else getecommon(A, reg32_t)
|
||||
#define testeb(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
@@ -131,19 +132,19 @@
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getebo(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
} else getecommono(A, reg32_t, O)
|
||||
#define geted(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon(A, reg32_t)
|
||||
#define getedo(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommono(A, reg32_t, O)
|
||||
#define tested(A, SZ, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else {\
|
||||
reg32_t* ret; \
|
||||
@@ -154,11 +155,11 @@
|
||||
A = (reg32_t*)test->mem;\
|
||||
}
|
||||
#define getem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else getecommon(A, mmx87_regs_t)
|
||||
#define testem(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->mmx[(nextop&7)]; \
|
||||
} else {\
|
||||
mmx87_regs_t* ret; \
|
||||
@@ -169,11 +170,11 @@
|
||||
A = (mmx87_regs_t*)test->mem;\
|
||||
}
|
||||
#define getex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else getecommon(A, sse_regs_t)
|
||||
#define testex(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else {\
|
||||
sse_regs_t* ret; \
|
||||
@@ -184,15 +185,15 @@
|
||||
A = (sse_regs_t*)test->mem;\
|
||||
}
|
||||
#define getew16(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16(A, reg32_t)
|
||||
#define getew16o(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16o(A, reg32_t, O)
|
||||
#define testtew16(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
if(MODREG) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else { \
|
||||
reg32_t* ret; \
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86compstrings.h"
|
||||
|
||||
static int overrideIfDataInvalid(sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, int j, int i, int imm8)
|
||||
{
|
||||
int valid1 = (i<lreg);
|
||||
int valid2 = (j<lmem);
|
||||
if(!valid1 && !valid2)
|
||||
switch((imm8>>2)&3) {
|
||||
case 0b00:
|
||||
case 0b01: return 0;
|
||||
case 0b10:
|
||||
case 0b11: return 1;
|
||||
}
|
||||
if(!valid1 && valid2)
|
||||
switch((imm8>>2)&3) {
|
||||
case 0b00:
|
||||
case 0b01:
|
||||
case 0b10: return 0;
|
||||
case 0b11: return 1;
|
||||
}
|
||||
if(valid1 && !valid2)
|
||||
return 0;
|
||||
switch((imm8>>2)&3) {
|
||||
case 0b01: // range
|
||||
switch (imm8&3) {
|
||||
case 0b00: // ub
|
||||
return (i&1)?((reg->ub[i]>=mem->ub[j])):((reg->ub[i]<=mem->ub[j]));
|
||||
case 0b01: // uw
|
||||
return (i&1)?((reg->uw[i]>=mem->uw[j])):((reg->uw[i]<=mem->uw[j]));
|
||||
case 0b10: // sb
|
||||
return (i&1)?((reg->sb[i]>=mem->sb[j])):((reg->sb[i]<=mem->sb[j]));
|
||||
case 0b11: // sw
|
||||
return (i&1)?((reg->sw[i]>=mem->sw[j])):((reg->sw[i]<=mem->sw[j]));
|
||||
}
|
||||
break;
|
||||
default: // the others
|
||||
switch (imm8&1) {
|
||||
case 0: // byte
|
||||
return (reg->ub[i] == mem->ub[j]);
|
||||
case 1: // word
|
||||
return (reg->uw[i] == mem->uw[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, uint8_t imm8)
|
||||
{
|
||||
// get number of packed byte/word
|
||||
int n_packed = (imm8&1)?8:16;
|
||||
if(lreg<0) lreg = -lreg;
|
||||
if(lmem<0) lmem = -lmem;
|
||||
if(lreg>n_packed) lreg = n_packed;
|
||||
if(lmem>n_packed) lmem = n_packed;
|
||||
// aggregate to intres1
|
||||
uint32_t intres1 = 0;
|
||||
switch((imm8>>2)&3) {
|
||||
case 0b00: //Equal any
|
||||
for(int j=0; j<n_packed; ++j)
|
||||
for(int i=0; i<n_packed; ++i) {
|
||||
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8)<<j;
|
||||
}
|
||||
break;
|
||||
case 0b01: // Range
|
||||
for(int j=0; j<n_packed; ++j)
|
||||
for(int i=0; i<n_packed; i+=2) {
|
||||
intres1 |= (overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8) & overrideIfDataInvalid(mem, lmem, reg, lreg, j, i+1, imm8))<<j;
|
||||
}
|
||||
break;
|
||||
case 0b10: // Equal each
|
||||
for(int i=0; i<n_packed; ++i) {
|
||||
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, i, i, imm8)<<i;
|
||||
}
|
||||
break;
|
||||
case 0b11: // Equal ordered
|
||||
intres1 = (1<<n_packed)-1;
|
||||
for(int j=0; j<n_packed; ++j)
|
||||
for(int i=0; i<n_packed-j; ++i) {
|
||||
int k = i+j;
|
||||
intres1 &= (((1<<n_packed)-1)^(1<<j)) | overrideIfDataInvalid(mem, lmem, reg, lreg, k, i, imm8)<<j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// build intres2
|
||||
uint32_t intres2 = intres1;
|
||||
switch((imm8>>4)&3) {
|
||||
case 0b01: intres2 ^= ((1<<n_packed)-1); break;
|
||||
case 0b11: intres2 ^= ((1<<lmem)-1); break;
|
||||
}
|
||||
// and now set the flags
|
||||
RESET_FLAGS(emu);
|
||||
CONDITIONAL_SET_FLAG(intres2, F_CF);
|
||||
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
|
||||
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CLEAR_FLAG(F_PF);
|
||||
|
||||
return intres2;
|
||||
}
|
||||
|
||||
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* mem, sse_regs_t* reg, uint8_t imm8)
|
||||
{
|
||||
int lmem = 0;
|
||||
int lreg = 0;
|
||||
// get lmem and lreg
|
||||
if(imm8&1) {
|
||||
while(lmem<8 && mem->uw[lmem]) ++lmem;
|
||||
while(lreg<8 && reg->uw[lreg]) ++lreg;
|
||||
} else {
|
||||
while(lmem<16 && mem->ub[lmem]) ++lmem;
|
||||
while(lreg<16 && reg->ub[lreg]) ++lreg;
|
||||
}
|
||||
return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef __X86_CMPSTRINGS_H__
|
||||
#define __X86_CMPSTRINGS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "regs.h"
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* a, int la, sse_regs_t* b, int lb, uint8_t imm8);
|
||||
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8);
|
||||
|
||||
#endif //__X86_CMPSTRINGS_H__
|
||||
+3
-5
@@ -422,8 +422,6 @@ void UnimpOpcode(x86emu_t* emu)
|
||||
tid, (void*)emu->old_ip, Peek(emu, -1),
|
||||
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
|
||||
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
}
|
||||
|
||||
void EmuCall(x86emu_t* emu, uintptr_t addr)
|
||||
@@ -440,9 +438,9 @@ void EmuCall(x86emu_t* emu, uintptr_t addr)
|
||||
Run(emu, 0);
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
|
||||
if(emu->flags.quitonlongjmp==1)
|
||||
emu->flags.longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_EBX = old_ebx;
|
||||
R_EDI = old_edi;
|
||||
|
||||
@@ -34,6 +34,21 @@ typedef struct x86test_s {
|
||||
uint8_t mem[16];
|
||||
} x86test_t;
|
||||
|
||||
typedef struct emu_flags_s {
|
||||
uint32_t need_jmpbuf:1; // need a new jmpbuff for signal handling
|
||||
uint32_t quitonlongjmp:2; // quit if longjmp is called
|
||||
uint32_t quitonexit:2; // quit if exit/_exit is called
|
||||
uint32_t longjmp:1; // if quit because of longjmp
|
||||
uint32_t jmpbuf_ready:1; // the jmpbuf in the emu is ok and don't need refresh
|
||||
} emu_flags_t;
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <setjmp.h>
|
||||
#define JUMPBUFF sigjmp_buf
|
||||
#else
|
||||
#define JUMPBUFF struct __jmp_buf_tag
|
||||
#endif
|
||||
|
||||
typedef struct x86emu_s {
|
||||
// cpu
|
||||
reg32_t regs[8];
|
||||
@@ -63,17 +78,17 @@ typedef struct x86emu_s {
|
||||
uintptr_t prev2_ip, prev_ip;
|
||||
#endif
|
||||
// segments
|
||||
uint32_t segs[6]; // only 32bits value?
|
||||
uint16_t segs[6];
|
||||
uint16_t dummy_seg6, dummy_seg7; // to stay aligned
|
||||
uintptr_t segs_offs[6]; // computed offset associate with segment
|
||||
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
|
||||
// emu control
|
||||
int quit;
|
||||
int error;
|
||||
int fork; // quit because need to fork
|
||||
forkpty_t* forkpty_info;
|
||||
int exit;
|
||||
int quitonlongjmp; // quit if longjmp is called
|
||||
int longjmp; // if quit because of longjmp
|
||||
forkpty_t* forkpty_info;
|
||||
emu_flags_t flags;
|
||||
x86test_t test; // used for dynarec testing
|
||||
// parent context
|
||||
box86context_t *context;
|
||||
@@ -86,6 +101,7 @@ typedef struct x86emu_s {
|
||||
void* stack2free; // this is the stack to free (can be NULL)
|
||||
void* init_stack; // initial stack (owned or not)
|
||||
uint32_t size_stack; // stack size (owned or not)
|
||||
JUMPBUFF* jmpbuf;
|
||||
|
||||
i386_ucontext_t *uc_link; // to handle setcontext
|
||||
|
||||
|
||||
+3
-3
@@ -67,7 +67,7 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
|
||||
R_EAX = v;
|
||||
return emu;
|
||||
}
|
||||
|
||||
void emit_signal(x86emu_t* emu, int sig, void* addr, int code); // in signals.c
|
||||
extern int errno;
|
||||
void x86Int3(x86emu_t* emu)
|
||||
{
|
||||
@@ -350,8 +350,8 @@ void x86Int3(x86emu_t* emu)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(0 && my_context->signals[SIGTRAP])
|
||||
raise(SIGTRAP);
|
||||
if(1 && my_context->signals[SIGTRAP])
|
||||
emit_signal(emu, SIGTRAP, (void*)R_EIP, 128);
|
||||
else
|
||||
printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_EIP);
|
||||
//emu->quit = 1;
|
||||
|
||||
+19
-29
@@ -484,10 +484,8 @@ uint8_t rcl8(x86emu_t *emu, uint8_t d, uint8_t s)
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
/* OVERFLOW is set *IFF* cnt==1, then it is the
|
||||
xor of CF and the most significant bit. Blecck. */
|
||||
/* parenthesized this expression since it appears to
|
||||
be causing OF to be misset */
|
||||
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
|
||||
F_OF);
|
||||
if(cnt == 1)
|
||||
CONDITIONAL_SET_FLAG((cf ^ (res >> 7)) & 0x1, F_OF);
|
||||
|
||||
}
|
||||
return (uint8_t)res;
|
||||
@@ -513,8 +511,8 @@ uint16_t rcl16(x86emu_t *emu, uint16_t d, uint8_t s)
|
||||
res |= 1 << (cnt - 1);
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
|
||||
F_OF);
|
||||
if(cnt == 1)
|
||||
CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF);
|
||||
}
|
||||
return (uint16_t)res;
|
||||
}
|
||||
@@ -539,8 +537,8 @@ uint32_t rcl32(x86emu_t *emu, uint32_t d, uint8_t s)
|
||||
res |= 1 << (cnt - 1);
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
|
||||
F_OF);
|
||||
if(cnt == 1)
|
||||
CONDITIONAL_SET_FLAG((cf ^ (res >> 31)) & 0x1, F_OF);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -592,6 +590,11 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
|
||||
(i.e. packed bit array or unpacked.)
|
||||
*/
|
||||
ocf = ACCESS_FLAG(F_CF) != 0;
|
||||
/* OVERFLOW is set *IFF* cnt==1, then it is the
|
||||
xor of CF and the most significant bit. Blecck. */
|
||||
/* parenthesized... */
|
||||
CONDITIONAL_SET_FLAG((ocf ^ (d >> 7)) & 0x1,
|
||||
F_OF);
|
||||
} else
|
||||
cf = (d >> (cnt - 1)) & 0x1;
|
||||
|
||||
@@ -620,13 +623,6 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
|
||||
}
|
||||
/* set the new carry flag, based on the variable "cf" */
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
/* OVERFLOW is set *IFF* cnt==1, then it is the
|
||||
xor of CF and the most significant bit. Blecck. */
|
||||
/* parenthesized... */
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
|
||||
F_OF);
|
||||
}
|
||||
}
|
||||
return (uint8_t)res;
|
||||
}
|
||||
@@ -648,6 +644,8 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
|
||||
if (cnt == 1) {
|
||||
cf = d & 0x1;
|
||||
ocf = ACCESS_FLAG(F_CF) != 0;
|
||||
CONDITIONAL_SET_FLAG((ocf ^ (d >> 15)) & 0x1,
|
||||
F_OF);
|
||||
} else
|
||||
cf = (d >> (cnt - 1)) & 0x1;
|
||||
mask = (1 << (16 - cnt)) - 1;
|
||||
@@ -657,10 +655,6 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
|
||||
res |= 1 << (16 - cnt);
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
|
||||
F_OF);
|
||||
}
|
||||
}
|
||||
return (uint16_t)res;
|
||||
}
|
||||
@@ -682,6 +676,8 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
|
||||
if (cnt == 1) {
|
||||
cf = d & 0x1;
|
||||
ocf = ACCESS_FLAG(F_CF) != 0;
|
||||
CONDITIONAL_SET_FLAG((ocf ^ (d >> 31)) & 0x1,
|
||||
F_OF);
|
||||
} else
|
||||
cf = (d >> (cnt - 1)) & 0x1;
|
||||
mask = (1 << (32 - cnt)) - 1;
|
||||
@@ -692,10 +688,6 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
|
||||
res |= 1 << (32 - cnt);
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
|
||||
F_OF);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -885,8 +877,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
|
||||
res = d;
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
|
||||
(ACCESS_FLAG(F_CF) != 0)), F_OF);
|
||||
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
@@ -927,8 +918,7 @@ uint32_t shld32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
|
||||
res = d;
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
|
||||
(ACCESS_FLAG(F_CF) != 0)), F_OF);
|
||||
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
@@ -959,7 +949,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
|
||||
}
|
||||
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
|
||||
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
@@ -1005,7 +995,7 @@ uint32_t shrd32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
|
||||
res = d;
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
|
||||
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
|
||||
+63
-29
@@ -93,12 +93,14 @@ x86emurun:
|
||||
opcode = F8;
|
||||
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
while((opcode==0xF2) || (opcode==0xF3) || (opcode==0x3E)) {
|
||||
switch (opcode) {
|
||||
case 0xF2: rep = 1; break;
|
||||
case 0xF3: rep = 2; break;
|
||||
case 0x3E: /* ignored*/ break;
|
||||
}
|
||||
opcode = F8;
|
||||
}
|
||||
while((opcode==0x3E)) //Branch Taken Hint ignored
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -428,7 +430,7 @@ x86emurun:
|
||||
case 0x6F: /* OUTSD */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -568,7 +570,7 @@ x86emurun:
|
||||
nextop = F8;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GET_EB;
|
||||
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
|
||||
if(MODREG) { // reg / reg: no lock
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
@@ -594,7 +596,7 @@ x86emurun:
|
||||
nextop = F8;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GET_ED;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
@@ -644,7 +646,7 @@ x86emurun:
|
||||
case 0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
else
|
||||
ED->word[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
@@ -664,7 +666,7 @@ x86emurun:
|
||||
break;
|
||||
case 0x8F: /* POP Ed */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
emu->regs[(nextop&7)].dword[0] = Pop(emu);
|
||||
} else {
|
||||
tmp32u = Pop(emu); // this order allows handling POP [ESP] and variant
|
||||
@@ -704,15 +706,6 @@ x86emurun:
|
||||
case 0x9D: /* POPF */
|
||||
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
RESET_FLAGS(emu);
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(ACCESS_FLAG(F_TF)) {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
CLEAR_FLAG(F_TF);
|
||||
STEP;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x9E: /* SAHF */
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
@@ -845,6 +838,7 @@ x86emurun:
|
||||
}
|
||||
if(R_ECX) cmp32(emu, tmp32u2, tmp32u3);
|
||||
R_ECX = tmp32u;
|
||||
break;
|
||||
case 2:
|
||||
tmp32u2 = 0;
|
||||
tmp32u3 = 0;
|
||||
@@ -860,6 +854,7 @@ x86emurun:
|
||||
}
|
||||
if(R_ECX) cmp32(emu, tmp32u2, tmp32u3);
|
||||
R_ECX = tmp32u;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA8: /* TEST AL, Ib */
|
||||
@@ -1042,6 +1037,12 @@ x86emurun:
|
||||
break;
|
||||
case 0xC4: /* LES Gd,Ed */
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
UnimpOpcode(emu);
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
}
|
||||
GET_ED;
|
||||
emu->segs[_ES] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_ES] = 0;
|
||||
@@ -1049,6 +1050,12 @@ x86emurun:
|
||||
break;
|
||||
case 0xC5: /* LDS Gd,Ed */
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
UnimpOpcode(emu);
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
}
|
||||
GET_ED;
|
||||
emu->segs[_DS] = *(__uint16_t*)(((char*)ED)+4);
|
||||
emu->segs_serial[_DS] = 0;
|
||||
@@ -1116,7 +1123,7 @@ x86emurun:
|
||||
printf_log(LOG_DEBUG, "INT 2D called\n");
|
||||
} else {
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
if(emu->quit) goto fini;
|
||||
STEP;
|
||||
#endif
|
||||
@@ -1126,8 +1133,9 @@ x86emurun:
|
||||
case 0xCE: /* INTO */
|
||||
emu->old_ip = R_EIP;
|
||||
#ifndef TEST_INTERPRETER
|
||||
emit_signal(emu, SIGFPE, (void*)R_EIP, FPE_INTOVF);
|
||||
if(emu->quit) goto fini;
|
||||
CHECK_FLAGS(emu);
|
||||
if(ACCESS_FLAG(F_OF))
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -1339,7 +1347,7 @@ x86emurun:
|
||||
case 0xE7: /* OUT Ib, EAX */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -1347,6 +1355,7 @@ x86emurun:
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, addr);
|
||||
addr += tmp32s;
|
||||
addr = (uintptr_t)getAlternate((void*)addr);
|
||||
STEP2;
|
||||
break;
|
||||
case 0xE9: /* JMP Id */
|
||||
@@ -1367,7 +1376,7 @@ x86emurun:
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -1394,7 +1403,7 @@ x86emurun:
|
||||
case 0xF4: /* HLT */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -1425,9 +1434,13 @@ x86emurun:
|
||||
imul8(emu, EB->byte[0]);
|
||||
break;
|
||||
case 6: /* DIV Eb */
|
||||
if(!EB->byte[0])
|
||||
emit_div0(emu, (void*)R_EIP, 0);
|
||||
div8(emu, EB->byte[0]);
|
||||
break;
|
||||
case 7: /* IDIV Eb */
|
||||
if(!EB->byte[0])
|
||||
emit_div0(emu, (void*)R_EIP, 0);
|
||||
idiv8(emu, EB->byte[0]);
|
||||
break;
|
||||
}
|
||||
@@ -1454,9 +1467,13 @@ x86emurun:
|
||||
imul32_eax(emu, ED->dword[0]);
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
if(!ED->dword[0])
|
||||
emit_div0(emu, (void*)R_EIP, 0);
|
||||
div32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 7: /* IDIV Ed */
|
||||
if(!ED->dword[0])
|
||||
emit_div0(emu, (void*)R_EIP, 0);
|
||||
idiv32(emu, ED->dword[0]);
|
||||
break;
|
||||
}
|
||||
@@ -1474,7 +1491,7 @@ x86emurun:
|
||||
case 0xFB: /* STI */
|
||||
#ifndef TEST_INTERPRETER
|
||||
// this is a privilege opcode
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
|
||||
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
|
||||
STEP;
|
||||
#endif
|
||||
break;
|
||||
@@ -1530,7 +1547,7 @@ x86emurun:
|
||||
GET_ED_;
|
||||
Push(emu, R_CS);
|
||||
Push(emu, addr);
|
||||
addr = ED->dword[0];
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
R_CS = (ED+1)->word[0];
|
||||
goto fini; // in case there is a change of CS
|
||||
}
|
||||
@@ -1550,7 +1567,7 @@ x86emurun:
|
||||
goto fini;
|
||||
} else {
|
||||
GET_ED_;
|
||||
addr = ED->dword[0];
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
R_CS = (ED+1)->word[0];
|
||||
STEP2;
|
||||
}
|
||||
@@ -1574,15 +1591,32 @@ x86emurun:
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
#ifndef TEST_INTERPRETER
|
||||
if(ACCESS_FLAG(F_TF)) {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
}
|
||||
#endif
|
||||
R_EIP = addr;
|
||||
}
|
||||
|
||||
fini:
|
||||
#ifndef TEST_INTERPRETER
|
||||
// check the TRACE flag before going to out, in case it's a step by step scenario
|
||||
if(!emu->quit && !emu->fork && !emu->uc_link && ACCESS_FLAG(F_TF)) {
|
||||
R_EIP = addr;
|
||||
emit_signal(emu, SIGTRAP, (void*)addr, 1);
|
||||
if(emu->quit) goto fini;
|
||||
}
|
||||
#endif
|
||||
#ifndef TEST_INTERPRETER
|
||||
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_EIP, (void*)R_ESP, unimp, emu->fork, emu->uc_link, emu->quit);
|
||||
if(unimp) {
|
||||
emu->quit = 1;
|
||||
UnimpOpcode(emu);
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
}
|
||||
// fork handling
|
||||
if(emu->fork) {
|
||||
@@ -1596,7 +1630,7 @@ fini:
|
||||
goto x86emurun;
|
||||
}
|
||||
// setcontext handling
|
||||
else if(emu->uc_link) {
|
||||
else if(emu->quit && emu->uc_link) {
|
||||
emu->quit = 0;
|
||||
my_setcontext(emu, emu->uc_link);
|
||||
addr = R_EIP;
|
||||
|
||||
+11
-7
@@ -53,6 +53,10 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t *emu = test->emu;
|
||||
#endif
|
||||
#ifdef TERMUX
|
||||
extern int isinff(float);
|
||||
extern int isnanf(float);
|
||||
#endif
|
||||
opcode = F8;
|
||||
|
||||
@@ -64,13 +68,13 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
case 0: /* SLDT Ew */
|
||||
GET_EW;
|
||||
EW->word[0] = 0;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
EW->word[1] = 0;
|
||||
break;
|
||||
case 1: /* STR Ew */
|
||||
GET_EW;
|
||||
EW->word[0] = 0x7f; // dummy return
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
EW->word[1] = 0;
|
||||
break;
|
||||
case 4: //VERR
|
||||
@@ -145,7 +149,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
case 0x12:
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if((nextop&0xC0)==0xC0) /* MOVHLPS Gx,Ex */
|
||||
if(MODREG) /* MOVHLPS Gx,Ex */
|
||||
GX.q[0] = EX->q[1];
|
||||
else
|
||||
GX.q[0] = EX->q[0]; /* MOVLPS Gx,Ex */
|
||||
@@ -183,7 +187,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
case 0x18: /* PREFETCHh Ed */
|
||||
nextop = F8;
|
||||
GET_ED_;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
} else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //PREFETCHnta
|
||||
@@ -1384,7 +1388,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
|
||||
case 0xD7: /* PMOVMSKB Gd,Em */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GET_EM;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -1500,7 +1504,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
|
||||
case 0xE7: /* MOVNTQ Em,Gm */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
return 0;
|
||||
GET_EM;
|
||||
EM->q = GM.q;
|
||||
@@ -1613,7 +1617,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
break;
|
||||
case 0xF7: /* MASKMOVQ Gm, Em */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GET_EM;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(EM->ub[i]&0x80) ((uint8_t*)(R_EDI))[i] = GM.ub[i];
|
||||
|
||||
+25
-9
@@ -75,7 +75,12 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
GD.dword[0] = adc32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x21: /* AND Ed,Gd */
|
||||
case 0x20: /* AND Seg:Eb,Gb */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
EB->byte[0] = and8(emu, EB->byte[0], GB);
|
||||
break;
|
||||
case 0x21: /* AND Seg:Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = and32(emu, ED->dword[0], GD.dword[0]);
|
||||
@@ -165,13 +170,18 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
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 0x65: /* GS: */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test64(test, _GS, addr);
|
||||
#else
|
||||
return Run64(emu, _GS, addr);
|
||||
#endif
|
||||
break;
|
||||
case 0x66:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test6466(test, tlsdata, addr);
|
||||
@@ -250,7 +260,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
nextop = F8;
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
@@ -268,16 +278,20 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
}
|
||||
#else
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
if(!MODREG)
|
||||
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)
|
||||
if(!MODREG)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x88: /* MOV Seg:Eb,Gb */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
EB->byte[0] = GB;
|
||||
break;
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -309,6 +323,8 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = Pop(emu);
|
||||
break;
|
||||
case 0x90: /* NOP */
|
||||
break;
|
||||
|
||||
case 0x9C: /* PUSHFD */
|
||||
// Segment override if for memory loc, no stack segment
|
||||
@@ -424,7 +440,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, addr);
|
||||
addr = ED->dword[0];
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
@@ -438,7 +454,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
addr = ED->dword[0];
|
||||
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
|
||||
+15
-5
@@ -99,11 +99,21 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x0F: /* 66 0f prefix */
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test660F(test, addr);
|
||||
#else
|
||||
return Run660F(emu, addr);
|
||||
#endif
|
||||
switch(rep) {
|
||||
case 2: return 0;
|
||||
case 1:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test66F20F(test, addr);
|
||||
#else
|
||||
return Run66F20F(emu, addr);
|
||||
#endif
|
||||
default:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test660F(test, addr);
|
||||
#else
|
||||
return Run660F(emu, addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
case 0x1E: /* PUSH DS */
|
||||
Push16(emu, emu->segs[_DS]);
|
||||
|
||||
+477
-7
@@ -15,6 +15,28 @@
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
#include "x86compstrings.h"
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if((b & 1) == 1)
|
||||
retval ^= a;
|
||||
|
||||
if((a & 0x80)) {
|
||||
a <<= 1;
|
||||
a ^= 0x1b;
|
||||
} else {
|
||||
a <<= 1;
|
||||
}
|
||||
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test660F(x86test_t *test, uintptr_t addr)
|
||||
@@ -33,14 +55,63 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
int32_t tmp32s;
|
||||
sse_regs_t *opex, eax1, *opx2;
|
||||
mmx87_regs_t *opem;
|
||||
float tmpf;
|
||||
double tmpd;
|
||||
#ifndef NOALIGN
|
||||
int is_nan;
|
||||
#endif
|
||||
// AES opcodes constants
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A F K P E J O D I N C H M B G L
|
||||
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
|
||||
const uint8_t subbytes[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A N K H E B O L I F C P M J G D
|
||||
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
|
||||
const uint8_t invsubbytes[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
#ifdef TERMUX
|
||||
extern int isinff(float);
|
||||
extern int isnanf(float);
|
||||
#endif
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
@@ -403,6 +474,15 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10: /* PBLENDVB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<16; ++i) {
|
||||
if(emu->xmm[0].ub[i]&0x80)
|
||||
GX.ub[i] = EX->ub[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x14: /* BLENDVPS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -411,6 +491,14 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GX.ud[i] = EX->ud[i];
|
||||
}
|
||||
break;
|
||||
case 0x15: /* BLENDVPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(emu->xmm[0].q[i]&0x8000000000000000LL)
|
||||
GX.q[i] = EX->q[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17: // PTEST GX, EX
|
||||
nextop = F8;
|
||||
@@ -418,6 +506,10 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
CHECK_FLAGS(emu);
|
||||
CONDITIONAL_SET_FLAG(!((GX.q[0]&EX->q[0])|(GX.q[1]&EX->q[1])), F_ZF);
|
||||
CONDITIONAL_SET_FLAG(!(((~GX.q[0])&EX->q[0])|((~GX.q[1])&EX->q[1])), F_CF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CLEAR_FLAG(F_OF);
|
||||
CLEAR_FLAG(F_SF);
|
||||
CLEAR_FLAG(F_PF);
|
||||
break;
|
||||
|
||||
case 0x1C: /* PABSB Gx, Ex */
|
||||
@@ -479,6 +571,36 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GX.sq[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x28: /* PMULDQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.sq[1] = ((int64_t)GX.sd[2])*(int64_t)EX->sd[2];
|
||||
GX.sq[0] = ((int64_t)GX.sd[0])*(int64_t)EX->sd[0];
|
||||
break;
|
||||
case 0x29: /* PCMPEQQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX.sq[i] = (GX.sq[i]==EX->sq[i])?-1LL:0LL;
|
||||
break;
|
||||
case 0x2A: /* MOVNTDQA Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.q[0] = EX->q[0];
|
||||
GX.q[1] = EX->q[1];
|
||||
break;
|
||||
case 0x2B: /* PACKUSDW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.uw[i] = (GX.sd[i]<0)?0:((GX.sd[i]>65535)?65535:GX.sd[i]);
|
||||
if(&GX==EX)
|
||||
GX.q[1] = GX.q[0];
|
||||
else
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.uw[i+4] = (EX->sd[i]<0)?0:((EX->sd[i]>65535)?65535:EX->sd[i]);
|
||||
break;
|
||||
|
||||
case 0x30: /* PMOVZXBW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -516,6 +638,19 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GX.q[i] = EX->ud[i];
|
||||
break;
|
||||
|
||||
case 0x37: /* PCMPGTQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX.sq[i] = (GX.sq[i]>EX->sq[i])?-1LL:0LL;
|
||||
break;
|
||||
case 0x38: /* PMINSB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<16; ++i)
|
||||
if(GX.sb[i]>EX->sb[i])
|
||||
GX.sb[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x39: /* PMINSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -523,7 +658,27 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
if(GX.sd[i]>EX->sd[i])
|
||||
GX.sd[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x3A: /* PMINUW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i)
|
||||
if(GX.uw[i]>EX->uw[i])
|
||||
GX.uw[i] = EX->uw[i];
|
||||
break;
|
||||
case 0x3B: /* PMINUD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(GX.ud[i]>EX->ud[i])
|
||||
GX.ud[i] = EX->ud[i];
|
||||
break;
|
||||
case 0x3C: /* PMAXSB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<16; ++i)
|
||||
if(GX.sb[i]<EX->sb[i])
|
||||
GX.sb[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x3D: /* PMAXSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -531,7 +686,20 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
if(GX.sd[i]<EX->sd[i])
|
||||
GX.sd[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x3E: /* PMAXUW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i)
|
||||
if(GX.uw[i]<EX->uw[i])
|
||||
GX.uw[i] = EX->uw[i];
|
||||
break;
|
||||
case 0x3F: /* PMAXUD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(GX.ud[i]<EX->ud[i])
|
||||
GX.ud[i] = EX->ud[i];
|
||||
break;
|
||||
case 0x40: /* PMULLD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -539,13 +707,136 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GX.sd[i] *= EX->sd[i];
|
||||
}
|
||||
break;
|
||||
case 0x41: /* PHMINPOSUW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp16u = EX->uw[0];
|
||||
tmp16s = 0;
|
||||
for(int i=1; i<8; ++i) {
|
||||
if(EX->uw[i]<tmp16u) {
|
||||
tmp16u = EX->uw[i];
|
||||
tmp16s = i;
|
||||
}
|
||||
}
|
||||
GX.q[1] = 0;
|
||||
GX.uw[0] = tmp16u;
|
||||
GX.uw[1] = tmp16s;
|
||||
GX.ud[1] = 0;
|
||||
break;
|
||||
|
||||
case 0xDB: /* AESIMC Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
//STATE ← InvMixColumns( STATE );
|
||||
if (EX == &GX) {
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = EX->ub[i];
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
} else {
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX.ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
|
||||
GX.ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
|
||||
GX.ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
|
||||
GX.ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xDC: /* AESENC Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← ShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX.ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = subbytes[eax1.ub[i]];
|
||||
//STATE ← MixColumns( STATE );
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX.ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
|
||||
GX.ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
|
||||
GX.ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
|
||||
GX.ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
|
||||
}
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX.q[0] ^= EX->q[0];
|
||||
GX.q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDD: /* AESENCLAST Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← ShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX.ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
GX.ub[i] = subbytes[eax1.ub[i]];
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX.q[0] ^= EX->q[0];
|
||||
GX.q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDE: /* AESDEC Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← InvShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX.ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = invsubbytes[eax1.ub[i]];
|
||||
//STATE ← InvMixColumns( STATE );
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX.q[0] ^= EX->q[0];
|
||||
GX.q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDF: /* AESDECLAST Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← InvShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX.ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
GX.ub[i] = invsubbytes[eax1.ub[i]];
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX.q[0] ^= EX->q[0];
|
||||
GX.q[1] ^= EX->q[1];
|
||||
break;
|
||||
|
||||
case 0xF0: /* MOVBE Gw, Ew */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GD.word[0] = __builtin_bswap16(ED->word[0]);
|
||||
break;
|
||||
case 0xF1: /* MOVBE Ew, Gw */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
ED->word[0] = __builtin_bswap16(GD.word[0]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3A: // these are some SSE3 opcodes
|
||||
case 0x3A: // these are some SSE3 & SSE4.x opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x08: // roundps GX, EX, u8
|
||||
@@ -644,7 +935,24 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0C: /* PBLENDPS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
for (int i=0; i<4; ++i) {
|
||||
if(tmp8u&(1<<i))
|
||||
GX.ud[i] = EX->ud[i];
|
||||
}
|
||||
break;
|
||||
case 0x0D: /* PBLENDPD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(tmp8u&(1<<i))
|
||||
GX.q[i] = EX->q[i];
|
||||
}
|
||||
break;
|
||||
case 0x0E: /* PBLENDW Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -669,12 +977,36 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x14: // PEXTRB ED, GX, u8
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if(MODREG)
|
||||
ED->dword[0] = GX.ub[tmp8u&0x0f];
|
||||
else
|
||||
ED->byte[0] = GX.ub[tmp8u&0x0f];
|
||||
break;
|
||||
case 0x15: // PEXTRW Ew,Gx,Ib
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
if(MODREG)
|
||||
ED->dword[0] = GX.uw[tmp8u&7]; // 16bits extract, 0 extended
|
||||
else
|
||||
ED->word[0] = GX.uw[tmp8u&7];
|
||||
break;
|
||||
case 0x16: // PEXTRD ED, GX, u8
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
ED->dword[0] = GX.ud[tmp8u&3];
|
||||
break;
|
||||
case 0x17: // EXTRACTPS ED, GX, u8
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
ED->dword[0] = GX.ud[tmp8u&3];
|
||||
break;
|
||||
|
||||
case 0x20: // PINSRB GX, Ed, Ib
|
||||
nextop = F8;
|
||||
@@ -686,7 +1018,7 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)==0xC0) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
|
||||
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
|
||||
GX.ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<i))
|
||||
@@ -699,6 +1031,144 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
GX.ud[tmp8u&0x3] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x40: /* DPPS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmpf = 0.0f;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<(i+4)))
|
||||
tmpf += GX.f[i]*EX->f[i];
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
|
||||
break;
|
||||
case 0x41: /* DPPD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmpd = 0.0;
|
||||
if(tmp8u&(1<<(4+0)))
|
||||
tmpd += GX.d[0]*EX->d[0];
|
||||
if(tmp8u&(1<<(4+1)))
|
||||
tmpd += GX.d[1]*EX->d[1];
|
||||
GX.d[0] = (tmp8u&(1<<(0)))?tmpd:0.0;
|
||||
GX.d[1] = (tmp8u&(1<<(1)))?tmpd:0.0;
|
||||
break;
|
||||
case 0x42: /* MPSADBW Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
{
|
||||
int src = tmp8u&3;
|
||||
int dst = (tmp8u>>2)&1;
|
||||
int b[11];
|
||||
for (int i=0; i<11; ++i)
|
||||
b[i] = GX.ub[dst*4+i];
|
||||
for(int i=0; i<8; ++i) {
|
||||
int tmp = abs(b[i+0]-EX->ub[src*4+0]);
|
||||
tmp += abs(b[i+1]-EX->ub[src*4+1]);
|
||||
tmp += abs(b[i+2]-EX->ub[src*4+2]);
|
||||
tmp += abs(b[i+3]-EX->ub[src*4+3]);
|
||||
GX.uw[i] = tmp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44: /* PCLMULQDQ Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
{
|
||||
int g = (tmp8u&1)?1:0;
|
||||
int e = (tmp8u&0b10000)?1:0;
|
||||
uint64_t result[2] = { 0 };
|
||||
for (int i=0; i<64; ++i)
|
||||
if(GX.q[g]&(1LL<<i)) {
|
||||
result[0] ^= (EX->q[e]<<i);
|
||||
if(i)
|
||||
result[1] ^= (EX->q[e]>>(64-i));
|
||||
}
|
||||
|
||||
GX.q[0] = result[0];
|
||||
GX.q[1] = result[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x60: /* PCMPESTRM */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
|
||||
if(tmp8u&0b1000000) {
|
||||
switch(tmp8u&1) {
|
||||
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
}
|
||||
} else {
|
||||
GX.q[1] = GX.q[0] = 0;
|
||||
GX.uw[0] = tmp32u;
|
||||
}
|
||||
break;
|
||||
case 0x61: /* PCMPESTRI */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
|
||||
if(!tmp32u)
|
||||
R_ECX = (tmp8u&1)?8:16;
|
||||
else if(tmp8u&0b1000000)
|
||||
R_ECX = 31-__builtin_clz(tmp32u);
|
||||
else
|
||||
R_ECX = __builtin_ffs(tmp32u) - 1;
|
||||
break;
|
||||
case 0x62: /* PCMPISTRM */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
|
||||
if(tmp8u&0b1000000) {
|
||||
switch(tmp8u&1) {
|
||||
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
|
||||
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
|
||||
}
|
||||
} else {
|
||||
GX.q[1] = GX.q[0] = 0;
|
||||
GX.uw[0] = tmp32u;
|
||||
}
|
||||
break;
|
||||
case 0x63: /* PCMPISTRI */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
|
||||
if(!tmp32u)
|
||||
R_ECX = (tmp8u&1)?8:16;
|
||||
else if(tmp8u&0b1000000)
|
||||
R_ECX = 31-__builtin_clz(tmp32u);
|
||||
else
|
||||
R_ECX = __builtin_ffs(tmp32u) - 1;
|
||||
break;
|
||||
|
||||
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp32u = F8;
|
||||
for (int i = 4; i < 8; ++i)
|
||||
GX.ub[i] = subbytes[EX->ub[i]];
|
||||
for (int i = 12; i < 16; ++i)
|
||||
GX.ub[i] = subbytes[EX->ub[i]];
|
||||
GX.ud[0] = GX.ud[1];
|
||||
tmp8u = GX.ub[4];
|
||||
GX.ud[1] = GX.ud[1] >> 8;
|
||||
GX.ub[7] = tmp8u;
|
||||
GX.ud[1] ^= tmp32u;
|
||||
GX.ud[2] = GX.ud[3];
|
||||
tmp8u = GX.ub[12];
|
||||
GX.ud[3] = GX.ud[3] >> 8;
|
||||
GX.ub[15] = tmp8u;
|
||||
GX.ud[3] ^= tmp32u;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1520,12 +1990,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
EX->q[0] = GX.q[0];
|
||||
if((nextop&0xC0)==0xC0)
|
||||
if(MODREG)
|
||||
EX->q[1] = 0;
|
||||
break;
|
||||
case 0xD7: /* PMOVMSKB Gd,Ex */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
GET_EX;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<16; ++i)
|
||||
|
||||
@@ -29,8 +29,8 @@ uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
|
||||
@@ -29,8 +29,8 @@ uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
|
||||
uint8_t opcode = F8;
|
||||
switch(opcode) {
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#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 "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#include "modrm.h"
|
||||
#include "x86compstrings.h"
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
uintptr_t Test66F20F(x86test_t *test, uintptr_t addr)
|
||||
#else
|
||||
uintptr_t Run66F20F(x86emu_t *emu, uintptr_t addr)
|
||||
#endif
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
uint16_t tmp16u;
|
||||
int16_t tmp16s;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
sse_regs_t *opex, eax1, *opx2;
|
||||
mmx87_regs_t *opem;
|
||||
float tmpf;
|
||||
double tmpd;
|
||||
|
||||
#ifdef TEST_INTERPRETER
|
||||
x86emu_t* emu = test->emu;
|
||||
#endif
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x38: // SSE 4.x
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xF1: // CRC32 Gd, Ew
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
for(int j=0; j<2; ++j) {
|
||||
GD.dword[0] ^= EW->byte[j];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (GD.dword[0] & 1)
|
||||
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
|
||||
else
|
||||
GD.dword[0] = (GD.dword[0] >> 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "x86trace.h"
|
||||
#endif
|
||||
#include "x86tls.h"
|
||||
#include "x86emu.h"
|
||||
|
||||
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
|
||||
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
|
||||
@@ -456,6 +457,8 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
|
||||
if(emu->op2==1)
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
} else {
|
||||
if (emu->op1&0x80) {
|
||||
@@ -479,6 +482,8 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
if(emu->op2==1)
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
} else {
|
||||
if (emu->op1&0x8000) {
|
||||
@@ -501,6 +506,8 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
if(emu->op2==1)
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
break;
|
||||
case d_shr8:
|
||||
@@ -514,7 +521,7 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
|
||||
CONDITIONAL_SET_FLAG(emu->op1 & 0x80, F_OF);
|
||||
}
|
||||
} else {
|
||||
CONDITIONAL_SET_FLAG((emu->op1 >> (emu->op2-1)) & 0x1, F_CF);
|
||||
@@ -534,7 +541,7 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
|
||||
CONDITIONAL_SET_FLAG(emu->op1 & 0x8000, F_OF);
|
||||
}
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
@@ -553,7 +560,35 @@ void UpdateFlags(x86emu_t *emu)
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
}
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
|
||||
CONDITIONAL_SET_FLAG(emu->op1 & 0x80000000, F_OF);
|
||||
}
|
||||
break;
|
||||
case d_shrd32:
|
||||
cnt = emu->op2;
|
||||
if (cnt > 0) {
|
||||
cc = emu->op1 & (1 << (cnt - 1));
|
||||
CONDITIONAL_SET_FLAG(cc, F_CF);
|
||||
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG((emu->op1 ^ emu->res) & 0x80000000, F_OF);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case d_shld32:
|
||||
cnt = emu->op2;
|
||||
if (cnt > 0) {
|
||||
cc = emu->op1 & (1 << (32 - cnt));
|
||||
CONDITIONAL_SET_FLAG(cc, F_CF);
|
||||
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
|
||||
if (cnt == 1) {
|
||||
CONDITIONAL_SET_FLAG((emu->op1 ^ emu->res) & 0x80000000, F_OF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case d_sub8:
|
||||
@@ -882,6 +917,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
|
||||
} else if(peek==0x55) {
|
||||
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
|
||||
printFunctionAddr(*(uintptr_t*)(R_ESP), "top:");
|
||||
printFunctionAddr(ip, "here: ");
|
||||
} else if(peek==0xE8) { // Call
|
||||
uintptr_t nextaddr = ip + 5 + PK32(1);
|
||||
|
||||
@@ -212,6 +212,7 @@ 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 Run66F20F(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);
|
||||
@@ -241,6 +242,7 @@ 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 Test66F20F(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);
|
||||
|
||||
@@ -554,15 +554,6 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
|
||||
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;
|
||||
|
||||
@@ -103,6 +103,42 @@ uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x38: // more opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xF0: // CRC32 Gd, Eb
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
GD.dword[0] ^= EB->byte[0];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (GD.dword[0] & 1)
|
||||
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
|
||||
else
|
||||
GD.dword[0] = (GD.dword[0] >> 1);
|
||||
}
|
||||
break;
|
||||
case 0xF1: // CRC32 Gd, Ed
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
for(int j=0; j<4; ++j) {
|
||||
GD.dword[0] ^= ED->byte[j];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (GD.dword[0] & 1)
|
||||
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
|
||||
else
|
||||
GD.dword[0] = (GD.dword[0] >> 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x51: /* SQRTSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
|
||||
@@ -42,6 +42,11 @@ uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
|
||||
x86emu_t*emu = test->emu;
|
||||
#endif
|
||||
|
||||
#ifdef TERMUX
|
||||
extern int isinff(float);
|
||||
extern int isnanf(float);
|
||||
#endif
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
@@ -215,6 +220,20 @@ uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
|
||||
memcpy(EX, &GX, 16); // unaligned...
|
||||
break;
|
||||
|
||||
case 0xB8: /* POPCNT Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GD.dword[0] = __builtin_popcount(ED->dword[0]);
|
||||
RESET_FLAGS(emu);
|
||||
CLEAR_FLAG(F_OF);
|
||||
CLEAR_FLAG(F_SF);
|
||||
CLEAR_FLAG(F_ZF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CLEAR_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_PF);
|
||||
CONDITIONAL_SET_FLAG(GD.dword[0]==0, F_ZF);
|
||||
break;
|
||||
|
||||
case 0xBC: /* TZCNT Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
|
||||
+298
-287
@@ -107,6 +107,7 @@ int my_socketcall(x86emu_t* emu, int n, unsigned long *args) {
|
||||
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", n);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -118,187 +119,184 @@ int my_fcntl(x86emu_t* emu, int fd, int cmd, ... /* arg */ );
|
||||
|
||||
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
|
||||
typedef struct scwrap_s {
|
||||
uint32_t x86s;
|
||||
int nats;
|
||||
int nbpars;
|
||||
} scwrap_t;
|
||||
|
||||
scwrap_t syscallwrap[] = {
|
||||
{ 2, __NR_fork, 1 }, // should wrap this one, because of the struct pt_regs (the only arg)?
|
||||
//{ 3, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//{ 4, __NR_write, 3 }, // same
|
||||
//{ 5, __NR_open, 3 }, // flags need transformation
|
||||
//{ 6, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
|
||||
[2] ={ __NR_fork, 1 }, // should wrap this one, because of the struct pt_regs (the only arg)?
|
||||
//[3] ={ __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//[4] ={ __NR_write, 3 }, // same
|
||||
//[5] ={ __NR_open, 3 }, // flags need transformation
|
||||
//[6] ={ __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
|
||||
#ifdef __NR_waitpid
|
||||
{ 7, __NR_waitpid, 3 },
|
||||
[7] ={ __NR_waitpid, 3 },
|
||||
#endif
|
||||
{ 10, __NR_unlink, 1 },
|
||||
{ 12, __NR_chdir, 1 },
|
||||
[10] { __NR_unlink, 1 },
|
||||
[12] { __NR_chdir, 1 },
|
||||
#ifdef __NR_time
|
||||
{ 13, __NR_time, 1 },
|
||||
[13] { __NR_time, 1 },
|
||||
#endif
|
||||
{ 15, __NR_chmod, 2 },
|
||||
{ 19, __NR_lseek, 3 },
|
||||
{ 20, __NR_getpid, 0 },
|
||||
{ 24, __NR_getuid, 0 },
|
||||
[15] { __NR_chmod, 2 },
|
||||
[19] { __NR_lseek, 3 },
|
||||
[20] { __NR_getpid, 0 },
|
||||
[24] { __NR_getuid, 0 },
|
||||
#ifdef __NR_alarm
|
||||
{ 27, __NR_alarm, 1 },
|
||||
[27] { __NR_alarm, 1 },
|
||||
#endif
|
||||
{ 33, __NR_access, 2 },
|
||||
{ 37, __NR_kill, 2 },
|
||||
{ 38, __NR_rename, 2 },
|
||||
{ 39, __NR_mkdir, 2 },
|
||||
{ 40, __NR_rmdir, 1 },
|
||||
{ 41, __NR_dup, 1 },
|
||||
{ 42, __NR_pipe, 1 },
|
||||
//{ 45, __NR_brk, 1 },
|
||||
{ 47, __NR_getgid, 0 },
|
||||
{ 49, __NR_geteuid, 0 },
|
||||
{ 50, __NR_getegid, 0 },
|
||||
{ 54, __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5
|
||||
//{ 55, __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD
|
||||
{ 60, __NR_umask, 1 },
|
||||
{ 63, __NR_dup2, 2 },
|
||||
{ 64, __NR_getppid, 0 },
|
||||
{ 66, __NR_setsid, 0 },
|
||||
//{ 67, __NR_sigaction, 3 },
|
||||
{ 75, __NR_setrlimit, 2 },
|
||||
[33] { __NR_access, 2 },
|
||||
[37] { __NR_kill, 2 },
|
||||
[38] { __NR_rename, 2 },
|
||||
[39] { __NR_mkdir, 2 },
|
||||
[40] { __NR_rmdir, 1 },
|
||||
[41] { __NR_dup, 1 },
|
||||
[42] { __NR_pipe, 1 },
|
||||
//[45] { __NR_brk, 1 },
|
||||
[47] { __NR_getgid, 0 },
|
||||
[49] { __NR_geteuid, 0 },
|
||||
[50] { __NR_getegid, 0 },
|
||||
[54] { __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5
|
||||
//[55] { __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD
|
||||
[60] { __NR_umask, 1 },
|
||||
[63] { __NR_dup2, 2 },
|
||||
[64] { __NR_getppid, 0 },
|
||||
[66] { __NR_setsid, 0 },
|
||||
//[67] { __NR_sigaction, 3 },
|
||||
[75] { __NR_setrlimit, 2 },
|
||||
#ifdef __NR_getrlimit
|
||||
{ 76, __NR_getrlimit, 2 },
|
||||
[76] { __NR_getrlimit, 2 },
|
||||
#endif
|
||||
{ 77, __NR_getrusage, 2 },
|
||||
{ 78, __NR_gettimeofday, 2 },
|
||||
{ 80, __NR_getgroups, 2 },
|
||||
{ 83, __NR_symlink, 2 },
|
||||
[77] { __NR_getrusage, 2 },
|
||||
[78] { __NR_gettimeofday, 2 },
|
||||
[80] { __NR_getgroups, 2 },
|
||||
[83] { __NR_symlink, 2 },
|
||||
#ifdef __NR_select
|
||||
{ 82, __NR_select, 5 },
|
||||
[82] { __NR_select, 5 },
|
||||
#endif
|
||||
{ 85, __NR_readlink, 3 },
|
||||
//{ 91, __NR_munmap, 2 },
|
||||
{ 94, __NR_fchmod, 2 },
|
||||
{ 99, __NR_statfs, 2 },
|
||||
[85] { __NR_readlink, 3 },
|
||||
//[91] { __NR_munmap, 2 },
|
||||
[94] { __NR_fchmod, 2 },
|
||||
[99] { __NR_statfs, 2 },
|
||||
#ifdef __NR_socketcall
|
||||
{ 102, __NR_socketcall, 2 },
|
||||
[102] { __NR_socketcall, 2 },
|
||||
#endif
|
||||
{ 104, __NR_setitimer, 3 },
|
||||
{ 105, __NR_getitimer, 2 },
|
||||
[104] { __NR_setitimer, 3 },
|
||||
[105] { __NR_getitimer, 2 },
|
||||
#ifdef __NR_newstat
|
||||
{ 106, __NR_newstat, 2 },
|
||||
[106] { __NR_newstat, 2 },
|
||||
#else
|
||||
{ 106, __NR_stat, 2 },
|
||||
[106] { __NR_stat, 2 },
|
||||
#endif
|
||||
#ifdef __NR_newlstat
|
||||
{ 107, __NR_newlstat, 2 },
|
||||
[107] { __NR_newlstat, 2 },
|
||||
#else
|
||||
{ 107, __NR_lstat, 2 },
|
||||
[107] { __NR_lstat, 2 },
|
||||
#endif
|
||||
#ifdef __NR_newfstat
|
||||
{ 108, __NR_newfstat, 2 },
|
||||
[108] { __NR_newfstat, 2 },
|
||||
#else
|
||||
{ 108, __NR_fstat, 2 },
|
||||
[108] { __NR_fstat, 2 },
|
||||
#endif
|
||||
#ifdef __NR_olduname
|
||||
{ 109, __NR_olduname, 1 },
|
||||
[109] { __NR_olduname, 1 },
|
||||
#endif
|
||||
#ifdef __NR_iopl
|
||||
{ 110, __NR_iopl, 1 },
|
||||
[110] { __NR_iopl, 1 },
|
||||
#endif
|
||||
{ 114, __NR_wait4, 4 }, //TODO: check struct rusage alignment
|
||||
[114] { __NR_wait4, 4 }, //TODO: check struct rusage alignment
|
||||
#ifdef __NR_ipc
|
||||
{ 117, __NR_ipc, 6 },
|
||||
[117] { __NR_ipc, 6 },
|
||||
#endif
|
||||
//{ 119, __NR_sigreturn, 0},
|
||||
//{ 120, __NR_clone, 5 }, // need works
|
||||
//{ 122, __NR_uname, 1 },
|
||||
//{ 123, __NR_modify_ldt },
|
||||
//{ 125, __NR_mprotect, 3 },
|
||||
{ 126, __NR_sigprocmask, 3 },
|
||||
{ 136, __NR_personality, 1 },
|
||||
{ 140, __NR__llseek, 5 },
|
||||
{ 141, __NR_getdents, 3 },
|
||||
{ 142, __NR__newselect, 5 },
|
||||
{ 143, __NR_flock, 2 },
|
||||
{ 144, __NR_msync, 3 },
|
||||
{ 145, __NR_readv, 3 },
|
||||
{ 146, __NR_writev, 3 },
|
||||
{ 148, __NR_fdatasync, 1 },
|
||||
{ 149, __NR__sysctl, 1 }, // need wrapping?
|
||||
{ 156, __NR_sched_setscheduler, 3 },
|
||||
{ 157, __NR_sched_getscheduler, 1 },
|
||||
{ 158, __NR_sched_yield, 0 },
|
||||
{ 162, __NR_nanosleep, 2 },
|
||||
{ 164, __NR_setresuid, 3 },
|
||||
//{ 168, __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc
|
||||
{ 172, __NR_prctl, 5 },
|
||||
//{ 173, __NR_rt_sigreturn, 0 },
|
||||
{ 175, __NR_rt_sigprocmask, 4 },
|
||||
{ 179, __NR_rt_sigsuspend, 2 },
|
||||
{ 183, __NR_getcwd, 2 },
|
||||
{ 184, __NR_capget, 2},
|
||||
{ 185, __NR_capset, 2},
|
||||
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
|
||||
{ 191, __NR_ugetrlimit, 2 },
|
||||
// { 192, __NR_mmap2, 6},
|
||||
//{ 195, __NR_stat64, 2 }, // need proprer wrap because of structure size change
|
||||
//{ 196, __NR_lstat64, 2 }, // need proprer wrap because of structure size change
|
||||
//{ 197, __NR_fstat64, 2 }, // need proprer wrap because of structure size change
|
||||
//[119] { __NR_sigreturn, 0},
|
||||
//[120] { __NR_clone, 5 }, // need works
|
||||
//[122] { __NR_uname, 1 },
|
||||
//[123] { __NR_modify_ldt },
|
||||
//[125] { __NR_mprotect, 3 },
|
||||
[126] { __NR_sigprocmask, 3 },
|
||||
[136] { __NR_personality, 1 },
|
||||
[140] { __NR__llseek, 5 },
|
||||
[141] { __NR_getdents, 3 },
|
||||
[142] { __NR__newselect, 5 },
|
||||
[143] { __NR_flock, 2 },
|
||||
[144] { __NR_msync, 3 },
|
||||
[145] { __NR_readv, 3 },
|
||||
[146] { __NR_writev, 3 },
|
||||
[148] { __NR_fdatasync, 1 },
|
||||
[149] { __NR__sysctl, 1 }, // need wrapping?
|
||||
[156] { __NR_sched_setscheduler, 3 },
|
||||
[157] { __NR_sched_getscheduler, 1 },
|
||||
[158] { __NR_sched_yield, 0 },
|
||||
[162] { __NR_nanosleep, 2 },
|
||||
[164] { __NR_setresuid, 3 },
|
||||
//[168] { __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc
|
||||
[172] { __NR_prctl, 5 },
|
||||
//[173] { __NR_rt_sigreturn, 0 },
|
||||
[175] { __NR_rt_sigprocmask, 4 },
|
||||
[179] { __NR_rt_sigsuspend, 2 },
|
||||
[183] { __NR_getcwd, 2 },
|
||||
[184] { __NR_capget, 2},
|
||||
[185] { __NR_capset, 2},
|
||||
[186] { __NR_sigaltstack, 2 }, // neeed wrap or something?
|
||||
[191] { __NR_ugetrlimit, 2 },
|
||||
// [192] { __NR_mmap2, 6},
|
||||
//[195] { __NR_stat64, 2 }, // need proprer wrap because of structure size change
|
||||
//[196] { __NR_lstat64, 2 }, // need proprer wrap because of structure size change
|
||||
//[197] { __NR_fstat64, 2 }, // need proprer wrap because of structure size change
|
||||
#ifndef POWERPCLE
|
||||
{ 199, __NR_getuid32, 0 },
|
||||
{ 200, __NR_getgid32, 0 },
|
||||
{ 201, __NR_geteuid32, 0 },
|
||||
{ 202, __NR_getegid32, 0 },
|
||||
{ 208, __NR_setresuid32, 3 },
|
||||
{ 209, __NR_getresuid32, 3 },
|
||||
{ 210, __NR_setresgid32, 3 },
|
||||
{ 211, __NR_getresgid32, 3 },
|
||||
[199] { __NR_getuid32, 0 },
|
||||
[200] { __NR_getgid32, 0 },
|
||||
[201] { __NR_geteuid32, 0 },
|
||||
[202] { __NR_getegid32, 0 },
|
||||
[208] { __NR_setresuid32, 3 },
|
||||
[209] { __NR_getresuid32, 3 },
|
||||
[210] { __NR_setresgid32, 3 },
|
||||
[211] { __NR_getresgid32, 3 },
|
||||
#else
|
||||
// PowerPC uses the same syscalls for 32/64 bit processes.
|
||||
{ 199, __NR_getuid, 0 },
|
||||
{ 200, __NR_getgid, 0 },
|
||||
{ 201, __NR_geteuid, 0 },
|
||||
{ 202, __NR_getegid, 0 },
|
||||
{ 208, __NR_setresuid, 3 },
|
||||
{ 209, __NR_getresuid, 3 },
|
||||
{ 210, __NR_setresgid, 3 },
|
||||
{ 211, __NR_getresgid, 3 },
|
||||
[199] { __NR_getuid, 0 },
|
||||
[200] { __NR_getgid, 0 },
|
||||
[201] { __NR_geteuid, 0 },
|
||||
[202] { __NR_getegid, 0 },
|
||||
[208] { __NR_setresuid, 3 },
|
||||
[209] { __NR_getresuid, 3 },
|
||||
[210] { __NR_setresgid, 3 },
|
||||
[211] { __NR_getresgid, 3 },
|
||||
#endif
|
||||
{ 220, __NR_getdents64, 3 },
|
||||
//{ 221, __NR_fcntl64, 3 },
|
||||
{ 224, __NR_gettid, 0 },
|
||||
{ 240, __NR_futex, 6 },
|
||||
{ 241, __NR_sched_setaffinity, 3 },
|
||||
{ 242, __NR_sched_getaffinity, 3 },
|
||||
{ 252, __NR_exit_group, 1 },
|
||||
[220] { __NR_getdents64, 3 },
|
||||
//[221] { __NR_fcntl64, 3 },
|
||||
[224] { __NR_gettid, 0 },
|
||||
[240] { __NR_futex, 6 },
|
||||
[241] { __NR_sched_setaffinity, 3 },
|
||||
[242] { __NR_sched_getaffinity, 3 },
|
||||
[252] { __NR_exit_group, 1 },
|
||||
#ifdef NOALIGN
|
||||
{ 254, __NR_epoll_create, 1 },
|
||||
{ 255, __NR_epoll_ctl, 4 },
|
||||
{ 256, __NR_epoll_wait, 4 },
|
||||
[254] { __NR_epoll_create, 1 },
|
||||
[255] { __NR_epoll_ctl, 4 },
|
||||
[256] { __NR_epoll_wait, 4 },
|
||||
#endif
|
||||
{ 265, __NR_clock_gettime, 2 },
|
||||
{ 266, __NR_clock_getres, 2 },
|
||||
//{ 270, __NR_tgkill, 3 },
|
||||
{ 271, __NR_utimes, 2 },
|
||||
{ 291, __NR_inotify_init, 0},
|
||||
{ 292, __NR_inotify_add_watch, 3},
|
||||
{ 293, __NR_inotify_rm_watch, 2},
|
||||
{ 311, __NR_set_robust_list, 2 },
|
||||
{ 312, __NR_get_robust_list, 4 },
|
||||
{ 318, __NR_getcpu, 3},
|
||||
{ 328, __NR_eventfd2, 2},
|
||||
[265] { __NR_clock_gettime, 2 },
|
||||
[266] { __NR_clock_getres, 2 },
|
||||
//[270] { __NR_tgkill, 3 },
|
||||
[271] { __NR_utimes, 2 },
|
||||
[291] { __NR_inotify_init, 0},
|
||||
[292] { __NR_inotify_add_watch, 3},
|
||||
[293] { __NR_inotify_rm_watch, 2},
|
||||
[311] { __NR_set_robust_list, 2 },
|
||||
[312] { __NR_get_robust_list, 4 },
|
||||
[318] { __NR_getcpu, 3},
|
||||
[328] { __NR_eventfd2, 2},
|
||||
#ifdef NOALIGN
|
||||
{ 329, __NR_epoll_create1, 1 },
|
||||
[329] { __NR_epoll_create1, 1 },
|
||||
#endif
|
||||
{ 331, __NR_pipe2, 2},
|
||||
{ 332, __NR_inotify_init1, 1},
|
||||
[331] { __NR_pipe2, 2},
|
||||
[332] { __NR_inotify_init1, 1},
|
||||
#ifdef __NR_getrandom
|
||||
{ 355, __NR_getrandom, 3 },
|
||||
[355] { __NR_getrandom, 3 },
|
||||
#endif
|
||||
#ifdef __NR_memfd_create
|
||||
{ 356, __NR_memfd_create, 2},
|
||||
#endif
|
||||
#ifdef __NR_futex_waitv
|
||||
{ 449, __NR_futex_waitv, 5},
|
||||
[356] { __NR_memfd_create, 2},
|
||||
#endif
|
||||
//[449] { __NR_futex_waitv, 5},
|
||||
};
|
||||
|
||||
struct mmap_arg_struct {
|
||||
@@ -413,27 +411,25 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p", (void*)R_EIP, s, s, (void*)R_EBX, (void*)R_ECX, (void*)R_EDX, (void*)R_ESI, (void*)R_EDI);
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
for (int i=0; i<cnt; i++) {
|
||||
if(syscallwrap[i].x86s == s) {
|
||||
int sc = syscallwrap[i].nats;
|
||||
switch(syscallwrap[i].nbpars) {
|
||||
case 0: *(int32_t*)&R_EAX = syscall(sc); break;
|
||||
case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DEBUG, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break;
|
||||
case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
|
||||
case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
|
||||
case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
|
||||
case 6: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
|
||||
emu->quit = 1;
|
||||
return;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
return;
|
||||
if(s<cnt && syscallwrap[s].nats) {
|
||||
int sc = syscallwrap[s].nats;
|
||||
switch(syscallwrap[s].nbpars) {
|
||||
case 0: S_EAX = syscall(sc); break;
|
||||
case 1: S_EAX = syscall(sc, R_EBX); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DEBUG, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; S_EAX = syscall(sc, R_EBX, R_ECX); break;
|
||||
case 3: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
|
||||
case 4: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
|
||||
case 5: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
|
||||
case 6: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[s].nbpars);
|
||||
emu->quit = 1;
|
||||
return;
|
||||
}
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
return;
|
||||
}
|
||||
switch (s) {
|
||||
case 1: // sys_exit
|
||||
@@ -443,32 +439,32 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the thread now
|
||||
break;
|
||||
case 3: // sys_read
|
||||
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = read(S_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 4: // sys_write
|
||||
R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = write(S_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 5: // sys_open
|
||||
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);};
|
||||
//R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
//S_EAX = open((void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
S_EAX = my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 6: // sys_close
|
||||
R_EAX = (uint32_t)close((int)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = close(S_EBX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef __NR_waitpid
|
||||
case 7: //sys_waitpid
|
||||
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, S_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 11: // sys_execve
|
||||
@@ -479,55 +475,55 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
printf_log(LOG_DEBUG, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
|
||||
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 13: // sys_time (it's deprecated and remove on ARM EABI it seems)
|
||||
R_EAX = time(NULL);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_alarm
|
||||
case 27:
|
||||
R_EAX = alarm(R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 45: // sys_brk
|
||||
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 54: // sys_ioctl
|
||||
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = ioctl(S_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 55: // sys_fcntl
|
||||
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = my_fcntl(emu, S_EBX, S_ECX, R_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 67: // sys_sigaction
|
||||
R_EAX = (uint32_t)my_syscall_sigaction(emu, R_EBX, (x86_sigaction_restorer_t*)R_ECX, (x86_sigaction_restorer_t*)R_EDX, R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = my_syscall_sigaction(emu, R_EBX, (x86_sigaction_restorer_t*)R_ECX, (x86_sigaction_restorer_t*)R_EDX, R_ESI);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef __NR_getrlimit
|
||||
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
|
||||
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
case 82: // select
|
||||
R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 90: // old_mmap
|
||||
@@ -535,19 +531,19 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
|
||||
R_EAX = (uintptr_t)my_mmap(emu, (void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 91: // munmap
|
||||
R_EAX = my_munmap(emu, (void*)R_EBX, (unsigned long)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef __NR_socketcall
|
||||
case 102:
|
||||
R_EAX = my_socketcall(emu, R_EBX, (unsigned long *)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_olduname
|
||||
@@ -563,8 +559,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
memcpy(old->version, un.version, 9);
|
||||
strcpy(old->machine, "i686");
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -575,9 +571,9 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
#endif
|
||||
#ifndef __NR_ipc
|
||||
case 117: // ipc
|
||||
R_EAX = (uint32_t)my_ipc(R_EBX, (int)R_ECX, (int)R_EDX, (int)R_ESI, (void*)R_EDI, (long)R_EBP);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = my_ipc(R_EBX, S_ECX, S_EDX, S_ESI, (void*)R_EDI, (long)R_EBP);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 119: // sys_sigreturn
|
||||
@@ -589,8 +585,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
if((R_EBX&~0xff)==0x4100) {
|
||||
// this is a case of vfork...
|
||||
R_EAX = my_vfork(emu);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1)
|
||||
S_EAX = -errno;
|
||||
} else {
|
||||
if(R_ECX)
|
||||
{
|
||||
@@ -626,12 +622,12 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
my_context->stack_clone_used = 1;
|
||||
}
|
||||
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
|
||||
R_EAX = (uint32_t)ret;
|
||||
S_EAX = ret;
|
||||
}
|
||||
else
|
||||
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
}
|
||||
break;
|
||||
case 122: // uname
|
||||
@@ -647,23 +643,23 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
strcpy(old->machine, "i686");
|
||||
}
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 123: // SYS_modify_ldt
|
||||
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 125: // mprotect
|
||||
R_EAX = my_mprotect(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 168: // sys_poll
|
||||
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = poll((void*)R_EBX, R_ECX, S_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 173: // sys_rt_sigreturn
|
||||
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
|
||||
@@ -671,19 +667,19 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
case 174: // sys_rt_sigaction
|
||||
//printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 190: // vfork
|
||||
{
|
||||
int r = my_vfork(emu);
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 192: // mmap2
|
||||
R_EAX = (uint32_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
|
||||
S_EAX = (intptr_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
|
||||
break;
|
||||
case 195: // stat64
|
||||
{
|
||||
@@ -693,8 +689,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 196: // lstat64
|
||||
{
|
||||
@@ -704,8 +700,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 197: // fstat64
|
||||
{
|
||||
@@ -715,65 +711,73 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 221: // sys_fcntl64
|
||||
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
S_EAX = my_fcntl(emu, S_EBX, S_ECX, R_EDX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 243: // set_thread_area
|
||||
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef NOALIGN
|
||||
case 254: // epoll_create
|
||||
R_EAX = my_epoll_create(emu, (int)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
R_EAX = my_epoll_create(emu, S_EBX);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 255: // epoll_ctl
|
||||
R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
R_EAX = my_epoll_ctl(emu, S_EBX, S_ECX, S_EDX, (void*)R_ESI);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
case 256: // epoll_wait
|
||||
R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
R_EAX = my_epoll_wait(emu, S_EBX, (void*)R_ECX, S_EDX, S_ESI);
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 270: // tgkill
|
||||
R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#ifndef NOALIGN
|
||||
case 329: // epoll_create1
|
||||
R_EAX = my_epoll_create1(emu, of_convert(R_EBX));
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_getrandom
|
||||
case 355: // getrandom
|
||||
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_memfd_create
|
||||
case 356: // memfd_create
|
||||
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
if(S_EAX==-1 && errno>0)
|
||||
S_EAX = -errno;
|
||||
break;
|
||||
#endif
|
||||
case 449:
|
||||
#ifdef __NR_futex_waitv
|
||||
if(box86_futex_waitv)
|
||||
S_EAX = syscall(R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
else
|
||||
#endif
|
||||
S_EAX = -ENOSYS;
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_INFO, "Warning: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
R_EAX = (uint32_t)-ENOSYS;
|
||||
S_EAX = -ENOSYS;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
@@ -784,62 +788,60 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
#define u32(n) *(uint32_t*)stack(n)
|
||||
#define p(n) *(void**)stack(n)
|
||||
|
||||
uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
long EXPORT my_syscall(x86emu_t *emu)
|
||||
{
|
||||
static uint32_t warned = 0;
|
||||
uint32_t s = u32(0);
|
||||
printf_log(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
for (int i=0; i<cnt; i++) {
|
||||
if(syscallwrap[i].x86s == s) {
|
||||
int sc = syscallwrap[i].nats;
|
||||
switch(syscallwrap[i].nbpars) {
|
||||
case 0: return syscall(sc);
|
||||
case 1: return syscall(sc, u32(4));
|
||||
case 2: return syscall(sc, u32(4), u32(8));
|
||||
case 3: return syscall(sc, u32(4), u32(8), u32(12));
|
||||
case 4: return syscall(sc, u32(4), u32(8), u32(12), u32(16));
|
||||
case 5: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20));
|
||||
case 6: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20), u32(24));
|
||||
default:
|
||||
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
|
||||
emu->quit = 1;
|
||||
return 0;
|
||||
}
|
||||
if(s<cnt && syscallwrap[s].nats) {
|
||||
int sc = syscallwrap[s].nats;
|
||||
switch(syscallwrap[s].nbpars) {
|
||||
case 0: return syscall(sc);
|
||||
case 1: return syscall(sc, u32(4));
|
||||
case 2: return syscall(sc, u32(4), u32(8));
|
||||
case 3: return syscall(sc, u32(4), u32(8), u32(12));
|
||||
case 4: return syscall(sc, u32(4), u32(8), u32(12), u32(16));
|
||||
case 5: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20));
|
||||
case 6: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20), u32(24));
|
||||
default:
|
||||
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[s].nbpars);
|
||||
emu->quit = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
switch (s) {
|
||||
case 1: // __NR_exit
|
||||
emu->quit = 1;
|
||||
return u32(4); // faking the syscall here, we don't want to really terminate the program now
|
||||
return i32(4); // faking the syscall here, we don't want to really terminate the program now
|
||||
case 3: // sys_read
|
||||
return (uint32_t)read(i32(4), p(8), u32(12));
|
||||
return read(i32(4), p(8), u32(12));
|
||||
case 4: // sys_write
|
||||
return (uint32_t)write(i32(4), p(8), u32(12));
|
||||
return write(i32(4), p(8), u32(12));
|
||||
case 5: // sys_open
|
||||
return my_open(emu, p(4), of_convert(u32(8)), u32(12));
|
||||
case 6: // sys_close
|
||||
return (uint32_t)close(i32(4));
|
||||
return close(i32(4));
|
||||
case 11: // execve
|
||||
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
|
||||
return my_execve(emu, p(4), p(8), p(12));
|
||||
#ifndef __NR_alarm
|
||||
case 27:
|
||||
return alarm(R_EBX);
|
||||
#endif
|
||||
case 45: // brk
|
||||
return (uintptr_t)ElfSetBrk(p(4));
|
||||
return (intptr_t)ElfSetBrk(p(4));
|
||||
case 67: // sys_sigaction
|
||||
return my_syscall_sigaction(emu, u32(4), (x86_sigaction_restorer_t*)p(8), (x86_sigaction_restorer_t*)p(12), u32(16));
|
||||
case 91: // munmap
|
||||
return (uint32_t)my_munmap(emu, p(4), u32(8));
|
||||
return 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));
|
||||
return my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
|
||||
#endif
|
||||
case 120: // clone
|
||||
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
|
||||
@@ -879,19 +881,19 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
}
|
||||
// x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
|
||||
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), u32(4), newemu, p(12), p(16), p(20));
|
||||
return (uint32_t)ret;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return (uint32_t)syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
|
||||
return syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
|
||||
break;
|
||||
case 123: // SYS_modify_ldt
|
||||
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
|
||||
case 125: // mprotect
|
||||
return (uint32_t)my_mprotect(emu, p(4), u32(8), i32(12));
|
||||
return my_mprotect(emu, p(4), u32(8), i32(12));
|
||||
case 174: // sys_rt_sigaction
|
||||
return (uint32_t)my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
|
||||
return my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
|
||||
case 192: // mmap2
|
||||
return (uint32_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
|
||||
return (intptr_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
|
||||
case 243: // set_thread_area
|
||||
return my_set_thread_area((thread_area_t*)p(4));
|
||||
#ifndef NOALIGN
|
||||
@@ -918,12 +920,22 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
#endif
|
||||
#ifndef __NR_getrandom
|
||||
case 355: // getrandom
|
||||
return (uint32_t)my_getrandom(emu, p(4), u32(8), u32(12));
|
||||
return my_getrandom(emu, p(4), u32(8), u32(12));
|
||||
#endif
|
||||
#ifndef __NR_memfd_create
|
||||
case 356: // memfd_create
|
||||
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
|
||||
return my_memfd_create(emu, (void*)R_EBX, R_ECX);
|
||||
#endif
|
||||
case 449:
|
||||
#ifdef __NR_futex_waitv
|
||||
if(box86_futex_waitv)
|
||||
return syscall(__NR_futex_waitv, u32(4), u32(8), u32(12), u32(16), u32(20));
|
||||
else
|
||||
#endif
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
if(!(warned&(1<<s))) {
|
||||
printf_log(LOG_INFO, "Warning: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
|
||||
@@ -932,5 +944,4 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+3
-1
@@ -217,7 +217,9 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
|
||||
mutex_lock(&context->mutex_tls);
|
||||
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
|
||||
if(sizeTLSData(oldata->tlssize)!=sizeTLSData(context->tlssize) || (oldata->n_elfs/0xff)!=(context->elfsize/0xff)) {
|
||||
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
|
||||
if(sizeTLSData(oldata->tlssize)) {
|
||||
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
|
||||
}
|
||||
tlsdatasize_t *data = setupTLSData(context);
|
||||
// copy the relevent old part, in case something changed
|
||||
memcpy((void*)((uintptr_t)data->data-oldata->tlssize), (void*)((uintptr_t)oldata->data-oldata->tlssize), oldata->tlssize);
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#ifdef DYNAREC
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
#ifdef DYNAREC
|
||||
// disabling for now, seems to have a negative impact on performances
|
||||
//#define USE_CUSTOM_MUTEX
|
||||
#endif
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -59,6 +63,7 @@ typedef struct needed_libs_s {
|
||||
int size;
|
||||
char** names;
|
||||
library_t** libs;
|
||||
int nb_done;
|
||||
} needed_libs_t;
|
||||
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
@@ -140,6 +145,7 @@ typedef struct box86context_s {
|
||||
pthread_mutex_t mutex_bridge;
|
||||
pthread_mutex_t mutex_lock;
|
||||
#else
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
uint32_t mutex_once;
|
||||
uint32_t mutex_once2;
|
||||
uint32_t mutex_trace;
|
||||
@@ -147,6 +153,15 @@ typedef struct box86context_s {
|
||||
uint32_t mutex_thread;
|
||||
uint32_t mutex_bridge;
|
||||
uint32_t mutex_dyndump;
|
||||
#else
|
||||
pthread_mutex_t mutex_once;
|
||||
pthread_mutex_t mutex_once2;
|
||||
pthread_mutex_t mutex_trace;
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
pthread_mutex_t mutex_bridge;
|
||||
pthread_mutex_t mutex_dyndump;
|
||||
#endif
|
||||
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
|
||||
@@ -192,10 +207,10 @@ typedef struct box86context_s {
|
||||
|
||||
uint8_t canary[4];
|
||||
|
||||
uintptr_t signals[MAX_SIGNAL];
|
||||
uintptr_t restorer[MAX_SIGNAL];
|
||||
int onstack[MAX_SIGNAL];
|
||||
int is_sigaction[MAX_SIGNAL];
|
||||
uintptr_t signals[MAX_SIGNAL+1];
|
||||
uintptr_t restorer[MAX_SIGNAL+1];
|
||||
int onstack[MAX_SIGNAL+1];
|
||||
int is_sigaction[MAX_SIGNAL+1];
|
||||
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
|
||||
int no_sigsegv;
|
||||
int no_sigill;
|
||||
@@ -208,7 +223,7 @@ typedef struct box86context_s {
|
||||
int current_line;
|
||||
} box86context_t;
|
||||
|
||||
#ifndef DYNAREC
|
||||
#ifndef USE_CUSTOM_MUTEX
|
||||
#define mutex_lock(A) pthread_mutex_lock(A)
|
||||
#define mutex_trylock(A) pthread_mutex_trylock(A)
|
||||
#define mutex_unlock(A) pthread_mutex_unlock(A)
|
||||
|
||||
@@ -40,13 +40,13 @@ uintptr_t getJumpAddress(uintptr_t addr);
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#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)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
|
||||
|
||||
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 setProtection_elf(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);
|
||||
@@ -61,7 +61,9 @@ int AreaInHotPage(uintptr_t start, uintptr_t end);
|
||||
void AddHotPage(uintptr_t addr);
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask);
|
||||
void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask);
|
||||
int isBlockFree(void* hint, size_t size);
|
||||
|
||||
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
|
||||
int unlockCustommemMutex();
|
||||
|
||||
+10
-1
@@ -27,15 +27,20 @@ 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_missing;
|
||||
extern int box86_dynarec_test;
|
||||
extern int box86_dynarec_jvm;
|
||||
extern int box86_dynarec_tbb;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
extern int arm_div;
|
||||
extern int arm_aes;
|
||||
extern int arm_pmull;
|
||||
#endif
|
||||
#endif
|
||||
extern int box86_libcef;
|
||||
extern int box86_sdl2_jguid;
|
||||
extern int dlsym_error; // log dlsym error
|
||||
extern int cycle_log; // if using rolling logs
|
||||
extern int trace_xmm; // include XMM reg in trace?
|
||||
@@ -53,8 +58,10 @@ extern int box86_musl;
|
||||
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
|
||||
extern int box86_nogtk; // disabling the use of wrapped gtk
|
||||
extern int box86_novulkan; // disabling the use of wrapped vulkan
|
||||
extern int box86_futex_waitv;
|
||||
extern int box86_mapclean;
|
||||
extern int box86_showsegv;
|
||||
extern int box86_mutex_aligned;
|
||||
extern int allow_missing_symbols;
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
@@ -99,6 +106,8 @@ void init_malloc_hook();
|
||||
#define box_calloc calloc
|
||||
#define box_free free
|
||||
#define box_memalign memalign
|
||||
#define box_strdup strdup
|
||||
#define box_realpath realpath
|
||||
#else
|
||||
extern size_t(*box_malloc_usable_size)(const void*);
|
||||
extern void* __libc_malloc(size_t);
|
||||
@@ -111,8 +120,8 @@ extern void* __libc_memalign(size_t, size_t);
|
||||
#define box_calloc __libc_calloc
|
||||
#define box_free __libc_free
|
||||
#define box_memalign __libc_memalign
|
||||
#endif
|
||||
extern char* box_strdup(const char* s);
|
||||
extern char* box_realpath(const char* path, char* ret);
|
||||
#endif
|
||||
|
||||
#endif //__DEBUG_H_
|
||||
@@ -14,6 +14,7 @@ typedef struct kh_defaultversion_s kh_defaultversion_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
#endif
|
||||
|
||||
// Open an elfheader. Transfert control of f to elfheader also!
|
||||
elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
|
||||
void FreeElfHeader(elfheader_t** head);
|
||||
const char* ElfName(elfheader_t* head);
|
||||
@@ -21,11 +22,9 @@ const char* ElfPath(elfheader_t* head);
|
||||
void ElfAttachLib(elfheader_t* head, library_t* lib);
|
||||
|
||||
int CalcLoadAddr(elfheader_t* head);
|
||||
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
|
||||
int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
|
||||
void FreeElfMemory(elfheader_t* head);
|
||||
int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded);
|
||||
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, size_t* stackalign);
|
||||
@@ -68,6 +67,7 @@ int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const
|
||||
int GetVersionIndice(elfheader_t* h, const char* vername);
|
||||
int GetNeededVersionCnt(elfheader_t* h, const char* libname);
|
||||
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx);
|
||||
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver);
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
|
||||
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
|
||||
|
||||
@@ -37,6 +37,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
|
||||
|
||||
void MapLibRemoveLib(lib_t* maplib, library_t* lib);
|
||||
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref);
|
||||
|
||||
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname);
|
||||
|
||||
|
||||
+17
-1
@@ -345,4 +345,20 @@ typedef struct my_GValue_s
|
||||
} my_GValue_t;
|
||||
|
||||
void alignNGValue(my_GValue_t* v, void* value, int n);
|
||||
void unalignNGValue(void* value, my_GValue_t* v, int n);
|
||||
void unalignNGValue(void* value, my_GValue_t* v, int n);
|
||||
|
||||
// longjmp / setjmp
|
||||
typedef struct jump_buff_i386_s {
|
||||
uint32_t save_ebx;
|
||||
uint32_t save_esi;
|
||||
uint32_t save_edi;
|
||||
uint32_t save_ebp;
|
||||
uint32_t save_esp;
|
||||
uint32_t save_eip;
|
||||
} jump_buff_i386_t;
|
||||
|
||||
typedef struct __jmp_buf_tag_s {
|
||||
jump_buff_i386_t __jmpbuf;
|
||||
int __mask_was_saved;
|
||||
sigset_t __saved_mask;
|
||||
} __jmp_buf_tag_t;
|
||||
+23
-1
@@ -96,7 +96,9 @@ typedef enum {
|
||||
d_rcr8,
|
||||
d_rcr16,
|
||||
d_rcr32,
|
||||
d_unknown //46
|
||||
d_shld32,
|
||||
d_shrd32,
|
||||
d_unknown //66
|
||||
} defered_flags_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@@ -289,6 +291,26 @@ typedef union {
|
||||
#define R_ES emu->segs[_ES]
|
||||
#define R_FS emu->segs[_FS]
|
||||
#define R_GS emu->segs[_GS]
|
||||
#define S_EAX emu->regs[_AX].sdword[0]
|
||||
#define S_EBX emu->regs[_BX].sdword[0]
|
||||
#define S_ECX emu->regs[_CX].sdword[0]
|
||||
#define S_EDX emu->regs[_DX].sdword[0]
|
||||
#define S_EDI emu->regs[_DI].sdword[0]
|
||||
#define S_ESI emu->regs[_SI].sdword[0]
|
||||
#define S_ESP emu->regs[_SP].sdword[0]
|
||||
#define S_EBP emu->regs[_BP].sdword[0]
|
||||
#define S_AX emu->regs[_AX].sword[0]
|
||||
#define S_BX emu->regs[_BX].sword[0]
|
||||
#define S_CX emu->regs[_CX].sword[0]
|
||||
#define S_DX emu->regs[_DX].sword[0]
|
||||
#define S_DI emu->regs[_DI].sword[0]
|
||||
#define S_SI emu->regs[_SI].sword[0]
|
||||
#define S_SP emu->regs[_SP].sword[0]
|
||||
#define S_BP emu->regs[_BP].sword[0]
|
||||
#define S_AL emu->regs[_AX].sbyte[0]
|
||||
#define S_AH emu->regs[_AX].sbyte[1]
|
||||
#define S_CX emu->regs[_CX].sword[0]
|
||||
#define S_CL emu->regs[_CX].sbyte[0]
|
||||
|
||||
#define ACCESS_FLAG(F) emu->eflags.f._##F
|
||||
#define SET_FLAG(F) emu->eflags.f._##F = 1
|
||||
|
||||
@@ -38,5 +38,6 @@ void init_signal_helper(box86context_t* context);
|
||||
void fini_signal_helper();
|
||||
|
||||
void emit_signal(x86emu_t* emu, int sig, void* addr, int code);
|
||||
void emit_div0(x86emu_t* emu, void* addr, int code);
|
||||
|
||||
#endif //__SIGNALS_H__
|
||||
@@ -4,23 +4,16 @@
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef struct emu_jmpbuf_s {
|
||||
void* jmpbuf;
|
||||
int jmpbuf_ok;
|
||||
x86emu_t* emu;
|
||||
} emu_jmpbuf_t;
|
||||
|
||||
void CleanStackSize(box86context_t* context);
|
||||
|
||||
emu_jmpbuf_t* GetJmpBuf();
|
||||
|
||||
void init_pthread_helper();
|
||||
void fini_pthread_helper(box86context_t* context);
|
||||
void clean_current_emuthread(void);
|
||||
|
||||
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
|
||||
void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet);
|
||||
|
||||
#ifndef DYNAREC
|
||||
#ifndef USE_CUSTOM_MUTEX
|
||||
//check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
|
||||
int checkUnlockMutex(void* m);
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
} \
|
||||
} else \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
@@ -30,7 +30,7 @@
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
} \
|
||||
} else \
|
||||
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
|
||||
memcpy(&A, (void*)globoffs, sizeof(A)); \
|
||||
|
||||
+95
-46
@@ -41,7 +41,7 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
|
||||
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
for(int i=0; i<(*maplib)->libsz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
DecRefCount(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
}*/
|
||||
@@ -105,6 +105,28 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
|
||||
++maplib->libsz;
|
||||
}
|
||||
|
||||
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref)
|
||||
{
|
||||
if(libraryInMapLib(maplib, lib))
|
||||
return;
|
||||
if (maplib->libsz == maplib->libcap) {
|
||||
maplib->libcap += 8;
|
||||
maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
|
||||
}
|
||||
// find insersion point
|
||||
int point = ref?maplib->libsz:0;
|
||||
if(ref)
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(maplib->libraries[i]==ref) {
|
||||
point = i;
|
||||
i = maplib->libsz;
|
||||
}
|
||||
if(point<maplib->libsz)
|
||||
memmove(&maplib->libraries[point+1], &maplib->libraries[point], sizeof(library_t*)*(maplib->libsz-point));
|
||||
maplib->libraries[point] = lib;
|
||||
++maplib->libsz;
|
||||
}
|
||||
|
||||
static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
|
||||
{
|
||||
if(!src)
|
||||
@@ -177,34 +199,31 @@ int isLibLocal(library_t* lib)
|
||||
return libraryInMapLib(my_context->local_maplib, lib);
|
||||
}
|
||||
|
||||
static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
|
||||
static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
const char* path = needed->names[n];
|
||||
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
|
||||
printf_dump(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
|
||||
// first check if lib is already loaded
|
||||
library_t *lib = getLib(my_context->maplib, path);
|
||||
if(lib) {
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
needed->libs[n] = lib;
|
||||
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
|
||||
printf_dump(LOG_DEBUG, "Already present in maplib => success\n");
|
||||
return 0;
|
||||
}
|
||||
// check also in the local loaded lib
|
||||
lib = getLib(my_context->local_maplib, path);
|
||||
if(lib) {
|
||||
printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
|
||||
printf_dump(LOG_DEBUG, "Already present in local_maplib => success\n");
|
||||
needed->libs[n] = lib;
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
if(local) {
|
||||
// add lib to maplib...
|
||||
if(maplib) {
|
||||
if(lib->maplib) {
|
||||
MapLibAddMapLib(maplib, lib, lib->maplib);
|
||||
}
|
||||
if(!libraryInMapLib(maplib, lib))
|
||||
MapLibAddLib(maplib, lib);
|
||||
if(maplib->ownlibs)
|
||||
MapLibRemoveMapLib(my_context->local_maplib, maplib);
|
||||
if(*maplib) {
|
||||
if(!libraryInMapLib(*maplib, lib))
|
||||
MapLibPrependLib(*maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution
|
||||
if((*maplib)->ownlibs)
|
||||
MapLibRemoveMapLib(my_context->local_maplib, *maplib);
|
||||
}
|
||||
} else {
|
||||
// promote lib from local to global...
|
||||
@@ -215,17 +234,15 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
|
||||
// load a new one
|
||||
needed->libs[n] = lib = NewLibrary(path, box86, verneeded);
|
||||
if(!lib) {
|
||||
printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
|
||||
printf_dump(LOG_DEBUG, "Faillure to create lib => fail\n");
|
||||
return 1; //Error
|
||||
}
|
||||
|
||||
// add lib now
|
||||
if(local) {
|
||||
MapLibAddLib(my_context->local_maplib, lib);
|
||||
if(maplib) {
|
||||
MapLibAddLib(maplib, lib);
|
||||
if(!lib->maplib)
|
||||
lib->maplib = maplib;
|
||||
if(*maplib) {
|
||||
MapLibAddLib(*maplib, lib);
|
||||
} else {
|
||||
lib->maplib = NewLibrarian(box86, 0);
|
||||
MapLibAddLib(lib->maplib, lib);
|
||||
@@ -234,11 +251,11 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
|
||||
MapLibAddLib(my_context->maplib, lib);
|
||||
}
|
||||
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
if(!*maplib)
|
||||
*maplib = (local)?lib->maplib:my_context->maplib;
|
||||
|
||||
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
|
||||
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
|
||||
if(AddSymbolsLibrary(*maplib, lib, emu)) { // also add needed libs
|
||||
printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -247,7 +264,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
|
||||
linkmap_t *lm = addLinkMapLib(lib);
|
||||
if(!lm) {
|
||||
// Crashed already
|
||||
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
|
||||
printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n");
|
||||
return 1;
|
||||
}
|
||||
lm->l_addr = (Elf32_Addr)GetElfDelta(lib->e.elf);
|
||||
@@ -271,8 +288,8 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// load dependancies and launch init sequence
|
||||
if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box86, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
if(LoadNeededLibs(mainelf, maplib, local, bindnow, box86, emu)) {
|
||||
printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// some special case, where dependancies may not be correct
|
||||
@@ -297,12 +314,12 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf
|
||||
|
||||
// finalize the lib
|
||||
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
|
||||
printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// success
|
||||
printf_log(LOG_DEBUG, "Created lib and added to maplib => success\n");
|
||||
printf_dump(LOG_DEBUG, "Created lib and added to maplib => success\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -326,7 +343,7 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, e
|
||||
int ret = 0;
|
||||
// Add libs and symbol
|
||||
for(int i=0; i<needed->size; ++i) {
|
||||
if(AddNeededLib_add(maplib, local, needed, i, verneeded, box86, emu)) {
|
||||
if(AddNeededLib_add(&maplib, local, needed, i, verneeded, box86, emu)) {
|
||||
printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]);
|
||||
ret = 1;
|
||||
}
|
||||
@@ -351,20 +368,20 @@ void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86conte
|
||||
return;
|
||||
for(int i=0; i<needed->size; ++i) {
|
||||
if(box86_log>=LOG_DEBUG && needed->libs[i])
|
||||
printf_log(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
|
||||
printf_dump(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
|
||||
AddNeededLib_remove(maplib, local, &needed->libs[i], box86, emu);
|
||||
}
|
||||
}
|
||||
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
|
||||
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
|
||||
return getLib(maplib, name);
|
||||
}
|
||||
|
||||
library_t* GetLibInternal(const char* name)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
|
||||
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
|
||||
library_t* lib = getLib(my_context->maplib, name);
|
||||
if(!lib) lib = getLib(my_context->local_maplib, name);
|
||||
return lib;
|
||||
@@ -388,6 +405,20 @@ static int isLocal(elfheader_t* self, library_t* l)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CheckNeededLibs(needed_libs_t* needed)
|
||||
{
|
||||
while(needed->nb_done<needed->size) {
|
||||
library_t* lib = needed->libs[needed->nb_done++];
|
||||
if(lib) {
|
||||
int n = GetNeededLibsN(lib);
|
||||
char** names = GetNeededLibsNames(lib);
|
||||
for (int i=0; i<n; ++i) {
|
||||
add1lib_neededlib(needed, GetNeededLib(lib, i), names[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver)
|
||||
{
|
||||
assert(self); // need self for this one
|
||||
@@ -450,26 +481,33 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
|
||||
if(my_context->preload)
|
||||
for(int i=0; i<my_context->preload->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
|
||||
// search in needed libs from neededlibs first, in order
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
if(maplib==my_context->maplib) {
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
// This kind-of create a map to search lib only 1 time, and in order of needed...
|
||||
if(my_context->neededlibs)
|
||||
CheckNeededLibs(my_context->neededlibs);
|
||||
// search in needed libs from neededlibs first, in order
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// search in global symbols
|
||||
if(maplib) {
|
||||
if(self && self!=my_context->elfs[0] && self!=(void*)1)
|
||||
if((maplib==my_context->maplib) && self && self!=my_context->elfs[0] && self!=(void*)1)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
|
||||
if(*start)
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
|
||||
if(*start) {
|
||||
@@ -482,8 +520,17 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
|
||||
int ok = 0;
|
||||
// GetSymbolStartEnd should not change start/end if symbol is not found
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
|
||||
if(*start)
|
||||
if(*start) {
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
// search in needed libs from neededlibs first, in order
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver))
|
||||
if(*start) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
|
||||
@@ -542,7 +589,9 @@ static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name,
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
|
||||
// This kind-of create a map to search lib only 1 time, and in order of needed...
|
||||
if(my_context->neededlibs)
|
||||
CheckNeededLibs(my_context->neededlibs);
|
||||
// search in needed libs from neededlibs first, in order
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
|
||||
+147
-171
@@ -51,7 +51,7 @@ typedef struct bridged_s {
|
||||
|
||||
KHASH_MAP_INIT_STR(bridgemap, bridged_t)
|
||||
|
||||
KHASH_MAP_IMPL_STR(symbolmap, wrapper_t)
|
||||
KHASH_MAP_IMPL_STR(symbolmap, symbol1_t)
|
||||
KHASH_MAP_IMPL_STR(symbol2map, symbol2_t)
|
||||
KHASH_MAP_IMPL_STR(datamap, uint32_t)
|
||||
|
||||
@@ -209,7 +209,7 @@ static void initWrappedLib(library_t *lib, box86context_t* context) {
|
||||
printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, error_str);
|
||||
return; // non blocker...
|
||||
}
|
||||
printf_log(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
|
||||
printf_dump(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
|
||||
lib->fini = wrappedlibs[i].fini;
|
||||
lib->getglobal = WrappedLib_GetGlobal;
|
||||
lib->getweak = WrappedLib_GetWeak;
|
||||
@@ -225,13 +225,13 @@ static void initWrappedLib(library_t *lib, box86context_t* context) {
|
||||
linkmap_t *lm = addLinkMapLib(lib);
|
||||
if(!lm) {
|
||||
// Crashed already
|
||||
printf_log(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name);
|
||||
printf_dump(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name);
|
||||
break;
|
||||
}
|
||||
struct link_map real_lm;
|
||||
#ifndef ANDROID
|
||||
if(dlinfo(lib->w.lib, RTLD_DI_LINKMAP, &real_lm)) {
|
||||
printf_log(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name);
|
||||
printf_dump(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name);
|
||||
}
|
||||
#endif
|
||||
lm->l_addr = real_lm.l_addr;
|
||||
@@ -253,7 +253,7 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
|
||||
}
|
||||
elfheader_t *elf_header = LoadAndCheckElfHeader(f, libname, 0);
|
||||
if(!elf_header) {
|
||||
printf_log(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming...
|
||||
printf_dump(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming...
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -261,25 +261,14 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
|
||||
if(CalcLoadAddr(elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname);
|
||||
FreeElfHeader(&elf_header);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
// allocate memory
|
||||
if(AllocElfMemory(context, elf_header, 0)) {
|
||||
printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", libname);
|
||||
// allocate and load elf
|
||||
if(AllocLoadElfMemory(context, elf_header, 0)) {
|
||||
printf_log(LOG_NONE, "Error: locading elf %s\n", libname);
|
||||
FreeElfHeader(&elf_header);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
// Load elf into memory
|
||||
if(LoadElfMemory(f, context, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: loading in memory elf %s\n", libname);
|
||||
FreeElfHeader(&elf_header);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
// can close the file now
|
||||
fclose(f);
|
||||
if(verneeded && !isElfHasNeededVer(elf_header, lib->name, verneeded)) {
|
||||
// incompatible, discard and continue the search
|
||||
FreeElfHeader(&elf_header);
|
||||
@@ -304,21 +293,25 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
|
||||
lib->path = box_strdup(libname);
|
||||
}
|
||||
|
||||
printf_log(LOG_INFO, "Using emulated %s\n", libname);
|
||||
printf_dump(LOG_INFO, "Using emulated %s\n", libname);
|
||||
#ifdef DYNAREC
|
||||
if(libname && box86_dynarec_bleeding_edge && strstr(libname, "libmonobdwgc-2.0.so")) {
|
||||
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
printf_dump(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
box86_dynarec_bigblock = 0;
|
||||
box86_dynarec_strongmem = 1;
|
||||
}
|
||||
if(libname && box86_dynarec_jvm && strstr(libname, "libjvm.so")) {
|
||||
printf_log(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
printf_dump(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
box86_dynarec_bigblock = 0;
|
||||
box86_dynarec_strongmem = 1;
|
||||
}
|
||||
if(libname && box86_dynarec_tbb && strstr(libname, "libtbb.so")) {
|
||||
printf_dump(LOG_INFO, "libtbb detected, enable Dynarec StrongMem\n");
|
||||
box86_dynarec_strongmem = 3;
|
||||
}
|
||||
#endif
|
||||
if(libname && box86_libcef && strstr(libname, "libcef.so")) {
|
||||
printf_log(LOG_INFO, "libcef detected, using malloc_hack_2\n");
|
||||
printf_dump(LOG_INFO, "libcef detected, using malloc_hack_2\n");
|
||||
box86_malloc_hack = 2;
|
||||
}
|
||||
return 1;
|
||||
@@ -372,7 +365,7 @@ static int isEssentialLib(const char* name) {
|
||||
|
||||
library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* verneeded)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
|
||||
printf_dump(LOG_DEBUG, "Trying to load \"%s\"\n", path);
|
||||
library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
|
||||
lib->path = box_realpath(path, NULL);
|
||||
if(!lib->path)
|
||||
@@ -383,7 +376,7 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
|
||||
lib->name = Path2Name(path);
|
||||
lib->nbdot = NbDot(lib->name);
|
||||
lib->type = LIB_UNNKNOW;
|
||||
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
printf_dump(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
if(box86_nopulse) {
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
box_free(lib->name);
|
||||
@@ -468,12 +461,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t*
|
||||
int weak;
|
||||
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
box_free(trace_func);
|
||||
trace_func = NULL;
|
||||
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
box_free(trace_func);
|
||||
trace_func = NULL;
|
||||
}
|
||||
@@ -484,50 +477,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t*
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReloadLibrary(library_t* lib, x86emu_t* emu)
|
||||
{
|
||||
if(lib->type==LIB_EMULATED) {
|
||||
elfheader_t *elf_header = lib->e.elf;
|
||||
// reload image in memory and re-run the mapping
|
||||
char libname[MAX_PATH];
|
||||
strcpy(libname, lib->path);
|
||||
int found = FileExist(libname, IS_FILE);
|
||||
if(!found && !strchr(lib->path, '/'))
|
||||
for(int i=0; i<my_context->box86_ld_lib.size; ++i)
|
||||
{
|
||||
strcpy(libname, my_context->box86_ld_lib.paths[i]);
|
||||
strcat(libname, lib->path);
|
||||
if(FileExist(libname, IS_FILE))
|
||||
break;
|
||||
}
|
||||
if(!FileExist(libname, IS_FILE)) {
|
||||
printf_log(LOG_NONE, "Error: open file to re-load elf %s\n", libname);
|
||||
return 1; // failed to reload...
|
||||
}
|
||||
FILE *f = fopen(libname, "rb");
|
||||
if(!f) {
|
||||
printf_log(LOG_NONE, "Error: cannot open file to re-load elf %s (errno=%d/%s)\n", libname, errno, strerror(errno));
|
||||
return 1; // failed to reload...
|
||||
}
|
||||
if(ReloadElfMemory(f, my_context, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: re-loading in memory elf %s\n", libname);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
// can close the file now
|
||||
fclose(f);
|
||||
// should bindnow be store in a per/library basis?
|
||||
if(RelocateElf(my_context->maplib, lib->maplib, 0, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
|
||||
return 1;
|
||||
}
|
||||
RelocateElfPlt(my_context->maplib, lib->maplib, 0, elf_header);
|
||||
// init (will use PltRelocator... because some other libs are not yet resolved)
|
||||
RunElfInit(elf_header, emu);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FiniLibrary(library_t* lib, x86emu_t* emu)
|
||||
{
|
||||
switch (lib->type) {
|
||||
@@ -546,7 +495,7 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
|
||||
|
||||
library_t* lib = *the_lib;
|
||||
|
||||
printf_log(LOG_DEBUG, "Free1Library %s\n", lib->name);
|
||||
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name);
|
||||
// remove lib from maplib/local_maplib...
|
||||
if(my_context) {
|
||||
MapLibRemoveLib(my_context->maplib, lib);
|
||||
@@ -655,7 +604,7 @@ int IsSameLib(library_t* lib, const char* path)
|
||||
}
|
||||
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!name[0])
|
||||
if(!lib || !name[0])
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
@@ -801,73 +750,8 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
|
||||
// check in mysymbolmap
|
||||
khint_t k = kh_get(symbolmap, lib->w.mysymbolmap, name);
|
||||
if (k!=kh_end(lib->w.mysymbolmap)) {
|
||||
char buff[200];
|
||||
if(lib->w.altmy)
|
||||
strcpy(buff, lib->w.altmy);
|
||||
else
|
||||
strcpy(buff, "my_");
|
||||
strcat(buff, name);
|
||||
symbol = dlsym(my_context->box86lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.mysymbolmap, k), symbol, 0, name);
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
// check in stsymbolmap (return struct...)
|
||||
k = kh_get(symbolmap, lib->w.stsymbolmap, name);
|
||||
if (k!=kh_end(lib->w.stsymbolmap)) {
|
||||
char buff[200];
|
||||
if(lib->w.altmy)
|
||||
strcpy(buff, lib->w.altmy);
|
||||
else
|
||||
strcpy(buff, "my_");
|
||||
strcat(buff, name);
|
||||
symbol = dlsym(my_context->box86lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.stsymbolmap, k), symbol, sizeof(void*), name);
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
// check in symbolmap
|
||||
k = kh_get(symbolmap, lib->w.symbolmap, name);
|
||||
if (k!=kh_end(lib->w.symbolmap)) {
|
||||
symbol = dlsym(lib->w.lib, name);
|
||||
if(!symbol && lib->w.altprefix) {
|
||||
char newname[200];
|
||||
strcpy(newname, lib->w.altprefix);
|
||||
strcat(newname, name);
|
||||
symbol = dlsym(lib->w.lib, newname);
|
||||
}
|
||||
if(!symbol)
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, name);
|
||||
if(!symbol && lib->w.altprefix) {
|
||||
char newname[200];
|
||||
strcpy(newname, lib->w.altprefix);
|
||||
strcat(newname, name);
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, newname);
|
||||
}
|
||||
if(!symbol) {
|
||||
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
|
||||
return 0;
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.symbolmap, k), symbol, 0, name);
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
if(!noweak) {
|
||||
// check in wmysymbolmap
|
||||
khint_t k = kh_get(symbolmap, lib->w.wmysymbolmap, name);
|
||||
if (k!=kh_end(lib->w.wmysymbolmap)) {
|
||||
symbol1_t *s = &kh_value(lib->w.mysymbolmap, k);
|
||||
if(!s->resolved) {
|
||||
char buff[200];
|
||||
if(lib->w.altmy)
|
||||
strcpy(buff, lib->w.altmy);
|
||||
@@ -877,15 +761,45 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
|
||||
symbol = dlsym(my_context->box86lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.wmysymbolmap, k), symbol, 0, name);
|
||||
*size = sizeof(void*);
|
||||
*weak = 1;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
k = kh_get(symbolmap, lib->w.wsymbolmap, name);
|
||||
if (k!=kh_end(lib->w.wsymbolmap)) {
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
// check in stsymbolmap (return struct...)
|
||||
k = kh_get(symbolmap, lib->w.stsymbolmap, name);
|
||||
if (k!=kh_end(lib->w.stsymbolmap)) {
|
||||
symbol1_t *s = &kh_value(lib->w.stsymbolmap, k);
|
||||
if(!s->resolved) {
|
||||
char buff[200];
|
||||
if(lib->w.altmy)
|
||||
strcpy(buff, lib->w.altmy);
|
||||
else
|
||||
strcpy(buff, "my_");
|
||||
strcat(buff, name);
|
||||
symbol = dlsym(my_context->box86lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
return 0;
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, sizeof(void*), name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
// check in symbolmap
|
||||
k = kh_get(symbolmap, lib->w.symbolmap, name);
|
||||
if (k!=kh_end(lib->w.symbolmap)) {
|
||||
symbol1_t *s = &kh_value(lib->w.symbolmap, k);
|
||||
if(!s->resolved) {
|
||||
symbol = dlsym(lib->w.lib, name);
|
||||
if(!symbol && lib->w.altprefix) {
|
||||
char newname[200];
|
||||
@@ -902,11 +816,69 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, newname);
|
||||
}
|
||||
if(!symbol) {
|
||||
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
|
||||
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
|
||||
return 0;
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.wsymbolmap, k), symbol, 0, name);
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = 0;
|
||||
return 1;
|
||||
}
|
||||
if(!noweak) {
|
||||
// check in wmysymbolmap
|
||||
khint_t k = kh_get(symbolmap, lib->w.wmysymbolmap, name);
|
||||
if (k!=kh_end(lib->w.wmysymbolmap)) {
|
||||
symbol1_t *s = &kh_value(lib->w.wmysymbolmap, k);
|
||||
if(!s->resolved) {
|
||||
char buff[200];
|
||||
if(lib->w.altmy)
|
||||
strcpy(buff, lib->w.altmy);
|
||||
else
|
||||
strcpy(buff, "my_");
|
||||
strcat(buff, name);
|
||||
symbol = dlsym(my_context->box86lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
return 0;
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = 1;
|
||||
return 1;
|
||||
}
|
||||
k = kh_get(symbolmap, lib->w.wsymbolmap, name);
|
||||
if (k!=kh_end(lib->w.wsymbolmap)) {
|
||||
symbol1_t *s = &kh_value(lib->w.wsymbolmap, k);
|
||||
if(!s->resolved) {
|
||||
symbol = dlsym(lib->w.lib, name);
|
||||
if(!symbol && lib->w.altprefix) {
|
||||
char newname[200];
|
||||
strcpy(newname, lib->w.altprefix);
|
||||
strcat(newname, name);
|
||||
symbol = dlsym(lib->w.lib, newname);
|
||||
}
|
||||
if(!symbol)
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, name);
|
||||
if(!symbol && lib->w.altprefix) {
|
||||
char newname[200];
|
||||
strcpy(newname, lib->w.altprefix);
|
||||
strcat(newname, name);
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, newname);
|
||||
}
|
||||
if(!symbol) {
|
||||
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
|
||||
return 0;
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = 1;
|
||||
return 1;
|
||||
@@ -914,25 +886,29 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
|
||||
}
|
||||
// check in symbol2map
|
||||
k = kh_get(symbol2map, lib->w.symbol2map, name);
|
||||
if (k!=kh_end(lib->w.symbol2map))
|
||||
if(!noweak || !kh_value(lib->w.symbol2map, k).weak)
|
||||
if (k!=kh_end(lib->w.symbol2map)) {
|
||||
symbol2_t *s = &kh_value(lib->w.symbol2map, k);
|
||||
if(!noweak || !s->weak)
|
||||
{
|
||||
symbol = dlsym(lib->w.lib, kh_value(lib->w.symbol2map, k).name);
|
||||
if(!symbol)
|
||||
symbol = dlsym(RTLD_DEFAULT, kh_value(lib->w.symbol2map, k).name); // search globaly maybe
|
||||
if(!symbol)
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, kh_value(lib->w.symbol2map, k).name);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name);
|
||||
return 0;
|
||||
} else
|
||||
AddOffsetSymbol(my_context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->w.bridge, kh_value(lib->w.symbol2map, k).w, symbol, 0, name);
|
||||
if(!s->resolved) {
|
||||
symbol = dlsym(lib->w.lib, kh_value(lib->w.symbol2map, k).name);
|
||||
if(!symbol)
|
||||
symbol = dlsym(RTLD_DEFAULT, kh_value(lib->w.symbol2map, k).name); // search globaly maybe
|
||||
if(!symbol)
|
||||
symbol = GetNativeSymbolUnversioned(lib->w.lib, kh_value(lib->w.symbol2map, k).name);
|
||||
if(!symbol) {
|
||||
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name);
|
||||
return 0;
|
||||
}
|
||||
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
|
||||
s->resolved = 1;
|
||||
}
|
||||
*addr = s->addr;
|
||||
*size = sizeof(void*);
|
||||
*weak = kh_value(lib->w.symbol2map, k).weak;
|
||||
*weak = s->weak;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -956,7 +932,7 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add
|
||||
int GetNeededLibsN(library_t* lib) {
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->size:0;
|
||||
case LIB_EMULATED: return lib->e.elf->needed->size;
|
||||
case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->size:0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -974,11 +950,11 @@ library_t* GetNeededLib(library_t* lib, int idx)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
char** GetNeededLibs(library_t* lib)
|
||||
char** GetNeededLibsNames(library_t* lib)
|
||||
{
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->names:NULL;
|
||||
case LIB_EMULATED: return lib->e.elf->needed->names;
|
||||
case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->names:NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1095,7 +1071,7 @@ void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name)
|
||||
// add it
|
||||
if(needed->size+1<=needed->cap)
|
||||
return;
|
||||
needed->cap = needed->size+1;
|
||||
needed->cap = needed->size+4;
|
||||
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
|
||||
needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*));
|
||||
needed->libs[needed->size] = lib;
|
||||
|
||||
@@ -17,13 +17,21 @@ typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
|
||||
typedef struct symbol1_s {
|
||||
wrapper_t w;
|
||||
int resolved;
|
||||
uintptr_t addr;
|
||||
} symbol1_t;
|
||||
|
||||
typedef struct symbol2_s {
|
||||
wrapper_t w;
|
||||
const char* name;
|
||||
int weak;
|
||||
wrapper_t w;
|
||||
const char* name;
|
||||
int weak;
|
||||
int resolved;
|
||||
uintptr_t addr;
|
||||
} symbol2_t;
|
||||
|
||||
KHASH_MAP_DECLARE_STR(symbolmap, wrapper_t)
|
||||
KHASH_MAP_DECLARE_STR(symbolmap, symbol1_t)
|
||||
KHASH_MAP_DECLARE_STR(symbol2map, symbol2_t)
|
||||
KHASH_MAP_DECLARE_STR(datamap, uint32_t)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
GO("libpthread.so.0", libpthread)
|
||||
GO("librt.so.1", librt)
|
||||
GO("libbsd.so.0", libbsd)
|
||||
GO("libGL.so.1", libgl)
|
||||
GO("libGL.so", libgl)
|
||||
GO("libGLU.so.1", libglu)
|
||||
@@ -70,6 +71,7 @@ GO("libopenal.so", openal)
|
||||
GO("openal.so", openal)
|
||||
GO("libalut.so.0", alut)
|
||||
GO("libalure.so.1", alure)
|
||||
GO("libOpenCL.so.1", opencl)
|
||||
GO("libcurl.so.4", curl)
|
||||
GO("libcurl-gnutls.so.4", curl)
|
||||
GO("libcurl.so.3", curl)
|
||||
@@ -107,6 +109,7 @@ GO("libdbus-glib-1.so.2", dbusglib1)
|
||||
GO("libgudev-1.0.so.0", gudev1)
|
||||
GO("libappindicator.so.1", appindicator)
|
||||
GO("libappindicator3.so.1", appindicator3)
|
||||
GO("libayatana-appindicator3.so.1", ayatanaappindicator3)
|
||||
GO("libatk-1.0.so.0", atk)
|
||||
GO("libatk-bridge-2.0.so.0", atkbridge)
|
||||
GO("libpangoft2-1.0.so", pangoft2)
|
||||
@@ -174,10 +177,13 @@ GO("libpcap.so.0", pcap)
|
||||
GO("libFAudio.so.0", faudio)
|
||||
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
|
||||
GO("libfuse.so.2", libfuse)
|
||||
GO("libatomic.so.1", atomic)
|
||||
GO("libpcre.so.3", libpcre)
|
||||
|
||||
#ifdef ANDROID
|
||||
GO("libc.so", libc)
|
||||
GO("libm.so", libm)
|
||||
GO("libbsd.so", libbsd)
|
||||
GO("libdl.so", libdl)
|
||||
GO("libcups.so", libcups)
|
||||
GO("liblber-2.4.so", lber)
|
||||
@@ -194,6 +200,48 @@ GO("libX11.so", libx11)
|
||||
GO("libXext.so", libxext)
|
||||
GO("libxcb.so", libxcb)
|
||||
GO("libXau.so", libxau)
|
||||
GO("libXxf86vm.so", libxxf86vm)
|
||||
GO("libXinerama.so", xinerama)
|
||||
GO("libXrandr.so", libxrandr)
|
||||
GO("libXfixes.so", libxfixes)
|
||||
GO("libXcursor.so", libxcursor)
|
||||
GO("libXrender.so", libxrender)
|
||||
GO("libXpresent.so", libxpresent)
|
||||
GO("libXft.so", libxft)
|
||||
GO("libXi.so", libxi)
|
||||
GO("libXss.so", libxss)
|
||||
GO("libXpm.so", libxpm)
|
||||
GO("libXdmcp.so", libxdmcp)
|
||||
GO("libX11-xcb.so", libx11xcb)
|
||||
GO("libxcb-xfixes.so", libxcbxfixes)
|
||||
GO("libxcb-shape.so", libxcbshape)
|
||||
GO("libxcb-shm.so", libxcbshm)
|
||||
GO("libxcb-randr.so", libxcbrandr)
|
||||
GO("libxcb-image.so", libxcbimage)
|
||||
GO("libxcb-keysyms.so", libxcbkeysyms)
|
||||
GO("libxcb-xtest.so", libxcbxtest)
|
||||
GO("libxcb-dri2.so", libxcbdri2)
|
||||
GO("libxcb-dri3.so", libxcbdri3)
|
||||
GO("libxcb-present.so", libxcbpresent)
|
||||
GO("libXtst.so", libxtst)
|
||||
GO("libXt.so", libxt)
|
||||
GO("libXcomposite.so", libxcomposite)
|
||||
GO("libXdamage.so", libxdamage)
|
||||
GO("libXmu.so", libxmu)
|
||||
GO("libpulse-simple.so", pulsesimple)
|
||||
GO("libpulse.so", pulse)
|
||||
GO("libsndfile.so", libsndfile)
|
||||
GO("libusb-1.0.so", libusb1)
|
||||
GO("libgstapp-1.0.so", gstapp)
|
||||
GO("libgstaudio-1.0.so", gstaudio)
|
||||
GO("libgstbase-1.0.so", gstbase)
|
||||
GO("libgstreamer-1.0.so", gstreamer)
|
||||
GO("libgsttag-1.0.so", gsttag)
|
||||
GO("libgstvideo-1.0.so", gstvideo)
|
||||
GO("libvorbisfile.so", vorbisfile)
|
||||
GO("libvorbis.so", libvorbis)
|
||||
GO("libogg.so", libogg)
|
||||
GO("libz.so", libz)
|
||||
GO("libandroid-shmem.so", androidshmem)
|
||||
#else
|
||||
GO("libc.so.6", libc)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <stdint.h>
|
||||
#include <asm/stat.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "x86emu.h"
|
||||
#include "emu/x86emu_private.h"
|
||||
|
||||
+169
-70
@@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -37,6 +38,7 @@
|
||||
|
||||
|
||||
/* Definitions taken from the kernel headers. */
|
||||
#ifndef __i386__
|
||||
enum
|
||||
{
|
||||
REG_GS = 0,
|
||||
@@ -78,6 +80,7 @@ enum
|
||||
REG_SS
|
||||
# define REG_SS REG_SS
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef uint32_t i386_gregset_t[19];
|
||||
struct i386_fpreg
|
||||
@@ -282,7 +285,7 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
emu->test.test = 0;
|
||||
#endif
|
||||
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_ESP);
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p, emu=%p\n", GetTID(), (void*)fnc, (void*)R_ESP, emu);
|
||||
|
||||
/*SetFS(emu, default_fs);*/
|
||||
for (int i=0; i<6; ++i)
|
||||
@@ -301,8 +304,8 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
}
|
||||
va_end (va);
|
||||
|
||||
int oldquitonlongjmp = emu->quitonlongjmp;
|
||||
emu->quitonlongjmp = 2;
|
||||
int oldquitonlongjmp = emu->flags.quitonlongjmp;
|
||||
emu->flags.quitonlongjmp = 2;
|
||||
|
||||
emu->eflags.x32 &= ~(1<<F_TF); // this one needs to cleared
|
||||
|
||||
@@ -312,17 +315,18 @@ uint32_t RunFunctionHandler(int* exit, int dynarec, i386_ucontext_t* sigcontext,
|
||||
EmuCall(emu, fnc);
|
||||
|
||||
uint32_t ret = R_EAX;
|
||||
emu->quitonlongjmp = oldquitonlongjmp;
|
||||
emu->flags.quitonlongjmp = oldquitonlongjmp;
|
||||
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec_test)
|
||||
if(box86_dynarec_test) {
|
||||
emu->test.test = 0;
|
||||
emu->test.clean = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(emu->longjmp) {
|
||||
if(emu->flags.longjmp) {
|
||||
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
|
||||
emu->longjmp = 0;
|
||||
emu->flags.longjmp = 0;
|
||||
if(sigcontext) {
|
||||
printf_log(LOG_DEBUG, "Longjmp in signal\n");
|
||||
#define GO(R) sigcontext->uc_mcontext.gregs[REG_E##R] = emu->regs[_##R].dword[0]
|
||||
@@ -485,11 +489,14 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
x86emu_t *emu = thread_get_emu();
|
||||
uintptr_t *frame = (uintptr_t*)R_ESP;
|
||||
#if defined(DYNAREC) && defined(__arm__)
|
||||
ucontext_t *p = (ucontext_t *)ucntx;
|
||||
void * pc = (void*)p->uc_mcontext.arm_pc;
|
||||
dynablock_t* db = (dynablock_t*)cur_db;//FindDynablockFromNativeAddress(pc);
|
||||
if(db) {
|
||||
frame = (uintptr_t*)p->uc_mcontext.arm_r8;
|
||||
ucontext_t *p = (ucontext_t *)ucntx;
|
||||
void* pc = NULL;
|
||||
if(ucntx) {
|
||||
pc = (void*)p->uc_mcontext.arm_pc;
|
||||
if(db) {
|
||||
frame = (uintptr_t*)p->uc_mcontext.arm_r8;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)ucntx; (void)cur_db;
|
||||
@@ -537,7 +544,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
sigcontext->uc_mcontext.gregs[REG_CS] = R_CS;
|
||||
sigcontext->uc_mcontext.gregs[REG_SS] = R_SS;
|
||||
#if defined(DYNAREC) && defined(__arm__)
|
||||
if(db) {
|
||||
if(db && p) {
|
||||
sigcontext->uc_mcontext.gregs[REG_EAX] = p->uc_mcontext.arm_r4;
|
||||
sigcontext->uc_mcontext.gregs[REG_ECX] = p->uc_mcontext.arm_r5;
|
||||
sigcontext->uc_mcontext.gregs[REG_EDX] = p->uc_mcontext.arm_r6;
|
||||
@@ -597,20 +604,59 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
else if(sig==SIGSEGV) {
|
||||
if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[REG_EIP]) {
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || ((uintptr_t)info->si_addr==0))?13:14;
|
||||
} else if((info->si_code==SEGV_ACCERR) && !(prot&PROT_WRITE)) {
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0002; // write flag issue
|
||||
/*if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[REG_ESP])<16)
|
||||
if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[REG_ESP])<8)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 12; // stack overflow probably
|
||||
else*/
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 14; // PAGE_FAULT
|
||||
else
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 14;
|
||||
} else {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code==SEGV_ACCERR)?13:14;
|
||||
//REG_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0004; // read error? there is no execute control in box86 anyway
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0004; // read error? there is no execute control in box86 anyway, and no easy way to see if it's a write error
|
||||
}
|
||||
if(info->si_code == SEGV_ACCERR && old_code)
|
||||
*old_code = -1;
|
||||
if(info->si_errno == 0x1234) {
|
||||
info2->si_errno = 0;
|
||||
if(*(uint8_t*)info->si_addr == 0xCD) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 13;
|
||||
info2->si_addr = NULL;
|
||||
uint8_t int_n = *(uint8_t*)(info->si_addr+1);
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x2 | (int_n<<3);
|
||||
// some special cases...
|
||||
if(int_n==3) {
|
||||
info2->si_signo = SIGTRAP;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 3;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP]+=2; // segfault after the INT
|
||||
} else if(int_n==0x04) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 4;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP]+=2; // segfault after the INT
|
||||
}
|
||||
} else if(*(uint8_t*)info->si_addr == 0xCC) {
|
||||
info2->si_signo = SIGTRAP;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 3;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP]+=1; // segfault after the INT
|
||||
} else if(*(uint8_t*)info->si_addr == 0xCE) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 4;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP]+=1; // segfault after the INTO
|
||||
info2->si_addr = NULL;
|
||||
} else {
|
||||
info2->si_code = 128;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP] = (uintptr_t)info2->si_addr;
|
||||
info2->si_addr = NULL;
|
||||
}
|
||||
} else if(info->si_errno==0xcafe) {
|
||||
info2->si_errno = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 0;
|
||||
info2->si_signo = SIGFPE;
|
||||
}
|
||||
} else if(sig==SIGFPE) {
|
||||
if (info->si_code == FPE_INTOVF) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 4;
|
||||
@@ -618,10 +664,18 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 19;
|
||||
}
|
||||
}
|
||||
else if(sig==SIGILL)
|
||||
else if(sig==SIGILL) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 6;
|
||||
else if(sig==SIGTRAP)
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = info->si_code;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0000;
|
||||
info2->si_addr = (void*)sigcontext->uc_mcontext.gregs[REG_EIP];
|
||||
info2->si_code = 2;
|
||||
}
|
||||
else if(sig==SIGTRAP) {
|
||||
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 3;
|
||||
sigcontext->uc_mcontext.gregs[REG_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP] = (uintptr_t)info2->si_addr;
|
||||
info2->si_addr = NULL;
|
||||
}
|
||||
// call the signal handler
|
||||
i386_mcontext_t sigmcontext_copy = sigcontext->uc_mcontext;
|
||||
// save old value from emu
|
||||
@@ -643,9 +697,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
dynarec = 1;
|
||||
#endif
|
||||
if(simple)
|
||||
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 1, sig);
|
||||
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[info2->si_signo], 1, info2->si_signo);
|
||||
else
|
||||
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext);
|
||||
ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[info2->si_signo], 3, info2->si_signo, info2, sigcontext);
|
||||
// restore old value from emu
|
||||
if(used_stack) // release stack
|
||||
new_ss->ss_flags = 0;
|
||||
@@ -656,9 +710,8 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
#undef GO
|
||||
|
||||
if(memcmp(&sigcontext->uc_mcontext, &sigmcontext_copy, sizeof(i386_mcontext_t))) {
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
if(ejb->jmpbuf_ok) {
|
||||
#define GO(R) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[REG_E##R]
|
||||
if(emu->jmpbuf) {
|
||||
#define GO(R) emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[REG_E##R]
|
||||
GO(AX);
|
||||
GO(CX);
|
||||
GO(DX);
|
||||
@@ -668,12 +721,12 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
GO(SP);
|
||||
GO(BX);
|
||||
#undef GO
|
||||
ejb->emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[REG_EIP];
|
||||
emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[REG_EIP];
|
||||
sigcontext->uc_mcontext.gregs[REG_EIP] = R_EIP;
|
||||
// flags
|
||||
ejb->emu->eflags.x32=sigcontext->uc_mcontext.gregs[REG_EFL];
|
||||
emu->eflags.x32=sigcontext->uc_mcontext.gregs[REG_EFL];
|
||||
// get segments
|
||||
#define GO(S) ejb->emu->segs[_##S]=sigcontext->uc_mcontext.gregs[REG_##S]; ejb->emu->segs_serial[_##S] = 0
|
||||
#define GO(S) emu->segs[_##S]=sigcontext->uc_mcontext.gregs[REG_##S]; emu->segs_serial[_##S] = 0
|
||||
GO(GS);
|
||||
GO(FS);
|
||||
GO(ES);
|
||||
@@ -681,7 +734,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
GO(CS);
|
||||
GO(SS);
|
||||
#undef GO
|
||||
load_fpreg(ejb->emu, &sigcontext->xstate.fpstate);
|
||||
load_fpreg(emu, &sigcontext->xstate.fpstate);
|
||||
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n");
|
||||
if(old_code)
|
||||
*old_code = -1; // re-init the value to allow another segfault at the same place
|
||||
@@ -692,7 +745,11 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock(1);
|
||||
#endif
|
||||
siglongjmp(ejb->jmpbuf, 1);
|
||||
#ifdef ANDROID
|
||||
siglongjmp(*emu->jmpbuf, 1);
|
||||
#else
|
||||
siglongjmp(emu->jmpbuf, 1);
|
||||
#endif
|
||||
}
|
||||
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[REG_EIP]!=sigmcontext_copy.gregs[REG_EIP])?" (EIP changed)":"");
|
||||
}
|
||||
@@ -732,8 +789,18 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
|
||||
}
|
||||
|
||||
extern void* current_helper;
|
||||
#ifdef DYNAREC
|
||||
#define USE_SIGNAL_MUTEX
|
||||
#ifdef USE_SIGNAL_MUTEX
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
static uint32_t mutex_dynarec_prot = 0;
|
||||
#else
|
||||
static pthread_mutex_t mutex_dynarec_prot = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||
#endif
|
||||
#define lock_signal() mutex_lock(&mutex_dynarec_prot)
|
||||
#define unlock_signal() mutex_unlock(&mutex_dynarec_prot)
|
||||
#else // USE_SIGNAL_MUTEX
|
||||
#define lock_signal()
|
||||
#define unlock_signal()
|
||||
#endif
|
||||
|
||||
void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
@@ -744,6 +811,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
void* addr = (void*)info->si_addr; // address that triggered the issue
|
||||
uintptr_t x86pc = (uintptr_t)-1;
|
||||
void* esp = NULL;
|
||||
x86emu_t* emu = thread_get_emu();
|
||||
#ifdef __arm__
|
||||
void * pc = (void*)p->uc_mcontext.arm_pc;
|
||||
#elif defined __i386
|
||||
@@ -767,13 +835,13 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
#ifdef DYNAREC
|
||||
if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) {
|
||||
CancelBlock(0);
|
||||
cancelFillBlock(); // Segfault inside a Fillblock
|
||||
relockMutex(Locks);
|
||||
cancelFillBlock(); // Segfault inside a Fillblock
|
||||
}
|
||||
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);
|
||||
lock_signal();
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
// check if SMC inside block
|
||||
@@ -792,53 +860,58 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
repeated_count = 0;
|
||||
}
|
||||
if(db && ((addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) || db_need_test)) {
|
||||
if(db && p->uc_mcontext.arm_r0>0x10000)
|
||||
emu = (x86emu_t*)p->uc_mcontext.arm_r0;
|
||||
// dynablock got auto-dirty! need to get out of it!!!
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
if(ejb->jmpbuf_ok) {
|
||||
ejb->emu->regs[_AX].dword[0] = p->uc_mcontext.arm_r4;
|
||||
ejb->emu->regs[_CX].dword[0] = p->uc_mcontext.arm_r5;
|
||||
ejb->emu->regs[_DX].dword[0] = p->uc_mcontext.arm_r6;
|
||||
ejb->emu->regs[_BX].dword[0] = p->uc_mcontext.arm_r7;
|
||||
ejb->emu->regs[_SP].dword[0] = p->uc_mcontext.arm_r8;
|
||||
ejb->emu->regs[_BP].dword[0] = p->uc_mcontext.arm_r9;
|
||||
ejb->emu->regs[_SI].dword[0] = p->uc_mcontext.arm_r10;
|
||||
ejb->emu->regs[_DI].dword[0] = p->uc_mcontext.arm_fp;
|
||||
ejb->emu->ip.dword[0] = getX86Address(db, (uintptr_t)pc);
|
||||
ejb->emu->eflags.x32 = p->uc_mcontext.arm_ip;
|
||||
if(emu->jmpbuf) {
|
||||
emu->regs[_AX].dword[0] = p->uc_mcontext.arm_r4;
|
||||
emu->regs[_CX].dword[0] = p->uc_mcontext.arm_r5;
|
||||
emu->regs[_DX].dword[0] = p->uc_mcontext.arm_r6;
|
||||
emu->regs[_BX].dword[0] = p->uc_mcontext.arm_r7;
|
||||
emu->regs[_SP].dword[0] = p->uc_mcontext.arm_r8;
|
||||
emu->regs[_BP].dword[0] = p->uc_mcontext.arm_r9;
|
||||
emu->regs[_SI].dword[0] = p->uc_mcontext.arm_r10;
|
||||
emu->regs[_DI].dword[0] = p->uc_mcontext.arm_fp;
|
||||
emu->ip.dword[0] = getX86Address(db, (uintptr_t)pc);
|
||||
emu->eflags.x32 = p->uc_mcontext.arm_ip;
|
||||
// check special case opcodes, to adjust regs
|
||||
int special = isSpecialCases(ejb->emu->ip.dword[0], getDBX86N(db, (uintptr_t)pc));
|
||||
int special = isSpecialCases(emu->ip.dword[0], getDBX86N(db, (uintptr_t)pc));
|
||||
switch(special) {
|
||||
case CASE_MOVS:
|
||||
ejb->emu->regs[_SI].dword[0] -= p->uc_mcontext.arm_r3;
|
||||
emu->regs[_SI].dword[0] -= p->uc_mcontext.arm_r3;
|
||||
break;
|
||||
}
|
||||
if(addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) {
|
||||
dynarec_log(LOG_INFO, "Auto-SMC detected, getting out of current Dynablock (speical=%d)!\n", special);
|
||||
} else {
|
||||
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);
|
||||
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*)emu->ip.dword[0], special);
|
||||
}
|
||||
//relockMutex(Locks); // do not relock because of he siglongjmp
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
unlock_signal();
|
||||
if(Locks & is_dyndump_locked)
|
||||
CancelBlock(1);
|
||||
ejb->emu->test.clean = 0;
|
||||
siglongjmp(ejb->jmpbuf, 2);
|
||||
emu->test.clean = 0;
|
||||
#ifdef ANDROID
|
||||
siglongjmp(*(JUMPBUFF*)emu->jmpbuf, 2);
|
||||
#else
|
||||
siglongjmp(emu->jmpbuf, 2);
|
||||
#endif
|
||||
}
|
||||
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);
|
||||
unlock_signal();
|
||||
// if there is no write permission, don't return and continue to program signal handling
|
||||
relockMutex(Locks);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
unlock_signal();
|
||||
} 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
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
|
||||
mutex_lock(&mutex_dynarec_prot);
|
||||
lock_signal();
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
if(db && db->x86_addr>= addr && (db->x86_addr+db->x86_size)<addr) {
|
||||
@@ -857,7 +930,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
relockMutex(Locks);
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
unlock_signal();
|
||||
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);
|
||||
@@ -879,14 +952,14 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for
|
||||
refreshProtection((uintptr_t)addr);
|
||||
relockMutex(Locks);
|
||||
sched_yield(); // give time to the other process
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
unlock_signal();
|
||||
return; // try again
|
||||
}
|
||||
glitch2_pc = NULL;
|
||||
glitch2_addr = NULL;
|
||||
glitch2_prot = 0;
|
||||
}
|
||||
mutex_unlock(&mutex_dynarec_prot);
|
||||
unlock_signal();
|
||||
}
|
||||
if(!db_searched)
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
@@ -943,6 +1016,8 @@ exit(-1);
|
||||
sprintf(myarg, "%d", pid);
|
||||
if(jit_gdb==2)
|
||||
execlp("gdbserver", "gdbserver", "127.0.0.1:1234", "--attach", myarg, (char*)NULL);
|
||||
else if(jit_gdb==3)
|
||||
execlp("lldb", "lldb", "-p", myarg, (char*)NULL);
|
||||
else
|
||||
execlp("gdb", "gdb", "-pid", myarg, (char*)NULL);
|
||||
exit(-1);
|
||||
@@ -1040,7 +1115,6 @@ void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
void emit_signal(x86emu_t* emu, int sig, void* addr, int code)
|
||||
{
|
||||
int Locks = unlockMutex();
|
||||
ucontext_t ctx = {0};
|
||||
void* db = NULL;
|
||||
siginfo_t info = {0};
|
||||
info.si_signo = sig;
|
||||
@@ -1048,12 +1122,26 @@ void emit_signal(x86emu_t* emu, int sig, void* addr, int code)
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
printf_log(LOG_INFO, "Emit Signal %d at IP=%p / addr=%p, code=%d\n", sig, (void*)R_EIP, addr, code);
|
||||
my_sigactionhandler_oldcode(sig, 0, Locks, &info, &ctx, NULL, db);
|
||||
my_sigactionhandler_oldcode(sig, 0, Locks, &info, NULL, NULL, db);
|
||||
}
|
||||
|
||||
void emit_div0(x86emu_t* emu, void* addr, int code)
|
||||
{
|
||||
int Locks = unlockMutex();
|
||||
siginfo_t info = {0};
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0xcafe;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
const char* x86name = NULL;
|
||||
const char* elfname = NULL;
|
||||
printf_log(LOG_INFO, "Emit Divide by 0 at IP=%p, addr=%p\n", (void*)R_EIP, addr);
|
||||
my_sigactionhandler_oldcode(SIGSEGV, 0, Locks, &info, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
EXPORT sighandler_t my_signal(x86emu_t* emu, int signum, sighandler_t handler)
|
||||
{
|
||||
if(signum<0 || signum>=MAX_SIGNAL) {
|
||||
if(signum<0 || signum>MAX_SIGNAL) {
|
||||
errno = EINVAL;
|
||||
return SIG_ERR;
|
||||
}
|
||||
@@ -1083,7 +1171,7 @@ EXPORT sighandler_t my_sysv_signal(x86emu_t* emu, int signum, sighandler_t handl
|
||||
|
||||
int EXPORT my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact)
|
||||
{
|
||||
if(signum<0 || signum>=MAX_SIGNAL) {
|
||||
if(signum<0 || signum>MAX_SIGNAL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -1137,7 +1225,7 @@ __attribute__((alias("my_sigaction")));
|
||||
int EXPORT my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Syscall/Sigaction(signum=%d, act=%p, old=%p, size=%d)\n", signum, act, oldact, sigsetsize);
|
||||
if(signum<0 || signum>=MAX_SIGNAL) {
|
||||
if(signum<0 || signum>MAX_SIGNAL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -1284,8 +1372,12 @@ EXPORT int my_getcontext(x86emu_t* emu, void* ucp)
|
||||
u->uc_mcontext.gregs[REG_CS] = R_CS;
|
||||
u->uc_mcontext.gregs[REG_SS] = R_SS;
|
||||
// get FloatPoint status
|
||||
if(u->uc_mcontext.fpregs)
|
||||
save_fpreg(emu, u->uc_mcontext.fpregs);
|
||||
// get signal mask
|
||||
sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
|
||||
// ensure uc_link is properly initialized
|
||||
u->uc_link = emu->uc_link;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1315,10 +1407,13 @@ EXPORT int my_setcontext(x86emu_t* emu, void* ucp)
|
||||
R_CS = u->uc_mcontext.gregs[REG_CS];
|
||||
R_SS = u->uc_mcontext.gregs[REG_SS];
|
||||
// set FloatPoint status
|
||||
if(u->uc_mcontext.fpregs)
|
||||
load_fpreg(emu, u->uc_mcontext.fpregs);
|
||||
// set signal mask
|
||||
//sigprocmask(SIG_SETMASK, NULL, (sigset_t*)&u->uc_sigmask);
|
||||
sigprocmask(SIG_SETMASK, (sigset_t*)&u->uc_sigmask, NULL);
|
||||
// set uc_link
|
||||
emu->uc_link = u->uc_link;
|
||||
errno = 0;
|
||||
|
||||
return R_EAX;
|
||||
}
|
||||
@@ -1329,11 +1424,10 @@ EXPORT int my_makecontext(x86emu_t* emu, void* ucp, void* fnc, int32_t argc, int
|
||||
// printf_log(LOG_NONE, "Warning: call to unimplemented makecontext\n");
|
||||
i386_ucontext_t *u = (i386_ucontext_t*)ucp;
|
||||
// setup stack
|
||||
u->uc_mcontext.gregs[REG_ESP] = (uintptr_t)u->uc_stack.ss_sp + u->uc_stack.ss_size - 4;
|
||||
uint32_t* esp = (uint32_t*)((uintptr_t)u->uc_stack.ss_sp + u->uc_stack.ss_size - 4);
|
||||
// setup the function
|
||||
u->uc_mcontext.gregs[REG_EIP] = (intptr_t)fnc;
|
||||
// setup args
|
||||
uint32_t* esp = (uint32_t*)u->uc_mcontext.gregs[REG_ESP];
|
||||
for (int i=0; i<argc; ++i) {
|
||||
// push value
|
||||
--esp;
|
||||
@@ -1356,16 +1450,21 @@ EXPORT int my_swapcontext(x86emu_t* emu, void* ucp1, void* ucp2)
|
||||
my_setcontext(emu, ucp2);
|
||||
return 0;
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_SIGNAL_MUTEX
|
||||
static void atfork_child_dynarec_prot(void)
|
||||
{
|
||||
arm_lock_stored(&mutex_dynarec_prot, 0);
|
||||
#ifdef USE_CUSTOM_MUTEX
|
||||
native_lock_store(&mutex_dynarec_prot, 0);
|
||||
#else
|
||||
pthread_mutex_t tmp = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||
memcpy(&mutex_dynarec_prot, &tmp, sizeof(mutex_dynarec_prot));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void init_signal_helper(box86context_t* context)
|
||||
{
|
||||
// setup signal handling
|
||||
for(int i=0; i<MAX_SIGNAL; ++i) {
|
||||
for(int i=0; i<=MAX_SIGNAL; ++i) {
|
||||
context->signals[i] = 1; // SIG_DFL
|
||||
}
|
||||
struct sigaction action = {0};
|
||||
@@ -1380,7 +1479,7 @@ void init_signal_helper(box86context_t* context)
|
||||
sigaction(SIGILL, &action, NULL);
|
||||
|
||||
pthread_once(&sigstack_key_once, sigstack_key_alloc);
|
||||
#ifdef DYNAREC
|
||||
#ifdef USE_SIGNAL_MUTEX
|
||||
atfork_child_dynarec_prot();
|
||||
pthread_atfork(NULL, NULL, atfork_child_dynarec_prot);
|
||||
#endif
|
||||
|
||||
+93
-170
@@ -25,6 +25,7 @@
|
||||
#include "x86trace.h"
|
||||
#include "dynarec.h"
|
||||
#include "bridge.h"
|
||||
#include "myalign.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
@@ -49,22 +50,6 @@ typedef struct threadstack_s {
|
||||
size_t stacksize;
|
||||
} threadstack_t;
|
||||
|
||||
// longjmp / setjmp
|
||||
typedef struct jump_buff_i386_s {
|
||||
uint32_t save_ebx;
|
||||
uint32_t save_esi;
|
||||
uint32_t save_edi;
|
||||
uint32_t save_ebp;
|
||||
uint32_t save_esp;
|
||||
uint32_t save_eip;
|
||||
} jump_buff_i386_t;
|
||||
|
||||
typedef struct __jmp_buf_tag_s {
|
||||
jump_buff_i386_t __jmpbuf;
|
||||
int __mask_was_saved;
|
||||
sigset_t __saved_mask;
|
||||
} __jmp_buf_tag_t;
|
||||
|
||||
typedef struct x86_unwind_buff_s {
|
||||
struct {
|
||||
jump_buff_i386_t __cancel_jmp_buf;
|
||||
@@ -136,53 +121,47 @@ int GetStackSize(x86emu_t* emu, uintptr_t attr, void** stack, size_t* stacksize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void InitCancelThread()
|
||||
{
|
||||
}
|
||||
|
||||
static void FreeCancelThread(box86context_t* context)
|
||||
{
|
||||
if(!context)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
static __pthread_unwind_buf_t* AddCancelThread(x86_unwind_buff_t* buff)
|
||||
{
|
||||
__pthread_unwind_buf_t* r = (__pthread_unwind_buf_t*)box_calloc(1, sizeof(__pthread_unwind_buf_t));
|
||||
buff->__pad[3] = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
static __pthread_unwind_buf_t* GetCancelThread(x86_unwind_buff_t* buff)
|
||||
{
|
||||
return (__pthread_unwind_buf_t*)buff->__pad[3];
|
||||
}
|
||||
|
||||
static void DelCancelThread(x86_unwind_buff_t* buff)
|
||||
{
|
||||
__pthread_unwind_buf_t* r = (__pthread_unwind_buf_t*)buff->__pad[3];
|
||||
box_free(r);
|
||||
buff->__pad[3] = NULL;
|
||||
}
|
||||
#endif
|
||||
void my_longjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val);
|
||||
|
||||
typedef struct emuthread_s {
|
||||
uintptr_t fnc;
|
||||
void* arg;
|
||||
x86emu_t* emu;
|
||||
int cancel_cap, cancel_size;
|
||||
x86_unwind_buff_t **cancels;
|
||||
} emuthread_t;
|
||||
|
||||
static pthread_key_t thread_key;
|
||||
|
||||
static void emuthread_destroy(void* p)
|
||||
{
|
||||
emuthread_t *et = (emuthread_t*)p;
|
||||
if(!et)
|
||||
return;
|
||||
void* ptr;
|
||||
// free x86emu
|
||||
if(et) {
|
||||
FreeX86Emu(&et->emu);
|
||||
box_free(et);
|
||||
}
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
}
|
||||
|
||||
static pthread_key_t thread_key;
|
||||
static void emuthread_cancel(void* p)
|
||||
{
|
||||
emuthread_t *et = (emuthread_t*)p;
|
||||
if(!et)
|
||||
return;
|
||||
// check cancels threads
|
||||
for(int i=et->cancel_size-1; i>=0; --i) {
|
||||
et->emu->flags.quitonlongjmp = 0;
|
||||
my_longjmp(et->emu, et->cancels[i]->__cancel_jmp_buf, 1);
|
||||
DynaRun(et->emu); // will return after a __pthread_unwind_next()
|
||||
}
|
||||
box_free(et->cancels);
|
||||
et->cancels=NULL;
|
||||
et->cancel_size = et->cancel_cap = 0;
|
||||
}
|
||||
|
||||
void thread_set_emu(x86emu_t* emu)
|
||||
{
|
||||
@@ -243,7 +222,9 @@ static void* pthread_routine(void* p)
|
||||
Push32(emu, (uintptr_t)et->arg);
|
||||
PushExit(emu);
|
||||
R_EIP = et->fnc;
|
||||
pthread_cleanup_push(emuthread_cancel, p);
|
||||
DynaRun(et->emu);
|
||||
pthread_cleanup_pop(0);
|
||||
void* ret = (void*)R_EAX;
|
||||
//void* ret = (void*)RunFunctionWithEmu(et->emu, 0, et->fnc, 1, et->arg);
|
||||
return ret;
|
||||
@@ -343,66 +324,35 @@ void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet
|
||||
return pthread_routine;
|
||||
}
|
||||
|
||||
void my_longjmp(x86emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p, int32_t __val);
|
||||
|
||||
#ifndef ANDROID
|
||||
#define CANCEL_MAX 8
|
||||
static __thread x86emu_t* cancel_emu[CANCEL_MAX] = {0};
|
||||
static __thread x86_unwind_buff_t* cancel_buff[CANCEL_MAX] = {0};
|
||||
static __thread int cancel_deep = 0;
|
||||
EXPORT void my___pthread_register_cancel(x86emu_t* emu, void* B)
|
||||
EXPORT void my___pthread_register_cancel(x86emu_t* emu, void* buff)
|
||||
{
|
||||
(void)B;
|
||||
// get a stack local copy of the args, as may be live in some register depending the architecture (like ARM)
|
||||
if(cancel_deep<0) {
|
||||
printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
|
||||
cancel_deep = 0;
|
||||
}
|
||||
if(cancel_deep!=CANCEL_MAX-1)
|
||||
++cancel_deep;
|
||||
else
|
||||
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, calling __pthread_register_cancel(...) too many time\n");}
|
||||
|
||||
cancel_emu[cancel_deep] = emu;
|
||||
// on i386, the function as __cleanup_fct_attribute attribute: so 1st parameter is in register
|
||||
x86_unwind_buff_t* buff = cancel_buff[cancel_deep] = (x86_unwind_buff_t*)R_EAX;
|
||||
__pthread_unwind_buf_t * pbuff = AddCancelThread(buff);
|
||||
if(__sigsetjmp((struct __jmp_buf_tag*)(void*)pbuff->__cancel_jmp_buf, 0)) {
|
||||
//DelCancelThread(cancel_buff); // no del here, it will be delete by unwind_next...
|
||||
int i = cancel_deep--;
|
||||
emu = cancel_emu[i];
|
||||
my_longjmp(emu, cancel_buff[i]->__cancel_jmp_buf, 1);
|
||||
DynaRun(emu); // resume execution
|
||||
return;
|
||||
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
|
||||
if(et->cancel_cap == et->cancel_size) {
|
||||
et->cancel_cap+=8;
|
||||
et->cancels = box_realloc(et->cancels, sizeof(x86_unwind_buff_t*)*et->cancel_cap);
|
||||
}
|
||||
|
||||
__pthread_register_cancel(pbuff);
|
||||
et->cancels[et->cancel_size++] = (void*)R_EAX;
|
||||
}
|
||||
|
||||
EXPORT void my___pthread_unregister_cancel(x86emu_t* emu, x86_unwind_buff_t* buff)
|
||||
{
|
||||
// on i386, the function as __cleanup_fct_attribute attribute: so 1st parameter is in register
|
||||
buff = (x86_unwind_buff_t*)R_EAX;
|
||||
__pthread_unwind_buf_t * pbuff = GetCancelThread(buff);
|
||||
__pthread_unregister_cancel(pbuff);
|
||||
|
||||
--cancel_deep;
|
||||
DelCancelThread(buff);
|
||||
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
|
||||
for (int i=et->cancel_size-1; i>=0; --i) {
|
||||
if(et->cancels[i] == (x86_unwind_buff_t*)R_EAX) {
|
||||
if(i!=et->cancel_size-1)
|
||||
memmove(et->cancels+i, et->cancels+i+1, sizeof(x86_unwind_buff_t*)*(et->cancel_size-i-1));
|
||||
et->cancel_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT void my___pthread_unwind_next(x86emu_t* emu, void* p)
|
||||
{
|
||||
(void)p;
|
||||
// on i386, the function as __cleanup_fct_attribute attribute: so 1st parameter is in register
|
||||
x86_unwind_buff_t* buff = (x86_unwind_buff_t*)R_EAX;
|
||||
__pthread_unwind_buf_t pbuff = *GetCancelThread(buff);
|
||||
DelCancelThread(buff);
|
||||
// function is noreturn, putting stuff on the stack to have it auto-free (is that correct?)
|
||||
__pthread_unwind_next(&pbuff);
|
||||
// just in case it does return
|
||||
emu->quit = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
KHASH_MAP_INIT_INT(once, int)
|
||||
|
||||
@@ -438,28 +388,6 @@ GO(27) \
|
||||
GO(28) \
|
||||
GO(29)
|
||||
|
||||
// key_destructor
|
||||
#define GO(A) \
|
||||
static uintptr_t my_key_destructor_fct_##A = 0; \
|
||||
static void my_key_destructor_##A(void* a) \
|
||||
{ \
|
||||
RunFunctionFmt(my_key_destructor_fct_##A, "p", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findkey_destructorFct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_key_destructor_fct_##A == (uintptr_t)fct) return my_key_destructor_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_key_destructor_fct_##A == 0) {my_key_destructor_fct_##A = (uintptr_t)fct; return my_key_destructor_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for pthread key_destructor callback\n");
|
||||
return NULL;
|
||||
}
|
||||
// cleanup_routine
|
||||
#define GO(A) \
|
||||
static uintptr_t my_cleanup_routine_fct_##A = 0; \
|
||||
@@ -483,6 +411,28 @@ static void* findcleanup_routineFct(void* fct)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// key_dtor
|
||||
#define GO(A) \
|
||||
static uintptr_t my_key_dtor_fct_##A = 0; \
|
||||
static void my_key_dtor_##A(void* a) \
|
||||
{ \
|
||||
RunFunctionFmt(my_key_dtor_fct_##A, "p", a); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
static void* findkey_dtorFct(void* fct)
|
||||
{
|
||||
if(!fct) return fct;
|
||||
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
|
||||
#define GO(A) if(my_key_dtor_fct_##A == (uintptr_t)fct) return my_key_dtor_##A;
|
||||
SUPER()
|
||||
#undef GO
|
||||
#define GO(A) if(my_key_dtor_fct_##A == 0) {my_key_dtor_fct_##A = (uintptr_t)fct; return my_key_dtor_##A; }
|
||||
SUPER()
|
||||
#undef GO
|
||||
printf_log(LOG_NONE, "Warning, no more slot for pthread key_dtor callback\n");
|
||||
return NULL;
|
||||
}
|
||||
#undef SUPER
|
||||
|
||||
|
||||
@@ -509,13 +459,18 @@ int EXPORT my_pthread_once(x86emu_t* emu, int* once, void* cb)
|
||||
}
|
||||
EXPORT int my___pthread_once(x86emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));
|
||||
|
||||
EXPORT int my_pthread_key_create(x86emu_t* emu, void* key, void* dtor)
|
||||
EXPORT int my_pthread_key_create(x86emu_t* emu, pthread_key_t* key, void* dtor)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_key_create(key, findkey_destructorFct(dtor));
|
||||
int ret = pthread_key_create(key, findkey_dtorFct(dtor));
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my___pthread_key_create(x86emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
|
||||
EXPORT int my___pthread_key_create(x86emu_t* emu, pthread_key_t* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
|
||||
|
||||
EXPORT int my_pthread_key_delete(x86emu_t* emu, pthread_key_t key)
|
||||
{
|
||||
int ret = pthread_key_delete(key);
|
||||
return ret;
|
||||
}
|
||||
// phtread_cond_init with null attr seems to only write 1 (NULL) dword on x86, while it's 48 bytes on ARM.
|
||||
// Not sure why as sizeof(pthread_cond_init) is 48 on both platform... But Neverwinter Night init seems to rely on that
|
||||
// What about cond that are statically initialized?
|
||||
@@ -554,10 +509,10 @@ static pthread_cond_t* get_cond(void* cond)
|
||||
ret = (pthread_cond_t*)box_calloc(1, sizeof(pthread_cond_t));
|
||||
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &r);
|
||||
kh_value(mapcond, k) = ret;
|
||||
*(void**)cond = cond;
|
||||
pthread_cond_init(ret, NULL);
|
||||
} else
|
||||
ret = kh_value(mapcond, k);
|
||||
*(void**)cond = cond;
|
||||
pthread_cond_init(ret, NULL);
|
||||
} else
|
||||
ret = kh_value(mapcond, k);
|
||||
mutex_unlock(&my_context->mutex_thread);
|
||||
@@ -575,7 +530,7 @@ static void del_cond(void* cond)
|
||||
}
|
||||
mutex_unlock(&my_context->mutex_thread);
|
||||
}
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
|
||||
static pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
|
||||
|
||||
EXPORT int my_pthread_cond_broadcast_old(x86emu_t* emu, void* cond)
|
||||
{
|
||||
@@ -802,7 +757,7 @@ typedef struct mutexes_block_s {
|
||||
} mutexes_block_t;
|
||||
|
||||
static mutexes_block_t *mutexes = NULL;
|
||||
#ifndef DYNAREC
|
||||
#ifndef USE_CUSTOM_MUTEX
|
||||
static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER;
|
||||
#else
|
||||
static uint32_t mutex_mutexes = 0;
|
||||
@@ -884,8 +839,10 @@ typedef struct aligned_mutex_s {
|
||||
} aligned_mutex_t;
|
||||
#define SIGNMTX *(uint32_t*)"MUTX"
|
||||
|
||||
pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
static pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
{
|
||||
if(box86_mutex_aligned)
|
||||
return m;
|
||||
if(!m)
|
||||
return NULL;
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
@@ -917,15 +874,15 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
am->m = ret;
|
||||
return ret;
|
||||
}
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
|
||||
static pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
|
||||
{
|
||||
return getAlignedMutexWithInit(m, 1);
|
||||
}
|
||||
|
||||
EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
|
||||
{
|
||||
/*if(!(((uintptr_t)m)&3))
|
||||
return pthread_mutex_destroy(m);*/ // alignent to check...
|
||||
if(box86_mutex_aligned)
|
||||
return pthread_mutex_destroy(m);
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
if(am->sign!=SIGNMTX) {
|
||||
return 1; //???
|
||||
@@ -969,28 +926,6 @@ EXPORT int my___pthread_mutex_unlock(pthread_mutex_t *m) __attribute__((alias("m
|
||||
|
||||
#endif
|
||||
|
||||
static void emujmpbuf_destroy(void* p)
|
||||
{
|
||||
emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
|
||||
if(ej) {
|
||||
box_free(ej->jmpbuf);
|
||||
box_free(ej);
|
||||
}
|
||||
}
|
||||
|
||||
static pthread_key_t jmpbuf_key;
|
||||
|
||||
emu_jmpbuf_t* GetJmpBuf()
|
||||
{
|
||||
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
|
||||
if(!ejb) {
|
||||
ejb = (emu_jmpbuf_t*)box_calloc(1, sizeof(emu_jmpbuf_t));
|
||||
ejb->jmpbuf = box_calloc(1, sizeof(jmp_buf));
|
||||
pthread_setspecific(jmpbuf_key, ejb);
|
||||
}
|
||||
return ejb;
|
||||
}
|
||||
|
||||
void init_pthread_helper()
|
||||
{
|
||||
real_pthread_cleanup_push_defer = (vFppp_t)dlsym(NULL, "_pthread_cleanup_push_defer");
|
||||
@@ -1009,10 +944,7 @@ void init_pthread_helper()
|
||||
real_phtread_kill_old = (iFli_t)pthread_kill;
|
||||
}
|
||||
|
||||
InitCancelThread();
|
||||
mapcond = kh_init(mapcond);
|
||||
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
|
||||
pthread_setspecific(jmpbuf_key, NULL);
|
||||
pthread_key_create(&thread_key, emuthread_destroy);
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
#if !defined(NOALIGN) && defined(ANDROID)
|
||||
@@ -1020,9 +952,17 @@ void init_pthread_helper()
|
||||
#endif
|
||||
}
|
||||
|
||||
void clean_current_emuthread()
|
||||
{
|
||||
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
|
||||
if(et) {
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
emuthread_destroy(et);
|
||||
}
|
||||
}
|
||||
|
||||
void fini_pthread_helper(box86context_t* context)
|
||||
{
|
||||
FreeCancelThread(context);
|
||||
CleanStackSize(context);
|
||||
pthread_cond_t *cond;
|
||||
kh_foreach_value(mapcond, cond,
|
||||
@@ -1043,18 +983,13 @@ void fini_pthread_helper(box86context_t* context)
|
||||
FreeAllMutexes(mutexes);
|
||||
#endif //!ANDROID
|
||||
#endif
|
||||
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
|
||||
if(ejb) {
|
||||
pthread_setspecific(jmpbuf_key, NULL);
|
||||
emujmpbuf_destroy(ejb);
|
||||
}
|
||||
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
|
||||
if(et) {
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
emuthread_destroy(et);
|
||||
}
|
||||
}
|
||||
#ifndef DYNAREC
|
||||
|
||||
int checkUnlockMutex(void* m)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
|
||||
@@ -1064,15 +999,3 @@ int checkUnlockMutex(void* m)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int checkLockMutex(void* m)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
|
||||
int ret = pthread_mutex_unlock(mutex);
|
||||
if(ret==0) {
|
||||
pthread_mutex_lock(mutex); // how to check the lock without unlock?
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
Executable → Regular
+134
-42
@@ -54,6 +54,8 @@ int box86_showbt = 0;
|
||||
int box86_isglibc234 = 0;
|
||||
int box86_nosandbox = 0;
|
||||
int box86_malloc_hack = 0;
|
||||
int box86_mutex_aligned = 0;
|
||||
int box86_quit = 0;
|
||||
#ifdef DYNAREC
|
||||
int box86_dynarec = 1;
|
||||
int box86_dynarec_dump = 0;
|
||||
@@ -69,21 +71,26 @@ int box86_dynarec_safeflags = 1;
|
||||
int box86_dynarec_hotpage = 16;
|
||||
int box86_dynarec_bleeding_edge = 1;
|
||||
int box86_dynarec_jvm = 1;
|
||||
int box86_dynarec_tbb = 1;
|
||||
int box86_dynarec_wait = 1;
|
||||
int box86_dynarec_fastpage = 0;
|
||||
uintptr_t box86_nodynarec_start = 0;
|
||||
uintptr_t box86_nodynarec_end = 0;
|
||||
int box86_dynarec_test = 0;
|
||||
int box86_dynarec_missing = 0;
|
||||
#ifdef ARM
|
||||
int arm_vfp = 0; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
int arm_swap = 0;
|
||||
int arm_div = 0;
|
||||
int arm_v8 = 0;
|
||||
int arm_aes = 0;
|
||||
int arm_pmull = 0;
|
||||
#endif
|
||||
#else //DYNAREC
|
||||
int box86_dynarec = 0;
|
||||
#endif
|
||||
int box86_libcef = 1;
|
||||
int box86_sdl2_jguid = 0;
|
||||
int dlsym_error = 0;
|
||||
int cycle_log = 0;
|
||||
int trace_xmm = 0;
|
||||
@@ -120,6 +127,11 @@ int box86_musl = 0;
|
||||
int box86_nopulse = 0;
|
||||
int box86_nogtk = 0;
|
||||
int box86_novulkan = 0;
|
||||
#ifdef BAD_SIGNAL
|
||||
int box86_futex_waitv = 0;
|
||||
#else
|
||||
int box86_futex_waitv = 1;
|
||||
#endif
|
||||
int box86_showsegv = 0;
|
||||
char* box86_libGL = NULL;
|
||||
uintptr_t trace_start = 0, trace_end = 0;
|
||||
@@ -232,6 +244,10 @@ void GatherDynarecExtensions()
|
||||
arm_div = 1;
|
||||
#ifdef AT_HWCAP2
|
||||
unsigned long hwcap2 = real_getauxval(AT_HWCAP2);
|
||||
if(hwcap2&HWCAP2_AES)
|
||||
arm_aes = 1;
|
||||
if(hwcap2&HWCAP2_PMULL)
|
||||
arm_pmull = 1;
|
||||
if((hwcap2&HWCAP2_AES) || (hwcap2&HWCAP2_CRC32))
|
||||
arm_v8 = 1;
|
||||
#endif
|
||||
@@ -240,6 +256,10 @@ void GatherDynarecExtensions()
|
||||
printf_log(LOG_INFO, " SWP");
|
||||
if(arm_div)
|
||||
printf_log(LOG_INFO, " IDIVA");
|
||||
if(arm_aes)
|
||||
printf_log(LOG_INFO, " AES");
|
||||
if(arm_pmull)
|
||||
printf_log(LOG_INFO, " PMULL");
|
||||
|
||||
printf_log(LOG_INFO, " PageSize:%zd ", box86_pagesize);
|
||||
#endif
|
||||
@@ -380,11 +400,11 @@ void LoadLogEnv()
|
||||
p = getenv("BOX86_DYNAREC_STRONGMEM");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='2')
|
||||
if(p[0]>='0' && p[0]<='3')
|
||||
box86_dynarec_strongmem = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_strongmem)
|
||||
printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box86_dynarec_strongmem==1)?" with limited performace loss":"");
|
||||
printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box86_dynarec_strongmem==1)?" with limited performance loss":((box86_dynarec_strongmem==3)?" with more performance loss":""));
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_X87DOUBLE");
|
||||
if(p) {
|
||||
@@ -472,6 +492,24 @@ void LoadLogEnv()
|
||||
if(!box86_dynarec_jvm)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect libjvm\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_TBB");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_tbb = p[0]-'0';
|
||||
}
|
||||
if(!box86_dynarec_tbb)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect libtbb\n");
|
||||
}
|
||||
p = getenv("BOX86_DYNAREC_MISSING");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_dynarec_missing = p[0]-'0';
|
||||
}
|
||||
if(box86_dynarec_missing)
|
||||
printf_log(LOG_INFO, "Dynarec will print missing opcodes\n");
|
||||
}
|
||||
p = getenv("BOX86_NODYNAREC");
|
||||
if(p) {
|
||||
if (strchr(p,'-')) {
|
||||
@@ -539,6 +577,15 @@ void LoadLogEnv()
|
||||
if(!box86_libcef)
|
||||
printf_log(LOG_INFO, "Dynarec will not detect libcef\n");
|
||||
}
|
||||
p = getenv("BOX86_SDL2_JGUID");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box86_sdl2_jguid = p[0]-'0';
|
||||
}
|
||||
if(!box86_sdl2_jguid)
|
||||
printf_log(LOG_INFO, "BOX86 will workaround the use of SDL_GetJoystickGUIDInfo with 4 args instead of 5\n");
|
||||
}
|
||||
p = getenv("BOX86_LOAD_ADDR");
|
||||
if(p) {
|
||||
if(sscanf(p, "0x%zx", &box86_load_addr)!=1)
|
||||
@@ -628,6 +675,19 @@ void LoadLogEnv()
|
||||
printf_log(LOG_INFO, "Malloc hook will check for mmap/free occurrences\n");
|
||||
}
|
||||
}
|
||||
p = getenv("BOX86_MUTEX_ALIGNED");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box86_mutex_aligned = p[0]-'0';
|
||||
}
|
||||
if(!box86_mutex_aligned) {
|
||||
if(box86_mutex_aligned==1) {
|
||||
printf_log(LOG_INFO, "BOX86 will not aligned mutexes\n");
|
||||
} else
|
||||
printf_log(LOG_INFO, "BOX86 will wrap mutex to for them aligned\n");
|
||||
}
|
||||
}
|
||||
p = getenv("BOX86_NOPULSE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -655,6 +715,20 @@ void LoadLogEnv()
|
||||
if(box86_novulkan)
|
||||
printf_log(LOG_INFO, "Disable the use of wrapped vulkan libs\n");
|
||||
}
|
||||
p = getenv("BOX86_FUTEX_WAITV");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box86_futex_waitv = p[0]-'0';
|
||||
}
|
||||
#ifdef BAD_SIGNAL
|
||||
if(box86_futex_waitv)
|
||||
printf_log(LOG_INFO, "Enable the use of futex waitv syscall (if available on the system\n");
|
||||
#else
|
||||
if(!box86_futex_waitv)
|
||||
printf_log(LOG_INFO, "Disable the use of futex waitv syscall\n");
|
||||
#endif
|
||||
}
|
||||
p = getenv("BOX86_FIX_64BIT_INODES");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
@@ -667,11 +741,11 @@ void LoadLogEnv()
|
||||
p = getenv("BOX86_JITGDB");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='0'+2)
|
||||
if(p[0]>='0' && p[0]<='0'+3)
|
||||
jit_gdb = p[0]-'0';
|
||||
}
|
||||
if(jit_gdb)
|
||||
printf_log(LOG_INFO, "Launch %s on segfault\n", (jit_gdb==2)?"gdbserver":"gdb");
|
||||
printf_log(LOG_INFO, "Launch %s on segfault\n", (jit_gdb==2)?"gdbserver":((jit_gdb==3)?"lldb":"gdb"));
|
||||
}
|
||||
p = getenv("BOX86_SHOWSEGV");
|
||||
if(p) {
|
||||
@@ -778,14 +852,8 @@ int GatherEnv(char*** dest, char** env, const char* prog)
|
||||
}
|
||||
|
||||
|
||||
void PrintHelp() {
|
||||
printf("\n\nThis is Box86, the Linux x86 emulator with a twist\n");
|
||||
printf("\nUsage is box86 [options] path/to/software [args]\n");
|
||||
printf("to launch x86 software\n");
|
||||
printf(" options can be :\n");
|
||||
printf(" '-v'|'--version' to print box86 version and quit\n");
|
||||
printf(" '-h'|'--help' to print box86 help and quit\n");
|
||||
printf("You can also set some environment variables:\n");
|
||||
void PrintFlags() {
|
||||
printf("Environment Variables:\n");
|
||||
printf(" BOX86_PATH is the box86 version of PATH (default is '.:bin')\n");
|
||||
printf(" BOX86_LD_LIBRARY_PATH is the box86 version LD_LIBRARY_PATH (default is '.:lib')\n");
|
||||
printf(" BOX86_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info (level 3 is level 2 + BOX86_DUMP)\n");
|
||||
@@ -813,7 +881,7 @@ void PrintHelp() {
|
||||
printf(" BOX86_DYNAREC_TRACE with 0/1 to disable or enable Trace on generated code too\n");
|
||||
#endif
|
||||
#endif
|
||||
printf(" BOX86_TRACE_FILE with FileName to redirect logs in a file (or stderr to use stderr instead of stdout)");
|
||||
printf(" BOX86_TRACE_FILE with FileName to redirect logs in a file (or stderr to use stderr instead of stdout)\n");
|
||||
printf(" BOX86_DLSYM_ERROR with 1 to log dlsym errors\n");
|
||||
printf(" BOX86_LOAD_ADDR=0xXXXXXX try to load at 0xXXXXXX main binary (if binary is a PIE)\n");
|
||||
printf(" BOX86_NOSIGSEGV=1 to disable handling of SigSEGV\n");
|
||||
@@ -822,11 +890,11 @@ void PrintHelp() {
|
||||
#ifdef PANDORA
|
||||
printf(" BOX86_X11COLOR16=1 to try convert X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows\n");
|
||||
#endif
|
||||
printf(" BOX86_X11THREADS=1 to call XInitThreads when loading X11 (for old Loki games with Loki_Compat lib)");
|
||||
printf(" BOX86_X11THREADS=1 to call XInitThreads when loading X11 (for old Loki games with Loki_Compat lib)\n");
|
||||
printf(" BOX86_LIBGL=libXXXX set the name (and optionnaly full path) for libGL.so.1\n");
|
||||
printf(" BOX86_LD_PRELOAD=XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary\n");
|
||||
printf(" BOX86_ALLOWMISSINGLIBS with 1 to allow to continue even if a lib is missing (unadvised, will probably crash later)\n");
|
||||
printf(" BOX64_PREFER_EMULATED=1 to prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11\n");
|
||||
printf(" BOX86_ALLOWMISSINGLIBS with 1 to allow to continue even if a lib is missing (unadvised, will probably crash later)\n");
|
||||
printf(" BOX64_PREFER_EMULATED=1 to prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11)\n");
|
||||
printf(" BOX64_PREFER_WRAPPED if box86 will use wrapped libs even if the lib is specified with absolute path\n");
|
||||
printf(" BOX86_NOPULSE=1 to disable the loading of pulseaudio libs\n");
|
||||
printf(" BOX86_NOGTK=1 to disable the loading of wrapped gtk libs\n");
|
||||
@@ -836,6 +904,15 @@ void PrintHelp() {
|
||||
printf(" BOX86_JITGDB with 1 to launch \"gdb\" when a segfault is trapped, attached to the offending process\n");
|
||||
}
|
||||
|
||||
void PrintHelp() {
|
||||
printf("This is Box86, the Linux x86 emulator with a twist\n");
|
||||
printf("\nUsage is 'box86 [options] path/to/software [args]' to launch x86 software.\n");
|
||||
printf(" options are:\n");
|
||||
printf(" '-v'|'--version' to print box86 version and quit\n");
|
||||
printf(" '-h'|'--help' to print this and quit\n");
|
||||
printf(" '-f'|'--flags' to print box86 flags and quit\n");
|
||||
}
|
||||
|
||||
void addNewEnvVar(const char* s)
|
||||
{
|
||||
if(!s)
|
||||
@@ -880,6 +957,7 @@ void LoadEnvVars(box86context_t *context)
|
||||
AddPath("/mnt/utmp/box86/lib/i386-linux-gnu", &context->box86_ld_lib, 1);
|
||||
//TODO: add relative path to box86 location
|
||||
#endif
|
||||
#ifndef TERMUX
|
||||
if(FileExist("/lib/box86", 0))
|
||||
AddPath("/lib/box86", &context->box86_ld_lib, 1);
|
||||
if(FileExist("/usr/lib/box86", 0))
|
||||
@@ -894,6 +972,12 @@ void LoadEnvVars(box86context_t *context)
|
||||
AddPath("/usr/lib/i686-pc-linux-gnu", &context->box86_ld_lib, 1);
|
||||
if(FileExist("/usr/lib32", 0))
|
||||
AddPath("/usr/lib32", &context->box86_ld_lib, 1);
|
||||
#else
|
||||
if(FileExist("/data/data/com.termux/files/usr/lib/i386-linux-gnu", 0))
|
||||
AddPath("/data/data/com.termux/files/usr/lib/i386-linux-gnu", &context->box86_ld_lib, 1);
|
||||
if(FileExist("/data/data/com.termux/files/usr/lib/i686-linux-gnu", 0))
|
||||
AddPath("/data/data/com.termux/files/usr/lib/i686-linux-gnu", &context->box86_ld_lib, 1);
|
||||
#endif
|
||||
if(getenv("LD_LIBRARY_PATH"))
|
||||
PrependList(&context->box86_ld_lib, getenv("LD_LIBRARY_PATH"), 1); // in case some of the path are for x86 world
|
||||
if(getenv("BOX86_EMULATED_LIBS")) {
|
||||
@@ -978,10 +1062,10 @@ void setupTraceInit()
|
||||
if(s_trace_start || s_trace_end)
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
} else {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
if (my_context->elfs && GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
} else if(my_context->elfs && GetLocalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, NULL, NULL, NULL)) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
} else {
|
||||
@@ -1042,8 +1126,10 @@ void setupTrace()
|
||||
|
||||
void endBox86()
|
||||
{
|
||||
if(!my_context)
|
||||
if(!my_context || box86_quit)
|
||||
return;
|
||||
|
||||
box86_quit = 1;
|
||||
x86emu_t* emu = thread_get_emu();
|
||||
//atexit first
|
||||
printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
|
||||
@@ -1101,8 +1187,13 @@ void endBox86()
|
||||
|
||||
static void load_rcfiles()
|
||||
{
|
||||
#ifndef TERMUX
|
||||
if(FileExist("/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/etc/box86.box86rc");
|
||||
#else
|
||||
if(FileExist("/data/data/com.termux/files/usr/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/data/data/com.termux/files/usr/etc/box86.box86rc");
|
||||
#endif
|
||||
#ifdef PANDORA
|
||||
if(FileExist("/mnt/utmp/codeblocks/usr/etc/box86.box86rc", IS_FILE))
|
||||
LoadRCFile("/mnt/utmp/codeblocks/usr/etc/box86.box86rc");
|
||||
@@ -1170,9 +1261,12 @@ int main(int argc, const char **argv, char **env)
|
||||
init_auxval(argc, argv, environ?environ:env);
|
||||
// trying to open and load 1st arg
|
||||
if(argc==1) {
|
||||
PrintBox86Version();
|
||||
/*PrintBox86Version();
|
||||
PrintHelp();
|
||||
return 1;
|
||||
return 1;*/
|
||||
printf("BOX86: Missing operand after 'box86'\n");
|
||||
printf("See 'box86 --help' for more information.\n");
|
||||
exit(0);
|
||||
}
|
||||
if(argc>1 && !strcmp(argv[1], "/usr/bin/gdb"))
|
||||
exit(0);
|
||||
@@ -1226,6 +1320,10 @@ int main(int argc, const char **argv, char **env)
|
||||
PrintHelp();
|
||||
exit(0);
|
||||
}
|
||||
if(!strcmp(prog, "-f") || !strcmp(prog, "--flags")) {
|
||||
PrintFlags();
|
||||
exit(0);
|
||||
}
|
||||
// other options?
|
||||
if(!strcmp(prog, "--")) {
|
||||
prog = argv[++nextarg];
|
||||
@@ -1363,7 +1461,11 @@ int main(int argc, const char **argv, char **env)
|
||||
else
|
||||
++prgname;
|
||||
if(box86_wine) {
|
||||
AddPath("libdl.so.2", &ld_preload, 0);
|
||||
#ifdef ANDROID
|
||||
AddPath("libdl.so", &ld_preload, 0);
|
||||
#else
|
||||
AddPath("libdl.so.2", &ld_preload, 0);
|
||||
#endif
|
||||
}
|
||||
// special case for steam that somehow seems to alter libudev opaque pointer (udev_monitor)
|
||||
if(strstr(prgname, "steam")==prgname) {
|
||||
@@ -1476,7 +1578,7 @@ int main(int argc, const char **argv, char **env)
|
||||
if(!elf_header) {
|
||||
int x64 = my_context->box64path?FileIsX64ELF(my_context->fullpath):0;
|
||||
int script = my_context->bashpath?FileIsShell(my_context->fullpath):0;
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->fullpath, x64?"using box64":(script?"using bash":"natively"));
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s, trying to launch %s instead\n", my_context->fullpath, x64?"using box64":(script?"using bash":"natively"));
|
||||
fclose(f);
|
||||
FreeCollection(&ld_preload);
|
||||
int ret;
|
||||
@@ -1510,32 +1612,21 @@ int main(int argc, const char **argv, char **env)
|
||||
|
||||
if(CalcLoadAddr(elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->fullpath);
|
||||
fclose(f);
|
||||
free_contextargv();
|
||||
FreeBox86Context(&my_context);
|
||||
FreeCollection(&ld_preload);
|
||||
FreeElfHeader(&elf_header);
|
||||
return -1;
|
||||
}
|
||||
// allocate memory
|
||||
if(AllocElfMemory(my_context, elf_header, 1)) {
|
||||
printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->fullpath);
|
||||
fclose(f);
|
||||
if(AllocLoadElfMemory(my_context, elf_header, 1)) {
|
||||
printf_log(LOG_NONE, "Error: loading elf %s\n", my_context->fullpath);
|
||||
free_contextargv();
|
||||
FreeBox86Context(&my_context);
|
||||
FreeCollection(&ld_preload);
|
||||
FreeElfHeader(&elf_header);
|
||||
return -1;
|
||||
}
|
||||
// Load elf into memory
|
||||
if(LoadElfMemory(f, my_context, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->fullpath);
|
||||
fclose(f);
|
||||
free_contextargv();
|
||||
FreeBox86Context(&my_context);
|
||||
FreeCollection(&ld_preload);
|
||||
return -1;
|
||||
}
|
||||
// can close the file now
|
||||
fclose(f);
|
||||
my_context->brk = ElfGetBrk(elf_header);
|
||||
if(ElfCheckIfUseTCMallocMinimal(elf_header)) {
|
||||
if(!box86_tcmalloc_minimal) {
|
||||
@@ -1612,6 +1703,9 @@ int main(int argc, const char **argv, char **env)
|
||||
for(int i=nextarg; i<argc; ++i)
|
||||
argv[i] -= diff; // adjust strings
|
||||
}
|
||||
box86_isglibc234 = GetNeededVersionForLib(elf_header, "libc.so.6", "GLIBC_2.34");
|
||||
if(box86_isglibc234)
|
||||
printf_log(LOG_DEBUG, "Program linked with GLIBC 2.34+\n");
|
||||
// get and alloc stack size and align
|
||||
if(CalcStackSize(my_context)) {
|
||||
printf_log(LOG_NONE, "Error: allocating stack\n");
|
||||
@@ -1659,9 +1753,6 @@ int main(int argc, const char **argv, char **env)
|
||||
setupTraceInit(my_context);
|
||||
// export symbols
|
||||
AddSymbols(my_context->maplib, GetMapSymbols(elf_header), GetWeakSymbols(elf_header), GetLocalSymbols(elf_header), elf_header);
|
||||
box86_isglibc234 = GetVersionIndice(elf_header, "GLIBC_2.34")?1:0;
|
||||
if(box86_isglibc234)
|
||||
printf_log(LOG_DEBUG, "Program linked with GLIBC 2.34+\n");
|
||||
if(wine_preloaded) {
|
||||
uintptr_t wineinfo = FindSymbol(GetMapSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
|
||||
@@ -1683,7 +1774,7 @@ int main(int argc, const char **argv, char **env)
|
||||
needed_libs_t* tmp = new_neededlib(1);
|
||||
tmp->names[0] = ld_preload.paths[i];
|
||||
if(AddNeededLib(my_context->maplib, 0, 0, tmp, elf_header, my_context, emu)) {
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load of %s\n", tmp->names[0]);
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load %s\n", tmp->names[0]);
|
||||
RemoveNeededLib(my_context->maplib, 0, tmp, my_context, emu);
|
||||
} else {
|
||||
for(int j=0; j<tmp->size; ++j)
|
||||
@@ -1734,6 +1825,7 @@ int main(int argc, const char **argv, char **env)
|
||||
// Get EAX
|
||||
int ret = GetEAX(emu);
|
||||
printf_log(LOG_DEBUG, "Emulation finished, EAX=%d\n", ret);
|
||||
endBox86();
|
||||
|
||||
if(trace_func) {
|
||||
box_free(trace_func);
|
||||
|
||||
+24
-31
@@ -42,6 +42,7 @@
|
||||
This is the Exterminate strategy implementation
|
||||
*/
|
||||
|
||||
#ifndef ANDROID
|
||||
#include "bridge.h"
|
||||
#include "wrapper.h"
|
||||
|
||||
@@ -131,13 +132,6 @@ typedef void* (*pFpLp_t)(void*, size_t, void*);
|
||||
typedef void (*vFpLL_t)(void*, size_t, size_t);
|
||||
typedef void* (*pFpLLp_t)(void*, size_t, size_t, void*);
|
||||
|
||||
#ifdef ANDROID
|
||||
void*(*__libc_malloc)(size_t) = NULL;
|
||||
void*(*__libc_realloc)(size_t, void*) = NULL;
|
||||
void*(*__libc_calloc)(size_t, size_t) = NULL;
|
||||
void (*__libc_free)(void*) = NULL;
|
||||
void*(*__libc_memalign)(size_t, size_t) = NULL;
|
||||
#endif
|
||||
size_t(*box_malloc_usable_size)(const void*) = NULL;
|
||||
|
||||
int GetTID();
|
||||
@@ -200,11 +194,11 @@ EXPORT void* malloc(size_t l)
|
||||
|
||||
EXPORT void free(void* p)
|
||||
{
|
||||
if(malloc_hack_2 && FREE && p) {
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
if(real_free && FREE)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
@@ -225,7 +219,7 @@ EXPORT void* realloc(void* p, size_t s)
|
||||
if(malloc_hack_2)
|
||||
if(getMmapped((uintptr_t)p) || (!p && ALLOC && real_realloc)) {
|
||||
void* ret = p;
|
||||
if(real_realloc) {
|
||||
if(real_realloc && ALLOC) {
|
||||
ret = (void*)RunFunctionFmt(real_realloc, "pL", p, s);
|
||||
} else {
|
||||
// found! Will realloc using regular malloc then copy from old address as much as possible, but need to check size first
|
||||
@@ -235,7 +229,7 @@ EXPORT void* realloc(void* p, size_t s)
|
||||
memcpy(ret, p, s);
|
||||
printf_log(LOG_DEBUG, " -> %p (copied %zu from old)\n", ret, s);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
if(real_free && FREE)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
}
|
||||
return ret;
|
||||
@@ -291,11 +285,11 @@ EXPORT void* pvalloc(size_t size)
|
||||
|
||||
EXPORT void cfree(void* p)
|
||||
{
|
||||
if(malloc_hack_2 && FREE && p) {
|
||||
if(malloc_hack_2 && p) {
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
if(real_free && FREE)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
return;
|
||||
}
|
||||
@@ -467,8 +461,8 @@ EXPORT void my__ZdaPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void*
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
if(real__ZdaPvSt11align_val_tRKSt9nothrow_t)
|
||||
RunFunctionFmt(real__ZdaPvSt11align_val_tRKSt9nothrow_t, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -481,8 +475,8 @@ EXPORT void my__ZdlPvmSt11align_val_t(void* p, size_t sz, size_t align) //oper
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
if(real__ZdlPvmSt11align_val_t)
|
||||
RunFunctionFmt(real__ZdlPvmSt11align_val_t, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -495,8 +489,8 @@ EXPORT void my__ZdaPvRKSt9nothrow_t(void* p, void* n) //operator delete[](void
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
if(real__ZdaPvRKSt9nothrow_t)
|
||||
RunFunctionFmt(real__ZdaPvRKSt9nothrow_t, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -509,8 +503,8 @@ EXPORT void my__ZdaPvSt11align_val_t(void* p, size_t align) //operator delete[
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
if(real__ZdaPvSt11align_val_t)
|
||||
RunFunctionFmt(real__ZdaPvSt11align_val_t, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -523,8 +517,8 @@ EXPORT void my__ZdlPvSt11align_val_t(void* p, size_t align) //operator delete(
|
||||
if(getMmapped((uintptr_t)p)) {
|
||||
printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p);
|
||||
// Mmaped, free with original function
|
||||
if(real_free)
|
||||
RunFunctionFmt(real_free, "p", p);
|
||||
if(real__ZdlPvSt11align_val_t)
|
||||
RunFunctionFmt(real__ZdlPvSt11align_val_t, "p", p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -875,13 +869,6 @@ EXPORT int my___RML_open_factory(void* factory, void* server_version, int client
|
||||
}
|
||||
|
||||
void init_malloc_hook() {
|
||||
#ifdef ANDROID
|
||||
__libc_malloc = dlsym(RTLD_NEXT, "malloc");
|
||||
__libc_realloc = dlsym(RTLD_NEXT, "realloc");
|
||||
__libc_calloc = dlsym(RTLD_NEXT, "calloc");
|
||||
__libc_free = dlsym(RTLD_NEXT, "free");
|
||||
__libc_memalign = dlsym(RTLD_NEXT, "memalign");
|
||||
#endif
|
||||
box_malloc_usable_size = dlsym(RTLD_NEXT, "malloc_usable_size");
|
||||
#if 0
|
||||
#define GO(A, B)
|
||||
@@ -892,4 +879,10 @@ void init_malloc_hook() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SUPER
|
||||
#undef SUPER
|
||||
#else//ANDROID
|
||||
void init_malloc_hook() {}
|
||||
void startMallocHook() {}
|
||||
void endMallocHook() {}
|
||||
void checkHookedSymbols(elfheader_t* h) {}
|
||||
#endif //!ANDROID
|
||||
+15
-3
@@ -40,10 +40,22 @@ uint32_t RunSafeFunction(uintptr_t fnc, int nargs, ...)
|
||||
}
|
||||
va_end (va);
|
||||
|
||||
// save defered flags
|
||||
defered_flags_t old_df = emu->df;
|
||||
uint32_t old_op1 = emu->op1;
|
||||
uint32_t old_op2 = emu->op2;
|
||||
uint32_t old_res = emu->res;
|
||||
|
||||
uintptr_t oldip = R_EIP;
|
||||
DynaCall(emu, fnc);
|
||||
R_ESP+=(nargs*4);
|
||||
|
||||
// restore defered flags
|
||||
emu->df = old_df;
|
||||
emu->op1 = old_op1;
|
||||
emu->op2 = old_op2;
|
||||
emu->res = old_res;
|
||||
|
||||
uint32_t ret = R_EAX;
|
||||
R_EIP = oldip;
|
||||
|
||||
@@ -281,10 +293,10 @@ uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
|
||||
|
||||
uint32_t oldip = R_EIP;
|
||||
int old_quit = emu->quit;
|
||||
int oldlong = emu->quitonlongjmp;
|
||||
int oldlong = emu->flags.quitonlongjmp;
|
||||
|
||||
emu->quit = 0;
|
||||
emu->quitonlongjmp = QuitOnLongJump;
|
||||
emu->flags.quitonlongjmp = QuitOnLongJump;
|
||||
|
||||
DynaCall(emu, fnc);
|
||||
|
||||
@@ -292,7 +304,7 @@ uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, in
|
||||
R_ESP+=(nargs*4); // restore stack only if EIP is the one expected (else, it means return value is not the one expected)
|
||||
|
||||
emu->quit = old_quit;
|
||||
emu->quitonlongjmp = oldlong;
|
||||
emu->flags.quitonlongjmp = oldlong;
|
||||
|
||||
|
||||
return R_EAX;
|
||||
|
||||
+168
-19
@@ -11,7 +11,6 @@
|
||||
int get_cpuMhz()
|
||||
{
|
||||
int MHz = 0;
|
||||
#ifdef __arm__
|
||||
FILE *f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
|
||||
if(f) {
|
||||
int r;
|
||||
@@ -19,44 +18,170 @@ int get_cpuMhz()
|
||||
MHz = r/1000;
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
if(!MHz) {
|
||||
// try with lscpu, grabbing the max frequency
|
||||
FILE* f = popen("lscpu | grep \"CPU max MHz:\" | sed -r 's/CPU max MHz:\\s{1,}//g'", "r");
|
||||
if(f) {
|
||||
char tmp[200] = "";
|
||||
ssize_t s = fread(tmp, 1, 200, f);
|
||||
pclose(f);
|
||||
if(s>0) {
|
||||
// worked! (unless it's saying "lscpu: command not found" or something like that)
|
||||
if(!strstr(tmp, "lscpu")) {
|
||||
// trim ending
|
||||
while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
|
||||
tmp[strlen(tmp)-1] = 0;
|
||||
// incase multiple cpu type are present, there will be multiple lines
|
||||
while(strchr(tmp, '\n'))
|
||||
*strchr(tmp,'\n') = ' ';
|
||||
// cut the float part (so '.' or ','), it's not needed
|
||||
if(strchr(tmp, '.'))
|
||||
*strchr(tmp, '.')= '\0';
|
||||
if(strchr(tmp, ','))
|
||||
*strchr(tmp, ',')= '\0';
|
||||
int mhz;
|
||||
if(sscanf(tmp, "%d", &mhz)==1)
|
||||
MHz = mhz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!MHz)
|
||||
MHz = 1000; // default to 1Ghz...
|
||||
return MHz;
|
||||
}
|
||||
int getNCpu(); // defined in wrappedlibc.c
|
||||
const char* getCpuName(); // same
|
||||
static int nCPU = 0;
|
||||
static double bogoMips = 100.;
|
||||
|
||||
void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
void grabNCpu() {
|
||||
nCPU = 1; // default number of CPU to 1
|
||||
FILE *f = fopen("/proc/cpuinfo", "r");
|
||||
size_t dummy;
|
||||
if(f) {
|
||||
nCPU = 0;
|
||||
int bogo = 0;
|
||||
size_t len = 500;
|
||||
char* line = malloc(len);
|
||||
while ((dummy = getline(&line, &len, f)) != -1) {
|
||||
if(!strncmp(line, "processor\t", strlen("processor\t")))
|
||||
++nCPU;
|
||||
if(!bogo && !strncmp(line, "BogoMIPS\t", strlen("BogoMIPS\t"))) {
|
||||
// grab 1st BogoMIPS
|
||||
float tmp;
|
||||
if(sscanf(line, "BogoMIPS\t: %g", &tmp)==1) {
|
||||
bogoMips = tmp;
|
||||
bogo = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(f);
|
||||
if(!nCPU) nCPU=1;
|
||||
}
|
||||
}
|
||||
int getNCpu()
|
||||
{
|
||||
static char branding[3*4*4+1] = "";
|
||||
if(!nCPU)
|
||||
grabNCpu();
|
||||
if(box86_wine && nCPU>32)
|
||||
return 32;
|
||||
return nCPU;
|
||||
}
|
||||
|
||||
double getBogoMips()
|
||||
{
|
||||
if(!nCPU)
|
||||
grabNCpu();
|
||||
return bogoMips;
|
||||
}
|
||||
|
||||
const char* getCpuName()
|
||||
{
|
||||
static char name[200] = "Unknown CPU";
|
||||
static int done = 0;
|
||||
if(done)
|
||||
return name;
|
||||
done = 1;
|
||||
FILE* f = popen("lscpu | grep \"Model name:\" | sed -r 's/Model name:\\s{1,}//g'", "r");
|
||||
if(f) {
|
||||
char tmp[200] = "";
|
||||
ssize_t s = fread(tmp, 1, 200, f);
|
||||
pclose(f);
|
||||
if(s>0) {
|
||||
// worked! (unless it's saying "lscpu: command not found" or something like that)
|
||||
if(!strstr(tmp, "lscpu")) {
|
||||
// trim ending
|
||||
while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
|
||||
tmp[strlen(tmp)-1] = 0;
|
||||
// incase multiple cpu type are present, there will be multiple lines
|
||||
while(strchr(tmp, '\n'))
|
||||
*strchr(tmp,'\n') = ' ';
|
||||
strncpy(name, tmp, 199);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
// failled, try to get architecture at least
|
||||
f = popen("lscpu | grep \"Architecture:\" | sed -r 's/Architecture:\\s{1,}//g'", "r");
|
||||
if(f) {
|
||||
char tmp[200] = "";
|
||||
ssize_t s = fread(tmp, 1, 200, f);
|
||||
pclose(f);
|
||||
if(s>0) {
|
||||
// worked!
|
||||
// trim ending
|
||||
while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
|
||||
tmp[strlen(tmp)-1] = 0;
|
||||
// incase multiple cpu type are present, there will be multiple lines
|
||||
while(strchr(tmp, '\n'))
|
||||
*strchr(tmp,'\n') = ' ';
|
||||
snprintf(name, 199, "unknown %.*s cpu", 186, tmp);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
// Nope, bye
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* getBoxCpuName()
|
||||
{
|
||||
static char branding[3*4*4+1] = {0};
|
||||
static int done = 0;
|
||||
if(!done) {
|
||||
done = 1;
|
||||
const char* name = getCpuName();
|
||||
if(strstr(name, "MHz") || strstr(name, "GHz")) {
|
||||
// name already have the speed in it
|
||||
snprintf(branding, 3*4*4, "Box86 on %s", name);
|
||||
snprintf(branding, sizeof(branding), "Box86 on %.*s", 39, name);
|
||||
} else {
|
||||
int MHz = get_cpuMhz();
|
||||
if(MHz>15000) { // swiches to GHz display...
|
||||
snprintf(branding, 3*4*4, "Box86 on %s @%1.2f GHz", name, MHz/1000.);
|
||||
unsigned int MHz = get_cpuMhz();
|
||||
if(MHz>1500) { // swiches to GHz display...
|
||||
snprintf(branding, sizeof(branding), "Box86 on %.*s @%1.2f GHz", 28, name, MHz/1000.);
|
||||
} else {
|
||||
snprintf(branding, 3*4*4, "Box86 on %s @%04d MHz", name, MHz);
|
||||
snprintf(branding, sizeof(branding), "Box86 on %.*s @%04d MHz", 28, name, MHz);
|
||||
}
|
||||
}
|
||||
while(strlen(branding)<3*4*4) {
|
||||
memmove(branding+1, branding, strlen(branding));
|
||||
branding[0] = ' ';
|
||||
}
|
||||
}
|
||||
return branding;
|
||||
}
|
||||
|
||||
void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
{
|
||||
int ncpu = getNCpu();
|
||||
if(ncpu>255) ncpu = 255;
|
||||
if(!ncpu) ncpu = 1;
|
||||
char branding[3*4*4+1] = {0};
|
||||
if(!branding[0]) {
|
||||
strcpy(branding, getBoxCpuName());
|
||||
while(strlen(branding)<3*4*4) {
|
||||
memmove(branding+1, branding, strlen(branding)+1);
|
||||
branding[0] = ' ';
|
||||
}
|
||||
}
|
||||
switch(tmp32u) {
|
||||
case 0x0:
|
||||
// emulate a P4
|
||||
R_EAX = 0x0000000D;//0x80000004;
|
||||
R_EAX = 0x0000000F;//0x80000004;
|
||||
// return GenuineIntel
|
||||
R_EBX = 0x756E6547;
|
||||
R_EDX = 0x49656E69;
|
||||
@@ -64,12 +189,12 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
break;
|
||||
case 0x1:
|
||||
R_EAX = 0x00000601; // familly and all
|
||||
R_EBX = 0 | (8<<0x8) | (ncpu<<16); // Brand index, CLFlush (8), Max APIC ID (16-23), Local APIC ID (24-31)
|
||||
{
|
||||
R_EBX = 0 | (8<<0x8) | (/*ncpu*/1<<16); // Brand index, CLFlush (8), Max APIC ID (16-23), Local APIC ID (24-31)
|
||||
/*{
|
||||
int cpu = sched_getcpu();
|
||||
if(cpu<0) cpu=0;
|
||||
R_EAX |= cpu<<24;
|
||||
}
|
||||
}*/
|
||||
R_EDX = 1 // fpu
|
||||
| 1<<2 // debugging extension (checked by Burnout Paradise
|
||||
| 1<<3 // Large Page Extension
|
||||
@@ -85,10 +210,15 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
| 1<<28 // HT / Multi-core
|
||||
;
|
||||
R_ECX = 1<<0 // SSE3
|
||||
| 1<<1 // PCLMULQDQ
|
||||
| 1<<9 // SSSE3
|
||||
| 1<<12 // fma
|
||||
| 1<<13 // cx16 (cmpxchg16)
|
||||
| 1<<19 // SSE4_1
|
||||
| 1<<20 // SSE4_2
|
||||
| 1<<22 // MOVBE
|
||||
| 1<<23 // POPCOUNT
|
||||
| 1<<25 // aesni
|
||||
;
|
||||
break;
|
||||
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...
|
||||
@@ -167,6 +297,25 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
|
||||
R_EAX = R_ECX = R_EBX = R_EDX = 0;
|
||||
}
|
||||
break;
|
||||
case 0xE: //?
|
||||
R_EAX = 0;
|
||||
break;
|
||||
case 0xF: //L3 Cache
|
||||
switch(R_ECX) {
|
||||
case 0:
|
||||
R_EAX = 0;
|
||||
R_EBX = 0; // maximum range of RMID of physical processor
|
||||
R_ECX = 0;
|
||||
R_EDX = 0; // bit 1 support L3 RDT Cache monitoring
|
||||
break;
|
||||
case 1:
|
||||
R_EAX = 0;
|
||||
R_EBX = 0; // Conversion factor
|
||||
R_EDX = 0; // bit 0 = occupency monitoring
|
||||
break;
|
||||
default: R_EAX = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80000000: // max extended
|
||||
R_EAX = 0x80000005;
|
||||
|
||||
+9
-2
@@ -44,13 +44,16 @@ ENTRYBOOL(BOX86_PREFER_EMULATED, box86_prefer_emulated) \
|
||||
ENTRYBOOL(BOX86_NOPULSE, box86_nopulse) \
|
||||
ENTRYBOOL(BOX86_NOGTK, box86_nogtk) \
|
||||
ENTRYBOOL(BOX86_NOVULKAN, box86_novulkan) \
|
||||
ENTRYBOOL(BOX86_FUTEX_WAITV, box86_futex_waitv) \
|
||||
ENTRYBOOL(BOX86_FIX_64BIT_INODES, fix_64bit_inodes) \
|
||||
ENTRYSTRING_(BOX86_BASH, bash) \
|
||||
ENTRYINT(BOX86_JITGDB, jit_gdb, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_JITGDB, jit_gdb, 0, 3, 2) \
|
||||
ENTRYSTRING_(BOX86_BOX64, box64) \
|
||||
ENTRYSTRING_(BOX86_LD_PRELOAD, ld_preload) \
|
||||
ENTRYBOOL(BOX86_NOSANDBOX, box86_nosandbox) \
|
||||
ENTRYBOOL(BOX86_LIBCEF, box86_libcef) \
|
||||
ENTRYBOOL(BOX86_SDL2_JGUID, box86_sdl2_jguid) \
|
||||
ENTRYBOOL(BOX86_MUTEX_ALIGNED, box86_mutex_aligned) \
|
||||
ENTRYINT(BOX86_MALLOC_HACK, box86_malloc_hack, 0, 2, 2) \
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -78,7 +81,7 @@ ENTRYINT(BOX86_DYNAREC_DUMP, box86_dynarec_dump, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_LOG, box86_dynarec_log, 0, 3, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_BIGBLOCK, box86_dynarec_bigblock, 0, 3, 2) \
|
||||
ENTRYSTRING_(BOX86_DYNAREC_FORWARD, box86_dynarec_forward) \
|
||||
ENTRYINT(BOX86_DYNAREC_STRONGMEM, box86_dynarec_strongmem, 0, 2, 2) \
|
||||
ENTRYINT(BOX86_DYNAREC_STRONGMEM, box86_dynarec_strongmem, 0, 3, 2) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_X87DOUBLE, box86_dynarec_x87double) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTNAN, box86_dynarec_fastnan) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_FASTROUND, box86_dynarec_fastround) \
|
||||
@@ -88,8 +91,10 @@ ENTRYBOOL(BOX86_DYNAREC_FASTPAGE, box86_dynarec_fastpage) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_WAIT, box86_dynarec_wait) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_BLEEDING_EDGE, box86_dynarec_bleeding_edge) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_JVM, box86_dynarec_jvm) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_TBB, box86_dynarec_tbb) \
|
||||
ENTRYSTRING_(BOX86_NODYNAREC, box86_nodynarec) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_TEST, box86_dynarec_test) \
|
||||
ENTRYBOOL(BOX86_DYNAREC_MISSING, box86_dynarec_missing) \
|
||||
|
||||
#else
|
||||
#define SUPER3() \
|
||||
@@ -108,8 +113,10 @@ IGNORE(BOX86_DYNAREC_FASTPAGE) \
|
||||
IGNORE(BOX86_DYNAREC_WAIT) \
|
||||
IGNORE(BOX86_DYNAREC_BLEEDING_EDGE) \
|
||||
IGNORE(BOX86_DYNAREC_JVM) \
|
||||
IGNORE(BOX86_DYNAREC_TBB) \
|
||||
IGNORE(BOX86_NODYNAREC) \
|
||||
IGNORE(BOX86_DYNAREC_TEST) \
|
||||
IGNORE(BOX86_DYNAREC_MISSING) \
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "wine_tools.h"
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
#include "custommem.h"
|
||||
|
||||
typedef struct wine_prereserve_s
|
||||
{
|
||||
@@ -76,6 +77,7 @@ void wine_prereserve(const char* reserve)
|
||||
my_wine_reserve[idx].addr = NULL;
|
||||
my_wine_reserve[idx].size = 0;
|
||||
} else {
|
||||
setProtection_mmap((uintptr_t)my_wine_reserve[idx].addr, my_wine_reserve[idx].size, 0);
|
||||
printf_log(LOG_DEBUG, "WINE prereserve of %p:0x%x done\n", my_wine_reserve[idx].addr, my_wine_reserve[idx].size);
|
||||
++idx;
|
||||
}
|
||||
|
||||
@@ -75,12 +75,12 @@
|
||||
#() dFp
|
||||
#() dFG
|
||||
#() lFv
|
||||
#() lFi
|
||||
#() lFu
|
||||
#() lFl
|
||||
#() lFp
|
||||
#() lFG
|
||||
#() LFv
|
||||
#() LFi
|
||||
#() LFu
|
||||
#() LFL
|
||||
#() LFp
|
||||
@@ -100,6 +100,7 @@
|
||||
#() pFV
|
||||
#() pFG
|
||||
#() vFEv
|
||||
#() vFEi
|
||||
#() vFEp
|
||||
#() vFcc
|
||||
#() vFww
|
||||
@@ -167,6 +168,7 @@
|
||||
#() vFGG
|
||||
#() cFpp
|
||||
#() iFEv
|
||||
#() iFEu
|
||||
#() iFEL
|
||||
#() iFEp
|
||||
#() iFwp
|
||||
@@ -213,7 +215,6 @@
|
||||
#() CFpu
|
||||
#() CFpp
|
||||
#() WFpp
|
||||
#() uFEv
|
||||
#() uFEu
|
||||
#() uFEp
|
||||
#() uFii
|
||||
@@ -221,7 +222,6 @@
|
||||
#() uFui
|
||||
#() uFuu
|
||||
#() uFup
|
||||
#() uFUp
|
||||
#() uFpw
|
||||
#() uFpi
|
||||
#() uFpu
|
||||
@@ -253,12 +253,15 @@
|
||||
#() dFpd
|
||||
#() dFpp
|
||||
#() DFpp
|
||||
#() lFEv
|
||||
#() lFEi
|
||||
#() lFui
|
||||
#() lFll
|
||||
#() lFpi
|
||||
#() lFpp
|
||||
#() LFii
|
||||
#() LFuu
|
||||
#() LFUp
|
||||
#() LFLi
|
||||
#() LFpi
|
||||
#() LFpL
|
||||
@@ -413,6 +416,7 @@
|
||||
#() iFiip
|
||||
#() iFiiO
|
||||
#() iFiII
|
||||
#() iFiui
|
||||
#() iFiuu
|
||||
#() iFiup
|
||||
#() iFiLN
|
||||
@@ -609,6 +613,7 @@
|
||||
#() pFplu
|
||||
#() pFpll
|
||||
#() pFplp
|
||||
#() pFpLu
|
||||
#() pFpLL
|
||||
#() pFpLp
|
||||
#() pFppi
|
||||
@@ -718,6 +723,7 @@
|
||||
#() vFffff
|
||||
#() vFdddd
|
||||
#() vFllii
|
||||
#() vFLppi
|
||||
#() vFpiii
|
||||
#() vFpiiu
|
||||
#() vFpiip
|
||||
@@ -818,6 +824,7 @@
|
||||
#() iFiuwp
|
||||
#() iFiuii
|
||||
#() iFiuui
|
||||
#() iFiLpL
|
||||
#() iFipii
|
||||
#() iFipip
|
||||
#() iFipui
|
||||
@@ -950,10 +957,12 @@
|
||||
#() lFipLI
|
||||
#() lFipLl
|
||||
#() lFipLL
|
||||
#() lFippL
|
||||
#() lFpili
|
||||
#() lFpilp
|
||||
#() lFpuip
|
||||
#() lFpupp
|
||||
#() lFpppL
|
||||
#() LFippp
|
||||
#() LFpLCL
|
||||
#() LFpLLp
|
||||
@@ -1136,6 +1145,7 @@
|
||||
#() vFfffff
|
||||
#() vFddddp
|
||||
#() vFluipp
|
||||
#() vFLpppi
|
||||
#() vFpiiii
|
||||
#() vFpiiiI
|
||||
#() vFpiiiu
|
||||
@@ -1198,6 +1208,7 @@
|
||||
#() iFEiipp
|
||||
#() iFEiipV
|
||||
#() iFEiupp
|
||||
#() iFEipip
|
||||
#() iFEipuu
|
||||
#() iFEippi
|
||||
#() iFEippL
|
||||
@@ -1233,6 +1244,7 @@
|
||||
#() iFipuii
|
||||
#() iFipuui
|
||||
#() iFippui
|
||||
#() iFippuu
|
||||
#() iFippup
|
||||
#() iFipppi
|
||||
#() iFipppp
|
||||
@@ -1270,6 +1282,8 @@
|
||||
#() iFpuuLL
|
||||
#() iFpuupu
|
||||
#() iFpuupp
|
||||
#() iFpuLpL
|
||||
#() iFpuLpp
|
||||
#() iFpupiU
|
||||
#() iFpupuu
|
||||
#() iFpupup
|
||||
@@ -1329,7 +1343,6 @@
|
||||
#() uFppupp
|
||||
#() uFpplip
|
||||
#() uFppLpp
|
||||
#() uFppppu
|
||||
#() uFppppp
|
||||
#() UFuiiii
|
||||
#() lFEipiI
|
||||
@@ -1353,6 +1366,7 @@
|
||||
#() pFEpipL
|
||||
#() pFEpipp
|
||||
#() pFEpupp
|
||||
#() pFEpUpp
|
||||
#() pFEppii
|
||||
#() pFEppip
|
||||
#() pFEppCC
|
||||
@@ -1384,6 +1398,9 @@
|
||||
#() pFpuiii
|
||||
#() pFpuiip
|
||||
#() pFpuuip
|
||||
#() pFpuuup
|
||||
#() pFpuupp
|
||||
#() pFpuLpp
|
||||
#() pFpuppp
|
||||
#() pFpUdii
|
||||
#() pFpdddd
|
||||
@@ -1512,6 +1529,7 @@
|
||||
#() vFppiiii
|
||||
#() vFppiiip
|
||||
#() vFppiiui
|
||||
#() vFppiiuu
|
||||
#() vFppiipi
|
||||
#() vFppiipp
|
||||
#() vFppilpp
|
||||
@@ -1560,7 +1578,9 @@
|
||||
#() iFiiiiip
|
||||
#() iFiiiuwp
|
||||
#() iFiuiipi
|
||||
#() iFiuUuUu
|
||||
#() iFipipuu
|
||||
#() iFipuIup
|
||||
#() iFipupup
|
||||
#() iFipuppp
|
||||
#() iFipppup
|
||||
@@ -1568,6 +1588,7 @@
|
||||
#() iFuppipp
|
||||
#() iFuppppp
|
||||
#() iFdipppL
|
||||
#() iFLpppii
|
||||
#() iFpiiiii
|
||||
#() iFpiiiip
|
||||
#() iFpiiipp
|
||||
@@ -1584,6 +1605,8 @@
|
||||
#() iFpipppp
|
||||
#() iFpCpipu
|
||||
#() iFpuiiii
|
||||
#() iFpuuupp
|
||||
#() iFpuuLpp
|
||||
#() iFpupipi
|
||||
#() iFpupuui
|
||||
#() iFpUuupp
|
||||
@@ -1605,6 +1628,7 @@
|
||||
#() iFppuipp
|
||||
#() iFppuIII
|
||||
#() iFppuupp
|
||||
#() iFppuLpp
|
||||
#() iFppupip
|
||||
#() iFppuppp
|
||||
#() iFppUipp
|
||||
@@ -1677,7 +1701,9 @@
|
||||
#() pFpiiuuu
|
||||
#() pFpiUUUU
|
||||
#() pFpippip
|
||||
#() pFpipppp
|
||||
#() pFpuuuuu
|
||||
#() pFpupppp
|
||||
#() pFplpppp
|
||||
#() pFpLiLpp
|
||||
#() pFpLpLLi
|
||||
@@ -1794,13 +1820,14 @@
|
||||
#() iFEpUuppp
|
||||
#() iFEpLiipV
|
||||
#() iFEppiuui
|
||||
#() iFEppupIi
|
||||
#() iFEppuppp
|
||||
#() iFEpplppi
|
||||
#() iFEppLpIi
|
||||
#() iFEpppiiu
|
||||
#() iFEpppppp
|
||||
#() iFiiiiiii
|
||||
#() iFiiiiiip
|
||||
#() iFippuIup
|
||||
#() iFpiiiiii
|
||||
#() iFpiiiiip
|
||||
#() iFpiiiuwp
|
||||
@@ -1822,6 +1849,7 @@
|
||||
#() iFpuupppp
|
||||
#() iFpupuuui
|
||||
#() iFpupuufu
|
||||
#() iFpupuupp
|
||||
#() iFpupupui
|
||||
#() iFpuppppp
|
||||
#() iFpLipipi
|
||||
@@ -1829,7 +1857,6 @@
|
||||
#() iFppiipii
|
||||
#() iFppiipiL
|
||||
#() iFppiippp
|
||||
#() iFppiuppi
|
||||
#() iFppipiip
|
||||
#() iFppipipi
|
||||
#() iFppipipp
|
||||
@@ -1859,11 +1886,13 @@
|
||||
#() uFEpuuppp
|
||||
#() uFEpppppp
|
||||
#() uFuippppp
|
||||
#() uFppiuppi
|
||||
#() uFppiuppp
|
||||
#() uFppuuuup
|
||||
#() LFEppLppU
|
||||
#() LFEpppppu
|
||||
#() pFEpiiiiu
|
||||
#() pFEpupppp
|
||||
#() pFEpLiiii
|
||||
#() pFEpLiiiI
|
||||
#() pFEppCuup
|
||||
@@ -1879,6 +1908,7 @@
|
||||
#() pFdiiiIiI
|
||||
#() pFpiiUdii
|
||||
#() pFpipippp
|
||||
#() pFpuppppp
|
||||
#() pFplppppp
|
||||
#() pFpLpLLiL
|
||||
#() pFpLppiip
|
||||
@@ -1912,7 +1942,6 @@
|
||||
#() vFEiippppV
|
||||
#() vFEiupippp
|
||||
#() vFEippippp
|
||||
#() vFEuuuuppp
|
||||
#() vFEppipppp
|
||||
#() vFEpppippp
|
||||
#() vFEpppuipV
|
||||
@@ -1989,11 +2018,13 @@
|
||||
#() iFpdiiiIiI
|
||||
#() iFppiiiiiu
|
||||
#() iFppIIIppp
|
||||
#() iFpppiiipi
|
||||
#() iFpppiippp
|
||||
#() iFpppipipi
|
||||
#() iFpppipppp
|
||||
#() iFppppiipi
|
||||
#() iFppppippp
|
||||
#() iFpppppupp
|
||||
#() iFppppppii
|
||||
#() iFpppppppi
|
||||
#() iFpppppppp
|
||||
@@ -2033,12 +2064,14 @@
|
||||
#() pFpWWiCpup
|
||||
#() pFpuuuupup
|
||||
#() pFpupupuuu
|
||||
#() pFpupLLLpp
|
||||
#() pFpdwwWWui
|
||||
#() pFplpppppp
|
||||
#() pFpLppLLiL
|
||||
#() pFppiiiiii
|
||||
#() pFpppuuuuu
|
||||
#() pFpppppupp
|
||||
#() vFEuuuupppp
|
||||
#() vFEpiiiiipp
|
||||
#() vFEpuuuippp
|
||||
#() vFEppiipppp
|
||||
@@ -2102,11 +2135,18 @@
|
||||
#() iFppiiiiiii
|
||||
#() iFppiuiippu
|
||||
#() iFppipiiipi
|
||||
#() iFppuLLpupp
|
||||
#() iFppupppupp
|
||||
#() iFppLpiippp
|
||||
#() iFpppiiipip
|
||||
#() iFpppiiuuii
|
||||
#() iFpppiipiiu
|
||||
#() iFpppLLLupp
|
||||
#() iFpppLppupp
|
||||
#() iFppppiiupp
|
||||
#() iFppppupiii
|
||||
#() iFpppppLupp
|
||||
#() iFppppppupp
|
||||
#() iFppppppppu
|
||||
#() iFppppppppp
|
||||
#() uFEipippppp
|
||||
@@ -2179,6 +2219,7 @@
|
||||
#() iFppipiippii
|
||||
#() iFppuuiiiiii
|
||||
#() iFppuuiiuupi
|
||||
#() iFpppiiipipi
|
||||
#() iFpppLLipppp
|
||||
#() iFppppiiuuii
|
||||
#() iFpppppppipi
|
||||
@@ -2190,8 +2231,10 @@
|
||||
#() pFEppCuwwWWu
|
||||
#() pFEppCuuuCup
|
||||
#() pFEppuuWWCuu
|
||||
#() pFpupLLLLLpp
|
||||
#() pFplllllllll
|
||||
#() pFppuiipuuii
|
||||
#() pFppuuLLuppp
|
||||
#() pFpppppppppp
|
||||
#() vFEpiiiupupup
|
||||
#() vFiiiiillliip
|
||||
@@ -2229,6 +2272,7 @@
|
||||
#() iFiiiiiiiiiip
|
||||
#() iFpiippiiipip
|
||||
#() iFppippipppip
|
||||
#() iFppuppLLpupp
|
||||
#() iFppppiiuuiiu
|
||||
#() uFEpiiupppiuV
|
||||
#() uFEpiippppiup
|
||||
@@ -2273,6 +2317,7 @@
|
||||
#() pFWWiCCCCiipup
|
||||
#() pFppiiuuuiupup
|
||||
#() pFppippLLLiLpp
|
||||
#() pFppuuppppuppp
|
||||
#() pFpppppppppppp
|
||||
#() vFEpppppppiippp
|
||||
#() vFuiiiiiiiiiuup
|
||||
@@ -2290,9 +2335,10 @@
|
||||
#() iFpippppppppppp
|
||||
#() iFpupiiiipppppp
|
||||
#() iFpuppppppppppp
|
||||
#() iFppppppLLLLupp
|
||||
#() iFppppppppppppp
|
||||
#() uFippuuuulllipp
|
||||
#() uFppppuuupppppp
|
||||
#() uFpppppuupppppp
|
||||
#() pFppLppppiiLpip
|
||||
#() pFppppppppppppp
|
||||
#() vFuffiiffiiffiip
|
||||
@@ -2301,6 +2347,7 @@
|
||||
#() vFpppppppppppppp
|
||||
#() iFpipppppppppppp
|
||||
#() iFpupppppppppppp
|
||||
#() iFppupppLLLLpupp
|
||||
#() iFpppppppppppppp
|
||||
#() pFEppCuuWWwwCCup
|
||||
#() pFEppuuuWWWWWWWW
|
||||
@@ -2388,6 +2435,8 @@ wrappedappindicator:
|
||||
wrappedappindicator3:
|
||||
wrappedatk:
|
||||
wrappedatkbridge:
|
||||
wrappedatomic:
|
||||
wrappedayatanaappindicator3:
|
||||
wrappedbz2:
|
||||
- iFp:
|
||||
- BZ2_bzCompressEnd
|
||||
@@ -3077,9 +3126,15 @@ wrappedlibasound:
|
||||
- snd_async_add_pcm_handler
|
||||
- pFpipL:
|
||||
- snd_dlopen
|
||||
wrappedlibbsd:
|
||||
- pFpLL:
|
||||
wrappedlibc:
|
||||
- vFv:
|
||||
- __cxa_pure_virtual
|
||||
- vFi:
|
||||
- _Exit
|
||||
- _exit
|
||||
- exit
|
||||
- vFp:
|
||||
- iFv:
|
||||
- iFi:
|
||||
@@ -3088,9 +3143,12 @@ wrappedlibc:
|
||||
- iFp:
|
||||
- getwc
|
||||
- iFO:
|
||||
- uFv:
|
||||
- uFu:
|
||||
- uFp:
|
||||
- lFv:
|
||||
- lFi:
|
||||
- __sysconf
|
||||
- sysconf
|
||||
- LFL:
|
||||
- pFu:
|
||||
- getpwuid
|
||||
@@ -3170,7 +3228,6 @@ wrappedlibc:
|
||||
- __read_nocancel
|
||||
- pFpii:
|
||||
- pFpip:
|
||||
- pFpLL:
|
||||
- vFiipV:
|
||||
- __syslog_chk
|
||||
- vFpLLp:
|
||||
@@ -3253,6 +3310,8 @@ wrappedlibdl:
|
||||
- iFpppi:
|
||||
- dladdr1
|
||||
wrappedlibdrm:
|
||||
- vFpV:
|
||||
- drmMsg
|
||||
wrappedlibformw:
|
||||
wrappedlibfuse:
|
||||
- iFpp:
|
||||
@@ -3493,6 +3552,7 @@ wrappedlibnm:
|
||||
- nm_client_add_and_activate_connection_async
|
||||
wrappedlibogg:
|
||||
wrappedlibpanel:
|
||||
wrappedlibpcre:
|
||||
wrappedlibpthread:
|
||||
- vFv:
|
||||
- __pthread_initialize
|
||||
@@ -3500,6 +3560,8 @@ wrappedlibpthread:
|
||||
- __pthread_register_cancel
|
||||
- __pthread_unregister_cancel
|
||||
- __pthread_unwind_next
|
||||
- iFu:
|
||||
- pthread_key_delete
|
||||
- iFp:
|
||||
- __pthread_mutex_destroy
|
||||
- __pthread_mutex_lock
|
||||
@@ -3561,8 +3623,17 @@ wrappedlibpthread:
|
||||
- pthread_create
|
||||
wrappedlibresolv:
|
||||
wrappedlibrt:
|
||||
- iFp:
|
||||
- aio_read
|
||||
- aio_read64
|
||||
- aio_write
|
||||
- aio_write64
|
||||
- iFip:
|
||||
- aio_cancel
|
||||
- iFupp:
|
||||
- timer_create
|
||||
- iFipip:
|
||||
- lio_listio
|
||||
wrappedlibsm:
|
||||
- iFppp:
|
||||
- SmcRequestSaveYourselfPhase2
|
||||
@@ -4083,6 +4154,13 @@ wrappedopenal:
|
||||
- alcGetProcAddress
|
||||
- vFiiipp:
|
||||
- alRequestFoldbackStart
|
||||
wrappedopencl:
|
||||
- pFpuppp:
|
||||
- clCreateContextFromType
|
||||
- iFpupppp:
|
||||
- clBuildProgram
|
||||
- pFpupppp:
|
||||
- clCreateContext
|
||||
wrappedpango:
|
||||
- vFpp:
|
||||
- pango_attribute_init
|
||||
@@ -4147,6 +4225,7 @@ wrappedpulse:
|
||||
- pa_context_set_event_callback
|
||||
- pa_context_set_state_callback
|
||||
- pa_context_set_subscribe_callback
|
||||
- pa_mainloop_api_once
|
||||
- pa_mainloop_set_poll_func
|
||||
- pa_stream_set_buffer_attr_callback
|
||||
- pa_stream_set_event_callback
|
||||
@@ -4197,6 +4276,8 @@ wrappedpulse:
|
||||
- pa_context_subscribe
|
||||
- pa_context_unload_module
|
||||
- pa_stream_update_sample_rate
|
||||
- pFpUpp:
|
||||
- pa_context_rttime_new
|
||||
- pFpppp:
|
||||
- pa_context_get_sink_info_by_name
|
||||
- pa_context_get_source_info_by_name
|
||||
@@ -4230,7 +4311,7 @@ wrappedpulse:
|
||||
- pa_context_load_module
|
||||
- pa_context_set_sink_port_by_name
|
||||
- pa_context_set_source_volume_by_name
|
||||
- iFppupIi:
|
||||
- iFppLpIi:
|
||||
- pa_stream_write
|
||||
- pFpiuCppp:
|
||||
- pa_ext_device_restore_save_formats
|
||||
@@ -4447,8 +4528,6 @@ wrappedsdl2:
|
||||
- SDL_LogMessage
|
||||
- vFpuup:
|
||||
- SDL_qsort
|
||||
- vFJppp:
|
||||
- SDL_GetJoystickGUIDInfo
|
||||
- iFpupp:
|
||||
- SDL_vsnprintf
|
||||
- iFpupV:
|
||||
@@ -4456,6 +4535,8 @@ wrappedsdl2:
|
||||
- uFppuu:
|
||||
- SDL_RWread
|
||||
- SDL_RWwrite
|
||||
- vFJpppp:
|
||||
- SDL_GetJoystickGUIDInfo
|
||||
- iFpippi:
|
||||
- SDL_OpenAudioDevice
|
||||
- pFpippp:
|
||||
@@ -4467,7 +4548,7 @@ wrappedsdl2:
|
||||
% JFEi -> pFEpi
|
||||
% JFEp -> pFEpp
|
||||
% gFEpi -> pFEppi
|
||||
% vFEJppp -> vFEuuuuppp
|
||||
% vFEJpppp -> vFEuuuupppp
|
||||
wrappedsdl2image:
|
||||
- pFp:
|
||||
- IMG_LoadBMP_RW
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedandroidshmemDEFS_H_
|
||||
#define __wrappedandroidshmemDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedandroidshmemDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedandroidshmemTYPES_H_
|
||||
#define __wrappedandroidshmemTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedandroidshmemTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedandroidshmemUNDEFS_H_
|
||||
#define __wrappedandroidshmemUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedandroidshmemUNDEFS_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatomicDEFS_H_
|
||||
#define __wrappedatomicDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedatomicDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatomicTYPES_H_
|
||||
#define __wrappedatomicTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedatomicTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedatomicUNDEFS_H_
|
||||
#define __wrappedatomicUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedatomicUNDEFS_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedayatanaappindicator3DEFS_H_
|
||||
#define __wrappedayatanaappindicator3DEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedayatanaappindicator3DEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedayatanaappindicator3TYPES_H_
|
||||
#define __wrappedayatanaappindicator3TYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedayatanaappindicator3TYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedayatanaappindicator3UNDEFS_H_
|
||||
#define __wrappedayatanaappindicator3UNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedayatanaappindicator3UNDEFS_H_
|
||||
Loaded 100 of 223 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user