mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-09 04:09:46 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59ab48b99e | ||
|
|
a7a58b920f | ||
|
|
1c26df2a90 | ||
|
|
c60e4839eb | ||
|
|
b626fc5095 | ||
|
|
bcd504eb05 | ||
|
|
7057b7f929 | ||
|
|
6af070e25f | ||
|
|
af1a7bd6f4 | ||
|
|
dfd3d0ec93 | ||
|
|
1791c0937a | ||
|
|
c2dd6a0c6a | ||
|
|
f300e76c9b | ||
|
|
8f6f880b6a | ||
|
|
3dcef655c3 | ||
|
|
4c476de74b | ||
|
|
c9e277aee5 | ||
|
|
689d6906ef | ||
|
|
1712afdae9 | ||
|
|
8428fafd3a | ||
|
|
3074846477 | ||
|
|
6c1825ba65 | ||
|
|
bef0a5f793 | ||
|
|
8e694eac57 | ||
|
|
8622f9fdc3 | ||
|
|
6e6a8f47af | ||
|
|
7a57c70d81 | ||
|
|
b2a1af1029 | ||
|
|
c44961c063 | ||
|
|
aceb234c2e | ||
|
|
dd6b60818c | ||
|
|
1978b16581 | ||
|
|
0d079b8c0b | ||
|
|
913029f4c5 | ||
|
|
c667c71a99 | ||
|
|
3cd8b9a44e | ||
|
|
126119b1fb | ||
|
|
701bf913e8 | ||
|
|
00b5944271 | ||
|
|
196076f952 | ||
|
|
e350224157 | ||
|
|
730e129a80 | ||
|
|
883fc1681d | ||
|
|
6b2b672c5e | ||
|
|
1d31bf699f | ||
|
|
c62728f44f | ||
|
|
90efb1ff31 | ||
|
|
7625cc7ceb | ||
|
|
a074115bf5 | ||
|
|
c3aa068179 | ||
|
|
e07be95646 | ||
|
|
0777a568d7 | ||
|
|
f6ce622841 | ||
|
|
508545aa87 | ||
|
|
52d86177c5 | ||
|
|
979d1cfba9 | ||
|
|
31a01aceab | ||
|
|
3b39d1270d | ||
|
|
d5b286c050 | ||
|
|
1f23848e25 | ||
|
|
db1c033c7c | ||
|
|
489afcfb41 | ||
|
|
5519ddad0b | ||
|
|
e788589944 | ||
|
|
7a894540b9 | ||
|
|
30f0f3a5a1 | ||
|
|
debc7284b3 | ||
|
|
60f5dfabd8 | ||
|
|
dd2f209096 | ||
|
|
3b181576c8 | ||
|
|
409334ea56 | ||
|
|
71218a6f70 | ||
|
|
a5be3727e9 | ||
|
|
836b646e24 | ||
|
|
15e4830dff | ||
|
|
ac1156d165 | ||
|
|
370ec24987 | ||
|
|
3bdcae10c8 | ||
|
|
681df1604d | ||
|
|
05abd88ea5 | ||
|
|
42670c0130 | ||
|
|
f4c15979db | ||
|
|
8d97f13677 | ||
|
|
75c4c3d6b9 | ||
|
|
a71e81c842 | ||
|
|
add55f3cec | ||
|
|
c6f6a9ef72 | ||
|
|
1c1e39ef64 | ||
|
|
f5655d85a3 | ||
|
|
c31262d339 | ||
|
|
570798358c | ||
|
|
05c9644ea6 | ||
|
|
051bd2b10b | ||
|
|
b1b9d10656 | ||
|
|
506f78eb32 | ||
|
|
1336ddfad7 | ||
|
|
f3617f720b | ||
|
|
844a1f43ed | ||
|
|
8e42412490 | ||
|
|
2737180a20 | ||
|
|
57e9e55705 | ||
|
|
3f3f8b41e9 | ||
|
|
d3ea390983 | ||
|
|
2f1cc844fd | ||
|
|
543af50ff8 | ||
|
|
f6444c8d45 | ||
|
|
df96dd0060 | ||
|
|
956e2aace3 | ||
|
|
1951d525d1 | ||
|
|
3d4d678bdc | ||
|
|
b78d92d288 | ||
|
|
e5dc4d7e78 | ||
|
|
cd247ef6c1 | ||
|
|
104cf8a58b | ||
|
|
976f175aa9 | ||
|
|
81a06c47a1 | ||
|
|
46b8c6bc83 | ||
|
|
5f83a3f98a | ||
|
|
2f6129bfd5 | ||
|
|
26698b6449 | ||
|
|
61839151c0 | ||
|
|
b38c9ea253 | ||
|
|
25754a47e0 | ||
|
|
278888c912 | ||
|
|
7faa4704e6 | ||
|
|
ba48b6c793 | ||
|
|
f8a969d43e | ||
|
|
55720342ad | ||
|
|
085239ef4a | ||
|
|
df61d561f6 | ||
|
|
3cd8b5f48b | ||
|
|
2e21e46e86 | ||
|
|
cb73a9a6bc | ||
|
|
5199df9b61 | ||
|
|
537ca9f724 | ||
|
|
fc5f5dab29 | ||
|
|
4be307820b | ||
|
|
15227bbc06 | ||
|
|
d0da2c24fb | ||
|
|
152a8a4666 | ||
|
|
86669beb7a | ||
|
|
ba2a70a484 | ||
|
|
88ffcf6396 | ||
|
|
4d347f9ff0 | ||
|
|
252258d138 | ||
|
|
e35b25015b | ||
|
|
422844f842 | ||
|
|
61725c8b49 | ||
|
|
727178df57 | ||
|
|
66b3303f22 | ||
|
|
47c3fad83b | ||
|
|
3928222395 | ||
|
|
414d33a46c | ||
|
|
40a2c8393e | ||
|
|
48fe298a36 | ||
|
|
2865f0eab2 | ||
|
|
a5780632ca | ||
|
|
bd5d29a825 | ||
|
|
5255935a31 | ||
|
|
a31ee062b6 | ||
|
|
c56c991bf7 | ||
|
|
5ea4b796a5 | ||
|
|
8fe7378f86 | ||
|
|
1224ffa7cd | ||
|
|
56766df719 | ||
|
|
e505e5e466 | ||
|
|
4cdc3c62b2 | ||
|
|
4402f08245 | ||
|
|
954830032b | ||
|
|
6f3fad8a16 | ||
|
|
2bb956bb06 | ||
|
|
7fa2a273d0 | ||
|
|
52e125e35a | ||
|
|
57bea35004 | ||
|
|
890842286b | ||
|
|
aec0ad9128 | ||
|
|
4f5b5a995b | ||
|
|
bcd07ff6c7 | ||
|
|
68d7188f3e | ||
|
|
a924a74d82 | ||
|
|
a20b830379 | ||
|
|
12fe96b114 | ||
|
|
3432721379 | ||
|
|
b39b7fd374 | ||
|
|
406ddff9a1 | ||
|
|
d16d985a48 | ||
|
|
0a2ea72d72 | ||
|
|
3b4de7152c | ||
|
|
5520dae2e7 | ||
|
|
7a7f26c80e | ||
|
|
35f4944afb | ||
|
|
0a107d10eb | ||
|
|
2c56ccfabe | ||
|
|
d1497e98db | ||
|
|
7925a8e1b3 | ||
|
|
d529bf3c0c | ||
|
|
802c5a9d5b | ||
|
|
3a22c36d04 | ||
|
|
512ee40dbc | ||
|
|
d84e1f49ce | ||
|
|
c4abaf8c8d | ||
|
|
59fe5f3572 | ||
|
|
18320e19bc | ||
|
|
248cd2e749 | ||
|
|
3b550eeed3 | ||
|
|
097c0ac0b7 | ||
|
|
7a95dcd6b6 | ||
|
|
47d0c04b30 | ||
|
|
16be2bd305 | ||
|
|
7cf6ee06a1 | ||
|
|
dd4c413e41 | ||
|
|
08d2ac41f6 | ||
|
|
fd939c6fce | ||
|
|
82755b5ef2 | ||
|
|
7b4cbee8e7 | ||
|
|
5346f594d4 | ||
|
|
6f217d78da | ||
|
|
cdf71c4cbc | ||
|
|
e93a280d2c | ||
|
|
51fa96c44b | ||
|
|
48d6135106 | ||
|
|
0d38b1cd91 |
No files matched your search
@@ -1,3 +1,19 @@
|
||||
v0.1.0
|
||||
======
|
||||
* Improvement to ElfLoader
|
||||
* More opcode added to the Dynarec
|
||||
* More lib wrapping
|
||||
* Some fixes to a few function signature
|
||||
* Improvement to Signal handling, and internal mutex handling
|
||||
* A few fixes to some dynarec opcodes
|
||||
* A few fixes to some interpretor opcodes
|
||||
|
||||
v0.0.8
|
||||
======
|
||||
* Improvement to SSE/x87 handling
|
||||
* More opcode added to the Dynarec
|
||||
* More lib wrapping
|
||||
|
||||
v0.0.6
|
||||
======
|
||||
* Added Dynarec for ARM64
|
||||
|
||||
+47
-15
@@ -1,4 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
|
||||
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
|
||||
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
|
||||
@@ -36,7 +38,7 @@ project(box64 C ASM)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(default_build_type "RelwithDebInfo")
|
||||
set(default_build_type "RelWithDebInfo")
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
@@ -46,8 +48,8 @@ endif()
|
||||
if(RPI4ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8")
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
|
||||
endif()
|
||||
|
||||
if(RK3326)
|
||||
@@ -101,6 +103,8 @@ if(USE_CCACHE)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
else()
|
||||
message(SEND_ERROR "ccache not found!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -137,6 +141,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64run6664.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
@@ -158,6 +163,9 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64trace.c"
|
||||
"${BOX64_ROOT}/src/librarian/librarian.c"
|
||||
"${BOX64_ROOT}/src/librarian/library.c"
|
||||
"${BOX64_ROOT}/src/librarian/dictionnary.c"
|
||||
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX64_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX64_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX64_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
|
||||
@@ -177,30 +185,44 @@ set(ELFLOADER_SRC
|
||||
set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatk.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcrypt.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibuuid.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibvorbis.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
|
||||
@@ -213,6 +235,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxdmcp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxext.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxfixes.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxft.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxmu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxpm.c"
|
||||
@@ -228,11 +251,14 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1image.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1mixer.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
|
||||
@@ -241,11 +267,13 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
|
||||
)
|
||||
|
||||
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
|
||||
@@ -259,9 +287,9 @@ set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/w
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
|
||||
${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
@@ -338,9 +366,9 @@ if(ARM_DYNAREC)
|
||||
add_dependencies(arm64_pass2 WRAPPERS)
|
||||
add_dependencies(arm64_pass3 WRAPPERS)
|
||||
|
||||
add_library(dynarec STATIC
|
||||
$<TARGET_OBJECTS:dynarec_arm>
|
||||
$<TARGET_OBJECTS:arm64_pass0>
|
||||
add_library(dynarec STATIC
|
||||
$<TARGET_OBJECTS:dynarec_arm>
|
||||
$<TARGET_OBJECTS:arm64_pass0>
|
||||
$<TARGET_OBJECTS:arm64_pass1>
|
||||
$<TARGET_OBJECTS:arm64_pass2>
|
||||
$<TARGET_OBJECTS:arm64_pass3>
|
||||
@@ -364,6 +392,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
|
||||
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
|
||||
add_dependencies(${BOX64} WRAPPERS)
|
||||
#add_dependencies(${BOX64} PRINTER)
|
||||
target_link_libraries(${BOX64} m dl rt pthread)
|
||||
@@ -373,14 +402,12 @@ endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic")
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
endif()
|
||||
else()
|
||||
target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
if(NOT NOLOADADDR)
|
||||
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -481,6 +508,11 @@ add_test(test15 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(test16 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.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)
|
||||
|
||||
+10
-9
@@ -39,29 +39,31 @@ sudo systemctl restart systemd-binfmt
|
||||
|
||||
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
|
||||
#### use ccmake
|
||||
If you encounter some linking errors, try activating `NOLOADADDR` (`cmake -DNOLOADADDR=ON; make -j$(nproc)`).
|
||||
|
||||
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
|
||||
### use ccmake
|
||||
|
||||
#### Customize your build
|
||||
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
|
||||
|
||||
*use ccache if you have it*
|
||||
### Customize your build
|
||||
|
||||
*Use ccache if you have it*
|
||||
|
||||
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
|
||||
|
||||
*have some debug info*
|
||||
*To have some debug info*
|
||||
|
||||
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
|
||||
|
||||
*to have a Trace Enabled build*
|
||||
*To have a Trace Enabled build*
|
||||
|
||||
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
|
||||
|
||||
*to have ARM Dynarec*
|
||||
*To have ARM Dynarec*
|
||||
|
||||
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
|
||||
|
||||
*not building from a git clone*
|
||||
*Not building from a git clone*
|
||||
|
||||
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box64 print).
|
||||
|
||||
@@ -72,4 +74,3 @@ Testing
|
||||
A few tests are included.
|
||||
They can be launched with `ctest`
|
||||
They are very basic and don't test much for now.
|
||||
|
||||
@@ -31,6 +31,7 @@ Enables/Disables the logging of `dlsym` errors.
|
||||
#### BOX64_TRACE_FILE
|
||||
Send all log and trace to a file instead of `stdout`
|
||||
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
|
||||
Use `stderr` to use this instead of default `stdout`
|
||||
|
||||
#### BOX64_TRACE
|
||||
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
|
||||
|
||||
+578
-274
File diff suppressed because it is too large.
Load diff
+10
-3
@@ -73,9 +73,8 @@ int unlockMutex()
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
|
||||
@@ -158,6 +157,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
|
||||
context->maplib = NewLibrarian(context, 1);
|
||||
context->local_maplib = NewLibrarian(context, 1);
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
|
||||
@@ -175,7 +175,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
|
||||
for (int i=0; i<8; ++i) context->canary[i] = 1 + getrand(255);
|
||||
context->canary[getrand(4)] = 0;
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x14, value:%08X\n", *(uint32_t*)context->canary);
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary);
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
@@ -197,6 +197,7 @@ void FreeBox64Context(box64context_t** context)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
FreeLibrarian(&ctx->maplib, NULL);
|
||||
FreeDictionnary(&ctx->versym);
|
||||
|
||||
for(int i=0; i<ctx->elfsize; ++i) {
|
||||
FreeElfHeader(&ctx->elfs[i]);
|
||||
@@ -311,6 +312,9 @@ void add_neededlib(needed_libs_t* needed, library_t* lib)
|
||||
{
|
||||
if(!needed)
|
||||
return;
|
||||
for(int i=0; i<needed->size; ++i)
|
||||
if(needed->libs[i] == lib)
|
||||
return;
|
||||
if(needed->size == needed->cap) {
|
||||
needed->cap += 8;
|
||||
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
|
||||
@@ -333,6 +337,9 @@ void add_dependedlib(needed_libs_t* depended, library_t* lib)
|
||||
{
|
||||
if(!depended)
|
||||
return;
|
||||
for(int i=0; i<depended->size; ++i)
|
||||
if(depended->libs[i] == lib)
|
||||
return;
|
||||
if(depended->size == depended->cap) {
|
||||
depended->cap += 8;
|
||||
depended->libs = (library_t**)realloc(depended->libs, depended->cap*sizeof(library_t*));
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
#define __BOX64_VERSION_H_
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 0
|
||||
#define BOX64_REVISION 8
|
||||
#define BOX64_MINOR 1
|
||||
#define BOX64_REVISION 0
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+140
-95
@@ -33,7 +33,7 @@ KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
|
||||
static pthread_mutex_t mutex_mmap;
|
||||
static mmaplist_t *mmaplist;
|
||||
static int mmapsize;
|
||||
static size_t mmapsize;
|
||||
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
|
||||
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
|
||||
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
|
||||
@@ -50,7 +50,7 @@ static int inited = 0;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t maxfree;
|
||||
size_t size;
|
||||
} blocklist_t;
|
||||
|
||||
@@ -73,14 +73,14 @@ typedef struct blockmark_s {
|
||||
} blockmark_t;
|
||||
|
||||
|
||||
// get first subblock free in block, stating at start (from block). return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, int maxsize, int* size)
|
||||
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
|
||||
*size = m->next.size;
|
||||
*size = m->next.size-sizeof(blockmark_t);
|
||||
return m;
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m + m->next.size);
|
||||
@@ -89,24 +89,26 @@ static void* getFirstBlock(void* block, int maxsize, int* size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int getMaxFreeBlock(void* block, size_t block_size)
|
||||
static size_t getMaxFreeBlock(void* block, size_t block_size)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // styart with the end
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return maxsize; // no block large enough left...
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
|
||||
}
|
||||
return maxsize;
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
|
||||
}
|
||||
|
||||
static void* allocBlock(void* block, void *sub, int size)
|
||||
static void* allocBlock(void* block, void *sub, size_t size)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
|
||||
@@ -152,14 +154,17 @@ static void freeBlock(void *block, void* sub)
|
||||
}
|
||||
}
|
||||
// return 1 if block has been expanded to new size, 0 if not
|
||||
static int expandBlock(void* block, void* sub, int newsize)
|
||||
static int expandBlock(void* block, void* sub, size_t newsize)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
newsize = (newsize+3)&~3;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
if(s->next.fill)
|
||||
return 0; // next block is filled
|
||||
if(s->next.size + n->next.size < newsize)
|
||||
// unsigned bitfield of this length gets "promoted" to *signed* int...
|
||||
if((size_t)(s->next.size + n->next.size) < newsize)
|
||||
return 0; // free space too short
|
||||
// ok, doing the alloc!
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
@@ -178,7 +183,7 @@ static int expandBlock(void* block, void* sub, int newsize)
|
||||
return 1;
|
||||
}
|
||||
// return size of block
|
||||
static int sizeBlock(void* sub)
|
||||
static size_t sizeBlock(void* sub)
|
||||
{
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
return s->next.size;
|
||||
@@ -191,7 +196,7 @@ void* customMalloc(size_t size)
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if(p_blocks[i].maxfree>=size) {
|
||||
int rsize = 0;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
|
||||
if(sub) {
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size);
|
||||
@@ -253,17 +258,16 @@ void* customRealloc(void* p, size_t size)
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return p;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
if(n_blocks)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
|
||||
return customMalloc(size);
|
||||
}
|
||||
void customFree(void* p)
|
||||
@@ -290,19 +294,19 @@ void customFree(void* p)
|
||||
#ifdef DYNAREC
|
||||
typedef struct mmaplist_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t maxfree;
|
||||
size_t size;
|
||||
kh_dynablocks_t* dblist;
|
||||
uint8_t* helper;
|
||||
} mmaplist_t;
|
||||
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].maxfree>=size) {
|
||||
int rsize = 0;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
|
||||
@@ -317,7 +321,7 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
|
||||
return ret;
|
||||
}
|
||||
@@ -326,15 +330,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
int i = mmapsize++;
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
|
||||
size_t i = mmapsize++;
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, MMAPSIZE)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
@@ -342,7 +346,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
#else
|
||||
void* p = mmap(NULL, MMAPSIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
@@ -370,16 +374,17 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
|
||||
return sub;
|
||||
}
|
||||
|
||||
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
{
|
||||
(void)db;
|
||||
if(!addr || !size)
|
||||
return;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if ((addr>(uintptr_t)mmaplist[i].block)
|
||||
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
@@ -390,20 +395,20 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(mmapsize)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
|
||||
dynarec_log(LOG_NONE, "Warning, block %p (size %zu) not found in mmaplist for Free\n", (void*)addr, size);
|
||||
}
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
{
|
||||
// look in actual list
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
|
||||
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) {
|
||||
if(!mmaplist[i].helper)
|
||||
@@ -422,7 +427,7 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
return FindDynablockDynablocklist(addr, dblist_oversized);
|
||||
}
|
||||
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
if(!size)
|
||||
return 0;
|
||||
@@ -431,14 +436,14 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#else
|
||||
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -467,7 +472,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
{
|
||||
if(!addr || !size)
|
||||
return;
|
||||
@@ -508,7 +513,7 @@ dynablocklist_t* getDB(uintptr_t idx)
|
||||
|
||||
// each dynmap is 64k of size
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
@@ -535,7 +540,15 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
static int dynmapempty(void** mem)
|
||||
{
|
||||
for (int i=0; i<(1<<DYNAMAP_SHIFT); ++i)
|
||||
if(mem[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
@@ -547,9 +560,26 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
if(dynmap123[idx3] && dynmap123[idx3][idx2]) {
|
||||
dynablocklist_t* dblist = dynmap123[idx3][idx2][idx1];
|
||||
if(dblist) {
|
||||
if(destroy)
|
||||
FreeRangeDynablock(dblist, addr, size);
|
||||
else
|
||||
if(destroy) {
|
||||
if(FreeRangeDynablock(dblist, addr, size) && 0) { // dblist is empty, check if we can delete more...
|
||||
// disabling this for now. It seems to cause random crash in Terraria
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
|
||||
dynablocklist_t** p = dynmap123[idx3][idx2];
|
||||
if(dynmapempty((void**)p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
|
||||
dynablocklist_t*** p2 = dynmap123[idx3];
|
||||
if(dynmapempty((void**)p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2)) {
|
||||
free(p2);
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
FreeDynablockList(&dblist);
|
||||
}
|
||||
}
|
||||
} else
|
||||
MarkRangeDynablock(dblist, addr, size);
|
||||
}
|
||||
}
|
||||
@@ -662,15 +692,13 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
return (uintptr_t)&box64_jmptbl3[idx3][idx2][idx1][idx0];
|
||||
}
|
||||
|
||||
// Remove the Write flag from an adress range, so DB can be executed
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void protectDB(uintptr_t addr, uintptr_t size)
|
||||
// Remove the Write flag from an adress range, so DB can be executed safely
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -686,30 +714,13 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
if(!(prot&PROT_DYNAREC))
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
void protectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
|
||||
if(!(prot&PROT_DYNAREC))
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
protectDBnolock(addr, size);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void lockDB()
|
||||
@@ -724,7 +735,7 @@ void unlockDB()
|
||||
|
||||
// Add the Write flag from an adress range, and mark all block as dirty
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
void unprotectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
@@ -751,12 +762,14 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
|
||||
#endif
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t last = idx<<MEMPROT_SHIFT;
|
||||
uint8_t oldprot = 0xff;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
@@ -765,16 +778,33 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint32_t dyn = kh_value(memprot, k)[ii]&PROT_DYNAREC;
|
||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC;
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t* block = kh_value(memprot, k);
|
||||
for(uintptr_t ii = start; ii<=finish; ++ii) {
|
||||
uint32_t dyn = block[ii]&PROT_DYNAREC;
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
if(oldprot!=prot) {
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i<<MEMPROT_SHIFT;
|
||||
oldprot = prot;
|
||||
}
|
||||
} else if(prot!=0xff) {
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i << MEMPROT_SHIFT;
|
||||
oldprot = 0xff;
|
||||
}
|
||||
block[ii] = prot|dyn|PROT_ALLOC;
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
@@ -788,28 +818,42 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = prot|PROT_ALLOC;
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
static int blockempty(uint8_t* mem)
|
||||
{
|
||||
for (int i=0; i<(MEMPROT_SIZE); ++i)
|
||||
if(mem[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k!=kh_end(memprot)) {
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
memset(block+start, 0, finish-start+1);
|
||||
if(blockempty(block)) {
|
||||
free(block);
|
||||
kh_del(memprot, memprot, k);
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -832,7 +876,7 @@ uint32_t getProtection(uintptr_t addr)
|
||||
#define LOWEST (void*)0x20000
|
||||
int availableBlock(uint8_t* p, size_t n)
|
||||
{
|
||||
for (int i=0; i<n; ++i, ++p)
|
||||
for (size_t i=0; i<n; ++i, ++p)
|
||||
if(*p)
|
||||
return 0;
|
||||
return 1;
|
||||
@@ -857,7 +901,7 @@ void* find32bitBlock(size_t size)
|
||||
return p;
|
||||
p += 0x10000;
|
||||
} while(p!=(void*)0xffff0000);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
@@ -883,7 +927,7 @@ void* findBlockNearHint(void* hint, size_t size)
|
||||
return p;
|
||||
p += step;
|
||||
} while(p!=end);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
#undef LOWEST
|
||||
@@ -893,9 +937,8 @@ int unlockCustommemMutex()
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
@@ -943,6 +986,7 @@ static void atfork_child_custommem(void)
|
||||
|
||||
void init_custommem_helper(box64context_t* ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
@@ -966,13 +1010,14 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
|
||||
void fini_custommem_helper(box64context_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(!inited)
|
||||
return;
|
||||
inited = 0;
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec) {
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
for (int i=0; i<mmapsize; ++i) {
|
||||
for (size_t i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(mmaplist[i].block, mmaplist[i].size);
|
||||
|
||||
+86
-15
@@ -110,8 +110,9 @@
|
||||
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
|
||||
// This macro will give a -Wsign-compare warning, probably bug #38341
|
||||
#define MOV32w(Rd, imm32) \
|
||||
if(~((uint32_t)(imm32))<0xffff) { \
|
||||
if(~((uint32_t)(imm32))<0xffffu) { \
|
||||
MOVNw(Rd, (~(uint32_t)(imm32))&0xffff); \
|
||||
} else { \
|
||||
MOVZw(Rd, (imm32)&0xffff); \
|
||||
@@ -210,14 +211,14 @@
|
||||
#define LDRSW_S9_preindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
|
||||
|
||||
#define LD_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
|
||||
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
|
||||
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)(imm12>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
|
||||
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
|
||||
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
|
||||
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
|
||||
#define LDS_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
|
||||
#define LDR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b01<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
|
||||
@@ -251,10 +252,10 @@
|
||||
#define STRH_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b01, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
|
||||
|
||||
#define ST_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
|
||||
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
|
||||
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
|
||||
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
|
||||
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
|
||||
#define STRxw_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
|
||||
#define STR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b00<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
@@ -345,6 +346,8 @@
|
||||
#define PLD_L2_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00011))
|
||||
#define PLD_L3_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00101))
|
||||
|
||||
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
|
||||
|
||||
|
||||
// BR and Branches
|
||||
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
|
||||
@@ -430,11 +433,16 @@
|
||||
#define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORRw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORNx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EORx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define EORw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define EORxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
@@ -447,6 +455,12 @@
|
||||
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
|
||||
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
|
||||
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
|
||||
#define LSLw_IMM(Rd, Rm, lsl) ORRw_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSLx_IMM(Rd, Rm, lsl) ORRx_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSLxw_IMM(Rd, Rm, lsl) ORRxw_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSRw_IMM(Rd, Rm, lsr) ORRw_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define LSRx_IMM(Rd, Rm, lsr) ORRx_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define LSRxw_IMM(Rd, Rm, lsr) ORRxw_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define MVNx_REG(Rd, Rm) ORNx_REG(Rd, xZR, Rm)
|
||||
#define MVNx_REG_LSL(Rd, Rm, lsl) ORNx_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define MVNw_REG(Rd, Rm) ORNw_REG(Rd, xZR, Rm)
|
||||
@@ -575,13 +589,27 @@
|
||||
#define UMULH(Xd, Xn, Xm) EMIT(MULH_gen(1, Xm, Xn, Xd))
|
||||
#define SMULH(Xd, Xn, Xm) EMIT(MULH_gen(0, Xm, Xn, Xd))
|
||||
|
||||
#define MADD_gen(sf, Rm, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (Ra)<<10 | (Rn)<<5 | (Rd))
|
||||
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, Ra, Rn, Rd))
|
||||
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, Ra, Rn, Rd))
|
||||
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, Ra, Rn, Rd))
|
||||
#define MADD_gen(sf, Rm, o0, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (o0)<<15 | (Ra)<<10 | (Rn)<<5 | (Rd))
|
||||
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 0, Ra, Rn, Rd))
|
||||
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 0, Ra, Rn, Rd))
|
||||
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 0, Ra, Rn, Rd))
|
||||
#define MULx(Rd, Rn, Rm) MADDx(Rd, Rn, Rm, xZR)
|
||||
#define MULw(Rd, Rn, Rm) MADDw(Rd, Rn, Rm, xZR)
|
||||
#define MULxw(Rd, Rn, Rm) MADDxw(Rd, Rn, Rm, xZR)
|
||||
#define MSUBx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 1, Ra, Rn, Rd))
|
||||
#define MSUBw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 1, Ra, Rn, Rd))
|
||||
#define MSUBxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 1, Ra, Rn, Rd))
|
||||
#define MNEGx(Rd, Rn, Rm) EMIT(MADD_gen(1, Rm, 1, xZR, Rn, Rd))
|
||||
#define MNEGw(Rd, Rn, Rm) EMIT(MADD_gen(0, Rm, 1, xZR, Rn, Rd))
|
||||
#define MNEGxw(Rd, Rn, Rm) EMIT(MADD_gen(rex.w, Rm, 1, xZR, Rn, Rd))
|
||||
|
||||
|
||||
// DIV
|
||||
#define DIV_gen(sf, Rm, o1, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b00001<<11 | (o1)<<10 | (Rn)<<5 | (Rd))
|
||||
#define UDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 0, Wn, Wd))
|
||||
#define UDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 0, Xn, Xd))
|
||||
#define SDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 1, Wn, Wd))
|
||||
#define SDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 1, Xn, Xd))
|
||||
|
||||
// CLZ
|
||||
#define CL_gen(sf, op, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | 0b00010<<11 | (op)<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -740,6 +768,7 @@
|
||||
|
||||
#define SHL_scalar(U, size, Rm, R, S, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b010<<13 | (R)<<12 | (S)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SSHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(0, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(1, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
|
||||
#define SHL_scalar_imm(U, immh, immb, Rn, Rd) (0b01<<30 | 0b111110<<23 | (immh)<<19 | (immb)<<16 | 0b01010<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SHL_64(Vd, Vn, shift) EMIT(SHL_scalar_imm(0, 0b1000 | (((shift)>>3)&7), (shift)&7, Vn, Vd))
|
||||
@@ -752,6 +781,13 @@
|
||||
#define SSHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
|
||||
#define SHR_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b00000<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VSHRQ_8(Vd, Vn, shift) EMIT(SHR_vector(1, 1, 0b0001, (8-(shift))&7, Vn, Vd))
|
||||
@@ -830,6 +866,10 @@
|
||||
#define ABSQ_32(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b10, Vn, Vd))
|
||||
#define ABSQ_64(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b11, Vn, Vd))
|
||||
|
||||
#define NEGABS_vector_scalar(U, size, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define NEG_64(Vd, Vn) EMIT(NEGABS_vector_scalar(1, 0b11, Vn, Vd))
|
||||
#define ABS_64(Vd, Vn) EMIT(NEGABS_vector_scalar(0, 0b11, Vn, Vd))
|
||||
|
||||
// FMOV
|
||||
#define FMOV_general(sf, type, mode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (mode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
|
||||
// 32-bit to single-precision
|
||||
@@ -962,6 +1002,16 @@
|
||||
#define FDIVS(Sd, Sn, Sm) EMIT(FDIV_scalar(0b00, Sm, Sn, Sd))
|
||||
#define FDIVD(Dd, Dn, Dm) EMIT(FDIV_scalar(0b01, Dm, Dn, Dd))
|
||||
|
||||
#define FRECPE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRECPES(Vd, Vn) EMIT(FRECPE_vector(0, 0, Vn, Vd))
|
||||
#define VFRECPEQS(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
|
||||
#define VFRECPEQD(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
|
||||
|
||||
#define FRECPS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 0<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRECPSS(Vd, Vn, Vm) EMIT(FRECPS_vector(0, 0, Vm, Vn, Vd))
|
||||
#define VFRECPSQS(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFRECPSQD(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
|
||||
|
||||
// SQRT
|
||||
#define FSQRT_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFSQRTS(Sd, Sn) EMIT(FSQRT_vector(0, 0, Sn, Sd))
|
||||
@@ -972,6 +1022,16 @@
|
||||
#define FSQRTS(Sd, Sn) EMIT(FSQRT_scalar(0b00, Sn, Sd))
|
||||
#define FSQRTD(Dd, Dn) EMIT(FSQRT_scalar(0b01, Dn, Dd))
|
||||
|
||||
#define FRSQRTE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRSQRTES(Vd, Vn) EMIT(FRSQRTE_vector(0, 0, Vn, Vd))
|
||||
#define VFRSQRTEQS(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
|
||||
#define VFRSQRTEQD(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
|
||||
|
||||
#define FRSQRTS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRSQRTSS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(0, 0, Vm, Vn, Vd))
|
||||
#define VFRSQRTSQS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFRSQRTSQD(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
|
||||
|
||||
// CMP
|
||||
#define FCMP_scalar(type, Rn, Rm, opc) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
|
||||
#define FCMPS(Sn, Sm) EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
|
||||
@@ -1173,10 +1233,18 @@
|
||||
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
|
||||
|
||||
#define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
// round toward 0 (truncate)
|
||||
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
|
||||
// round toward 0 (truncate)
|
||||
#define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
|
||||
// round with current FPCR mode
|
||||
#define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
|
||||
// round with current FPCR mode
|
||||
#define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
|
||||
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
|
||||
#define FRINTRRS(Sd, Sn, mode) EMIT(FRINT_scalar(0b00, ((mode)&3), Sn, Sd))
|
||||
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
|
||||
#define FRINTRRD(Dd, Dn, mode) EMIT(FRINT_scalar(0b01, ((mode)&3), Dn, Dd))
|
||||
|
||||
// FMAX / FMIN
|
||||
#define FMINMAX_vector(Q, U, o1, sz, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o1)<<23 | (sz)<<22 | 0b1<<21 | (Rm)<<16 | 0b11110<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -1342,6 +1410,9 @@
|
||||
#define VCMGTQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b01, 0, Rm, Rn, Rd))
|
||||
#define VCMGTQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b10, 0, Rm, Rn, Rd))
|
||||
#define VCMGTQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b11, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_8(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b00, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_16(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b01, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_32(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b10, 0, Rm, Rn, Rd))
|
||||
// Unsigned Higher
|
||||
#define VCHIQQ_8(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b00, 0, Rm, Rn, Rd))
|
||||
#define VCHIQQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b01, 0, Rm, Rn, Rd))
|
||||
|
||||
@@ -45,15 +45,12 @@ arm64_lock_write_h:
|
||||
arm64_lock_read_d:
|
||||
// address is x0, return is x0
|
||||
ldaxr w0, [x0]
|
||||
#ldx w0,[x0]
|
||||
ret
|
||||
|
||||
arm64_lock_write_d:
|
||||
// address is x0, value is w1, return is x0
|
||||
mov x2, x0
|
||||
stlxr w0, w1, [x2]
|
||||
#str w1, [x2]
|
||||
mov w0, 0
|
||||
ret
|
||||
|
||||
arm64_lock_read_dd:
|
||||
|
||||
@@ -278,12 +278,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "STR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "101110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
if(isMask(opcode, "1011100110iiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
int offset = imm<<2;
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn]);
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", Xt[Rt], XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], offset);
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", Xt[Rt], XtSp[Rn], offset);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "011110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
@@ -620,7 +620,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
else if(immr==0 && imms==0b001111)
|
||||
snprintf(buff, sizeof(buff), "SXTH %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
|
||||
else if(sf && immr==0 && imms==0b011111)
|
||||
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Xt[Rn]);
|
||||
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Wt[Rn]);
|
||||
else if(imms>=immr)
|
||||
snprintf(buff, sizeof(buff), "SBFX %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
|
||||
else
|
||||
@@ -777,6 +777,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "MADD %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "f0011011000mmmmm1aaaaannnnnddddd", &a)) {
|
||||
if(Ra==31)
|
||||
snprintf(buff, sizeof(buff), "MNEG %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "MSUB %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// DIV
|
||||
if(isMask(opcode, "f0011010110mmmmm00001onnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "%cDIV %s, %s, %s", option?'S':'U', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// MRS / MSR
|
||||
if(isMask(opcode, "110101010001opppnnnnmmmm222ttttt", &a)) {
|
||||
|
||||
+35
-28
@@ -165,10 +165,10 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
if(dynablocks->direct) {
|
||||
dynablock_t* db;
|
||||
@@ -176,34 +176,38 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
khint_t k;
|
||||
kh_dynablocks_t *blocks = kh_init(dynablocks);
|
||||
// copy in a temporary list
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father;
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father;
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
// check emptyness
|
||||
for(uintptr_t i=0; i<dynablocks->textsz; ++i)
|
||||
if(dynablocks->direct[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
@@ -214,7 +218,7 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
uintptr_t new_size = size + dynablocks->maxsz;
|
||||
MarkDirectDynablock(dynablocks, new_addr, new_size);
|
||||
// the blocks check before
|
||||
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
MarkDirectDynablock(getDB(idx), new_addr, new_size);
|
||||
}
|
||||
}
|
||||
@@ -254,7 +258,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if(dynablocks->direct) {
|
||||
block = dynablocks->direct[addr-dynablocks->text];
|
||||
if(block) {
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
|
||||
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
@@ -270,7 +274,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
}
|
||||
|
||||
// create and add new block
|
||||
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
@@ -333,7 +337,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
if(old!=block && old) {// put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// doing nothing else, the block as not be writen
|
||||
// doing nothing else, the block has not be writen
|
||||
}
|
||||
free(block);
|
||||
block = NULL;
|
||||
@@ -347,7 +351,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
int blocksz = block->x64_size;
|
||||
if(dynablocks->maxsz<blocksz) {
|
||||
dynablocks->maxsz = blocksz;
|
||||
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
dynablocklist_t* dblist;
|
||||
if((dblist = getDB(idx)))
|
||||
if(dblist->maxsz<blocksz)
|
||||
@@ -358,8 +362,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault64(block->x64_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i)
|
||||
for(int i=0; i<block->sons_size; ++i) {
|
||||
addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
|
||||
block->sons[i]->done = 1;
|
||||
}
|
||||
block->done = 1;
|
||||
unlockDB();
|
||||
}
|
||||
|
||||
|
||||
+14
-7
@@ -30,9 +30,8 @@ void arm64_epilog_fast() EXPORTDYN;
|
||||
#endif
|
||||
|
||||
#ifdef DYNAREC
|
||||
#ifdef HAVE_TRACE
|
||||
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
|
||||
#endif
|
||||
|
||||
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -65,6 +64,11 @@ printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Disable "clobbered" warnings
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclobbered"
|
||||
#endif
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
@@ -76,7 +80,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_RIP; // not sure if it should still be inside DynaCall!
|
||||
}
|
||||
@@ -125,7 +129,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
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_RIP;
|
||||
}
|
||||
@@ -166,7 +170,7 @@ int DynaRun(x64emu_t* emu)
|
||||
#ifdef DYNAREC
|
||||
jmpbuf_reset = 1;
|
||||
#endif
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
@@ -203,7 +207,7 @@ int DynaRun(x64emu_t* emu)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
@@ -214,4 +218,7 @@ int DynaRun(x64emu_t* emu)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
+11
-13
@@ -351,8 +351,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
helper.cap = helper.size+3; // needs epilog handling
|
||||
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr+1);
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr+1);
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
// calculate barriers
|
||||
@@ -383,10 +383,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
int sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
|
||||
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
free(helper.table64);
|
||||
@@ -401,17 +401,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
// pass 3, emit (log emit arm opcode)
|
||||
if(box64_dynarec_dump) {
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
printFunctionAddr(helper.start, " => ");
|
||||
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
int oldtable64size = helper.table64size;
|
||||
int oldarmsize = helper.arm_size;
|
||||
size_t oldarmsize = helper.arm_size;
|
||||
helper.arm_size = 0;
|
||||
helper.table64size = 0; // reset table64 (but not the cap)
|
||||
arm_pass3(&helper, addr);
|
||||
if((oldarmsize!=helper.arm_size) || (oldtable64size<helper.table64size)) {
|
||||
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size+helper.table64size*8);
|
||||
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.arm_size+helper.table64size*8);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
@@ -450,9 +450,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->block = p;
|
||||
block->need_test = 0;
|
||||
//block->x64_addr = (void*)start;
|
||||
block->x64_size = end-start+1;
|
||||
if(box64_dynarec_largest<block->x64_size)
|
||||
box64_dynarec_largest = block->x64_size;
|
||||
block->x64_size = end-start;
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
@@ -476,7 +474,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / ARM=%p)", son->x64_addr, son->block);}
|
||||
son->father = block;
|
||||
son->size = sz + son->block - block->block; // update size count, for debugging
|
||||
son->done = 1;
|
||||
//son->done = 1;
|
||||
if(!son->parent)
|
||||
son->parent = block->parent;
|
||||
sons[sons_size] = son;
|
||||
@@ -491,6 +489,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
block->done = 1;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
}
|
||||
+254
-109
File diff suppressed because it is too large.
Load diff
+303
-52
@@ -64,33 +64,32 @@
|
||||
|
||||
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, i32_, j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int32_t i32, i32_;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
MAYUSE(s0);
|
||||
uint64_t tmp64u;
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(u8);
|
||||
#if STEP == 3
|
||||
//static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
MAYUSE(s0);
|
||||
MAYUSE(j64);
|
||||
#if 0//STEP == 3
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
@@ -98,9 +97,24 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x0B:
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL(arm_ud, -1);
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
INST_NAME("PREFETCHW");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PST_L1_STREAM_U12(ed, fixedaddress);
|
||||
break;
|
||||
default: //???
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("MOVUPS Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -264,6 +278,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("MOVNTPS Ex,Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -284,6 +313,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("RDTSC");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
CALL(ReadTSC, xRAX); // will return the u64 in xEAX
|
||||
LSRx(xRDX, xRAX, 32);
|
||||
MOVw_REG(xRAX, xRAX); // wipe upper part
|
||||
@@ -348,7 +378,39 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
GOCOND(0x40, "CMOV", "Gd, Ed");
|
||||
#undef GO
|
||||
|
||||
case 0x50:
|
||||
INST_NAME("MOVMSPKPS Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
MOV32w(gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
// EX is an xmm reg
|
||||
GETEX(q0, 0);
|
||||
VMOVQDto(x1, q0, 0);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 0, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
VMOVQDto(x1, q0, 1);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 2, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 3, 1);
|
||||
} else {
|
||||
// EX is memory
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, 0, 0);
|
||||
LDRx_U12(x1, ed, fixedaddress+0);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 0, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
LDRx_U12(x1, ed, fixedaddress+8);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 2, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 3, 1);
|
||||
}
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -356,7 +418,36 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETGX_empty(v0);
|
||||
VFSQRTQS(v0, q0);
|
||||
break;
|
||||
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX_empty(q1);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
// more precise
|
||||
if(q1==q0)
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
VFRSQRTEQS(v0, q0);
|
||||
VFMULQS(v1, v0, q0);
|
||||
VFRSQRTSQS(v1, v1, v0);
|
||||
VFMULQS(q1, v1, v0);
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX_empty(q1);
|
||||
if(q0 == q1)
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFRECPEQS(v0, q0);
|
||||
VFRECPSQS(v1, v0, q0);
|
||||
VFMULQS(q1, v0, v1);
|
||||
break;
|
||||
case 0x54:
|
||||
INST_NAME("ANDPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -479,7 +570,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
SQXTN_8(d0, q0);
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
INST_NAME("PCMPGTB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_8(v0, v0, v1);
|
||||
break;
|
||||
case 0x65:
|
||||
INST_NAME("PCMPGTW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_16(v0, v0, v1);
|
||||
break;
|
||||
case 0x66:
|
||||
INST_NAME("PCMPGTD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_32(v0, v0, v1);
|
||||
break;
|
||||
case 0x67:
|
||||
INST_NAME("PACKUSWB Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -516,6 +627,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEM(q1, 1);
|
||||
VZIP2_32(q0, q0, q1);
|
||||
break;
|
||||
case 0x6B:
|
||||
INST_NAME("PACKSSDW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 1, v1, 0);
|
||||
} else {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VLD1_64(q0, 1, ed);
|
||||
}
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
SQXTN_16(v0, q0);
|
||||
break;
|
||||
|
||||
case 0x6E:
|
||||
INST_NAME("MOVD Gm, Ed");
|
||||
@@ -575,6 +702,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
VMOVeH(v0, 1, v1, 0);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
} else if(u8==0x55) {
|
||||
// dumplicate 16bits slot 1 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 1, v1, 1);
|
||||
}
|
||||
VMOVeH(v0, 0, v1, 1);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
} else if(u8==0xAA) {
|
||||
// dumplicate 16bits slot 2 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 2, v1, 2);
|
||||
}
|
||||
VMOVeH(v0, 3, v1, 2);
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
} else if(u8==0xFF) {
|
||||
// dumplicate 16bits slot 3 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 3, v1, 3);
|
||||
}
|
||||
VMOVeH(v0, 2, v1, 3);
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeH(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeH(v0, 1, v1, (u8>>(1*2))&3);
|
||||
@@ -663,7 +811,55 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x72:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>31) {
|
||||
VEOR(d0, d0, d0);
|
||||
} else if(u8) {
|
||||
VSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8>31) u8=31;
|
||||
if(u8) {
|
||||
VSSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>31) {
|
||||
VEOR(d0, d0, d0);
|
||||
} else {
|
||||
VSHL_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x73:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -704,7 +900,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEM(d1, 0);
|
||||
VCMEQ_8(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0x75:
|
||||
INST_NAME("PCMPEQW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(q0, 0);
|
||||
VCMEQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0x76:
|
||||
INST_NAME("PCMPEQD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMEQ_32(v0, v0, v1);
|
||||
break;
|
||||
case 0x77:
|
||||
INST_NAME("EMMS");
|
||||
// empty MMX, FPU now usable
|
||||
@@ -799,19 +1008,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("BT Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
@@ -821,10 +1029,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
break;
|
||||
|
||||
case 0xA4:
|
||||
nextop = F8;
|
||||
INST_NAME("SHLD Ed, Gd, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED(1);
|
||||
GETGD;
|
||||
u8 = F8;
|
||||
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xA5:
|
||||
nextop = F8;
|
||||
INST_NAME("SHLD Ed, Gd, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
UXTBw(x3, xRCX);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEDW(x4, x1, 0);
|
||||
@@ -836,7 +1054,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xAB:
|
||||
INST_NAME("BTS Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -844,8 +1063,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -870,10 +1089,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAC:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED(1);
|
||||
GETGD;
|
||||
u8 = F8;
|
||||
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xAD:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
UXTBw(x3, xRCX);
|
||||
GETEDW(x4, x1, 0);
|
||||
@@ -897,6 +1126,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FXSAVE Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
@@ -908,6 +1138,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FXRSTOR Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
@@ -972,7 +1203,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xB3:
|
||||
INST_NAME("BTR Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -980,8 +1212,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -1045,17 +1277,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
INST_NAME("BT Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
u8&=rex.w?0x3f:0x1f;
|
||||
if(u8) {
|
||||
LSRxw(x1, ed, u8);
|
||||
@@ -1066,17 +1297,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 5:
|
||||
INST_NAME("BTS Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction
|
||||
@@ -1090,17 +1320,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 6:
|
||||
INST_NAME("BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction
|
||||
@@ -1114,17 +1343,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 7:
|
||||
INST_NAME("BTC Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
@@ -1140,7 +1368,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xBB:
|
||||
INST_NAME("BTC Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -1148,8 +1377,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -1175,7 +1404,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xBC:
|
||||
INST_NAME("BSF Gd, Ed");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
@@ -1186,11 +1416,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("BSR Gd, Ed");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
@@ -1202,7 +1432,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBE:
|
||||
INST_NAME("MOVSX Gd, Eb");
|
||||
@@ -1336,6 +1565,19 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
REVxw(gd, gd);
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
if(MODREG)
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
else
|
||||
q0 = d1;
|
||||
NEG_64(q0, d1);
|
||||
USHL_R_64(d0, d0, q0);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
INST_NAME("PMULLW Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -1502,6 +1744,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SSHL_32(d0, d0, v0);
|
||||
break;
|
||||
|
||||
case 0xF5:
|
||||
INST_NAME("PMADDWD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VSMULL_16(q0, v0, v1);
|
||||
VADDPQ_32(q0, q0, q0); //ADDP from Q to non-Q?
|
||||
VMOVQ(v0, q0);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("PSADBW Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -1564,4 +1816,3 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
+203
-30
@@ -22,20 +22,30 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t u8;
|
||||
int32_t j32;
|
||||
uint8_t gd, ed, eb1, eb2;
|
||||
uint8_t wback;
|
||||
int64_t i64;
|
||||
int fixedaddress;
|
||||
MAYUSE(j32);
|
||||
uint8_t wback, wb1, wb2;
|
||||
int64_t i64, j64;
|
||||
int v0;
|
||||
int q0;
|
||||
int d0;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(v0);
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
@@ -51,33 +61,197 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("ADD Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10:
|
||||
switch(rep) {
|
||||
case 1:
|
||||
INST_NAME("MOVSD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
VMOVeS(v0, 0, q0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR32_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 1:
|
||||
INST_NAME("MOVSD Ex, Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOVeD(d0, 0, v0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR64_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVSS Ex, Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
VMOVeS(q0, 0, v0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR32_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("XOR Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x1, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
MOV32w(x2, u8);
|
||||
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
emit_cmp8_0(dyn, ninst, x1, x3, x4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
|
||||
@@ -85,7 +259,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -94,7 +268,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
@@ -104,7 +278,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
@@ -113,7 +287,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -121,7 +295,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
|
||||
@@ -129,7 +303,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -137,7 +311,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
if(i64) {
|
||||
@@ -150,8 +324,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ed, Gd");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Ed, Gd");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
@@ -163,8 +337,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Gd, Seg:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
@@ -176,8 +350,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0xC6:
|
||||
INST_NAME("MOV FS:Eb, Ib");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Eb, Ib");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
if(MODREG) { // reg <= u8
|
||||
u8 = F8;
|
||||
@@ -199,8 +373,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
INST_NAME("MOV FS:Ed, Id");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Ed, Id");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
if(MODREG) { // reg <= i32
|
||||
i64 = F32S;
|
||||
@@ -219,4 +393,3 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -27,15 +27,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, j32;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
uint64_t u64;
|
||||
int32_t i32;
|
||||
int64_t j64;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
int fixedaddress;
|
||||
MAYUSE(u16);
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(u8);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(u16);
|
||||
MAYUSE(u64);
|
||||
MAYUSE(j64);
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
opcode = F8;
|
||||
@@ -57,7 +60,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch(opcode) {
|
||||
case 0x01:
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -66,7 +69,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -75,7 +78,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("ADD AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -85,7 +88,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("OR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -94,7 +97,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x0B:
|
||||
INST_NAME("OR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -103,7 +106,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x0D:
|
||||
INST_NAME("OR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -117,7 +120,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -127,7 +130,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -137,7 +140,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x15:
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -148,7 +151,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x19:
|
||||
INST_NAME("SBB Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -158,7 +161,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x1B:
|
||||
INST_NAME("SBB Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -168,7 +171,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x1D:
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i16);
|
||||
@@ -178,7 +181,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -187,7 +190,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x23:
|
||||
INST_NAME("AND Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -196,7 +199,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x25:
|
||||
INST_NAME("AND AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -206,7 +209,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("SUB Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -215,7 +218,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -224,7 +227,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("SUB AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -234,7 +237,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("XOR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -243,7 +246,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -252,7 +255,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x35:
|
||||
INST_NAME("XOR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -262,7 +265,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("CMP Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -270,7 +273,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -278,7 +281,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x3D:
|
||||
INST_NAME("CMP AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
if(i32) {
|
||||
@@ -335,7 +338,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
INST_NAME("ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -344,7 +347,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -354,7 +357,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -364,7 +367,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -373,7 +376,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -382,7 +385,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -391,7 +394,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -400,7 +403,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(i16) {
|
||||
@@ -414,7 +417,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x85:
|
||||
INST_NAME("TEST Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEW(x1, 0);
|
||||
GETGW(x2);
|
||||
@@ -455,6 +458,21 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("NOP");
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,Od");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
LDRH_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od,EAX");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRH_U12(xRAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xA5:
|
||||
if(rep) {
|
||||
INST_NAME("REP MOVSW");
|
||||
@@ -484,7 +502,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xA9:
|
||||
INST_NAME("TEST AX,Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
u16 = F16;
|
||||
MOV32w(x2, u16);
|
||||
UBFXx(x1, xRAX, 0, 16);
|
||||
@@ -534,6 +552,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
@@ -543,6 +562,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
@@ -552,6 +572,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
@@ -562,6 +583,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
@@ -573,24 +595,26 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSLw_REG(ed, ed, x2);
|
||||
LSLw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSRw_REG(ed, ed, x2);
|
||||
LSRw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
@@ -598,6 +622,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
GETSEW(x1, 0);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
@@ -638,6 +663,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("ROL Ew, CL");
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rol16, x1, x3);
|
||||
@@ -651,6 +677,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("ROR Ew, CL");
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL_(ror16, x1, x3);
|
||||
@@ -658,6 +685,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
|
||||
@@ -667,6 +695,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
|
||||
@@ -683,6 +712,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SHL Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -699,6 +729,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SHR Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -715,6 +746,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SAR Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -732,7 +764,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("TEST Ew, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, 2);
|
||||
u16 = F16;
|
||||
MOV32w(x2, u16);
|
||||
@@ -746,7 +778,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("NEG Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, 0);
|
||||
emit_neg16(dyn, ninst, ed, x2, x4);
|
||||
EWBACK;
|
||||
@@ -775,12 +807,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL(div16, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL(idiv16, -1);
|
||||
@@ -800,7 +834,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SET);
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
GETEW(x1, 0);
|
||||
emit_dec16(dyn, ninst, x1, x2, x4);
|
||||
EWBACK;
|
||||
@@ -814,4 +848,3 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -44,17 +44,20 @@
|
||||
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, j32;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
@@ -62,7 +65,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
#if 0//STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
@@ -261,6 +264,53 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQRDMULHQ_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("PMOVSXBD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
break;
|
||||
case 0x22:
|
||||
INST_NAME("PMOVSXBQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
SXTL_32(q0, q0); //32bits->64bits
|
||||
break;
|
||||
case 0x23:
|
||||
INST_NAME("PMOVSXWD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
break;
|
||||
case 0x24:
|
||||
INST_NAME("PMOVSXWQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
case 0x25:
|
||||
INST_NAME("PMOVSXDQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -269,6 +319,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x3A: // these are some more SSSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0B:
|
||||
INST_NAME("ROUNDSD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 1);
|
||||
u8 = F8;
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
if(u8&4) {
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
FRINTXD(v1, q1);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
} else {
|
||||
const uint8_t rounds[] = {0, 2, 1, 3};
|
||||
MAYUSE(rounds);
|
||||
FRINTRRD(v1, q1, rounds[u8&3]);
|
||||
}
|
||||
VMOVeD(q0, 0, v1, 0);
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
INST_NAME("PALIGNR Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -572,12 +641,33 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeD(v0, 1, v1, 0);
|
||||
}
|
||||
} else if(u8==0x00) {
|
||||
// dumplicate lower 32bits to all spot
|
||||
// duplicate lower 32bits to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, 0);
|
||||
}
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else if(u8==0x55) {
|
||||
// duplicate slot 1 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 1, v1, 1);
|
||||
}
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else if(u8==0xAA) {
|
||||
// duplicate slot 2 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 2, v1, 2);
|
||||
}
|
||||
VMOVeS(v0, 3, v1, 2);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
} else if(u8==0xFF) {
|
||||
// duplicate slot 3 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 3, v1, 3);
|
||||
}
|
||||
VMOVeS(v0, 2, v1, 3);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
|
||||
@@ -594,9 +684,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
tmp64u = swp[(u8>>(0*2))&3] | (swp[(u8>>(1*2))&3]<<32);
|
||||
MOV64x(x2, tmp64u);
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
tmp64u = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
|
||||
MOV64x(x3, tmp64u);
|
||||
VMOVQDfrom(d0, 1, x3);
|
||||
tmp64u2 = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
|
||||
if(tmp64u2==tmp64u) {
|
||||
VMOVQDfrom(d0, 1, x2);
|
||||
} else {
|
||||
MOV64x(x3, tmp64u2);
|
||||
VMOVQDfrom(d0, 1, x3);
|
||||
}
|
||||
VTBLQ1_8(v0, v1, d0);
|
||||
}
|
||||
} else {
|
||||
@@ -613,7 +707,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VLD1_32(v0, i, x2);
|
||||
}
|
||||
} else {
|
||||
VLD1R_32(v0, ed);
|
||||
VLDQ1R_32(v0, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -847,10 +941,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("BT Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -864,6 +967,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("SHLD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xA4)?1:0);
|
||||
GETGW(x2);
|
||||
@@ -877,10 +981,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xAB:
|
||||
INST_NAME("BTS Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -888,8 +1002,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cNE);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
@@ -900,6 +1016,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("SHRD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xAC)?1:0);
|
||||
GETGW(x2);
|
||||
@@ -925,10 +1042,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xB3:
|
||||
INST_NAME("BTR Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -936,28 +1064,65 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cEQ);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6:
|
||||
INST_NAME("MOVZX Gw, Eb");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
}
|
||||
UBFXxw(x1, eb1, eb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
|
||||
LDRB_U12(x1, ed, fixedaddress);
|
||||
}
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
|
||||
BFIx(gd, x1, 0, 16); // insert in Gw
|
||||
break;
|
||||
|
||||
case 0xBB:
|
||||
INST_NAME("BTC Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
ANDw_mask(x1, x1, 0, 0); //mask=1
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
INST_NAME("BSF Ew,Gw");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEW(x1, 0); // Get EW
|
||||
@@ -969,11 +1134,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("BSR Ew,Gw");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEW(x1, 0); // Get EW
|
||||
@@ -987,7 +1152,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBE:
|
||||
INST_NAME("MOVSX Gw, Eb");
|
||||
@@ -1061,6 +1225,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
break;
|
||||
|
||||
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
NEG_64(v0, q1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
USHLQ_64(q0, q0, v0);
|
||||
break;
|
||||
case 0xD4:
|
||||
INST_NAME("PADDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1208,31 +1382,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQSHRN2_16(v0, q1, 16);
|
||||
break;
|
||||
case 0xE6:
|
||||
INST_NAME("CVTPD2DQ Gx, Ex");
|
||||
INST_NAME("CVTTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(v1, 0);
|
||||
GETGX_empty(v0);
|
||||
#ifdef PRECISE_CVT
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
UBFXx(x1, x1, 13, 2); // extract round requested
|
||||
LSLx_REG(x1, x1, 3);
|
||||
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
|
||||
// Construct a "switch case", with each case 2 instructions, so 8 bytes
|
||||
BL(+4); // Branch with Link to next, so LR gets next PC address
|
||||
ADDx_REG(xLR, xLR, x1);
|
||||
B(xLR); // could use RET, but it's not really one
|
||||
VFCVTNSQD(v0, v1); // 0: Nearest (even)
|
||||
B_NEXT_nocond;
|
||||
VFCVTMSQD(v0, v1); // 1: Toward -inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTPSQD(v0, v1); // 2: Toward +inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTZSQD(v0, v1); // 3: Toward 0
|
||||
#else
|
||||
VFCVTNSQD(v0, v1);
|
||||
#endif
|
||||
VFCVTNSQD(v0, v1); // convert double -> int64
|
||||
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
|
||||
break;
|
||||
case 0xE7:
|
||||
INST_NAME("MOVNTDQ Ex, Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("PSUBSB Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1303,7 +1471,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SSHLQ_32(q0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xF3:
|
||||
INST_NAME("PSLLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVQ(v0, q1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
USHLQ_64(q0, q0, v0);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("PMULUDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1345,7 +1522,23 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
UADDLVQ_16(d1, d0);
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
break;
|
||||
|
||||
case 0xF7:
|
||||
INST_NAME("MASKMOVDQU Gx, Ex")
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VLDR128_U12(v0, xRDI, 0);
|
||||
if(MODREG)
|
||||
v1 = fpu_get_scratch(dyn); // need to preserve the register
|
||||
else
|
||||
v1 = q1;
|
||||
VSSHRQ_8(v1, q1, 7); // get the mask
|
||||
VBICQ(v0, v0, v1); // mask destination
|
||||
VANDQ(v1, q0, v1); // mask source
|
||||
VORRQ(v1, v1, v0); // combine
|
||||
VSTR128_U12(v1, xRDI, 0); // put back
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("PSUBB Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1401,4 +1594,3 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
|
||||
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
|
||||
// REX prefix before the 66 are ignored
|
||||
rex.rex = 0;
|
||||
@@ -76,4 +78,3 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,26 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETGX(a) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd)
|
||||
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int8_t i8;
|
||||
int32_t i32, j32;
|
||||
MAYUSE(j32);
|
||||
int32_t i32;
|
||||
int64_t j64;
|
||||
int v0, s0;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(s0);
|
||||
|
||||
// REX prefix before the 67 are ignored
|
||||
rex.rex = 0;
|
||||
@@ -40,9 +49,45 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
opcode=F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
if(rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
}
|
||||
FCMPS(v0, s0);
|
||||
FCOMI(x1, x2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8D:
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -117,4 +162,3 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
@@ -228,4 +230,3 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
|
||||
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback, wb1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int i1, i2, i3;
|
||||
@@ -93,6 +95,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("FXAM");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_refresh(dyn, ninst, x1, x2, 0);
|
||||
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
|
||||
break;
|
||||
@@ -141,6 +144,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xFC:
|
||||
INST_NAME("FRNDINT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
// use C helper for now, nothing staightforward is available
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_frndint, -1);
|
||||
@@ -158,11 +162,13 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("F2XM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_f2xm1, -1);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("FYL2X");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2x, -1);
|
||||
@@ -170,6 +176,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FTAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_ftan, -1);
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
@@ -177,6 +184,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("FPATAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fpatan, -1);
|
||||
@@ -184,12 +192,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fxtract, -1);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem1, -1);
|
||||
@@ -212,12 +222,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem, -1);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("FYL2XP1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2xp1, -1);
|
||||
@@ -225,23 +237,27 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fsincos, -1);
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("FSCALE");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fscale, -1);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fsin, -1);
|
||||
break;
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fcos, -1);
|
||||
break;
|
||||
@@ -297,6 +313,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
@@ -314,6 +331,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
@@ -336,4 +354,3 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,19 +26,21 @@
|
||||
|
||||
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
uint8_t u8;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int j32;
|
||||
int64_t j64;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -184,17 +186,18 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTZD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
@@ -215,17 +218,18 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
@@ -246,29 +250,43 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDRx_U12(x5, ed, 0);
|
||||
LDRH_U12(x6, ed, 8);
|
||||
// no persistant scratch register, so unrool both instruction here...
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
STRx_U12(x5, ed, 0);
|
||||
STRH_U12(x6, ed, 8);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
CALL(arm_fld, -1);
|
||||
}
|
||||
CALL(arm_fld, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
@@ -286,4 +304,3 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
@@ -46,7 +48,11 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREE STx");
|
||||
break; // not handling Tag...
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_purgecache(dyn, ninst, x1, x2, x3);
|
||||
MOV32w(x1, nextop-0xC0);
|
||||
CALL(fpu_do_free, -1);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
@@ -168,6 +174,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
@@ -175,6 +182,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
@@ -195,4 +203,3 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,17 +26,19 @@
|
||||
|
||||
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed, wback, u8;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int j32;
|
||||
int s0;
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -158,17 +160,18 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
VFCVTZSd(s0, v1);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
@@ -187,18 +190,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
@@ -217,18 +221,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
@@ -267,16 +272,17 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VFCVTZSd(s0, s0);
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV64x(x5, 0x8000000000000000LL);
|
||||
STRx_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
@@ -286,4 +292,3 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit OR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -89,9 +90,10 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
|
||||
}
|
||||
}
|
||||
|
||||
// emit XOR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -155,9 +157,10 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit AND32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -227,9 +230,10 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit OR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -292,9 +296,10 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit XOR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -357,9 +362,10 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
}
|
||||
|
||||
// emit AND8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -429,9 +435,10 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
|
||||
|
||||
// emit OR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -507,9 +514,10 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit XOR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -585,9 +593,10 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit AND16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit AND16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -667,4 +676,4 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// IFX(X_PF) {
|
||||
// emit_pf(dyn, ninst, s1, s3, s4);
|
||||
// }
|
||||
//}
|
||||
//}
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit ADD32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADD32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -51,21 +52,17 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
Bcond(cCC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCS);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -76,9 +73,10 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADD32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
@@ -126,21 +124,17 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
Bcond(cCC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCS);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -151,9 +145,10 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -180,22 +175,18 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -206,9 +197,10 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
|
||||
{
|
||||
// special case when doing math on RSP and only PEND is needed: ignoring it!
|
||||
@@ -256,22 +248,18 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -282,9 +270,10 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -331,7 +320,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -383,9 +372,10 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SUB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -434,9 +424,10 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOV32w(s5, c&0xff);
|
||||
}
|
||||
@@ -491,9 +482,10 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -541,7 +533,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -608,9 +600,10 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SUB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SUB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -659,7 +652,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -756,17 +749,13 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, rex.w?63:31);
|
||||
@@ -777,7 +766,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
}
|
||||
}
|
||||
|
||||
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch
|
||||
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -822,7 +811,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit INC16 instruction, from s1 , store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
|
||||
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -900,17 +889,13 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, rex.w?63:31);
|
||||
@@ -1009,9 +994,10 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADC32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1062,7 +1048,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADC32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1132,9 +1118,10 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit ADC8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1185,9 +1172,10 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -1239,9 +1227,10 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1292,7 +1281,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1359,9 +1348,10 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SBB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1414,7 +1404,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1486,9 +1476,10 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SBB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SBB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1540,9 +1531,10 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -1595,9 +1587,10 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SBB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1649,7 +1642,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1853,4 +1846,4 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,9 @@
|
||||
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
|
||||
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
MAYUSE(s2);
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -60,9 +61,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -71,9 +71,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
IFX(X_OF) {
|
||||
CMPSxw_U12(s2, 1); // if s2==1
|
||||
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
|
||||
Bcond(cNE, 4+3*4);
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
|
||||
CSELw(s4, s4, wZR, cEQ);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
@@ -101,7 +100,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
IFX(X_CF|X_OF) {
|
||||
LSRxw(s3, s1, (rex.w?64:32)-c);
|
||||
BFIxw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
@@ -112,9 +111,8 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -123,7 +121,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
|
||||
Bcond(cNE, +12);
|
||||
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
@@ -138,8 +135,9 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit SHR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
MAYUSE(s2);
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -167,9 +165,8 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -218,9 +215,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -255,19 +251,18 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
ASRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -281,6 +276,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -312,6 +308,7 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -343,119 +340,104 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// c&=0x1f;
|
||||
// IFX(X_PEND) {
|
||||
// MOVW(s3, c);
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// // same flags calc as shr32
|
||||
// SET_DF(s4, d_shr32);
|
||||
// } else IFX(X_ALL) {
|
||||
// SET_DFNONE(s4);
|
||||
// }
|
||||
// if(!c) {
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// MOVS_REG_LSR_IMM5(s1, s1, c);
|
||||
// } else {
|
||||
// MOV_REG_LSR_IMM5(s1, s1, c);
|
||||
// }
|
||||
// IFX(X_ZF|X_CF) {
|
||||
// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
|
||||
// } else {
|
||||
// ORR_REG_LSL_IMM5(s1, s1, s2, 32-c);
|
||||
// }
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 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);
|
||||
// }
|
||||
//}
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// same flags computation as with shl64/shl32
|
||||
SET_DF(s4, rex.w?d_shl64:d_shl32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
LSRxw_REG(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
ORRxw_REG_LSL(s1, s1, s2, (rex.w?64:32)-c);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
LSRxw(s4, s1, rex.w?62:30);
|
||||
EORw_REG_LSR(s4, s4, s4, 1);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// c&=0x1f;
|
||||
// IFX(X_PEND) {
|
||||
// MOVW(s3, c);
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// // same flags computation as with shl32
|
||||
// SET_DF(s4, d_shl32);
|
||||
// } else IFX(X_ALL) {
|
||||
// SET_DFNONE(s4);
|
||||
// }
|
||||
// if(c==0) {
|
||||
// IFX(F_OF) {
|
||||
// BFC(xFlags, F_OF, 1);
|
||||
// }
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// MOV_REG_LSR_IMM5(s3, s1, 32-c);
|
||||
// BFI(xFlags, s3, F_CF, 1);
|
||||
// }
|
||||
// IFX(X_OF) {
|
||||
// MOVS_REG_LSL_IMM5(s1, s1, c);
|
||||
// } else {
|
||||
// MOV_REG_LSL_IMM5(s1, s1, c);
|
||||
// }
|
||||
// IFX(X_OF) {
|
||||
// if(c==1) {
|
||||
// UBFX(s3, s2, 0, 1);
|
||||
// XOR_IMM8_COND(cCS, s3, s3, 1);
|
||||
// BFI(xFlags, s3, F_OF, 1);
|
||||
// } else {
|
||||
// BFC(xFlags, F_OF, 1);
|
||||
// }
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
|
||||
// } else {
|
||||
// ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
|
||||
// }
|
||||
//
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
// }
|
||||
// IFX(X_SF) {
|
||||
// MOV_REG_LSR_IMM5(s3, s1, 31);
|
||||
// BFI(xFlags, s3, F_SF, 1);
|
||||
// }
|
||||
// IFX(X_PF) {
|
||||
// emit_pf(dyn, ninst, s1, s3, s4);
|
||||
// }
|
||||
//}
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// same flags computation as with shl64/shl32
|
||||
SET_DF(s4, rex.w?d_shl64:d_shl32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c==0) {
|
||||
IFX(F_OF) {
|
||||
BFCx(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF|X_OF) {
|
||||
LSRxw(s3, s1, (rex.w?64:32)-c);
|
||||
BFIxw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
LSLxw(s1, s1, c);
|
||||
ORRxw_REG_LSR(s1, s1, s2, (rex.w?64:32)-c);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
UBFXxw(s3, s1, rex.w?63:31, 1);
|
||||
EORxw_REG(s3, s3, xFlags); // CF is set if OF is asked
|
||||
BFIw(xFlags, s3, F_OF, 1);
|
||||
} else {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -47,22 +48,18 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s5, (rex.w)?63:31);
|
||||
@@ -88,18 +85,18 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
|
||||
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
|
||||
// and now the tricky ones (and mostly unused), PF and AF
|
||||
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
|
||||
IFX(X_ZF|X_CF|X_OF|X_AF) {
|
||||
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF)|(1<<F_AF));
|
||||
IFX(X_OF|X_AF) {
|
||||
MOV32w(s4, (1<<F_OF)|(1<<F_AF));
|
||||
BICw(xFlags, xFlags, s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -110,9 +107,10 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
|
||||
}
|
||||
}
|
||||
|
||||
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -189,9 +187,10 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP8 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -252,8 +251,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
// bc = (res & (~d | s)) | (~d & s) = 0
|
||||
IFX(X_CF | X_AF | X_ZF | X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
IFX(X_CF | X_AF | X_OF) {
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -270,9 +269,10 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, rex.w?d_tst64:d_tst32);
|
||||
} else {
|
||||
@@ -307,9 +307,10 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst16);
|
||||
} else {
|
||||
@@ -339,9 +340,10 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST8 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst8);
|
||||
} else {
|
||||
|
||||
+291
-23
@@ -25,17 +25,20 @@
|
||||
|
||||
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
int32_t j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb2, gb1, gb2;
|
||||
int64_t i64;
|
||||
int fixedaddress;
|
||||
uint8_t wback, wb1, wb2, gb1, gb2;
|
||||
int32_t i32;
|
||||
int64_t i64, j64;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(gb1);
|
||||
MAYUSE(gb2);
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
@@ -51,7 +54,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
INST_NAME("LOCK ADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
@@ -77,7 +80,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("LOCK ADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
@@ -99,7 +102,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xB1:
|
||||
INST_NAME("LOCK CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -146,7 +149,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xC1:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -184,7 +187,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
@@ -212,7 +215,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("LOCK SUB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -228,6 +231,211 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
INST_NAME("LOCK ADD Ew, Iw");
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ew, Iw");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_add16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
}
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Iw");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_or16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ew, Iw");} else {INST_NAME("LOCK ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_adc16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ew, Iw");} else {INST_NAME("LOCK SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_and16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_and16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_sub16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
}
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_xor16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_xor16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ew, Iw");} else {INST_NAME("(LOCK) CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x6, (opcode==0x81)?2:1);
|
||||
(void)wb1;
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
if(i32) {
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
emit_cmp16_0(dyn, ninst, ed, x3, x4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
@@ -238,7 +446,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -248,7 +456,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
@@ -268,7 +476,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -288,7 +496,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -308,7 +516,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -327,7 +535,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -346,7 +554,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -356,7 +564,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
@@ -376,7 +584,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -395,8 +603,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETED(0);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED((opcode==0x81)?4:1);
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
if(i64) {
|
||||
@@ -436,9 +644,69 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Ed
|
||||
INST_NAME("LOCK INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_inc32(dyn, ninst, rex, ed, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_inc32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8); // re-inject
|
||||
emit_inc32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("LOCK DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_dec32(dyn, ninst, rex, ed, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_dec32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8); // re-inject
|
||||
emit_dec32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
@@ -51,7 +53,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int v0, v1;
|
||||
int q0;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
|
||||
#ifdef PRECISE_CVT
|
||||
int j32;
|
||||
@@ -73,7 +75,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOV(v0, d0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
@@ -88,7 +90,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOV(d0, v0);
|
||||
VMOVeD(d0, 0, v0, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
@@ -255,6 +257,9 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
if(v0!=v1) {
|
||||
VMOVeD(v0, 1, v1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7C:
|
||||
@@ -316,4 +321,3 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
uint8_t gd, ed;
|
||||
@@ -50,8 +52,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int j32;
|
||||
int64_t fixedaddress;
|
||||
int64_t j64;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
@@ -59,7 +61,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -118,6 +120,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VTRNQ2_32(q0, q1, q1);
|
||||
break;
|
||||
|
||||
case 0x1E:
|
||||
INST_NAME("NOP / ENDBR32 / ENDBR64");
|
||||
nextop = F8;
|
||||
FAKEED;
|
||||
break;
|
||||
|
||||
case 0x2A:
|
||||
INST_NAME("CVTSI2SS Gx, Ed");
|
||||
nextop = F8;
|
||||
@@ -295,6 +303,9 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 1, d0, 0);
|
||||
if(v0!=v1) {
|
||||
VMOVeD(v0, 0, v1, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7E:
|
||||
@@ -328,11 +339,11 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xBC:
|
||||
INST_NAME("TZCNT Gd, Ed");
|
||||
SETFLAGS(X_CF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
SET_DFNONE(x1);
|
||||
TSTxw_REG(ed, ed);
|
||||
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
|
||||
RBITxw(x1, ed); // reverse
|
||||
@@ -396,4 +407,3 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ void arm_fstp(x64emu_t* emu, void* p)
|
||||
|
||||
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "R%ld=0x%lx (%ld)\n", n, reg, reg);
|
||||
(void)emu;
|
||||
dynarec_log(LOG_DEBUG, "R%lu=0x%lx (%lu)\n", n, reg, reg);
|
||||
}
|
||||
|
||||
void arm_f2xm1(x64emu_t* emu)
|
||||
@@ -85,7 +86,8 @@ void arm_frndint(x64emu_t* emu)
|
||||
}
|
||||
void arm_fscale(x64emu_t* emu)
|
||||
{
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
}
|
||||
void arm_fsin(x64emu_t* emu)
|
||||
{
|
||||
@@ -118,7 +120,7 @@ void arm_fbstp(x64emu_t* emu, uint8_t* ed)
|
||||
void arm_fistp64(x64emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid aligments issues
|
||||
if(STll(0).ref==ST(0).q) {
|
||||
if((uint64_t)STll(0).ref==ST(0).q) {
|
||||
memcpy(ed, &STll(0).ll, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
@@ -244,6 +246,7 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
|
||||
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
|
||||
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
|
||||
{
|
||||
(void)dyn; (void)ninst;
|
||||
|
||||
uint32_t tested = (1<<parity)-1;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
@@ -282,6 +285,8 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
|
||||
// Do the GETED, but don't emit anything...
|
||||
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
{
|
||||
(void)dyn; (void)addr; (void)ninst;
|
||||
|
||||
if((nextop&0xC0)==0xC0)
|
||||
return addr;
|
||||
if(!(nextop&0xC0)) {
|
||||
@@ -310,6 +315,8 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
|
||||
{
|
||||
(void)dyn;
|
||||
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(int32_t*)(addr+a)
|
||||
|
||||
@@ -332,4 +339,3 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
#undef PK32
|
||||
#undef PK
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x2;
|
||||
*fixaddress = 0;
|
||||
@@ -41,7 +43,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
uint8_t sib = F8;
|
||||
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
if((sib&0x7)==5) {
|
||||
uint64_t tmp = F32S64;
|
||||
int64_t tmp = F32S;
|
||||
if (sib_reg!=4) {
|
||||
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
|
||||
MOV64x(scratch, tmp);
|
||||
@@ -62,9 +64,21 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
}
|
||||
} else if((nextop&7)==5) {
|
||||
uint64_t tmp = F32S64;
|
||||
MOV64x(ret, tmp);
|
||||
GETIP(addr+delta);
|
||||
ADDx_REG(ret, ret, xRIP);
|
||||
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
|
||||
GETIP(addr+delta);
|
||||
ret = xRIP;
|
||||
*fixaddress = tmp;
|
||||
} else if(tmp<0x1000) {
|
||||
GETIP(addr+delta);
|
||||
ADDx_U12(ret, xRIP, tmp);
|
||||
} else if(tmp+addr+delta<0x1000000000000LL) { // 3 opcodes to load immediate is cheap enough
|
||||
tmp += addr+delta;
|
||||
MOV64x(ret, tmp);
|
||||
} else {
|
||||
MOV64x(ret, tmp);
|
||||
GETIP(addr+delta);
|
||||
ADDx_REG(ret, ret, xRIP);
|
||||
}
|
||||
} else {
|
||||
ret = xRAX+(nextop&7)+(rex.b<<3);
|
||||
}
|
||||
@@ -141,8 +155,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
}
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x2;
|
||||
*fixaddress = 0;
|
||||
@@ -156,17 +172,17 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
uint8_t sib = F8;
|
||||
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
if((sib&0x7)==5) {
|
||||
uint32_t tmp = F32;
|
||||
int64_t tmp = F32S;
|
||||
if (sib_reg!=4) {
|
||||
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
|
||||
MOV32w(scratch, tmp);
|
||||
MOV64x(scratch, tmp);
|
||||
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
LSLw(ret, xRAX+sib_reg, (sib>>6));
|
||||
*fixaddress = tmp;
|
||||
}
|
||||
} else {
|
||||
MOV32w(ret, tmp);
|
||||
MOV64x(ret, tmp);
|
||||
}
|
||||
} else {
|
||||
if (sib_reg!=4) {
|
||||
@@ -260,8 +276,10 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
}
|
||||
|
||||
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s)
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x3;
|
||||
*fixaddress = 0;
|
||||
@@ -270,7 +288,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
MAYUSE(scratch);
|
||||
uint32_t m = nextop&0xC7;
|
||||
uint32_t n = (m>>6)&3;
|
||||
int32_t offset = 0;
|
||||
int64_t offset = 0;
|
||||
int absmin = 0;
|
||||
if(s) absmin = -absmax;
|
||||
if(!n && m==6) {
|
||||
@@ -338,7 +356,9 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
|
||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Jump to epilog\n");
|
||||
|
||||
if(reg) {
|
||||
if(reg!=xRIP) {
|
||||
MOVx_REG(xRIP, reg);
|
||||
@@ -352,6 +372,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
|
||||
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Jump to next\n");
|
||||
|
||||
if(reg) {
|
||||
@@ -387,7 +408,8 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
|
||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Ret next\n");
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Ret to epilog\n");
|
||||
POP1(xRIP);
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MOV64x(x2, tbl);
|
||||
@@ -405,7 +427,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Retn epilog\n");
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Retn to epilog\n");
|
||||
POP1(xRIP);
|
||||
if(n>0xfff) {
|
||||
MOV32w(w1, n);
|
||||
@@ -429,7 +452,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "IRet epilog\n");
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "IRet to epilog\n");
|
||||
// POP IP
|
||||
POP1(xRIP);
|
||||
// POP CS
|
||||
@@ -450,6 +474,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
|
||||
{
|
||||
MAYUSE(fnc);
|
||||
if(savereg==0)
|
||||
savereg = 7;
|
||||
if(saveflags) {
|
||||
@@ -494,8 +519,9 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
|
||||
|
||||
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
(void)addr;
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
|
||||
int t1 = x1, t2 = x4;
|
||||
if(reg==t1) ++t1;
|
||||
@@ -519,16 +545,20 @@ void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int se
|
||||
// x87 stuffs
|
||||
static void x87_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->x87cache[i] = -1;
|
||||
dyn->x87stack = 0;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(scratch);
|
||||
if(!dyn->x87stack)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
|
||||
@@ -553,11 +583,14 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
// reset x87stack
|
||||
dyn->x87stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)scratch;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
dyn->x87stack+=1;
|
||||
// move all regs in cache, and find a free one
|
||||
@@ -571,6 +604,7 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst)
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -584,10 +618,13 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
++dyn->x87cache[i];
|
||||
if(s1)
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1;
|
||||
#endif
|
||||
}
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
dyn->x87stack-=1;
|
||||
// move all regs in cache, poping ST0
|
||||
@@ -599,12 +636,16 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst)
|
||||
dyn->x87reg[i] = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3);
|
||||
int ret = 0;
|
||||
for (int i=0; i<8 && !ret; ++i)
|
||||
if(dyn->x87cache[i] != -1)
|
||||
@@ -666,6 +707,8 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
dyn->x87cache[i] = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)s3;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -673,6 +716,7 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2); MAYUSE(s3);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = 0;
|
||||
for (int i=0; (i<8) && (!ret); ++i)
|
||||
@@ -691,13 +735,17 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
|
||||
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
|
||||
}
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)s3;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st)
|
||||
@@ -727,6 +775,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)st;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -736,6 +785,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
#if STEP > 1
|
||||
return dyn->x87reg[x87_get_cache(dyn, ninst, s1, s2, a)];
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -744,6 +794,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -763,12 +814,15 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
}
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -792,12 +846,16 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
fpu_free_reg(dyn, dyn->x87reg[ret]);
|
||||
dyn->x87cache[ret] = -1;
|
||||
dyn->x87reg[ret] = -1;
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st) {
|
||||
@@ -838,21 +896,22 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int round_map[] = {0, 2, 1, 3}; // map x64 -> arm round flag
|
||||
|
||||
// Set rounding according to cw flags, return reg to restore flags
|
||||
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
LDRH_U12(s1, xEmu, offsetof(x64emu_t, cw));
|
||||
UBFXx(s2, s1, 10, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
RBITw(s2, s1); // round is on bits 10-11 on x86,
|
||||
LSRw(s2, s2, 20); // but we want the reverse of that
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
MSR_fpcr(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
@@ -860,10 +919,11 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags
|
||||
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
UBFXx(s2, s1, 13, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
RBITw(s2, s1); // round is on bits 13-14 on x86,
|
||||
LSRw(s2, s2, 17); // but we want the reverse of that
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
@@ -874,20 +934,27 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
// Restore round flag
|
||||
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1);
|
||||
MSR_fpcr(s1); // put back fpscr
|
||||
}
|
||||
|
||||
// MMX helpers
|
||||
static void mmx_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(dyn);
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->mmxcache[i] = -1;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a MMX reg, create the entry if needed
|
||||
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
@@ -895,24 +962,28 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx87[a]));
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
|
||||
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// purge the MMX cache only(needs 3 scratch registers)
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -928,16 +999,21 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -946,14 +1022,18 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
// SSE / SSE2 helpers
|
||||
static void sse_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<16; ++i)
|
||||
dyn->ssecache[i] = -1;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a SSE reg, create the entry if needed
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
@@ -961,24 +1041,28 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
VLDR128_U12(ret, xEmu, offsetof(x64emu_t, xmm[a]));
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
int ret = dyn->ssecache[a] = fpu_get_reg_xmm(dyn, a);
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// purge the SSE cache for XMM0..XMM7 (to use before function native call)
|
||||
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -994,12 +1078,15 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge XMM0..7 Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
// purge the SSE cache only
|
||||
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<16; ++i)
|
||||
@@ -1015,22 +1102,28 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<16; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
// only SSE regs needs to be push back to xEmu
|
||||
int n=0;
|
||||
@@ -1045,11 +1138,14 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Push XMM Cache (%d)\n", n);
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
// only SSE regs needs to be pop back from xEmu
|
||||
int n=0;
|
||||
@@ -1064,6 +1160,8 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
VLDR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1096,6 +1194,8 @@ void fpu_reset(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
@@ -1105,4 +1205,4 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
LSRw_REG(s4, s4, s3);
|
||||
MVNw_REG(s4, s4);
|
||||
BFIw(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
}
|
||||
+144
-113
@@ -47,7 +47,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 3, rex, 0, D); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
|
||||
LDRx_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -55,10 +55,20 @@
|
||||
ed = xEAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 2, rex, 0, D); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
LDRw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define GETSEDw(D) if((nextop&0xC0)==0xC0) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
SXTWx(x1, ed); \
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
LDRw_U12(x1, wback, fixedaddress); \
|
||||
wb = ed = x1; \
|
||||
}
|
||||
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDH(hint, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
@@ -166,19 +176,24 @@
|
||||
ed = i; \
|
||||
}
|
||||
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
|
||||
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
|
||||
wback = (nextop&7); \
|
||||
wb2 = (wback>>2); \
|
||||
wback = xEAX+(wback&3); \
|
||||
UBFXx(i, wback, wb2, 8);\
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
|
||||
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
#define GETEBO(i, D) if(MODREG) { \
|
||||
if(rex.rex) { \
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wb2 = 0; \
|
||||
} else { \
|
||||
wback = (nextop&7); \
|
||||
wb2 = (wback>>2)*8; \
|
||||
wback = xRAX+(wback&3); \
|
||||
} \
|
||||
UBFXx(i, wback, wb2, 8); \
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, D); \
|
||||
ADDx_REG(wback, wback, i); \
|
||||
LDRB_U12(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
|
||||
#define GETSEB(i, D) if(MODREG) { \
|
||||
@@ -243,115 +258,123 @@
|
||||
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
|
||||
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
|
||||
// Branch to MARK if cond (use j32)
|
||||
// Branch to MARK if cond (use j64)
|
||||
#define B_MARK(cond) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK unconditionnal (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK unconditionnal (use j64)
|
||||
#define B_MARK_nocond \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK if reg is 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK if reg is 0 (use j64)
|
||||
#define CBZxw_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBZxw(reg, j32)
|
||||
// Branch to MARK if reg is not 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBZxw(reg, j64)
|
||||
// Branch to MARK if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
// Branch to MARK if reg is not 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Branch to MARK if reg is not 0 (use j64)
|
||||
#define CBNZw_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBNZw(reg, j32)
|
||||
// Branch to MARK2 if cond (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBNZw(reg, j64)
|
||||
// Branch to MARK2 if cond (use j64)
|
||||
#define B_MARK2(cond) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK2 unconditionnal (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK2 unconditionnal (use j64)
|
||||
#define B_MARK2_nocond \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK2 if reg is not 0 (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK2 if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK2(reg) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to MARK2 if set
|
||||
#define TBNZ_MARK2(A, N) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
TBNZ(A, N, j32)
|
||||
// Branch to MARK3 if cond (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
TBNZ(A, N, j64)
|
||||
// Branch to MARK3 if cond (use j64)
|
||||
#define B_MARK3(cond) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK3 unconditionnal (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK3 unconditionnal (use j64)
|
||||
#define B_MARK3_nocond \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK3 if reg is not 0 (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK3 if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK3(reg) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to MARK3 if set
|
||||
#define TBNZ_MARK3(A, N) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
TBNZ(A, N, j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
TBNZ(A, N, j64)
|
||||
// Test bit N of A and branch to MARK3 if not set
|
||||
#define TBZ_MARK3(A, N) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
TBZ(A, N, j32)
|
||||
// Branch to next instruction if cond (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
TBZ(A, N, j64)
|
||||
// Branch to next instruction if cond (use j64)
|
||||
#define B_NEXT(cond) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
Bcond(cond, j32)
|
||||
// Branch to next instruction unconditionnal (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
Bcond(cond, j64)
|
||||
// Branch to next instruction unconditionnal (use j64)
|
||||
#define B_NEXT_nocond \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
|
||||
B(j32)
|
||||
// Branch to next instruction if reg is 0 (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
|
||||
B(j64)
|
||||
// Branch to next instruction if reg is 0 (use j64)
|
||||
#define CBZw_NEXT(reg) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZw(reg, j32)
|
||||
// Branch to next instruction if reg is 0 (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZw(reg, j64)
|
||||
// Branch to next instruction if reg is 0 (use j64)
|
||||
#define CBZx_NEXT(reg) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZx(reg, j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZx(reg, j64)
|
||||
// Branch to next instruction if reg is not 0 (use j64)
|
||||
#define CBNZx_NEXT(reg) \
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to next instruction if not set
|
||||
#define TBZ_NEXT(A, N) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBZ(A, N, j32)
|
||||
// Branch to MARKSEG if cond (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBZ(A, N, j64)
|
||||
// Test bit N of A and branch to next instruction if set
|
||||
#define TBNZ_NEXT(A, N) \
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBNZ(A, N, j64)
|
||||
// Branch to MARKSEG if cond (use j64)
|
||||
#define B_MARKSEG(cond) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKSEG if reg is 0 (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARKSEG if reg is 0 (use j64)
|
||||
#define CBZw_MARKSEG(reg) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBZw(reg, j32)
|
||||
// Branch to MARKSEG if reg is not 0 (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBZw(reg, j64)
|
||||
// Branch to MARKSEG if reg is not 0 (use j64)
|
||||
#define CBNZw_MARKSEG(reg) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBNZw(reg, j32)
|
||||
// Branch to MARKLOCK if cond (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBNZw(reg, j64)
|
||||
// Branch to MARKLOCK if cond (use j64)
|
||||
#define B_MARKLOCK(cond) \
|
||||
j32 = GETMARKLOCK-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j32)
|
||||
j64 = GETMARKLOCK-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j64)
|
||||
#define CBNZx_MARKLOCK(reg) \
|
||||
j32 = GETMARKLOCK-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARKLOCK-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
|
||||
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
|
||||
@@ -400,6 +423,7 @@
|
||||
|
||||
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define STP_REGS(A, B) STPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define LDP_REGS(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define STORE_XEMU_REGS(A) \
|
||||
STORE_REG(RAX); \
|
||||
STORE_REG(RCX); \
|
||||
@@ -465,11 +489,16 @@
|
||||
if(A) {STPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
|
||||
else {STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}
|
||||
|
||||
#define LOAD_XEMU_CALL(A) \
|
||||
#define LOAD_XEMU_CALL(A) \
|
||||
if(A) {LDPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
|
||||
else {LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}; \
|
||||
if(A==xRIP) dyn->last_ip = 0
|
||||
|
||||
#define LOAD_XEMU_REM() \
|
||||
LDP_REGS(R10, R11); \
|
||||
LDP_REGS(R12, R13); \
|
||||
LDP_REGS(R14, R15)
|
||||
|
||||
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=1;}
|
||||
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
|
||||
#define SET_NODF() dyn->dfnone = 0
|
||||
@@ -477,11 +506,11 @@
|
||||
|
||||
#ifndef READFLAGS
|
||||
#define READFLAGS(A) \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
|
||||
if(dyn->state_flags!=SF_PENDING) { \
|
||||
LDRw_U12(x3, xEmu, offsetof(x64emu_t, df)); \
|
||||
j32 = (GETMARKF)-(dyn->arm_size); \
|
||||
CBZw(x3, j32); \
|
||||
j64 = (GETMARKF)-(dyn->arm_size); \
|
||||
CBZw(x3, j64); \
|
||||
} \
|
||||
CALL_(UpdateFlags, -1, 0); \
|
||||
MARKF; \
|
||||
@@ -491,9 +520,11 @@
|
||||
#endif
|
||||
#ifndef SETFLAGS
|
||||
#define SETFLAGS(A, B) \
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)|X_PEND)))) \
|
||||
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A))); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)/*|X_PEND*/)))) \
|
||||
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A)|X_PEND)); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
|
||||
((B==SF_SET_PENDING && !(dyn->insts[ninst].x64.need_flags&X_PEND)?SF_SET:B))
|
||||
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
#define JUMP(A)
|
||||
@@ -595,16 +626,16 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
|
||||
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
|
||||
|
||||
#define geted STEPNAME(geted_)
|
||||
#define geted32 STEPNAME(geted32_)
|
||||
#define geted16 STEPNAME(geted16_)
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog_)
|
||||
#define jump_to_next STEPNAME(jump_to_next_)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog_)
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog_)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog_)
|
||||
#define call_c STEPNAME(call_c_)
|
||||
#define grab_segdata STEPNAME(grab_segdata_)
|
||||
#define geted STEPNAME(geted)
|
||||
#define geted32 STEPNAME(geted32)
|
||||
#define geted16 STEPNAME(geted16)
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog)
|
||||
#define jump_to_next STEPNAME(jump_to_next)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog)
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog)
|
||||
#define call_c STEPNAME(call_c)
|
||||
#define grab_segdata STEPNAME(grab_segdata)
|
||||
#define emit_cmp8 STEPNAME(emit_cmp8)
|
||||
#define emit_cmp16 STEPNAME(emit_cmp16)
|
||||
#define emit_cmp32 STEPNAME(emit_cmp32)
|
||||
@@ -706,13 +737,13 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#endif
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s);
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s);
|
||||
|
||||
|
||||
// generic x64 helper
|
||||
@@ -790,8 +821,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, 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_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
@@ -852,7 +883,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
@@ -978,4 +1009,4 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
, cNE, cEQ, X_SF|X_OF|X_ZF) \
|
||||
break
|
||||
|
||||
#endif //__DYNAREC_ARM64_HELPER_H__
|
||||
#endif //__DYNAREC_ARM64_HELPER_H__
|
||||
@@ -75,6 +75,10 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
while(pk==0x3E) { //Branch Taken Hint ignored
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
rex.rex = 0;
|
||||
while(pk>=0x40 && pk<=0x4f) {
|
||||
rex.rex = pk;
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct dynarec_arm_s {
|
||||
uint32_t isize; // size in byte of x64 instructions included
|
||||
void* block; // memory pointer where next instruction is emited
|
||||
uintptr_t arm_start; // start of the arm code
|
||||
int arm_size; // size of emitted arm code
|
||||
size_t arm_size; // size of emitted arm code
|
||||
int state_flags;// actual state for on-demand flags
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state)
|
||||
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
||||
@@ -59,4 +59,4 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
@@ -15,8 +15,9 @@
|
||||
#define SF_UNKNOWN 0
|
||||
#define SF_SET 1
|
||||
#define SF_PENDING 2
|
||||
#define SF_MAYSET 3
|
||||
#define SF_SUBSET 4
|
||||
#define SF_SET_PENDING 3
|
||||
#define SF_MAYSET 4
|
||||
#define SF_SUBSET 5
|
||||
|
||||
typedef struct instruction_x64_s {
|
||||
uintptr_t addr; //address of the instruction
|
||||
|
||||
+68
-65
@@ -225,13 +225,14 @@ const char* DumpRelType(int t)
|
||||
return buff;
|
||||
}
|
||||
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym)
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version)
|
||||
{
|
||||
static char buff[4096];
|
||||
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
|
||||
memset(buff, 0, sizeof(buff));
|
||||
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d",
|
||||
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)",
|
||||
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
|
||||
sym->st_info, sym->st_other, sym->st_shndx);
|
||||
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -246,116 +247,118 @@ const char* IdxSymName(elfheader_t *h, int sym)
|
||||
|
||||
void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP) {
|
||||
printf_log(LOG_DUMP, "ELF Dump main header\n");
|
||||
printf_log(LOG_DUMP, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_log(LOG_DUMP, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_log(LOG_DUMP, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_log(LOG_DUMP, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_log(LOG_DUMP, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_log(LOG_DUMP, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_log(LOG_DUMP, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_log(LOG_DUMP, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump ==========\n");
|
||||
if(box64_dump) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump main header\n");
|
||||
printf_dump(LOG_NEVER, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_dump(LOG_NEVER, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_dump(LOG_NEVER, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_dump(LOG_NEVER, " Program Header Entry num/size = %zu(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header Entry num/size = %zu(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header index num = %zu(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numPHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries ====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries (%zu)\n", h->numPHEntries);
|
||||
for (size_t i=0; i<h->numPHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " PHEntry %04zu : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numSHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections ====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections (%zu)\n", h->numSHEntries);
|
||||
for (size_t i=0; i<h->numSHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " Section %04zu : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpSymTab(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->SymTab) {
|
||||
if(box64_dump && h->SymTab) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab(%d)=\n", h->numSymTab);
|
||||
for (int i=0; i<h->numSymTab; ++i)
|
||||
printf_log(LOG_DUMP, " %s:SymTab[%d] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab(%zu)=\n", h->numSymTab);
|
||||
for (size_t i=0; i<h->numSymTab; ++i)
|
||||
printf_dump(LOG_NEVER, " %s:SymTab[%zu] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
|
||||
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
|
||||
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicSections(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->Dynamic) {
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
printf_log(LOG_DUMP, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic=====\n");
|
||||
if(box64_dump && h->Dynamic) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%zu)=\n", h->numDynamic);
|
||||
for (size_t i=0; i<h->numDynamic; ++i)
|
||||
printf_dump(LOG_NEVER, " Dynamic %04zu : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynSym(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynSym) {
|
||||
if(box64_dump && h->DynSym) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym(%d)=\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i)
|
||||
printf_log(LOG_DUMP, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym(%zu)=\n", h->numDynSym);
|
||||
for (size_t i=0; i<h->numDynSym; ++i) {
|
||||
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
|
||||
}
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicNeeded(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(box64_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
for (size_t i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
printf_log(LOG_DUMP, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicRPath(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
if(box64_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (size_t i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag==DT_RPATH) {
|
||||
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
|
||||
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
}
|
||||
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP) {
|
||||
if(box64_dump) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
|
||||
i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF64_R_TYPE(rel[i].r_info)),
|
||||
ELF64_R_SYM(rel[i].r_info), IdxSymName(h, ELF64_R_SYM(rel[i].r_info)));
|
||||
printf_log(LOG_DUMP, "ELF Dump Rel Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->rela) {
|
||||
if(box64_dump && h->rela) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:%s[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, name,
|
||||
i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF64_R_TYPE(rela[i].r_info)),
|
||||
ELF64_R_SYM(rela[i].r_info), IdxSymName(h, ELF64_R_SYM(rela[i].r_info)),
|
||||
rela[i].r_addend);
|
||||
printf_log(LOG_DUMP, "ELF Dump RelA Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,24 +369,24 @@ void DumpBinary(char* p, int sz)
|
||||
unsigned char* d = (unsigned char*)p;
|
||||
int delta = ((uintptr_t)p)&0xf;
|
||||
for (int i = 0; sz; ++i) {
|
||||
printf_log(LOG_DUMP, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
printf_dump(LOG_NEVER, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
int n = 16 - delta;
|
||||
if (n>sz) n = sz;
|
||||
int fill = 16-sz;
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%02X ", d[j]);
|
||||
printf_dump(LOG_NEVER, "%02X ", d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, " | ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, " | ");
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
printf_dump(LOG_NEVER, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, "\n");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, "\n");
|
||||
d+=n;
|
||||
sz-=n;
|
||||
delta=0;
|
||||
|
||||
+363
-201
File diff suppressed because it is too large.
Load diff
@@ -13,23 +13,28 @@ typedef struct needed_libs_s needed_libs_t;
|
||||
struct elfheader_s {
|
||||
char* name;
|
||||
char* path; // Resolved path to file
|
||||
int numPHEntries;
|
||||
size_t numPHEntries;
|
||||
Elf64_Phdr *PHEntries;
|
||||
int numSHEntries;
|
||||
size_t numSHEntries;
|
||||
Elf64_Shdr *SHEntries;
|
||||
int SHIdx;
|
||||
int numSST;
|
||||
size_t SHIdx;
|
||||
size_t numSST;
|
||||
char* SHStrTab;
|
||||
char* StrTab;
|
||||
Elf64_Sym* SymTab;
|
||||
int numSymTab;
|
||||
size_t numSymTab;
|
||||
char* DynStr;
|
||||
Elf64_Sym* DynSym;
|
||||
int numDynSym;
|
||||
size_t numDynSym;
|
||||
Elf64_Dyn* Dynamic;
|
||||
int numDynamic;
|
||||
size_t numDynamic;
|
||||
char* DynStrTab;
|
||||
int szDynStrTab;
|
||||
size_t szDynStrTab;
|
||||
Elf64_Half* VerSym;
|
||||
Elf64_Verneed* VerNeed;
|
||||
int szVerNeed;
|
||||
Elf64_Verdef* VerDef;
|
||||
int szVerDef;
|
||||
int e_type;
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
@@ -37,19 +42,19 @@ struct elfheader_s {
|
||||
uintptr_t entrypoint;
|
||||
uintptr_t initentry;
|
||||
uintptr_t initarray;
|
||||
int initarray_sz;
|
||||
size_t initarray_sz;
|
||||
uintptr_t finientry;
|
||||
uintptr_t finiarray;
|
||||
int finiarray_sz;
|
||||
size_t finiarray_sz;
|
||||
|
||||
uintptr_t rel;
|
||||
int relsz;
|
||||
size_t relsz;
|
||||
int relent;
|
||||
uintptr_t rela;
|
||||
int relasz;
|
||||
size_t relasz;
|
||||
int relaent;
|
||||
uintptr_t jmprel;
|
||||
int pltsz;
|
||||
size_t pltsz;
|
||||
int pltent;
|
||||
uint64_t pltrel;
|
||||
uintptr_t gotplt;
|
||||
@@ -60,18 +65,18 @@ struct elfheader_s {
|
||||
uintptr_t plt;
|
||||
uintptr_t plt_end;
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
size_t textsz;
|
||||
|
||||
uintptr_t paddr;
|
||||
uintptr_t vaddr;
|
||||
int align;
|
||||
size_t align;
|
||||
uint64_t memsz;
|
||||
uint64_t stacksz;
|
||||
int stackalign;
|
||||
uint32_t tlssize;
|
||||
int tlsalign;
|
||||
size_t stackalign;
|
||||
uint64_t tlssize;
|
||||
size_t tlsalign;
|
||||
|
||||
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
|
||||
int init_done;
|
||||
int fini_done;
|
||||
@@ -133,4 +138,4 @@ struct elfheader_s {
|
||||
|
||||
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
|
||||
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
+140
-66
@@ -43,7 +43,7 @@ int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
|
||||
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num)
|
||||
{
|
||||
int n = FindSection(s, size, SHStrTab, name);
|
||||
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
|
||||
@@ -141,7 +141,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->numSHEntries = section.sh_size;
|
||||
}
|
||||
// now read all section headers
|
||||
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
|
||||
printf_log(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries);
|
||||
h->SHEntries = (Elf64_Shdr*)calloc(h->numSHEntries, sizeof(Elf64_Shdr));
|
||||
fseeko64(f, header.e_shoff ,SEEK_SET);
|
||||
if(fread(h->SHEntries, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
|
||||
@@ -157,7 +157,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
}
|
||||
}
|
||||
|
||||
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
|
||||
printf_log(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries);
|
||||
h->PHEntries = (Elf64_Phdr*)calloc(h->numPHEntries, sizeof(Elf64_Phdr));
|
||||
fseeko64(f, header.e_phoff ,SEEK_SET);
|
||||
if(fread(h->PHEntries, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
|
||||
@@ -172,68 +172,125 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->SHIdx = h->SHEntries[0].sh_link;
|
||||
}
|
||||
if(h->SHIdx > h->numSHEntries) {
|
||||
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
|
||||
printf_log(LOG_INFO, "Incoherent Section String Table Index : %zu / %zu\n", h->SHIdx, h->numSHEntries);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
// load Section table
|
||||
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
|
||||
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx);
|
||||
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if(box64_log>=LOG_DUMP) DumpMainHeader(&header, h);
|
||||
if(box64_dump) DumpMainHeader(&header, h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
|
||||
if(box64_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
|
||||
if(box64_dump && h->SymTab) DumpSymTab(h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
|
||||
if(box64_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
|
||||
if(box64_dump && h->Dynamic) DumpDynamicSections(h);
|
||||
// grab DT_REL & DT_RELA stuffs
|
||||
// also grab the DT_STRTAB string table
|
||||
{
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag == DT_REL)
|
||||
h->rel = h->Dynamic[i].d_un.d_ptr;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELSZ)
|
||||
h->relsz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELENT)
|
||||
h->relent = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELA)
|
||||
h->rela = h->Dynamic[i].d_un.d_ptr;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELASZ)
|
||||
h->relasz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELAENT)
|
||||
h->relaent = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
|
||||
h->pltgot = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTREL)
|
||||
h->pltrel = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
|
||||
h->pltsz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_JMPREL)
|
||||
h->jmprel = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_STRTAB)
|
||||
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
|
||||
else if(h->Dynamic[i].d_tag == DT_STRSZ)
|
||||
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
|
||||
for (size_t i=0; i<h->numDynamic; ++i) {
|
||||
Elf64_Dyn d = h->Dynamic[i];
|
||||
Elf64_Word val = d.d_un.d_val;
|
||||
Elf64_Addr ptr = d.d_un.d_ptr;
|
||||
switch (d.d_tag) {
|
||||
case DT_REL:
|
||||
h->rel = ptr;
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
h->relsz = val;
|
||||
break;
|
||||
case DT_RELENT:
|
||||
h->relent = val;
|
||||
break;
|
||||
case DT_RELA:
|
||||
h->rela = ptr;
|
||||
break;
|
||||
case DT_RELASZ:
|
||||
h->relasz = val;
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
h->relaent = val;
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
h->pltgot = ptr;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
h->pltrel = val;
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
h->pltsz = val;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
h->jmprel = ptr;
|
||||
break;
|
||||
case DT_STRTAB:
|
||||
h->DynStrTab = (char*)(ptr);
|
||||
break;
|
||||
case DT_STRSZ:
|
||||
h->szDynStrTab = val;
|
||||
break;
|
||||
case DT_INIT: // Entry point
|
||||
h->initentry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
|
||||
break;
|
||||
case DT_INIT_ARRAY:
|
||||
h->initarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
|
||||
break;
|
||||
case DT_INIT_ARRAYSZ:
|
||||
h->initarray_sz = val / sizeof(Elf64_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
|
||||
break;
|
||||
case DT_FINI: // Exit hook
|
||||
h->finientry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
|
||||
break;
|
||||
case DT_FINI_ARRAY:
|
||||
h->finiarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
|
||||
break;
|
||||
case DT_FINI_ARRAYSZ:
|
||||
h->finiarray_sz = val / sizeof(Elf64_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz);
|
||||
break;
|
||||
case DT_VERNEEDNUM:
|
||||
h->szVerNeed = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
|
||||
break;
|
||||
case DT_VERNEED:
|
||||
h->VerNeed = (Elf64_Verneed*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
|
||||
break;
|
||||
case DT_VERDEFNUM:
|
||||
h->szVerDef = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
|
||||
break;
|
||||
case DT_VERDEF:
|
||||
h->VerDef = (Elf64_Verdef*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(h->rel) {
|
||||
if(h->relent != sizeof(Elf64_Rel)) {
|
||||
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%lx)\n", h->relent, sizeof(Elf64_Rel));
|
||||
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%zx)\n", h->relent, sizeof(Elf64_Rel));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
printf_log(LOG_DEBUG, "Rel Table @%p (0x%zx/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
}
|
||||
if(h->rela) {
|
||||
if(h->relaent != sizeof(Elf64_Rela)) {
|
||||
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%lx)\n", h->relaent, sizeof(Elf64_Rela));
|
||||
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%zx)\n", h->relaent, sizeof(Elf64_Rela));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
printf_log(LOG_DEBUG, "RelA Table @%p (0x%zx/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
}
|
||||
if(h->jmprel) {
|
||||
if(h->pltrel == DT_REL) {
|
||||
@@ -241,16 +298,16 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
} else if(h->pltrel == DT_RELA) {
|
||||
h->pltent = sizeof(Elf64_Rela);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%ld)\n", h->pltsz, h->pltrel);
|
||||
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%zx, type=%ld)\n", h->pltsz, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
|
||||
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%zx, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
}
|
||||
if(h->DynStrTab && h->szDynStrTab) {
|
||||
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
|
||||
@@ -275,44 +332,61 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
|
||||
}
|
||||
// look for .init entry point
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
|
||||
// grab version of symbols
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
|
||||
if(ii) {
|
||||
h->initentry = h->SHEntries[ii].sh_addr;
|
||||
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
|
||||
}
|
||||
// and .init_array
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array");
|
||||
if(ii) {
|
||||
h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
|
||||
h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %d elements\n", (void*)h->initarray, h->initarray_sz);
|
||||
}
|
||||
// look for .fini entry point
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
|
||||
if(ii) {
|
||||
h->finientry = h->SHEntries[ii].sh_addr;
|
||||
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
|
||||
}
|
||||
// and .fini_array
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array");
|
||||
if(ii) {
|
||||
h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
|
||||
h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %d elements\n", (void*)h->finiarray, h->finiarray_sz);
|
||||
h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
|
||||
}
|
||||
// grab .text for main code
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
|
||||
if(ii) {
|
||||
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
h->textsz = h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
|
||||
printf_log(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz);
|
||||
}
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
|
||||
if(box64_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version)
|
||||
{
|
||||
if(!h->VerNeed || (version<2))
|
||||
return NULL;
|
||||
/*if(version==1)
|
||||
return "*";*/
|
||||
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(aux->vna_other==version)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
|
||||
}
|
||||
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index)
|
||||
{
|
||||
if(!h->VerDef || (index<1))
|
||||
return NULL;
|
||||
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
|
||||
while(def) {
|
||||
if(def->vd_ndx==index) {
|
||||
if(def->vd_cnt<1)
|
||||
return NULL;
|
||||
/*if(def->vd_flags&VER_FLG_BASE)
|
||||
return NULL;*/
|
||||
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
|
||||
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
|
||||
}
|
||||
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#define F8 *(uint8_t*)(R_RIP++)
|
||||
#define F8S *(int8_t*)(R_RIP++)
|
||||
#define F16 *(uint16_t*)(R_RIP+=2, R_RIP-2)
|
||||
#define F16S *(int16_t*)(R_RIP+=2, R_RIP-2)
|
||||
#define F32 *(uint32_t*)(R_RIP+=4, R_RIP-4)
|
||||
#define F32S *(int32_t*)(R_RIP+=4, R_RIP-4)
|
||||
#define F32S64 (uint64_t)(int64_t)F32S
|
||||
|
||||
+8
-1
@@ -109,6 +109,7 @@ EXPORTDYN
|
||||
void SetupX64Emu(x64emu_t *emu)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
|
||||
(void)emu; // Not doing much here...
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -130,6 +131,8 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
|
||||
|
||||
void AddCleanup(x64emu_t *emu, void *p)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
@@ -141,6 +144,8 @@ void AddCleanup(x64emu_t *emu, void *p)
|
||||
|
||||
void AddCleanup1Arg(x64emu_t *emu, void *p, void* a)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
@@ -473,7 +478,9 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
|
||||
|
||||
uint64_t ReadTSC(x64emu_t* emu)
|
||||
{
|
||||
//TODO: implement hardware counter read?
|
||||
(void)emu;
|
||||
|
||||
//TODO: implement hardware counter read? (only available in kernel space?)
|
||||
// Read the TimeStamp Counter as 64bits.
|
||||
// this is supposed to be the number of instructions executed since last reset
|
||||
// fall back to gettime...
|
||||
|
||||
+82
-32
@@ -92,60 +92,110 @@ void x64Int3(x64emu_t* emu)
|
||||
char *tmp;
|
||||
int post = 0;
|
||||
int perr = 0;
|
||||
uint32_t *pu32 = NULL;
|
||||
uint64_t *pu64 = NULL;
|
||||
const char *s = NULL;
|
||||
s = GetNativeName((void*)addr);
|
||||
if(addr==(uintptr_t)PltResolver) {
|
||||
snprintf(buff, 256, "%s", " ... ");
|
||||
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "open ")) {
|
||||
} else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "mkdir")==s) {
|
||||
} else if (!strcmp(s, "fopen") || !strcmp(s, "fopen64")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
|
||||
perr = 2;
|
||||
} else if (!strcmp(s, "__openat64") || !strcmp(s, "openat64") || !strcmp(s, "__openat64_2")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
|
||||
perr = 1;
|
||||
} else if (strstr(s, "mkdir")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "opendir")==s) {
|
||||
} else if (strstr(s, "opendir")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
perr = 2;
|
||||
} else if(strstr(s, "strlen")==s) {
|
||||
} else if (!strcmp(s, "read")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "write")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "access")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "lseek64") || !strcmp(s, "my_lseek64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "lseek") || !strcmp(s, "my_lseek")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "puts")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if(strstr(s, "strcmp")==s) {
|
||||
} else if (strstr(s, "strlen")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (strstr(s, "strcmp")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)R_RSI);
|
||||
} else if(!strcmp(s, "poll")) {
|
||||
struct pollfd* pfd = (struct pollfd*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
|
||||
} else if(strstr(s, "my___printf_chk")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if(!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress")) {
|
||||
} else if (strstr(s, "getenv")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if(!strcmp(s, "glGetStringi")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
} else if (!strcmp(s, "poll")) {
|
||||
struct pollfd* pfd = (struct pollfd*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
|
||||
} else if (strstr(s, "my___printf_chk") || !strcmp(s, "__printf_chk")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if (strstr(s, "my___snprintf_chk") || !strcmp(s, "__snprintf_chk")) {
|
||||
tmp = (char*)(R_R8);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, R_EDX, R_RCX, (tmp)?tmp:"(nil)", (void*)(R_R9));
|
||||
} else if (strstr(s, "my_snprintf") || !strcmp(s, "snprintf")) {
|
||||
tmp = (char*)(R_RDX);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (tmp)?tmp:"(nil)", (void*)(R_RCX));
|
||||
} else if (!strcmp(s, "getcwd")) {
|
||||
post = 2;
|
||||
} else if(!strcmp(s, "glFramebufferTexture2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI);
|
||||
} else if (!strcmp(s, "ftok")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
perr = 1;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, tmp?tmp:"nil", R_ESI);
|
||||
} else if (!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress") || !strcmp(s, "glXGetProcAddressARB")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glLabelObjectEXT")) {
|
||||
tmp = (char*)(R_RCX);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, \"%s\")", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_ECX, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glGetStringi")) {
|
||||
post = 2;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
} else if (!strcmp(s, "glFramebufferTexture2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, 0x%x, 0x%x, %u, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d);
|
||||
} else if(!strcmp(s, "glTexSubImage2D")) {
|
||||
} else if (!strcmp(s, "glTexSubImage2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
|
||||
} else if(!strcmp(s, "glCompressedTexSubImage2D")) {
|
||||
} else if (!strcmp(s, "glCompressedTexSubImage2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
|
||||
} else if(!strcmp(s, "glVertexAttribPointer")) {
|
||||
} else if (!strcmp(s, "glVertexAttribPointer")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%u, %d, 0x%x, %d, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, (void*)R_R9);
|
||||
} else if(!strcmp(s, "glDrawElements")) {
|
||||
} else if (!strcmp(s, "glDrawElements")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, (void*)R_RCX);
|
||||
} else if(!strcmp(s, "glUniform4fv")) {
|
||||
} else if (!strcmp(s, "glUniform4fv")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %d, %p[%g/%g/%g/%g...])", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, (void*)R_RDX, ((float*)(R_RDX))[0], ((float*)(R_RDX))[1], ((float*)(R_RDX))[2], ((float*)(R_RDX))[3]);
|
||||
} else if(!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
|
||||
} else if (!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %lu, 0x%x, 0x%x, %d, %ld)", tid, *(void**)(R_RSP), s,
|
||||
(void*)R_RDI, R_RSI, (int)(R_RDX), (int)R_RCX, (int)R_R8, R_R9);
|
||||
} else if(!strcmp(s, "sscanf")) {
|
||||
} else if (!strcmp(s, "sscanf")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if(!strcmp(s, "XCreateWindow")) {
|
||||
} else if (!strcmp(s, "XCreateWindow")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, 0x%lx, %p)", tid, *(void**)(R_RSP), s,
|
||||
(void*)R_RDI, (void*)R_RSI, (int)R_EDX, (int)R_ECX, R_R8d, R_R9d,
|
||||
@@ -160,23 +210,23 @@ void x64Int3(x64emu_t* emu)
|
||||
w(emu, addr); // some function never come back, so unlock the mutex first!
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
if(post)
|
||||
switch(post) {
|
||||
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
|
||||
switch(post) { // Only ever 2 for now...
|
||||
case 1: snprintf(buff2, 63, " [%llu sec %llu nsec]", pu64?pu64[0]:~0ull, pu64?pu64[1]:~0ull);
|
||||
break;
|
||||
case 2: snprintf(buff2, 63, "(%s)", R_RAX?((char*)R_RAX):"nil");
|
||||
break;
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu64?((char*)pu64):"nil");
|
||||
break;
|
||||
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
|
||||
break;
|
||||
case 5: {
|
||||
uint32_t* p = (uint32_t*)R_RAX;
|
||||
uint32_t* p = (uint32_t*)R_RAX; // uint64_t? (case never used)
|
||||
if(p)
|
||||
snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
snprintf(buff2, 63, " size=%ux%u, pitch=%u, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
else
|
||||
snprintf(buff2, 63, "NULL Surface");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(perr==1 && ((int)R_EAX)<0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
@@ -199,4 +249,4 @@ void x64Int3(x64emu_t* emu)
|
||||
int GetTID()
|
||||
{
|
||||
return syscall(SYS_gettid);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -785,7 +785,7 @@ uint8_t rol8(x64emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -808,7 +808,7 @@ uint16_t rol16(x64emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -831,7 +831,7 @@ uint32_t rol32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -854,7 +854,7 @@ uint64_t rol64(x64emu_t *emu, uint64_t d, uint8_t s)
|
||||
if((cnt = s % 64) != 0) {
|
||||
d = (d << cnt) + ((d >> (64 - cnt)) & ((1L << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -881,7 +881,7 @@ uint8_t ror8(x64emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -904,7 +904,7 @@ uint16_t ror16(x64emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -927,7 +927,7 @@ uint32_t ror32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -950,7 +950,7 @@ uint64_t ror64(x64emu_t *emu, uint64_t d, uint8_t s)
|
||||
if((cnt = s % 64) != 0) {
|
||||
d = (d << (64 - cnt)) + ((d >> (cnt)) & ((1L << (64 - cnt)) - 1L));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -1400,7 +1400,7 @@ void idiv64(x64emu_t *emu, uint64_t s)
|
||||
}
|
||||
quot = dvd/(int64_t)s;
|
||||
mod = dvd%(int64_t)s;
|
||||
if (llabs(quot) > 0x7fffffffffffffffL) {
|
||||
if ((quot > 0x7fffffffffffffffLL) || (quot < -0x7fffffffffffffffLL)) {
|
||||
INTR_RAISE_DIV0(emu);
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-1
@@ -235,21 +235,25 @@ static inline uint64_t neg64(x64emu_t *emu, uint64_t s)
|
||||
|
||||
static inline uint8_t not8(x64emu_t *emu, uint8_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint16_t not16(x64emu_t *emu, uint16_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint32_t not32(x64emu_t *emu, uint32_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint64_t not64(x64emu_t *emu, uint64_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
@@ -588,7 +592,7 @@ static inline void mul32_eax(x64emu_t *emu, uint32_t s)
|
||||
static inline void mul64_rax(x64emu_t *emu, uint64_t s)
|
||||
{
|
||||
emu->df = d_mul64;
|
||||
__int128 res = (__int128)R_RAX * s;
|
||||
unsigned __int128 res = (unsigned __int128)R_RAX * s;
|
||||
emu->res.u64 = R_RAX = (uint64_t)res;
|
||||
emu->op1.u64 = R_RDX = (uint64_t)(res >> 64);
|
||||
}
|
||||
|
||||
+82
-20
@@ -70,6 +70,8 @@ x64emurun:
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
while((opcode==0x3E)) //Branch Taken Hint ignored
|
||||
opcode = F8;
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
@@ -234,19 +236,26 @@ x64emurun:
|
||||
GD->sq[0] = ED->sdword[0];
|
||||
else
|
||||
if(MODREG)
|
||||
GD->q[0] = ED->sdword[0];
|
||||
GD->q[0] = ED->dword[0]; // not really a sign extension
|
||||
else
|
||||
GD->sdword[0] = ED->sdword[0]; // meh?
|
||||
break;
|
||||
case 0x64: /* FS: prefix */
|
||||
if(Run64(emu, rex)) {
|
||||
if(Run64(emu, rex, _FS)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
case 0x65: /* GS: prefix */
|
||||
if(Run64(emu, rex, _GS)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0x66: /* 16bits prefix */
|
||||
if(Run66(emu, rex, rep)) {
|
||||
unimp = 1;
|
||||
@@ -274,10 +283,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, ED->q[0], tmp64u);
|
||||
else
|
||||
if((nextop&0xC0)==0xC0)
|
||||
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
else
|
||||
GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
break;
|
||||
case 0x6A: /* Push Ib */
|
||||
tmp64s = F8S;
|
||||
@@ -383,7 +389,7 @@ x64emurun:
|
||||
#ifdef DYNAREC
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
|
||||
if(MODREG) { // reg / reg: no lock
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
@@ -397,12 +403,12 @@ x64emurun:
|
||||
#else
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
if(!MODREG)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
if(!MODREG)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
@@ -411,7 +417,7 @@ x64emurun:
|
||||
#ifdef DYNAREC
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(rex.w) {
|
||||
tmp64u = GD->q[0];
|
||||
GD->q[0] = ED->q[0];
|
||||
@@ -487,7 +493,11 @@ x64emurun:
|
||||
else
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
break;
|
||||
case 0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -495,7 +505,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
GD->q[0] = (uint32_t)(uintptr_t)ED;
|
||||
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
|
||||
break;
|
||||
|
||||
case 0x8F: /* POP Ed */
|
||||
@@ -510,7 +520,26 @@ x64emurun:
|
||||
R_ESP += sizeof(void*);
|
||||
}
|
||||
break;
|
||||
case 0x90: /* NOP */
|
||||
case 0x90: /* NOP or XCHG R8, RAX*/
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97: /* XCHG reg,EAX */
|
||||
tmp8u = _AX+(opcode&7)+(rex.b<<3);
|
||||
if(tmp8u!=_AX) {
|
||||
if(rex.w) {
|
||||
tmp64u = R_RAX;
|
||||
R_RAX = emu->regs[tmp8u].q[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
} else {
|
||||
tmp64u = R_EAX;
|
||||
R_RAX = emu->regs[tmp8u].dword[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x98: /* CWDE */
|
||||
@@ -539,6 +568,7 @@ x64emurun:
|
||||
RESET_FLAGS(emu);
|
||||
break;
|
||||
case 0x9E: /* SAHF */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x01, F_CF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x04, F_PF);
|
||||
@@ -558,7 +588,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
R_RAX = *(uint64_t*)F64;
|
||||
else
|
||||
R_EAX = *(uint32_t*)F64;
|
||||
R_RAX = *(uint32_t*)F64;
|
||||
break;
|
||||
case 0xA2: /* MOV Ob,AL */
|
||||
*(uint8_t*)F64 = R_AL;
|
||||
@@ -1146,6 +1176,35 @@ x64emurun:
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
case 0xE0: /* LOOPNZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX && !ACCESS_FLAG(F_ZF))
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE1: /* LOOPZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX && ACCESS_FLAG(F_ZF))
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE2: /* LOOP */
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX)
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE3: /* JECXZ */
|
||||
tmp8s = F8S;
|
||||
if(!R_RCX)
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
@@ -1174,6 +1233,10 @@ x64emurun:
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
|
||||
break;
|
||||
case 0xF6: /* GRP3 Eb(,Ib) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
@@ -1263,13 +1326,13 @@ x64emurun:
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
div32(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
//emu->regs[_AX].dword[1] = 0; // already put high regs to 0
|
||||
//emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
case 7: /* IDIV Ed */
|
||||
idiv32(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
//emu->regs[_AX].dword[1] = 0;
|
||||
//emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1368,7 +1431,6 @@ x64emurun:
|
||||
} else {
|
||||
R_RIP = ED->q[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
STEP
|
||||
goto fini; // exit loop to recompute CS...
|
||||
}
|
||||
break;
|
||||
|
||||
+46
-33
@@ -49,6 +49,22 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
x64Syscall(emu);
|
||||
break;
|
||||
|
||||
case 0x0B: /* UD2 */
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 1: //PREFETCHW
|
||||
__builtin_prefetch((void*)ED, 1, 0);
|
||||
break;
|
||||
default: //???
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10: /* MOVUPS Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
@@ -288,7 +304,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
GD->dword[0] = 0;
|
||||
GD->q[0] = 0;
|
||||
for(int i=0; i<4; ++i)
|
||||
GD->dword[0] |= ((EX->ud[i]>>31)&1)<<i;
|
||||
break;
|
||||
@@ -696,19 +712,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
@@ -726,8 +742,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
tmp8u = R_CL;
|
||||
if(rex.w)
|
||||
ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u);
|
||||
else
|
||||
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else
|
||||
ED->dword[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAB: /* BTS Ed,Gd */
|
||||
@@ -735,13 +755,14 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
@@ -749,7 +770,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
@@ -768,8 +788,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
tmp8u = (opcode==0xAC)?(F8):R_CL;
|
||||
if(rex.w)
|
||||
ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u);
|
||||
else
|
||||
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else
|
||||
ED->dword[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
}
|
||||
break;
|
||||
case 0xAE: /* Grp Ed (SSE) */
|
||||
nextop = F8;
|
||||
@@ -818,7 +842,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
break;
|
||||
case 0xB0: /* CMPXCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
@@ -858,20 +882,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
@@ -902,8 +926,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -922,8 +944,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@@ -946,8 +966,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@@ -968,8 +986,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -996,23 +1012,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
if(rex.w)
|
||||
ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6));
|
||||
else
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
|
||||
+47
-7
@@ -22,20 +22,20 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run64(x64emu_t *emu, rex_t rex)
|
||||
int Run64(x64emu_t *emu, rex_t rex, int seg)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u; (void)tmp16u;
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
int rep;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
@@ -108,6 +108,32 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10:
|
||||
switch(rep) {
|
||||
case 1: /* MOVSD Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->q[0] = EX->q[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
// EX is not a register
|
||||
GX->q[1] = 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* MOVSS Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->ud[0] = EX->ud[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
// EX is not a register (reg to reg only move 31:0)
|
||||
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 1: /* MOVSD Ex, Gx */
|
||||
@@ -217,7 +243,21 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(1, tlsdata);
|
||||
tmp8u = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
|
||||
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
@@ -318,4 +358,4 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -246,6 +246,20 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Od */
|
||||
if(rex.w)
|
||||
R_RAX = *(uint64_t*)F64;
|
||||
else
|
||||
R_AX = *(uint16_t*)F64;
|
||||
break;
|
||||
|
||||
case 0xA3: /* MOV Od,EAX */
|
||||
if(rex.w)
|
||||
*(uint64_t*)F64 = R_RAX;
|
||||
else
|
||||
*(uint16_t*)F64 = R_AX;
|
||||
break;
|
||||
|
||||
case 0xA5: /* (REP) MOVSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
@@ -557,6 +571,9 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
R_RIP += tmp32s;
|
||||
break;
|
||||
|
||||
case 0xF0: /* LOCK: */
|
||||
return Run66F0(emu, rex);
|
||||
|
||||
case 0xF7: /* GRP3 Ew(,Iw) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
|
||||
+127
-16
@@ -256,7 +256,50 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = ((((int32_t)(GX->sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
|
||||
GX->uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x20: /* PMOVSXBW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=7; i>=0; --i)
|
||||
GX->sw[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x21: /* PMOVSXBD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=3; i>=0; --i)
|
||||
GX->sd[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x22: /* PMOVSXBQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x23: /* PMOVSXWD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=3; i>=0; --i)
|
||||
GX->sd[i] = EX->sw[i];
|
||||
break;
|
||||
case 0x24: /* PMOVSXWQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sw[i];
|
||||
break;
|
||||
case 0x25: /* PMOVSXDQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
@@ -266,6 +309,31 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
case 0x3A: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0B: // ROUNDSD Gx, Ex, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8; // ignoring bit 3 interupt thingy
|
||||
if(tmp8u&4)
|
||||
tmp8u = (emu->mxcsr>>13)&3;
|
||||
else
|
||||
tmp8u &= 3;
|
||||
switch(tmp8u) {
|
||||
case ROUND_Nearest:
|
||||
GX->d[0] = floor(EX->d[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->d[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->d[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->d[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0F: // PALIGNR GX, EX, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -756,13 +824,20 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
@@ -788,18 +863,25 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
EW->q[0] |= (1LL<<(GW->q[0]&63));
|
||||
EW->q[0] |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
EW->word[0] |= (1<<(GW->word[0]&15));
|
||||
EW->word[0] |= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
}
|
||||
@@ -855,31 +937,60 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63))) {
|
||||
if(EW->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->q[0] ^= (1LL<<(GW->q[0]&63));
|
||||
EW->q[0] ^= (1LL<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15))) {
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW->word[0]&15));
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gw,Eb */
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
GETGW;
|
||||
GW->word[0] = EB->byte[0];
|
||||
break;
|
||||
|
||||
case 0xBB: /* BTC Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW->word[0]&15));
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->q[0] ^= (1LL<<tmp8u);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
}
|
||||
break;
|
||||
case 0xBC: /* BSF Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64run_private.h"
|
||||
#include "x64primop.h"
|
||||
#include "x64trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "bridge.h"
|
||||
#include "dynarec/arm64_lock.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint16_t tmp16u2;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped;
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x81: /* GRP Ew,Iw */
|
||||
case 0x83: /* GRP Ew,Ib */
|
||||
nextop = F8;
|
||||
GETED((opcode==0x83)?1:2);
|
||||
tmp64s = (opcode==0x83)?(F8S):(F16S);
|
||||
tmp64u = (uint64_t)tmp64s;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 1: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = or64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 2: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = adc64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 3: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sbb64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 4: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = and64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 5: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sub64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 6: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = xor64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
|
||||
case 7: cmp64(emu, ED->q[0], tmp64u); break;
|
||||
}
|
||||
} else {
|
||||
if(MODREG)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
|
||||
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
|
||||
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
|
||||
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
|
||||
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
|
||||
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
|
||||
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
|
||||
case 7: cmp16(emu, ED->word[0], tmp64u); break;
|
||||
}
|
||||
else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = add16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 1: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = or16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 2: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = adc16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 3: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sbb16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 4: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = and16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 5: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sub16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 6: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = xor16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
|
||||
case 7: cmp16(emu, ED->word[0], tmp64u); break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;
|
||||
case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break;
|
||||
case 2: ED->q[0] = adc64(emu, ED->q[0], tmp64u); break;
|
||||
case 3: ED->q[0] = sbb64(emu, ED->q[0], tmp64u); break;
|
||||
case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break;
|
||||
case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break;
|
||||
case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break;
|
||||
case 7: cmp64(emu, ED->q[0], tmp64u); break;
|
||||
}
|
||||
} else {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
|
||||
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
|
||||
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
|
||||
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
|
||||
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
|
||||
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
|
||||
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
|
||||
case 7: cmp16(emu, ED->word[0], tmp64u); break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+5
-5
@@ -52,13 +52,13 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
|
||||
@@ -71,13 +71,13 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
|
||||
@@ -167,7 +167,7 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
GD->q[0] = (uint32_t)(uintptr_t)ED;
|
||||
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
|
||||
break;
|
||||
|
||||
case 0xC1: /* GRP2 Ed,Ib */
|
||||
|
||||
+13
-9
@@ -27,16 +27,17 @@
|
||||
|
||||
int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
{
|
||||
(void)rep;
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
int32_t tmp32s, tmp32s2; (void)tmp32s; (void)tmp32s2;
|
||||
uint32_t tmp32u, tmp32u2; (void)tmp32u; (void)tmp32u2;
|
||||
uint64_t tmp64u, tmp64u2; (void)tmp64u; (void)tmp64u2;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
sse_regs_t *opex, *opgx, eax1; (void)eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1; (void)opem; (void)opgm; (void)eam1;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -45,6 +46,9 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
case 0x2E: /* UCOMISS Gx, Ex */
|
||||
// same for now
|
||||
case 0x2F: /* COMISS Gx, Ex */
|
||||
if(rep) {
|
||||
return 1;
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
@@ -65,4 +69,4 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+14
-12
@@ -27,16 +27,18 @@
|
||||
|
||||
int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
{
|
||||
// Hmmmm....
|
||||
(void)rep;
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u, tmp8u2;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int32_t tmp32s;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3;
|
||||
reg64_t *oped, *opgd;
|
||||
uint8_t nextop; (void)nextop;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
uint8_t tmp8u, tmp8u2; (void)tmp8u; (void)tmp8u2;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u, tmp16u2; (void)tmp16u; (void)tmp16u2;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
int64_t tmp64s; (void)tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3; (void)tmp64u; (void)tmp64u2; (void)tmp64u3;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -47,7 +49,7 @@ int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
// REX prefix before the F0 are ignored
|
||||
// REX prefix before the 66 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
@@ -56,11 +58,11 @@ int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F: /* more opcdes */
|
||||
case 0x0F: /* more opcodes */
|
||||
return Run67660F(emu, rex);
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -26,22 +26,22 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u;
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1, *opex2;
|
||||
mmx87_regs_t *opem, *opgm;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u; (void)tmp16u;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
uint32_t tmp32u; (void)tmp32u;
|
||||
int64_t tmp64s; (void)tmp64s;
|
||||
uint64_t tmp64u; (void)tmp64u;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x6F: /* MOVDQA Gx,Ex */
|
||||
case 0x6F: /* MOVDQA Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
@@ -49,7 +49,7 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[1] = EX->q[1];
|
||||
break;
|
||||
|
||||
case 0x76: /* PCMPEQD Gx,Ex */
|
||||
case 0x76: /* PCMPEQD Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
@@ -61,4 +61,4 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
|
||||
{
|
||||
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
|
||||
|
||||
// let's cheat and set all args...
|
||||
if(init) {
|
||||
PushExit(emu);
|
||||
@@ -944,7 +946,7 @@ uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
|
||||
const char* getAddrFunctionName(uintptr_t addr)
|
||||
{
|
||||
static char ret[1000];
|
||||
uint32_t sz = 0;
|
||||
uint64_t sz = 0;
|
||||
uintptr_t start = 0;
|
||||
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
|
||||
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
|
||||
@@ -959,7 +961,7 @@ const char* getAddrFunctionName(uintptr_t addr)
|
||||
|
||||
void printFunctionAddr(uintptr_t nextaddr, const char* text)
|
||||
{
|
||||
uint32_t sz = 0;
|
||||
uint64_t sz = 0;
|
||||
uintptr_t start = 0;
|
||||
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
|
||||
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
|
||||
@@ -991,6 +993,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
my_context->trace_dynarec = dynarec;
|
||||
}
|
||||
#else
|
||||
(void)dynarec;
|
||||
if(my_context->trace_tid != tid) {
|
||||
printf_log(LOG_NONE, "Thread %04d|\n", tid);
|
||||
my_context->trace_tid = tid;
|
||||
@@ -1178,6 +1181,8 @@ reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t
|
||||
|
||||
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
@@ -1205,6 +1210,8 @@ reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint32_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
@@ -1279,6 +1286,8 @@ reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
return &emu->mmx87[m&7];
|
||||
}
|
||||
|
||||
@@ -102,12 +102,13 @@ void UpdateFlags(x64emu_t *emu);
|
||||
#define RESET_FLAGS(emu) emu->df = d_none
|
||||
|
||||
int Run0F(x64emu_t *emu, rex_t rex);
|
||||
int Run64(x64emu_t *emu, rex_t rex);
|
||||
int Run64(x64emu_t *emu, rex_t rex, int seg);
|
||||
int Run66(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run660F(x64emu_t *emu, rex_t rex);
|
||||
int Run6664(x64emu_t *emu, rex_t rex);
|
||||
int Run66D9(x64emu_t *emu, rex_t rex);
|
||||
int Run66DD(x64emu_t *emu, rex_t rex);
|
||||
int Run66F0(x64emu_t *emu, rex_t rex);
|
||||
int Run67(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run670F(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run6766(x64emu_t *emu, rex_t rex, int rep);
|
||||
@@ -123,12 +124,6 @@ int RunDF(x64emu_t *emu, rex_t rex);
|
||||
int RunF0(x64emu_t *emu, rex_t rex);
|
||||
int RunF20F(x64emu_t *emu, rex_t rex);
|
||||
int RunF30F(x64emu_t *emu, rex_t rex);
|
||||
//void Run66D9(x64emu_t *emu); // x87
|
||||
//void Run6766(x64emu_t *emu);
|
||||
//void RunGS(x64emu_t *emu);
|
||||
//void RunFS(x64emu_t *emu);
|
||||
//void RunFS66(x64emu_t *emu, uintptr_t tlsdata);
|
||||
//void RunLock66(x64emu_t *emu);
|
||||
|
||||
void x64Syscall(x64emu_t *emu);
|
||||
void x64Int3(x64emu_t* emu);
|
||||
@@ -146,4 +141,4 @@ const char* GetNativeName(void* p);
|
||||
void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec);
|
||||
#endif
|
||||
|
||||
#endif //__X86RUN_PRIVATE_H_
|
||||
#endif //__X86RUN_PRIVATE_H_
|
||||
+2
-1
@@ -191,7 +191,8 @@ int RunD9(x64emu_t *emu, rex_t rex)
|
||||
break;
|
||||
case 0xFD: /* FSCALE */
|
||||
// this could probably be done by just altering the exponant part of the float...
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
ST0.d = sin(ST0.d);
|
||||
|
||||
+2
-2
@@ -162,7 +162,7 @@ int RunDF(x64emu_t *emu, rex_t rex)
|
||||
break;
|
||||
case 7: /* FISTP i64 */
|
||||
GETED(0);
|
||||
if(STll(0).ref==ST(0).q)
|
||||
if(STll(0).ref==ST(0).sq)
|
||||
ED->sq[0] = STll(0).ll;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
@@ -177,4 +177,4 @@ int RunDF(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+73
-25
@@ -31,7 +31,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int32_t tmp32s;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
@@ -197,7 +197,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
} else {
|
||||
tmp64u |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp64u);
|
||||
tmp32s = arm64_lock_write_dd(ED, tmp64u);
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
@@ -281,27 +281,46 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
if(((uintptr_t)ED)&7) {
|
||||
do {
|
||||
tmp64u = ED->q[0] & ~0xffLL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_b(ED, GD->q[0]&0xff);
|
||||
if(!tmp32s)
|
||||
ED->q[0] = GD->q[0];
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
cmp32(emu, R_EAX, tmp32u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_d(ED, GD->dword[0]);
|
||||
} else {
|
||||
R_RAX = tmp32u;
|
||||
R_EAX = tmp32u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
@@ -318,6 +337,9 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
} else {
|
||||
R_EAX = ED->dword[0];
|
||||
}
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
@@ -347,7 +369,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
@@ -359,6 +381,9 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
@@ -388,7 +413,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
tmp64u2 = add64(emu, tmp64u, GD->dword[0]);
|
||||
tmp64u2 = add64(emu, tmp64u, GD->q[0]);
|
||||
} while(arm64_lock_write_dd(ED, tmp64u2));
|
||||
GD->q[0] = tmp64u;
|
||||
} else {
|
||||
@@ -482,8 +507,8 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
ED->dword[1] = R_ECX;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
R_RAX = tmp32u;
|
||||
R_RDX = tmp32u2;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
@@ -495,6 +520,9 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
return Run66F0(emu, rex); // more opcode F0 66 and 66 F0 is the same
|
||||
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
@@ -631,9 +659,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, inc64(emu, tmp64u)));
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
do {
|
||||
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
tmp64u = inc64(emu, tmp64u);
|
||||
} while(arm64_lock_write_b(ED, tmp64u&0xff));
|
||||
ED->q[0] = tmp64u;
|
||||
}
|
||||
else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, inc64(emu, tmp64u)));
|
||||
else {
|
||||
if((uintptr_t)ED&3) {
|
||||
//meh.
|
||||
@@ -667,9 +705,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, dec64(emu, tmp64u)));
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
do {
|
||||
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
tmp64u = dec64(emu, tmp64u);
|
||||
} while(arm64_lock_write_b(ED, tmp64u&0xff));
|
||||
ED->q[0] = tmp64u;
|
||||
}
|
||||
else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, dec64(emu, tmp64u)));
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
@@ -700,4 +748,4 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
GD->sdword[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->ud[0] = EX->ud[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
if(!MODREG) {
|
||||
// EX is not a register (reg to reg only move 31:0)
|
||||
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
|
||||
}
|
||||
|
||||
+178
-5
@@ -36,10 +36,13 @@
|
||||
typedef struct x64_sigaction_s x64_sigaction_t;
|
||||
typedef struct x64_stack_s x64_stack_t;
|
||||
|
||||
int mkdir(const char *path, mode_t mode);
|
||||
|
||||
//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
|
||||
int of_convert(int flag);
|
||||
int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
|
||||
ssize_t my_readlink(x64emu_t* emu, void* path, void* buf, size_t sz);
|
||||
int my_stat(x64emu_t *emu, void* filename, void* buf);
|
||||
|
||||
int my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact);
|
||||
int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss);
|
||||
@@ -47,6 +50,7 @@ int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss);
|
||||
void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
|
||||
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
|
||||
int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
|
||||
void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
@@ -57,7 +61,7 @@ int fcntl(int fd, int cmd, ... /* arg */ );
|
||||
|
||||
// Syscall table for x86_64 can be found
|
||||
typedef struct scwrap_s {
|
||||
int x64s;
|
||||
uint32_t x64s; // 32 bits?
|
||||
int nats;
|
||||
int nbpars;
|
||||
} scwrap_t;
|
||||
@@ -67,27 +71,71 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 1, __NR_write, 3 }, // same
|
||||
//{ 2, __NR_open, 3 }, // flags need transformation
|
||||
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//{ 4, __NR_stat, 2 }, // Need to align struct stat
|
||||
//{ 9, __NR_mmap, 6}, // wrapped to track mmap
|
||||
//{ 10, __NR_mprotect, 3}, // same
|
||||
//{ 11, __NR_munmap, 2}, // same
|
||||
{ 5, __NR_fstat, 2},
|
||||
//{ 13, __NR_rt_sigaction, 4} // wrapped to use my_ version
|
||||
//{ 13, __NR_rt_sigaction, 4}, // wrapped to use my_ version
|
||||
{ 14, __NR_rt_sigprocmask, 4},
|
||||
{ 16, __NR_ioctl, 3},
|
||||
{ 20, __NR_writev, 3},
|
||||
#ifdef __NR_access
|
||||
{ 21, __NR_access, 2},
|
||||
#endif
|
||||
#ifdef __NR_pipe
|
||||
{ 22, __NR_pipe, 1},
|
||||
#endif
|
||||
#ifdef __NR_select
|
||||
{ 23, __NR_select, 5},
|
||||
#endif
|
||||
//{ 25, __NR_mremap, 5}, // wrapped to track protection
|
||||
{ 39, __NR_getpid, 0},
|
||||
{ 46, __NR_sendmsg, 3},
|
||||
{ 47, __NR_recvmsg, 3},
|
||||
{ 53, __NR_socketpair, 4},
|
||||
#ifdef __NR_fork
|
||||
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
|
||||
#endif
|
||||
{ 61, __NR_wait4, 4},
|
||||
{ 66, __NR_semctl, 4},
|
||||
#ifdef __NR_getdents
|
||||
{ 78, __NR_getdents, 3},
|
||||
#endif
|
||||
#ifdef __NR_mkdir
|
||||
{ 83, __NR_mkdir, 2},
|
||||
#endif
|
||||
#ifdef __NR_unlink
|
||||
{ 87, __NR_unlink, 1},
|
||||
#endif
|
||||
//{ 89, __NR_readlink, 3}, // not always existing, better use the wrapped version anyway
|
||||
{ 96, __NR_gettimeofday, 2},
|
||||
{ 97, __NR_getrlimit, 2},
|
||||
{ 101, __NR_ptrace, 4},
|
||||
{ 125, __NR_capget, 2},
|
||||
{ 126, __NR_capset, 2},
|
||||
{ 127, __NR_rt_sigpending, 2},
|
||||
//{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack
|
||||
{ 157, __NR_prctl, 5 }, // needs wrapping?
|
||||
//{ 158, __NR_arch_prctl, 2}, //need wrapping
|
||||
{ 186, __NR_gettid, 0 }, //0xBA
|
||||
{ 200, __NR_tkill, 2 },
|
||||
#ifdef __NR_time
|
||||
{ 201, __NR_time, 1},
|
||||
#endif
|
||||
{ 202, __NR_futex, 6},
|
||||
{ 217, __NR_getdents64, 3},
|
||||
{ 220, __NR_semtimedop, 4},
|
||||
{ 228, __NR_clock_gettime, 2},
|
||||
{ 229, __NR_clock_getres, 2},
|
||||
{ 230, __NR_clock_nanosleep, 4},
|
||||
{ 234, __NR_tgkill, 3},
|
||||
#ifdef __NR_inotify_init
|
||||
{ 253, __NR_inotify_init, 0}, //0xFD
|
||||
#endif
|
||||
{ 254, __NR_inotify_add_watch, 3},
|
||||
{ 255, __NR_inotify_rm_watch, 2},
|
||||
{ 274, __NR_get_robust_list, 3},
|
||||
{ 294, __NR_inotify_init1, 1},
|
||||
{ 298, __NR_perf_event_open, 5},
|
||||
{ 318, __NR_getrandom, 3},
|
||||
@@ -102,6 +150,45 @@ struct mmap_arg_struct {
|
||||
unsigned long offset;
|
||||
};
|
||||
|
||||
#ifndef __NR_getdents
|
||||
typedef struct x86_linux_dirent_s {
|
||||
unsigned long d_ino;
|
||||
unsigned long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[];
|
||||
} x86_linux_dirent_t;
|
||||
|
||||
typedef struct nat_linux_dirent64_s {
|
||||
ino64_t d_ino;
|
||||
off64_t d_off;
|
||||
unsigned short d_reclen;
|
||||
unsigned char d_type;
|
||||
char d_name[];
|
||||
} nat_linux_dirent64_t;
|
||||
|
||||
ssize_t DirentFromDirent64(void* dest, void* source, ssize_t count)
|
||||
{
|
||||
nat_linux_dirent64_t *src = (nat_linux_dirent64_t*)source;
|
||||
x86_linux_dirent_t *dst = (x86_linux_dirent_t*)dest;
|
||||
ssize_t ret = count;
|
||||
while(count>0) {
|
||||
dst->d_ino = src->d_ino;
|
||||
dst->d_reclen = src->d_reclen+1;
|
||||
strcpy(dst->d_name, src->d_name);
|
||||
dst->d_off = src->d_off?(src->d_off+1):0;
|
||||
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -2) = 0;
|
||||
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -1) = src->d_type;
|
||||
|
||||
count -= src->d_reclen;
|
||||
ret += 1;
|
||||
src = (nat_linux_dirent64_t*)(((uintptr_t)src) + src->d_reclen);
|
||||
dst = (x86_linux_dirent_t*)(((uintptr_t)dst) + dst->d_reclen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//struct x86_pt_regs {
|
||||
// long ebx;
|
||||
// long ecx;
|
||||
@@ -135,7 +222,7 @@ struct mmap_arg_struct {
|
||||
void EXPORT x64Syscall(x64emu_t *emu)
|
||||
{
|
||||
RESET_FLAGS(emu);
|
||||
uint32_t s = R_EAX;
|
||||
uint32_t s = R_EAX; // EAX? (syscalls only go up to 547 anyways)
|
||||
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p %p", (void*)R_RIP, s, s, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8, (void*)R_R9);
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
@@ -145,7 +232,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
switch(syscallwrap[i].nbpars) {
|
||||
case 0: *(int64_t*)&R_RAX = syscall(sc); break;
|
||||
case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
|
||||
case 2: if(s==33) {printf_dump(LOG_DEBUG, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
|
||||
case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
|
||||
case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
|
||||
case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
|
||||
@@ -174,6 +261,9 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
case 3: // sys_close
|
||||
R_EAX = (uint32_t)close((int)R_EDI);
|
||||
break;
|
||||
case 4: // sys_stat
|
||||
R_EAX = (uint32_t)my_stat(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
case 9: // sys_mmap
|
||||
R_RAX = (uintptr_t)my_mmap64(emu, (void*)R_RDI, R_RSI, (int)R_EDX, (int)R_R10d, (int)R_R8d, R_R9);
|
||||
break;
|
||||
@@ -186,19 +276,64 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
case 13: // sys_rt_sigaction
|
||||
R_EAX = (uint32_t)my_sigaction(emu, (int)R_EDI, (const x64_sigaction_t *)R_RSI, (x64_sigaction_t *)R_RDX/*, (size_t)R_R10*/);
|
||||
break;
|
||||
#ifndef __NR_access
|
||||
case 21: // sys_access
|
||||
R_EAX = (uint32_t)access((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
R_EAX = (uint32_t)pipe((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
case 23: // sys_select
|
||||
R_EAX = (uint32_t)select(R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8);
|
||||
break;
|
||||
#endif
|
||||
case 25: // sys_mremap
|
||||
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
|
||||
break;
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
R_RAX = fork();
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
size_t count = R_RDX;
|
||||
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
|
||||
ssize_t ret = syscall(__NR_getdents64, R_EDI, d64, count);
|
||||
ret = DirentFromDirent64((void*)R_RSI, d64, ret);
|
||||
R_RAX = (uint64_t)ret;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
R_EAX = (uint32_t)mkdir((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
R_EAX = (uint32_t)unlink((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
case 89: // sys_readlink
|
||||
R_RAX = (ssize_t)my_readlink(emu,(void*)R_RDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
break;
|
||||
case 131: // sys_sigaltstack
|
||||
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
case 158: // sys_arch_prctl
|
||||
R_EAX = (uint32_t)my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 201: // sys_time
|
||||
R_RAX = (uintptr_t)time((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
R_EAX = (int)syscall(__NR_inotify_init1, 0);
|
||||
@@ -223,7 +358,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
{
|
||||
uint32_t s = R_EDI;;
|
||||
printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
printf_dump(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
for (int i=0; i<cnt; i++) {
|
||||
@@ -253,6 +388,8 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
return my_open(emu, (char*)R_RSI, of_convert(R_EDX), R_ECX);
|
||||
case 3: // sys_close
|
||||
return (uint32_t)close(R_ESI);
|
||||
case 4: // sys_stat
|
||||
return (uint32_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
|
||||
case 9: // sys_mmap
|
||||
return (uintptr_t)my_mmap64(emu, (void*)R_RSI, R_RDX, (int)R_RCX, (int)R_R8d, (int)R_R9, i64(0));
|
||||
case 10: // sys_mprotect
|
||||
@@ -261,16 +398,52 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
return (uint32_t)my_munmap(emu, (void*)R_RSI, R_RDX);
|
||||
case 13: // sys_rt_sigaction
|
||||
return (uint32_t)my_sigaction(emu, (int)R_ESI, (const x64_sigaction_t *)R_RDX, (x64_sigaction_t *)R_RCX/*, (size_t)R_R8*/);
|
||||
#ifndef __NR_access
|
||||
case 21: // sys_access
|
||||
return (uint32_t)access((void*)R_RSI, R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
return (uint32_t)pipe((void*)R_RSI);
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
case 23: // sys_select
|
||||
return (uint32_t)select(R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
#endif
|
||||
case 25: // sys_mremap
|
||||
return (uintptr_t)my_mremap(emu, (void*)R_RSI, R_RDX, R_RCX, R_R8d, (void*)R_R9);
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
return fork();
|
||||
#endif
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
size_t count = R_RCX;
|
||||
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
|
||||
ssize_t ret = syscall(__NR_getdents64, R_ESI, d64, count);
|
||||
ret = DirentFromDirent64((void*)R_RDX, d64, ret);
|
||||
return (uint64_t)ret;
|
||||
}
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
return (uint32_t)mkdir((void*)R_RSI, R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
return (uint32_t)unlink((void*)R_RSI);
|
||||
#endif
|
||||
case 89: // sys_readlink
|
||||
return (uintptr_t)my_readlink(emu,(void*)R_RSI, (void*)R_RDX, (size_t)R_RCX);
|
||||
case 131: // sys_sigaltstack
|
||||
return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
|
||||
case 158: // sys_arch_prctl
|
||||
return (uint32_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX);
|
||||
#ifndef __NR_time
|
||||
case 201: // sys_time
|
||||
return (uintptr_t)time((void*)R_RSI);
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
return (int)syscall(__NR_inotify_init1, 0);
|
||||
|
||||
+59
-8
@@ -8,6 +8,7 @@
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64tls.h"
|
||||
#include "elfloader.h"
|
||||
|
||||
@@ -27,6 +28,7 @@ typedef struct thread_area_s
|
||||
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once3 = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void thread_key_alloc0() {
|
||||
pthread_key_create(&my_context->segtls[0].key, NULL);
|
||||
@@ -37,6 +39,9 @@ static void thread_key_alloc1() {
|
||||
static void thread_key_alloc2() {
|
||||
pthread_key_create(&my_context->segtls[2].key, NULL);
|
||||
}
|
||||
static void thread_key_alloc3() {
|
||||
pthread_key_create(&my_context->segtls[3].key, NULL);
|
||||
}
|
||||
|
||||
uint32_t my_set_thread_area(thread_area_t* td)
|
||||
{
|
||||
@@ -123,12 +128,57 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
|
||||
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
|
||||
*/
|
||||
|
||||
ResetSegmentsCache(thread_get_emu());
|
||||
ResetSegmentsCache(emu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define POS_TLS 0x50
|
||||
int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
{
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_GET_GS 0x1004
|
||||
switch(code) {
|
||||
case ARCH_GET_GS:
|
||||
*(void**)addr = GetSegmentBase(emu->segs[_GS]);
|
||||
return 0;
|
||||
case ARCH_SET_GS:
|
||||
if(emu->segs[_GS]!=(0xa<<3)) {
|
||||
pthread_once(&thread_key_once3, thread_key_alloc3);
|
||||
emu->segs[_GS] = 0xa<<3;
|
||||
if(!default_gs)
|
||||
default_gs = 0xa<<3;
|
||||
}
|
||||
my_context->segtls[3].base = (uintptr_t)addr;
|
||||
my_context->segtls[3].limit = 0;
|
||||
my_context->segtls[3].present = 1;
|
||||
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
|
||||
return 0;
|
||||
}
|
||||
// other are unsupported
|
||||
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define POS_TLS 0x200
|
||||
/*
|
||||
tls record should looks like:
|
||||
void* tcb 0x00
|
||||
void* dtv 0x08
|
||||
void* self 0x10
|
||||
int multiple 0x18
|
||||
int gscope 0x1c
|
||||
void* sysinfo 0x20
|
||||
uintptr_t stack_guard 0x28
|
||||
uitnptr_t pointer_guard 0x30
|
||||
uint64_t vgetcpu[2] 0x38
|
||||
uint32_t features 0x48
|
||||
int unused 0x4c
|
||||
void* private[4] 0x50
|
||||
void* private_ss 0x70
|
||||
uintptr_t ssp_base 0x78
|
||||
.... padding .... 0x200?
|
||||
*/
|
||||
|
||||
static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
{
|
||||
@@ -142,20 +192,21 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
pthread_setspecific(context->tlskey, data);
|
||||
// copy canary...
|
||||
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, sizeof(void*)); // put canary in place
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x28), context->canary, sizeof(void*)); // put canary in place
|
||||
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, sizeof(void*));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &tlsptr, sizeof(void*)); // set tcb and self same address
|
||||
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
|
||||
memcpy((void*)(tlsptr+sizeof(void*)), &dtp, sizeof(void*));
|
||||
if(dtsize) {
|
||||
for (size_t i=0; i<context->elfsize; ++i) {
|
||||
for (int i=0; i<context->elfsize; ++i) {
|
||||
// set pointer
|
||||
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16), &dtp, sizeof(void*));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8), &i, sizeof(void*)); // index
|
||||
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16) = dtp;
|
||||
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8) = i; // index
|
||||
}
|
||||
}
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, sizeof(void*)); // address of vsyscall
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x20), &context->vsyscall, sizeof(void*)); // address of vsyscall
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -203,7 +254,7 @@ void* GetSegmentBase(uint32_t desc)
|
||||
if(base==0x6)
|
||||
return GetSeg33Base();
|
||||
|
||||
if(base>6 && base<10 && my_context->segtls[base-7].present) {
|
||||
if(base>6 && base<11 && my_context->segtls[base-7].present) {
|
||||
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
#include "x87emu_private.h"
|
||||
//#include "x64run_private.h"
|
||||
|
||||
void fpu_do_free(x64emu_t* emu, int i)
|
||||
{
|
||||
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
|
||||
// check if all empty
|
||||
for(int j=0; j<8; ++j)
|
||||
if(emu->p_regs[j].tag != 0b11)
|
||||
return;
|
||||
emu->fpu_stack = 0;
|
||||
}
|
||||
|
||||
void reset_fpu(x64emu_t* emu)
|
||||
{
|
||||
memset(emu->mmx87, 0, sizeof(emu->mmx87));
|
||||
@@ -196,6 +206,21 @@ double FromLD(void* ld)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef HAVE_LD80BITS
|
||||
long double LD2localLD(void* ld)
|
||||
{
|
||||
// local implementation may not be try Quad precision, but double-double precision, so simple way to keep the 80bits precision in the conversion
|
||||
double ret;
|
||||
LD2D(ld, &ret);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
long double LD2localLD(void* ld)
|
||||
{
|
||||
return *(long double*)ld;
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_loadenv(x64emu_t* emu, char* p, int b16)
|
||||
{
|
||||
emu->cw = *(uint16_t*)p;
|
||||
|
||||
@@ -14,10 +14,6 @@ typedef struct x64emu_s x64emu_t;
|
||||
#define LN2 0.69314718055994531
|
||||
#define LG2 0.3010299956639812
|
||||
|
||||
//void Run66D9(x64emu_t *emu);
|
||||
//void Run66DD(x64emu_t *emu);
|
||||
//void RunDF(x64emu_t *emu);
|
||||
|
||||
#define ST0 emu->mmx87[emu->top]
|
||||
#define ST1 emu->mmx87[(emu->top+1)&7]
|
||||
#define ST(a) emu->mmx87[(emu->top+(a))&7]
|
||||
@@ -54,15 +50,7 @@ static inline void fpu_do_pop(x64emu_t* emu)
|
||||
emu->top = (emu->top+1)&7;
|
||||
}
|
||||
|
||||
static inline void fpu_do_free(x64emu_t* emu, int i)
|
||||
{
|
||||
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
|
||||
// check if all empty
|
||||
for(int i=0; i<8; ++i)
|
||||
if(emu->p_regs[i].tag != 0b11)
|
||||
return;
|
||||
emu->fpu_stack = 0;
|
||||
}
|
||||
void fpu_do_free(x64emu_t* emu, int i);
|
||||
|
||||
void reset_fpu(x64emu_t* emu);
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ int init_auxval(int argc, const char **argv, const char **env);
|
||||
#endif
|
||||
|
||||
unsigned long real_getauxval(unsigned long type);
|
||||
//unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
|
||||
unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
|
||||
|
||||
#endif //__AUXVAL_H__
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include "pathcoll.h"
|
||||
#include "dictionnary.h"
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -82,8 +83,8 @@ typedef struct box64context_s {
|
||||
char* fullpath;
|
||||
char* box64path; // path of current box64 executable
|
||||
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
uint64_t stacksz;
|
||||
size_t stackalign;
|
||||
void* stack; // alocated stack
|
||||
|
||||
elfheader_t **elfs; // elf headers and memory
|
||||
@@ -97,6 +98,7 @@ typedef struct box64context_s {
|
||||
|
||||
lib_t *maplib; // lib and symbols handling
|
||||
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
|
||||
dic_t *versym; // dictionnary of versionned symbols
|
||||
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
@@ -144,6 +146,7 @@ typedef struct box64context_s {
|
||||
library_t *asound;
|
||||
library_t *pulse;
|
||||
library_t *d3dadapter9;
|
||||
library_t *libglu;
|
||||
|
||||
int deferedInit;
|
||||
elfheader_t **deferedInitList;
|
||||
@@ -152,8 +155,8 @@ typedef struct box64context_s {
|
||||
|
||||
pthread_key_t tlskey; // then tls key to have actual tlsdata
|
||||
void* tlsdata; // the initial global tlsdata
|
||||
int32_t tlssize; // wanted size of tlsdata
|
||||
base_segment_t segtls[3]; // only handling 0/1/2 descriptors
|
||||
int64_t tlssize; // wanted size of tlsdata
|
||||
base_segment_t segtls[4]; // only handling 0/1/2 descriptors (3 is internal use)
|
||||
|
||||
uintptr_t *auxval_start;
|
||||
|
||||
|
||||
+11
-11
@@ -20,11 +20,11 @@ void customFree(void* p);
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size);
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy);
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx);
|
||||
void addJumpTableIfDefault64(void* addr, void* jmp);
|
||||
@@ -38,14 +38,14 @@ uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
#define PROT_ALLOC 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, uintptr_t size);
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void protectDBnolock(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size);
|
||||
void lockDB();
|
||||
void unlockDB();
|
||||
#endif
|
||||
@@ -60,4 +60,4 @@ void relockCustommemMutex(int locks);
|
||||
void init_custommem_helper(box64context_t* ctx);
|
||||
void fini_custommem_helper(box64context_t* ctx);
|
||||
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
+5
-2
@@ -4,6 +4,7 @@
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
extern int box64_log; // log level
|
||||
extern int box64_dump; // dump elf or not
|
||||
extern int box64_dynarec_log;
|
||||
extern int box64_dynarec;
|
||||
extern int box64_pagesize;
|
||||
@@ -11,7 +12,6 @@ extern int box64_pagesize;
|
||||
extern int box64_dynarec_dump;
|
||||
extern int box64_dynarec_trace;
|
||||
extern int box64_dynarec_forced;
|
||||
extern int box64_dynarec_largest;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
@@ -34,12 +34,15 @@ extern int box64_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
#define LOG_NONE 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
#define LOG_DUMP 3
|
||||
#define LOG_NEVER 3
|
||||
#define LOG_VERBOSE 3
|
||||
|
||||
extern FILE* ftrace;
|
||||
|
||||
#define printf_log(L, ...) do {if(L<=box64_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define printf_dump(L, ...) do {if(box64_dump || (L<=box64_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if(L<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#ifndef __DICTIONNARY_H_
|
||||
#define __DICTIONNARY_H_
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void dic_t;
|
||||
|
||||
dic_t *NewDictionnary();
|
||||
void FreeDictionnary(dic_t **dic);
|
||||
|
||||
const char* AddDictionnary(dic_t* dic, const char* s);
|
||||
int ExistDictionnary(dic_t* dic, const char* s);
|
||||
|
||||
#endif //__DICTIONNARY_H_
|
||||
@@ -11,7 +11,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
//return 1 if Dynareblock is empty
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef struct elfheader_s elfheader_t;
|
||||
const char* DumpSection(Elf64_Shdr *s, char* SST);
|
||||
const char* DumpDynamic(Elf64_Dyn *s);
|
||||
const char* DumpPHEntry(Elf64_Phdr *e);
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym);
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version);
|
||||
const char* DumpRelType(int t);
|
||||
const char* SymName(elfheader_t *h, Elf64_Sym* sym);
|
||||
const char* IdxSymName(elfheader_t *h, int sym);
|
||||
|
||||
@@ -26,7 +26,7 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
|
||||
int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
|
||||
int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
|
||||
void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
|
||||
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
|
||||
uintptr_t GetLastByte(elfheader_t* h);
|
||||
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
|
||||
@@ -41,7 +41,7 @@ void* GetElfDelta(elfheader_t* h);
|
||||
uint32_t GetBaseSize(elfheader_t* h);
|
||||
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
|
||||
elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
|
||||
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
|
||||
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint64_t* sz);
|
||||
int32_t GetTLSBase(elfheader_t* h);
|
||||
uint32_t GetTLSSize(elfheader_t* h);
|
||||
void* GetTLSPointer(box64context_t* context, elfheader_t* h);
|
||||
@@ -55,5 +55,9 @@ void CreateMemorymapFile(box64context_t* context, int fd);
|
||||
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version);
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index);
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
|
||||
#endif //__ELF_LOADER_H_
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#ifndef _GLOBAL_SYMBOLS_H_
|
||||
#define _GLOBAL_SYMBOLS_H_
|
||||
|
||||
//GTK stuff
|
||||
//void my_checkGlobalGdkDisplay();
|
||||
//void my_setGlobalGThreadsInit();
|
||||
|
||||
//void** my_GetGTKDisplay();
|
||||
//void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
|
||||
|
||||
// NCurse / TInfo
|
||||
void my_checkGlobalTInfo();
|
||||
|
||||
// getopt
|
||||
void my_checkGlobalOpt();
|
||||
|
||||
#endif //_GLOBAL_SYMBOLS_H_
|
||||
+11
-17
@@ -24,26 +24,20 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name);
|
||||
library_t* GetLibInternal(const char* name);
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self);
|
||||
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
|
||||
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name);
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name);
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername);
|
||||
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // replace if already there
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name);
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // don't add if already there
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz);
|
||||
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base);
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base);
|
||||
|
||||
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
|
||||
const char* GetNameOffset(lib_t *maplib, void* offs);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __LIBRARY_H_
|
||||
#define __LIBRARY_H_
|
||||
#include <stdint.h>
|
||||
#include "symbols.h"
|
||||
|
||||
typedef struct library_s library_t;
|
||||
typedef struct lib_s lib_t;
|
||||
@@ -18,9 +19,9 @@ void Free1Library(library_t **lib, x64emu_t* emu);
|
||||
|
||||
char* GetNameLib(library_t *lib);
|
||||
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
|
||||
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
|
||||
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
void fillGLProcWrapper(box64context_t* context);
|
||||
void freeGLProcWrapper(box64context_t* context);
|
||||
void fillALProcWrapper(box64context_t* context);
|
||||
|
||||
@@ -114,3 +114,9 @@ void UnalignStat64(const void* source, void* dest);
|
||||
// defined in wrapperlibc.c
|
||||
int of_convert(int); // x86->arm
|
||||
int of_unconvert(int); // arm->x86
|
||||
|
||||
void UnalignEpollEvent(void* dest, void* source, int nbr); // Arm -> x86
|
||||
void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm
|
||||
|
||||
void UnalignSemidDs(void *dest, const void* source);
|
||||
void AlignSemidDs(void *dest, const void* source);
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef __SYMBOLS_PRIVATE_H_
|
||||
#define __SYMBOLS_PRIVATE_H_
|
||||
#include <stdint.h>
|
||||
|
||||
#include "custommem.h"
|
||||
#include "khash.h"
|
||||
|
||||
typedef struct versymbols_s versymbols_t;
|
||||
|
||||
KHASH_MAP_DECLARE_STR(mapsymbols, versymbols_t)
|
||||
|
||||
kh_mapsymbols_t* NewMapSymbols();
|
||||
void FreeMapSymbols(kh_mapsymbols_t** map);
|
||||
|
||||
// replace if already there
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local);
|
||||
// don't add if already there
|
||||
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local);
|
||||
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
|
||||
|
||||
#endif //__SYMBOLS_PRIVATE_H_
|
||||
@@ -20,7 +20,7 @@ void fini_pthread_helper(box64context_t* context);
|
||||
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
|
||||
void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet);
|
||||
|
||||
//check if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
|
||||
int checkMutex(void* m);
|
||||
//check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
|
||||
int checkUnlockMutex(void* m);
|
||||
|
||||
#endif //_THREADS_H_
|
||||
@@ -7,7 +7,7 @@ typedef struct box64context_s box64context_t;
|
||||
|
||||
typedef int (*wrappedlib_init_t)(library_t * lib, box64context_t* box64); // 0 = success
|
||||
typedef void (*wrappedlib_fini_t)(library_t * lib);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local);
|
||||
|
||||
typedef struct wrappedlib_s {
|
||||
const char* name;
|
||||
@@ -15,7 +15,6 @@ typedef struct wrappedlib_s {
|
||||
wrappedlib_fini_t fini;
|
||||
wrappedlib_get_t get;
|
||||
wrappedlib_get_t getnoweak;
|
||||
wrappedlib_get_t getlocal;
|
||||
} wrappedlib_t;
|
||||
|
||||
#endif //__WRAPPEDLIBS_H__
|
||||
#endif //__WRAPPEDLIBS_H__
|
||||
@@ -55,6 +55,7 @@ void UnimpOpcode(x64emu_t* emu);
|
||||
uint64_t ReadTSC(x64emu_t* emu);
|
||||
|
||||
double FromLD(void* ld); // long double (80bits pointer) -> double
|
||||
long double LD2localLD(void* ld); // long double (80bits pointer) -> long double (80 or 128bits)
|
||||
void LD2D(void* ld, void* d); // long double (80bits) -> double (64bits)
|
||||
void D2LD(void* d, void* ld); // double (64bits) -> long double (64bits)
|
||||
|
||||
|
||||
@@ -10,4 +10,6 @@ void* fillTLSData(box64context_t *context);
|
||||
void* resizeTLSData(box64context_t *context, void* oldptr);
|
||||
void* GetSegmentBase(uint32_t desc);
|
||||
|
||||
int my_arch_prctl(x64emu_t *emu, int code, void* addr);
|
||||
|
||||
#endif //__X64_TLS_H__
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "dictionnary.h"
|
||||
#include "custommem.h"
|
||||
#include "khash.h"
|
||||
|
||||
KHASH_SET_INIT_STR(dic);
|
||||
|
||||
dic_t *NewDictionnary()
|
||||
{
|
||||
dic_t *dic = kh_init(dic);
|
||||
return dic;
|
||||
}
|
||||
|
||||
void FreeDictionnary(dic_t **d)
|
||||
{
|
||||
if(!d || !*d)
|
||||
return;
|
||||
kh_dic_t* dic = (kh_dic_t*)*d;
|
||||
const char* k;
|
||||
kh_foreach_key(dic, k, free((void*)k));
|
||||
kh_destroy(dic, dic);
|
||||
*d = NULL;
|
||||
}
|
||||
|
||||
const char* AddDictionnary(dic_t* d, const char* s)
|
||||
{
|
||||
kh_dic_t* dic = (kh_dic_t*)d;
|
||||
khint_t k = kh_get(dic, dic, s);
|
||||
if(k!=kh_end(dic))
|
||||
return kh_key(dic, k);
|
||||
char* n = strdup(s);
|
||||
int ret;
|
||||
k = kh_put(dic, dic, n, &ret);
|
||||
return n;
|
||||
}
|
||||
|
||||
int ExistDictionnary(dic_t* d, const char* s)
|
||||
{
|
||||
kh_dic_t* dic = (kh_dic_t*)d;
|
||||
khint_t k = kh_get(dic, dic, s);
|
||||
if(k!=kh_end(dic))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "wrappedlibs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "wrapper.h"
|
||||
#include "bridge.h"
|
||||
#include "callback.h"
|
||||
#include "box64context.h"
|
||||
#include "librarian.h"
|
||||
#include "library.h"
|
||||
|
||||
// workaround for Globals symbols
|
||||
|
||||
#define GLOB(A) \
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL)) { \
|
||||
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <= %p\n", (void*)globoffs, &A); \
|
||||
memcpy((void*)globoffs, &A, sizeof(A)); \
|
||||
}
|
||||
|
||||
|
||||
// *********** GTK *****************
|
||||
#if 0
|
||||
EXPORT void* gdk_display = NULL; // in case it's used...
|
||||
|
||||
void my_checkGlobalGdkDisplay()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(gdk_display)
|
||||
}
|
||||
|
||||
void my_setGlobalGThreadsInit()
|
||||
{
|
||||
int val = 1;
|
||||
uintptr_t globoffs, globend;
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
|
||||
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
|
||||
memcpy((void*)globoffs, &val, sizeof(val));
|
||||
}
|
||||
}
|
||||
|
||||
char* getGDKX11LibName();
|
||||
void** my_GetGTKDisplay()
|
||||
{
|
||||
if(gdk_display)
|
||||
return &gdk_display;
|
||||
|
||||
char* name = getGDKX11LibName();
|
||||
library_t * lib = GetLibInternal(name?name:"libgtk-1.2.so.0");
|
||||
if(!lib) return &gdk_display; // mmm, that will crash later probably
|
||||
void* s = dlsym(GetHandle(lib), "gdk_display");
|
||||
gdk_display = *(void**)s;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
// **************** NCurses ****************
|
||||
EXPORT int COLS;
|
||||
EXPORT int LINES;
|
||||
EXPORT int TABSIZE;
|
||||
EXPORT void* curscr;
|
||||
EXPORT void* newscr;
|
||||
EXPORT void* stdscr;
|
||||
EXPORT void* acs_map[128];
|
||||
EXPORT void* UP;
|
||||
EXPORT void* BC;
|
||||
EXPORT uint8_t PC;
|
||||
EXPORT uint16_t ospeed;
|
||||
EXPORT void* ttytype;
|
||||
|
||||
void my_checkGlobalTInfo()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(COLS)
|
||||
GLOB(LINES)
|
||||
GLOB(TABSIZE)
|
||||
GLOB(curscr)
|
||||
GLOB(newscr)
|
||||
GLOB(stdscr)
|
||||
GLOB(acs_map)
|
||||
GLOB(UP)
|
||||
GLOB(BC)
|
||||
GLOB(PC)
|
||||
GLOB(ospeed)
|
||||
GLOB(ttytype)
|
||||
}
|
||||
|
||||
// **************** getopts ****************
|
||||
EXPORT char *optarg;
|
||||
EXPORT int optind, opterr, optopt;
|
||||
|
||||
void my_checkGlobalOpt()
|
||||
{
|
||||
uintptr_t globoffs, globend;
|
||||
GLOB(optarg);
|
||||
GLOB(optind);
|
||||
GLOB(opterr);
|
||||
GLOB(optopt);
|
||||
}
|
||||
+158
-156
@@ -14,18 +14,17 @@
|
||||
|
||||
#include "bridge.h"
|
||||
|
||||
KHASH_MAP_IMPL_STR(mapsymbols, onesymbol_t);
|
||||
KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
|
||||
|
||||
lib_t *NewLibrarian(box64context_t* context, int ownlibs)
|
||||
{
|
||||
lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t));
|
||||
|
||||
maplib->mapsymbols = kh_init(mapsymbols);
|
||||
maplib->weaksymbols = kh_init(mapsymbols);
|
||||
maplib->localsymbols = kh_init(mapsymbols);
|
||||
maplib->mapsymbols = NewMapSymbols();
|
||||
maplib->weaksymbols = NewMapSymbols();
|
||||
maplib->localsymbols = NewMapSymbols();
|
||||
maplib->mapoffsets = kh_init(mapoffsets);
|
||||
maplib->globaldata = kh_init(mapsymbols);
|
||||
maplib->globaldata = NewMapSymbols();
|
||||
maplib->bridge = NewBridge();
|
||||
|
||||
maplib->context = context;
|
||||
@@ -34,11 +33,12 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
|
||||
|
||||
return maplib;
|
||||
}
|
||||
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed) {
|
||||
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed, library_t* owner) {
|
||||
if (freed[idx]) return; // Already freed
|
||||
|
||||
freed[idx] = 1; // Avoid infinite loops
|
||||
library_t *lib = maplib->libraries[idx];
|
||||
if(lib==owner) return; // don't free owner of maplib
|
||||
printf_log(LOG_DEBUG, "Free %s\n", lib->name);
|
||||
for (int i = lib->depended.size - 1; i >= 0; --i) {
|
||||
int j;
|
||||
@@ -53,15 +53,15 @@ static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *free
|
||||
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->depended.libs[i]->name);
|
||||
continue;
|
||||
}
|
||||
freeLibraryRecurse(maplib, emu, j, freed);
|
||||
freeLibraryRecurse(maplib, emu, j, freed, owner);
|
||||
if (freed[idx] != 1) {
|
||||
printf_log(LOG_DEBUG, "Library cleared (cyclic dependancy break)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
library_t *oldptr = maplib->libraries[idx];
|
||||
Free1Library(&maplib->libraries[idx], emu);
|
||||
maplib->libraries[idx] = oldptr; // Temporarily save the old address
|
||||
library_t *ptr = maplib->libraries[idx];
|
||||
if(maplib->ownlibs)
|
||||
Free1Library(&ptr, emu);
|
||||
freed[idx] = 2;
|
||||
}
|
||||
void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
|
||||
@@ -69,43 +69,37 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
|
||||
if(!maplib || !*maplib)
|
||||
return;
|
||||
|
||||
library_t* owner = (*maplib)->owner;
|
||||
(*maplib)->owner = NULL; // to avoid recursive free
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
|
||||
char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
|
||||
if (!freed) {
|
||||
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i)
|
||||
if((*maplib)->libraries[i]!=owner) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
} else {
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
freeLibraryRecurse(*maplib, emu, i, freed);
|
||||
}
|
||||
for (int i=0; i<(*maplib)->libsz; ++i) {
|
||||
(*maplib)->libraries[i] = NULL;
|
||||
freeLibraryRecurse(*maplib, emu, i, freed, owner);
|
||||
}
|
||||
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
|
||||
(*maplib)->libsz = 0;
|
||||
free(freed);
|
||||
}
|
||||
}
|
||||
free((*maplib)->libraries);
|
||||
(*maplib)->libraries = NULL;
|
||||
|
||||
if((*maplib)->mapsymbols) {
|
||||
kh_destroy(mapsymbols, (*maplib)->mapsymbols);
|
||||
}
|
||||
if((*maplib)->weaksymbols) {
|
||||
kh_destroy(mapsymbols, (*maplib)->weaksymbols);
|
||||
}
|
||||
if((*maplib)->localsymbols) {
|
||||
kh_destroy(mapsymbols, (*maplib)->localsymbols);
|
||||
}
|
||||
FreeMapSymbols(&(*maplib)->mapsymbols);
|
||||
FreeMapSymbols(&(*maplib)->weaksymbols);
|
||||
FreeMapSymbols(&(*maplib)->localsymbols);
|
||||
if((*maplib)->mapoffsets) {
|
||||
kh_destroy(mapoffsets, (*maplib)->mapoffsets);
|
||||
}
|
||||
if((*maplib)->globaldata) {
|
||||
kh_destroy(mapsymbols, (*maplib)->globaldata);
|
||||
}
|
||||
FreeMapSymbols(&(*maplib)->globaldata);
|
||||
(*maplib)->libsz = (*maplib)->libcap = 0;
|
||||
|
||||
if((*maplib)->bridge)
|
||||
@@ -164,6 +158,8 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib)
|
||||
|
||||
void MapLibAddLib(lib_t* maplib, library_t* lib)
|
||||
{
|
||||
if(libraryInMapLib(maplib, lib))
|
||||
return;
|
||||
if (maplib->libsz == maplib->libcap) {
|
||||
maplib->libcap += 8;
|
||||
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
|
||||
@@ -178,14 +174,13 @@ void MapLibAddMapLib(lib_t* dest, lib_t* src)
|
||||
return;
|
||||
for(int i=0; i<src->libsz; ++i) {
|
||||
library_t* lib = src->libraries[i];
|
||||
if(!lib) continue;
|
||||
if(!lib || libraryInMapLib(dest, lib)) continue;
|
||||
MapLibAddLib(dest, lib);
|
||||
if(lib->maplib && src!=lib->maplib) { //TODO: find why is src!=lib->maplib needed
|
||||
MapLibAddMapLib(dest, lib->maplib);
|
||||
free(lib->maplib);
|
||||
lib->maplib = NULL;
|
||||
}
|
||||
if(!libraryInMapLib(dest, lib))
|
||||
MapLibAddLib(dest, lib);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +197,24 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib)
|
||||
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx));
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
|
||||
static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
|
||||
{
|
||||
if(!src)
|
||||
return;
|
||||
//library_t *owner = src->owner;
|
||||
for(int i=0; i<src->libsz; ++i) {
|
||||
library_t* lib = src->libraries[i];
|
||||
if(!lib || !libraryInMapLib(dest, lib)) continue;
|
||||
MapLibRemoveLib(dest, lib);
|
||||
if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) {
|
||||
MapLibRemoveMapLib(dest, lib->maplib);
|
||||
if(lib->maplib && src==my_context->local_maplib)
|
||||
lib->maplib = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
|
||||
// first check if lib is already loaded
|
||||
@@ -226,6 +237,8 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
}
|
||||
if(!libraryInMapLib(maplib, lib))
|
||||
MapLibAddLib(maplib, lib);
|
||||
if(maplib->ownlibs)
|
||||
MapLibRemoveMapLib(my_context->local_maplib, maplib);
|
||||
}
|
||||
} else {
|
||||
// promote lib from local to global...
|
||||
@@ -237,7 +250,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
}
|
||||
if(!libraryInMapLib(my_context->maplib, lib))
|
||||
MapLibAddLib(my_context->maplib, lib);
|
||||
MapLibRemoveLib(my_context->local_maplib, lib);
|
||||
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
|
||||
}
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
|
||||
@@ -267,33 +280,38 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
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");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, library_t* lib, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
|
||||
int mainelf = GetElfIndex(lib);
|
||||
|
||||
if(mainelf==-1) {
|
||||
// It's a native libs, just add wrapped symbols to global map
|
||||
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
|
||||
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// It's a native libs, nothing else to do
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// lets load dependancies before adding symbols and launch init sequence
|
||||
// load dependancies and launch init sequence
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// some special case, where dependancies may not be correct
|
||||
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libGL.so.1", box64, emu);
|
||||
const char* libs[] = {"libGL.so.1"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box64, emu);
|
||||
}
|
||||
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libSDL-1.2.so.0", box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libdl.so.2", box64, emu);
|
||||
}
|
||||
// add symbols
|
||||
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
|
||||
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
|
||||
return 1;
|
||||
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box64, emu);
|
||||
}
|
||||
|
||||
// finalize the lib
|
||||
@@ -308,6 +326,31 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!neededlibs) {
|
||||
neededlibs = alloca(sizeof(needed_libs_t));
|
||||
memset(neededlibs, 0, sizeof(needed_libs_t));
|
||||
}
|
||||
int idx = neededlibs->size;
|
||||
// Add libs and symbol
|
||||
for(int i=0; i<npath; ++i) {
|
||||
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading needed lib %s\n", paths[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
int idx_end = neededlibs->size;
|
||||
// add dependant libs and init them
|
||||
for (int i=idx; i<idx_end; ++i)
|
||||
if(AddNeededLib_init(maplib, neededlibs, deplib, local, neededlibs->libs[i], box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
|
||||
if(!allow_missing_libs) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
|
||||
@@ -323,44 +366,53 @@ library_t* GetLibInternal(const char* name)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name)
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start = 0, end = 0;
|
||||
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end))
|
||||
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername))
|
||||
return start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self)
|
||||
static int isLocal(elfheader_t* self, library_t* l)
|
||||
{
|
||||
if(GetElfIndex(l)==-1)
|
||||
return 1;
|
||||
if(my_context->elfs[GetElfIndex(l)]==self)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
{
|
||||
//excude self if defined
|
||||
if(maplib->context->elfs[0]!=self) {
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
// if self defined, give it another chance with self...
|
||||
if(self) {
|
||||
if(maplib->context->elfs[0]==self) {
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 1))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
@@ -368,48 +420,48 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
{
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins)
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
|
||||
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
|
||||
for(int i=0; i<my_context->neededlibs.size; ++i)
|
||||
if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search in global symbols
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// library from newer to older, weak only now
|
||||
for(int i=maplib->libsz-1; i>=0; --i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) // only weak symbol haven't been found yet
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
|
||||
if(*start)
|
||||
return 1;
|
||||
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) // only weak symbol haven't been found yet
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
|
||||
if(*start)
|
||||
return 1;
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
//void** my_GetGTKDisplay();
|
||||
//void** my_GetGthreadsGotInitialized();
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
{
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end)) {
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
|
||||
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
|
||||
uintptr_t start2, end2;
|
||||
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
|
||||
strcpy(buff, name);
|
||||
strcat(buff, "_END");
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2)) {
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
|
||||
if(end2>*end && start2==end2)
|
||||
*end = end2;
|
||||
}
|
||||
@@ -418,32 +470,32 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
return 1;
|
||||
}
|
||||
// some special case symbol, defined inside box64 itself
|
||||
// if(!strcmp(name, "gdk_display")) {
|
||||
// *start = (uintptr_t)my_GetGTKDisplay();
|
||||
// *end = *start+sizeof(void*);
|
||||
// printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
|
||||
// return 1;
|
||||
// }
|
||||
// if(!strcmp(name, "g_threads_got_initialized")) {
|
||||
// *start = (uintptr_t)my_GetGthreadsGotInitialized();
|
||||
// *end = *start+sizeof(int);
|
||||
// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
|
||||
// return 1;
|
||||
// }
|
||||
//if(!strcmp(name, "gdk_display")) {
|
||||
// *start = (uintptr_t)my_GetGTKDisplay();
|
||||
// *end = *start+sizeof(void*);
|
||||
// printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
|
||||
// return 1;
|
||||
//}
|
||||
//if(!strcmp(name, "g_threads_got_initialized")) {
|
||||
// *start = (uintptr_t)my_GetGthreadsGotInitialized();
|
||||
// *end = *start+sizeof(int);
|
||||
// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
|
||||
// return 1;
|
||||
//}
|
||||
// not found...
|
||||
return 0;
|
||||
}
|
||||
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
|
||||
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start = 0;
|
||||
uintptr_t end = 0;
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end, version, vername, 1))
|
||||
return maplib->context->elfs[0];
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end, version, vername, 1))
|
||||
return maplib->context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end)) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
@@ -456,26 +508,25 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
|
||||
{
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start=0;
|
||||
uintptr_t end=0;
|
||||
uintptr_t start, end;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i])==-1)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1))
|
||||
if(start || end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
@@ -483,10 +534,10 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
|
||||
|
||||
}
|
||||
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
|
||||
{
|
||||
if(maplib->context->elfs[0]==self || !self) {
|
||||
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
@@ -494,7 +545,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(self)
|
||||
@@ -504,16 +555,16 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
|
||||
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
|
||||
{
|
||||
if(maplib->context->elfs[0]==self) {
|
||||
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
} else {
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
}
|
||||
@@ -521,78 +572,28 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
|
||||
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
|
||||
{
|
||||
if(maplib->context->elfs[0]==self) {
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
} else {
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
kh_value(mapsymbols, k).offs = addr;
|
||||
kh_value(mapsymbols, k).sz = sz;
|
||||
}
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name)
|
||||
{
|
||||
khint_t k = kh_get(mapsymbols, mapsymbols, name);
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
return kh_val(mapsymbols, k).offs;
|
||||
}
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
if(ret==0)
|
||||
return; // Symbol already there, don't touch it
|
||||
kh_value(mapsymbols, k).offs = addr;
|
||||
kh_value(mapsymbols, k).sz = sz;
|
||||
}
|
||||
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
{
|
||||
khint_t k = kh_get(mapsymbols, mapsymbols, name);
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
*start = kh_val(mapsymbols, k).offs;
|
||||
*end = *start + kh_val(mapsymbols, k).sz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint32_t* sz)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
onesymbol_t *one;
|
||||
kh_foreach_value_ref(mapsymbols, one,
|
||||
if((one->offs >= addr) && (one->offs+one->sz<addr)) {
|
||||
*start = one->offs;
|
||||
*sz = one->sz;
|
||||
return kh_key(mapsymbols, __i);
|
||||
}
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base)
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base)
|
||||
{
|
||||
// first, search in self...
|
||||
const char* ret = NULL;
|
||||
uintptr_t offs = 0;
|
||||
uint32_t size = 0;
|
||||
uint64_t size = 0;
|
||||
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)p);
|
||||
if(h) {
|
||||
ret = FindNearestSymbolName(h, p, &offs, &size);
|
||||
@@ -609,6 +610,7 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
|
||||
return ret;
|
||||
}
|
||||
// TODO: find if cyclic references exists (should also fix MapLibAddMapLib)
|
||||
(void)maplib;
|
||||
/* for (int i = 0; i < maplib->libsz; ++i) {
|
||||
// if (maplib == maplib->libraries[i]->maplib) continue;
|
||||
const char *nameInLib = FindSymbolName(maplib->libraries[i]->maplib, p, start, sz, libname, base);
|
||||
|
||||
@@ -6,18 +6,10 @@
|
||||
#include "khash.h"
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
|
||||
typedef struct onesymbol_s {
|
||||
uintptr_t offs;
|
||||
uint32_t sz;
|
||||
// need to track type of symbol?
|
||||
// need to track origin?
|
||||
} onesymbol_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
|
||||
typedef char* cstr_t;
|
||||
|
||||
KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t)
|
||||
|
||||
KHASH_MAP_DECLARE_INT(mapoffsets, cstr_t);
|
||||
|
||||
typedef struct lib_s {
|
||||
@@ -30,6 +22,7 @@ typedef struct lib_s {
|
||||
int libsz;
|
||||
int libcap;
|
||||
int ownlibs;
|
||||
library_t *owner; // in case that maplib is owned by a lib
|
||||
|
||||
box64context_t* context;
|
||||
|
||||
|
||||
+95
-67
@@ -27,8 +27,8 @@
|
||||
// create the native lib list
|
||||
#define GO(P, N) int wrapped##N##_init(library_t* lib, box64context_t *box64); \
|
||||
void wrapped##N##_fini(library_t* lib);\
|
||||
int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz); \
|
||||
int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz);
|
||||
int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); \
|
||||
int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local);
|
||||
#include "library_list.h"
|
||||
#undef GO
|
||||
|
||||
@@ -41,14 +41,14 @@ wrappedlib_t wrappedlibs[] = {
|
||||
typedef struct bridged_s {
|
||||
char* name;
|
||||
uintptr_t start;
|
||||
uint32_t end;
|
||||
uintptr_t end;
|
||||
} bridged_t;
|
||||
|
||||
KHASH_MAP_INIT_STR(bridgemap, bridged_t)
|
||||
|
||||
KHASH_MAP_IMPL_STR(datamap, uint32_t)
|
||||
KHASH_MAP_IMPL_STR(symbolmap, wrapper_t)
|
||||
KHASH_MAP_IMPL_STR(symbol2map, symbol2_t)
|
||||
KHASH_MAP_IMPL_STR(datamap, uint64_t)
|
||||
|
||||
char* Path2Name(const char* path)
|
||||
{
|
||||
@@ -85,50 +85,51 @@ void EmuLib_Fini(library_t* lib)
|
||||
kh_destroy(mapsymbols, lib->priv.n.localsymbols);
|
||||
}
|
||||
|
||||
int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
|
||||
int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
khint_t k;
|
||||
// symbols...
|
||||
k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name);
|
||||
if(k!=kh_end(lib->priv.n.mapsymbols)) {
|
||||
*offs = kh_value(lib->priv.n.mapsymbols, k).offs;
|
||||
*sz = kh_value(lib->priv.n.mapsymbols, k).sz;
|
||||
uintptr_t start, end;
|
||||
if(GetSymbolStartEnd(lib->priv.n.mapsymbols, name, &start, &end, version, vername, local))
|
||||
{
|
||||
*offs = start;
|
||||
*sz = end-start;
|
||||
return 1;
|
||||
}
|
||||
// weak symbols...
|
||||
k = kh_get(mapsymbols, lib->priv.n.weaksymbols, name);
|
||||
if(k!=kh_end(lib->priv.n.weaksymbols)) {
|
||||
*offs = kh_value(lib->priv.n.weaksymbols, k).offs;
|
||||
*sz = kh_value(lib->priv.n.weaksymbols, k).sz;
|
||||
if(GetSymbolStartEnd(lib->priv.n.weaksymbols, name, &start, &end, version, vername, local))
|
||||
{
|
||||
*offs = start;
|
||||
*sz = end-start;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
|
||||
int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
khint_t k;
|
||||
k = kh_get(mapsymbols, lib->priv.n.mapsymbols, name);
|
||||
if(k!=kh_end(lib->priv.n.mapsymbols)) {
|
||||
*offs = kh_value(lib->priv.n.mapsymbols, k).offs;
|
||||
*sz = kh_value(lib->priv.n.mapsymbols, k).sz;
|
||||
uintptr_t start, end;
|
||||
if(GetSymbolStartEnd(lib->priv.n.mapsymbols, name, &start, &end, version, vername, local))
|
||||
{
|
||||
*offs = start;
|
||||
*sz = end-start;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
|
||||
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
khint_t k;
|
||||
k = kh_get(mapsymbols, lib->priv.n.localsymbols, name);
|
||||
if(k!=kh_end(lib->priv.n.localsymbols)) {
|
||||
*offs = kh_value(lib->priv.n.localsymbols, k).offs;
|
||||
*sz = kh_value(lib->priv.n.localsymbols, k).sz;
|
||||
uintptr_t start, end;
|
||||
if(GetSymbolStartEnd(lib->priv.n.localsymbols, name, &start, &end, version, vername, local))
|
||||
{
|
||||
*offs = start;
|
||||
*sz = end-start;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NativeLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz)
|
||||
int NativeLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -150,11 +151,9 @@ static void initNativeLib(library_t *lib, box64context_t* context) {
|
||||
lib->getlocal = NativeLib_GetLocal;
|
||||
lib->type = 0;
|
||||
// Call librarian to load all dependant elf
|
||||
for(int i=0; i<lib->priv.w.needed; ++i) {
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, lib->priv.w.neededlibs[i], context, thread_get_emu())) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[i]);
|
||||
return;
|
||||
}
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, thread_get_emu())) {
|
||||
printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -220,43 +219,55 @@ static void initEmulatedLib(const char* path, library_t *lib, box64context_t* co
|
||||
{
|
||||
char libname[MAX_PATH];
|
||||
strcpy(libname, path);
|
||||
int found = FileExist(libname, IS_FILE);
|
||||
if(!found && !strchr(path, '/'))
|
||||
int found = FileIsX64ELF(libname);
|
||||
if(found)
|
||||
if(loadEmulatedLib(libname, lib, context))
|
||||
return;
|
||||
if(!strchr(path, '/'))
|
||||
for(int i=0; i<context->box64_ld_lib.size; ++i)
|
||||
{
|
||||
strcpy(libname, context->box64_ld_lib.paths[i]);
|
||||
strcat(libname, path);
|
||||
if(FileExist(libname, IS_FILE))
|
||||
if(FileIsX64ELF(libname))
|
||||
if(loadEmulatedLib(libname, lib, context))
|
||||
return;
|
||||
}
|
||||
else
|
||||
loadEmulatedLib(libname, lib, context);
|
||||
}
|
||||
|
||||
extern char* libGL;
|
||||
library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
|
||||
library_t *lib = (library_t*)calloc(1, sizeof(library_t));
|
||||
lib->path = strdup(path);
|
||||
lib->name = Path2Name(path);
|
||||
if(libGL && !strcmp(path, libGL))
|
||||
lib->name = strdup("libGL.so.1");
|
||||
else
|
||||
lib->name = Path2Name(path);
|
||||
lib->nbdot = NbDot(lib->name);
|
||||
lib->context = context;
|
||||
lib->type = -1;
|
||||
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
if(box64_nopulse) {
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
Free1Library(&lib, NULL);
|
||||
free(lib->name);
|
||||
free(lib->path);
|
||||
free(lib);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(box64_novulkan) {
|
||||
if(strstr(lib->name, "libvulkan.so")==lib->name) {
|
||||
Free1Library(&lib, NULL);
|
||||
free(lib->name);
|
||||
free(lib->path);
|
||||
free(lib);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
int notwrapped = FindInCollection(lib->name, &context->box64_emulated_libs);
|
||||
// check if name is libSDL_sound-1.0.so.1 but with SDL2 loaded, then try emulated first...
|
||||
if(!notwrapped && !strcmp(lib->name, "libSDL_sound-1.0.so.1") && my_context->sdl2lib)
|
||||
notwrapped = 1;
|
||||
// And now, actually loading a library
|
||||
// look for native(wrapped) libs first
|
||||
if(!notwrapped)
|
||||
@@ -270,7 +281,9 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
// nothing loaded, so error...
|
||||
if(lib->type==-1)
|
||||
{
|
||||
Free1Library(&lib, NULL);
|
||||
free(lib->name);
|
||||
free(lib->path);
|
||||
free(lib);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -280,6 +293,8 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
}
|
||||
int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
lib->active = 1;
|
||||
if(lib->type==1) {
|
||||
elfheader_t *elf_header = lib->context->elfs[lib->priv.n.elf_index];
|
||||
@@ -305,12 +320,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_func) {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end)) {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
free(trace_func);
|
||||
trace_func = NULL;
|
||||
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end)) {
|
||||
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, -1, NULL, 0)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
|
||||
free(trace_func);
|
||||
@@ -320,11 +335,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
#endif
|
||||
RunElfInit(elf_header, emu);
|
||||
}
|
||||
if(box64_dynarec && strcmp(lib->name, "libfmod.so")==0) {
|
||||
if (GetGlobalSymbolStartEnd(lib->maplib?lib->maplib:my_context->maplib, "FSOUND_Mixer_FPU_Ramp", &fmod_smc_start, &fmod_smc_end)) {
|
||||
printf_log(LOG_INFO, "Detected libfmod with potential SMC part, applying workaround in Dynarec\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -448,22 +458,22 @@ int IsSameLib(library_t* lib, const char* path)
|
||||
free(name);
|
||||
return ret;
|
||||
}
|
||||
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
|
||||
{
|
||||
if(!name[0] || !lib->active)
|
||||
return 0;
|
||||
khint_t k;
|
||||
// check first if already in the map
|
||||
k = kh_get(bridgemap, lib->bridgemap, name);
|
||||
k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername));
|
||||
if(k!=kh_end(lib->bridgemap)) {
|
||||
*start = kh_value(lib->bridgemap, k).start;
|
||||
*end = kh_value(lib->bridgemap, k).end;
|
||||
return 1;
|
||||
}
|
||||
// get a new symbol
|
||||
if(lib->get(lib, name, start, end)) {
|
||||
if(lib->get(lib, name, start, end, version, vername, local)) {
|
||||
*end += *start; // lib->get(...) gives size, not end
|
||||
char* symbol = strdup(name);
|
||||
char* symbol = strdup(VersionnedName(name, version, vername));
|
||||
int ret;
|
||||
k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
|
||||
kh_value(lib->bridgemap, k).name = symbol;
|
||||
@@ -474,22 +484,22 @@ int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uin
|
||||
// nope
|
||||
return 0;
|
||||
}
|
||||
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
|
||||
{
|
||||
if(!name[0] || !lib->active)
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
if(lib->getnoweak(lib, name, start, end)) {
|
||||
if(lib->getnoweak(lib, name, start, end, version, vername, local)) {
|
||||
*end += *start; // lib->get(...) gives size, not end
|
||||
// check if already in the map
|
||||
k = kh_get(bridgemap, lib->bridgemap, name);
|
||||
k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername));
|
||||
if(k!=kh_end(lib->bridgemap)) {
|
||||
*start = kh_value(lib->bridgemap, k).start;
|
||||
*end = kh_value(lib->bridgemap, k).end;
|
||||
return 1;
|
||||
}
|
||||
char* symbol = strdup(name);
|
||||
char* symbol = strdup(VersionnedName(name, version, vername));
|
||||
int ret;
|
||||
k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
|
||||
kh_value(lib->bridgemap, k).name = symbol;
|
||||
@@ -500,22 +510,22 @@ int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
|
||||
// nope
|
||||
return 0;
|
||||
}
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end)
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
|
||||
{
|
||||
if(!name[0] || !lib->active)
|
||||
return 0;
|
||||
khint_t k;
|
||||
// check first if already in the map
|
||||
k = kh_get(bridgemap, lib->bridgemap, name);
|
||||
k = kh_get(bridgemap, lib->bridgemap, VersionnedName(name, version, vername));
|
||||
if(k!=kh_end(lib->bridgemap)) {
|
||||
*start = kh_value(lib->bridgemap, k).start;
|
||||
*end = kh_value(lib->bridgemap, k).end;
|
||||
return 1;
|
||||
}
|
||||
// get a new symbol
|
||||
if(lib->getlocal(lib, name, start, end)) {
|
||||
if(lib->getlocal(lib, name, start, end, version, vername, local)) {
|
||||
*end += *start; // lib->get(...) gives size, not end
|
||||
char* symbol = strdup(name);
|
||||
char* symbol = strdup(VersionnedName(name, version, vername));
|
||||
int ret;
|
||||
k = kh_put(bridgemap, lib->bridgemap, symbol, &ret);
|
||||
kh_value(lib->bridgemap, k).name = symbol;
|
||||
@@ -533,14 +543,10 @@ int GetElfIndex(library_t* lib)
|
||||
return lib->priv.n.elf_index;
|
||||
}
|
||||
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size)
|
||||
static int getSymbolInDataMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size)
|
||||
{
|
||||
if(!lib->active)
|
||||
return 0;
|
||||
khint_t k;
|
||||
void* symbol;
|
||||
// check in datamap
|
||||
k = kh_get(datamap, lib->datamap, name);
|
||||
khint_t k = kh_get(datamap, lib->datamap, name);
|
||||
if (k!=kh_end(lib->datamap)) {
|
||||
symbol = dlsym(lib->priv.w.lib, kh_key(lib->datamap, k));
|
||||
if(symbol) {
|
||||
@@ -581,8 +587,13 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size)
|
||||
{
|
||||
void* symbol;
|
||||
// check in mysymbolmap
|
||||
k = kh_get(symbolmap, lib->mysymbolmap, name);
|
||||
khint_t k = kh_get(symbolmap, lib->mysymbolmap, name);
|
||||
if (k!=kh_end(lib->mysymbolmap)) {
|
||||
char buff[200];
|
||||
if(lib->altmy)
|
||||
@@ -677,6 +688,23 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int version, const char* vername, int local)
|
||||
{
|
||||
if(!lib->active)
|
||||
return 0;
|
||||
// check in datamaps (but no version, it's not handled there)
|
||||
if(getSymbolInDataMaps(lib, name, noweak, addr, size))
|
||||
return 1;
|
||||
|
||||
if(getSymbolInSymbolMaps(lib, VersionnedName(name, version, vername), noweak, addr, size))
|
||||
return 1;
|
||||
|
||||
if(getSymbolInSymbolMaps(lib, name, noweak, addr, size))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNeededLibN(library_t* lib) {
|
||||
return lib->needed.size;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ typedef struct symbol2_s {
|
||||
|
||||
KHASH_MAP_DECLARE_STR(symbolmap, wrapper_t)
|
||||
KHASH_MAP_DECLARE_STR(symbol2map, symbol2_t)
|
||||
KHASH_MAP_DECLARE_STR(datamap, uint32_t)
|
||||
KHASH_MAP_DECLARE_STR(datamap, uint64_t)
|
||||
|
||||
|
||||
#ifndef MAX_PATH
|
||||
@@ -62,7 +62,7 @@ typedef struct library_s {
|
||||
union {
|
||||
wlib_t w;
|
||||
nlib_t n;
|
||||
} priv; // private lib data
|
||||
} priv; // private lib data
|
||||
box64context_t *context; // parent context
|
||||
kh_bridgemap_t *bridgemap;
|
||||
kh_symbolmap_t *symbolmap;
|
||||
@@ -93,10 +93,10 @@ typedef struct map_onesymbol2_s {
|
||||
} map_onesymbol2_t;
|
||||
typedef struct map_onedata_s {
|
||||
const char* name;
|
||||
uint32_t sz;
|
||||
uint32_t sz; // TODO: convert to size_t
|
||||
int weak;
|
||||
} map_onedata_t;
|
||||
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size); // Add bridges to functions
|
||||
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int version, const char* vername, int local); // Add bridges to functions
|
||||
|
||||
#endif //__LIBRARY_PRIVATE_H_
|
||||
@@ -0,0 +1,233 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64context.h"
|
||||
#include "symbols.h"
|
||||
#include "dictionnary.h"
|
||||
|
||||
typedef struct onesymbol_s {
|
||||
uintptr_t offs;
|
||||
uint32_t sz;
|
||||
// need to track type of symbol?
|
||||
// need to track origin?
|
||||
} onesymbol_t;
|
||||
|
||||
typedef struct versymbol_s {
|
||||
int version; // -1 = no-version, 0=local, 1=global, X=versionned
|
||||
const char* vername; // NULL or version name if version=X
|
||||
onesymbol_t sym;
|
||||
} versymbol_t;
|
||||
|
||||
typedef struct versymbols_s {
|
||||
int sz;
|
||||
int cap;
|
||||
versymbol_t *syms;
|
||||
} versymbols_t;
|
||||
|
||||
KHASH_MAP_IMPL_STR(mapsymbols, versymbols_t);
|
||||
|
||||
kh_mapsymbols_t* NewMapSymbols()
|
||||
{
|
||||
kh_mapsymbols_t* map = kh_init(mapsymbols);
|
||||
return map;
|
||||
}
|
||||
|
||||
void FreeMapSymbols(kh_mapsymbols_t** map)
|
||||
{
|
||||
if(!map || !(*map))
|
||||
return;
|
||||
versymbols_t *v;
|
||||
kh_foreach_value_ref(*map, v, free(v->syms););
|
||||
|
||||
kh_destroy(mapsymbols, *map);
|
||||
*map = NULL;
|
||||
}
|
||||
|
||||
// Exact same version (ver<2 or vername if ver>=2)
|
||||
static int SameVersion(versymbol_t* s, int ver, const char* vername)
|
||||
{
|
||||
if(ver<2)
|
||||
return (s->version == ver)?1:0;
|
||||
if(s->vername && !strcmp(s->vername, vername))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static versymbol_t* FindVersionLocal(versymbols_t* s)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==0)
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindNoVersion(versymbols_t* s)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==-1)
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindVersionGlobal(versymbols_t* s)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==1)
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindVersion(versymbols_t* s, const char* vername)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindFirstVersion(versymbols_t* s)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version>1)
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
|
||||
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, int local)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
versymbol_t* ret = NULL;
|
||||
if(ver==0) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
return ret;
|
||||
}
|
||||
if(ver==-1) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(!ret) ret = FindFirstVersion(s);
|
||||
return ret;
|
||||
}
|
||||
if(ver==1) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindFirstVersion(s);
|
||||
return ret;
|
||||
}
|
||||
ret = FindVersion(s, vername);
|
||||
if(local && !ret) FindVersionLocal(s);
|
||||
if(!ret) return FindVersionGlobal(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
|
||||
// now check if that version already exist, and update record and exit if yes
|
||||
for(int i=0; i<v->sz; ++i)
|
||||
if(SameVersion(&v->syms[i], ver, vername)) {
|
||||
v->syms[i].sym.offs = addr;
|
||||
v->syms[i].sym.sz = sz;
|
||||
return;
|
||||
}
|
||||
// add a new record
|
||||
if(v->sz == v->cap) {
|
||||
v->cap+=4;
|
||||
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
}
|
||||
int idx = v->sz++;
|
||||
v->syms[idx].version = ver;
|
||||
v->syms[idx].vername = vername;
|
||||
v->syms[idx].sym.offs = addr;
|
||||
v->syms[idx].sym.sz = sz;
|
||||
}
|
||||
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
return 0;
|
||||
khint_t k = kh_get(mapsymbols, mapsymbols, name);
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t * s = MatchVersion(v, ver, vername, local);
|
||||
if(s)
|
||||
return s->sym.offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
|
||||
// now check if that version already exist, and exit if yes
|
||||
for(int i=0; i<v->sz; ++i)
|
||||
if(SameVersion(&v->syms[i], ver, vername)) {
|
||||
return;
|
||||
}
|
||||
// add a new record
|
||||
if(v->sz == v->cap) {
|
||||
v->cap+=4;
|
||||
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
}
|
||||
int idx = v->sz++;
|
||||
v->syms[idx].version = ver;
|
||||
v->syms[idx].vername = vername;
|
||||
v->syms[idx].sym.offs = addr;
|
||||
v->syms[idx].sym.sz = sz;
|
||||
}
|
||||
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
return 0;
|
||||
khint_t k = kh_get(mapsymbols, mapsymbols, name);
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t* s = MatchVersion(v, ver, vername, local);
|
||||
if(s) {
|
||||
*start = s->sym.offs;
|
||||
*end = *start + s->sym.sz;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint32_t* sz, const char** vername)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
versymbols_t *s;
|
||||
kh_foreach_value_ref(mapsymbols, s,
|
||||
for(int i=0; i<s->sz; ++i)
|
||||
if((s->syms[i].sym.offs >= addr) && (s->syms[i].sym.offs+s->syms[i].sym.sz<addr)) {
|
||||
*start = s->syms[i].sym.offs;
|
||||
*sz = s->syms[i].sym.sz;
|
||||
if(vername)
|
||||
*vername = s->syms[i].vername;
|
||||
return kh_key(mapsymbols, __i);
|
||||
}
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
+26
-12
@@ -7,6 +7,7 @@ GO("libpthread.so.0", libpthread)
|
||||
GO("librt.so.1", librt)
|
||||
GO("libGL.so.1", libgl)
|
||||
GO("libGL.so", libgl)
|
||||
GO("libOpenGL.so.0", libgl)
|
||||
GO("libGLU.so.1", libglu)
|
||||
GO("libX11.so.6", libx11)
|
||||
GO("libasound.so.2", libasound)
|
||||
@@ -18,19 +19,24 @@ GO("libSDL2.so", sdl2)
|
||||
GO("libsdl2-2.0.so.0", sdl2)
|
||||
GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
|
||||
GO("libSDL2_image-2.0.so.0", sdl2image)
|
||||
GO("libSDL2_image.so", sdl2image)
|
||||
GO("libSDL2_net-2.0.so.0", sdl2net)
|
||||
GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
|
||||
GO("libSDL2_ttf.so", sdl2ttf)
|
||||
GO("libSDL-1.2.so.0", sdl1)
|
||||
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
|
||||
GO("libSDL_image-1.2.so.0", sdl1image)
|
||||
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
|
||||
GO("libSDL_net-1.2.so.0", sdl1net)
|
||||
GO("libSDL_sound-1.0.so.1", sdl1sound)
|
||||
GO("libSDL_ttf-2.0.so.0", sdl1ttf)
|
||||
GO("libsmpeg-0.4.so.0", smpeg)
|
||||
GO("libsmpeg2-2.0.so.0", smpeg2)
|
||||
GO("libvorbisfile.so.3", vorbisfile)
|
||||
GO("libvorbis.so.0", libvorbis)
|
||||
GO("libogg.so.0", libogg)
|
||||
GO("libFLAC.so.8", flac)
|
||||
//GO("libpng12.so.0", png12)
|
||||
//GO("libpng16.so.16", png16)
|
||||
GO("libpng16.so.16", png16)
|
||||
GO("libXxf86vm.so.1", libxxf86vm)
|
||||
GO("libXinerama.so.1", xinerama)
|
||||
GO("libXrandr.so.2", libxrandr)
|
||||
@@ -38,6 +44,7 @@ GO("libXext.so.6", libxext)
|
||||
GO("libXfixes.so.3", libxfixes)
|
||||
GO("libXcursor.so.1", libxcursor)
|
||||
GO("libXrender.so.1", libxrender)
|
||||
GO("libXft.so.2", libxft)
|
||||
GO("libXi.so.6", libxi)
|
||||
GO("libXss.so.1", libxss)
|
||||
GO("libXpm.so.4", libxpm)
|
||||
@@ -72,14 +79,17 @@ GO("libalure.so.1", alure)
|
||||
//GO("libturbojpeg.so.0", turbojpeg)
|
||||
GO("libcurl.so.4", curl)
|
||||
GO("libcurl-gnutls.so.4", curl)
|
||||
GO("libcurl.so.3", curl)
|
||||
GO("libudev.so.0", udev0)
|
||||
GO("libudev.so.1", udev1)
|
||||
GO("libdbus-1.so.3", dbus)
|
||||
//GO("libiconv.so.2", iconv)
|
||||
//GO("libdrm.so.2", libdrm)
|
||||
GO("libexpat.so.1", expat)
|
||||
GO("libexpat.so", expat)
|
||||
GO("libcrypto.so.1", crypto)
|
||||
GO("libssl.so.1", libssl)
|
||||
//GO("libcrypt.so.1", libcrypt)
|
||||
GO("libcrypt.so.1", libcrypt)
|
||||
GO("libutil.so.1", util)
|
||||
GO("libuuid.so.1", libuuid)
|
||||
GO("libresolv.so.2", libresolv)
|
||||
@@ -103,7 +113,9 @@ GO("libpulse.so.0", pulse)
|
||||
//GO("libdbus-glib-1.so.2", dbusglib1)
|
||||
//GO("libgudev-1.0.so.0", gudev1)
|
||||
//GO("libappindicator.so.1", appindicator)
|
||||
//GO("libatk-1.0.so.0", atk)
|
||||
GO("libatk-1.0.so.0", atk)
|
||||
GO("libatk-bridge-2.0.so.0", atkbridge)
|
||||
GO("libatspi.so.0", atspi)
|
||||
GO("libpangoft2-1.0.so", pangoft2)
|
||||
GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
@@ -119,13 +131,15 @@ GO("liblzma.so.5", lzma)
|
||||
GO("libSM.so.6", libsm)
|
||||
GO("libICE.so.6", libice)
|
||||
//GO("libusb-1.0.so.0", libusb1)
|
||||
//GO("libncursesw.so.5", libncursesw)
|
||||
//GO("libformw.so.5", libformw)
|
||||
//GO("libncurses.so.5", libncurses)
|
||||
//GO("libtinfo.so.5", libtinfo)
|
||||
//GO("libncurses.so.6", libncurses6)
|
||||
//GO("libtinfo.so.6", libtinfo6)
|
||||
//GO("libtcmalloc_minimal.so.4", tcmallocminimal)
|
||||
GO("libncursesw.so.5", libncursesw)
|
||||
GO("libform.so.5", libform)
|
||||
GO("libformw.so.5", libformw)
|
||||
GO("libncurses.so.5", libncurses)
|
||||
GO("libtinfo.so.5", libtinfo)
|
||||
GO("libpanel.so.5", libpanel)
|
||||
GO("libncurses.so.6", libncurses6)
|
||||
GO("libtinfo.so.6", libtinfo6)
|
||||
GO("libtcmalloc_minimal.so.4", tcmallocminimal)
|
||||
//GO("libmpg123.so.0", mpg123)
|
||||
GO("libgnutls.so.30", gnutls)
|
||||
GO("libcups.so.2", libcups)
|
||||
@@ -133,7 +147,7 @@ GO("libcups.so.2", libcups)
|
||||
//GO("libvulkan.so.1", vulkan)
|
||||
//GO("libvulkan.so", vulkan)
|
||||
//GO("libwayland-client.so.0", waylandclient)
|
||||
//GO("libxml2.so.2", xml2)
|
||||
GO("libxml2.so.2", xml2)
|
||||
//GO("libxslt.so.1", xslt)
|
||||
//GO("libldap_r-2.4.so.2", ldapr)
|
||||
//GO("liblber-2.4.so.2", lber)
|
||||
|
||||
+14
-12
@@ -15,14 +15,16 @@
|
||||
|
||||
#include "box64context.h"
|
||||
#include "debug.h"
|
||||
//#include "x64emu.h"
|
||||
//#include "emu/x64emu_private.h"
|
||||
#include "x64emu.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "box64stack.h"
|
||||
#include "auxval.h"
|
||||
|
||||
static uintptr_t* auxval_start = NULL;
|
||||
|
||||
int init_auxval(int argc, const char **argv, const char **env) {
|
||||
(void)argc; (void)argv;
|
||||
|
||||
// auxval vector is after envs...
|
||||
while(*env)
|
||||
env++;
|
||||
@@ -47,13 +49,13 @@ unsigned long real_getauxval(unsigned long type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//EXPORT unsigned long my_getauxval(x64emu_t* emu, unsigned long type)
|
||||
//{
|
||||
// uintptr_t* p = emu->context->auxval_start;
|
||||
// while(*p) {
|
||||
// if(*p == type)
|
||||
// return p[1];
|
||||
// p+=2;
|
||||
// }
|
||||
// return 0;
|
||||
//}
|
||||
EXPORT unsigned long my_getauxval(x64emu_t* emu, unsigned long type)
|
||||
{
|
||||
uintptr_t* p = emu->context->auxval_start;
|
||||
while(*p) {
|
||||
if(*p == type)
|
||||
return p[1];
|
||||
p+=2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+134
-19
@@ -6,6 +6,7 @@
|
||||
#include <sys/epoll.h>
|
||||
#include <fts.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include "x64emu.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
@@ -40,10 +41,12 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
case 5: // z
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'z': state = 5; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
@@ -79,7 +82,16 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case '*':
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
++p;
|
||||
break; // fetch an int in the stack....
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
@@ -88,6 +100,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 15: //%zg, meh.. double?
|
||||
if(xmm) {
|
||||
*mystack = emu->xmm[x++].q[0];
|
||||
--xmm;
|
||||
@@ -124,6 +137,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 25: // size_t int
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
@@ -150,10 +164,12 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
|
||||
// loop...
|
||||
const char* p = fmt;
|
||||
int state = 0;
|
||||
int ign = 0;
|
||||
while(*p)
|
||||
{
|
||||
switch(state) {
|
||||
case 0:
|
||||
ign = 0;
|
||||
switch(*p) {
|
||||
case '%': state = 1; ++p; break;
|
||||
default:
|
||||
@@ -164,10 +180,12 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
case 5: // z
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'z': state = 5; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
@@ -203,7 +221,7 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case '*': ign=1; ++p; break; // ignore arg
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
@@ -212,20 +230,24 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 14: //%LG long double
|
||||
case 14: //%Lg long double
|
||||
case 15: //%zg
|
||||
case 20: // fallback
|
||||
case 21:
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 25: // size_t int
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
if(!ign) {
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
}
|
||||
++mystack;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
@@ -260,10 +282,12 @@ void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mysta
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
case 5: // z
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'z': state = 5; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
@@ -299,7 +323,16 @@ void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mysta
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case '*':
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
++p;
|
||||
break; // fetch an int in the stack....
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
@@ -308,6 +341,7 @@ void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mysta
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 15: //%zg, meh .. double
|
||||
if(xmm) {
|
||||
*mystack = emu->xmm[x++].q[0];
|
||||
--xmm;
|
||||
@@ -344,6 +378,7 @@ void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mysta
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 25: // size_t int
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
@@ -370,10 +405,12 @@ void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t*
|
||||
// loop...
|
||||
const wchar_t* p = (const wchar_t*)fmt;
|
||||
int state = 0;
|
||||
int ign = 0;
|
||||
while(*p)
|
||||
{
|
||||
switch(state) {
|
||||
case 0:
|
||||
ign = 0;
|
||||
switch(*p) {
|
||||
case '%': state = 1; ++p; break;
|
||||
default:
|
||||
@@ -384,10 +421,12 @@ void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t*
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
case 5: // z
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'z': state = 5; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
@@ -423,7 +462,7 @@ void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t*
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case '*': ign = 1; ++p; break; // ignore arg
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
@@ -432,20 +471,24 @@ void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t*
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 14: //%LG long double
|
||||
case 14: //%Lg long double
|
||||
case 15: //%zg
|
||||
case 20: // fallback
|
||||
case 21:
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 25: // size_t int
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
if(!ign) {
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
}
|
||||
++mystack;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
@@ -665,4 +708,76 @@ void UnalignStat64(const void* source, void* dest)
|
||||
x64st->st_atim = st->st_atim;
|
||||
x64st->st_mtim = st->st_mtim;
|
||||
x64st->st_ctim = st->st_ctim;
|
||||
}
|
||||
}
|
||||
|
||||
typedef union __attribute__((packed)) x64_epoll_data {
|
||||
void *ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
} x64_epoll_data_t;
|
||||
|
||||
struct __attribute__((packed)) x64_epoll_event {
|
||||
uint32_t events;
|
||||
x64_epoll_data_t data;
|
||||
};
|
||||
// Arm -> x64
|
||||
void UnalignEpollEvent(void* dest, void* source, int nbr)
|
||||
{
|
||||
struct x64_epoll_event *x64_struct = (struct x64_epoll_event*)dest;
|
||||
struct epoll_event *arm_struct = (struct epoll_event*)source;
|
||||
while(nbr) {
|
||||
x64_struct->events = arm_struct->events;
|
||||
x64_struct->data.u64 = arm_struct->data.u64;
|
||||
++x64_struct;
|
||||
++arm_struct;
|
||||
--nbr;
|
||||
}
|
||||
}
|
||||
|
||||
// x64 -> Arm
|
||||
void AlignEpollEvent(void* dest, void* source, int nbr)
|
||||
{
|
||||
struct x64_epoll_event *x64_struct = (struct x64_epoll_event*)source;
|
||||
struct epoll_event *arm_struct = (struct epoll_event*)dest;
|
||||
while(nbr) {
|
||||
arm_struct->events = x64_struct->events;
|
||||
arm_struct->data.u64 = x64_struct->data.u64;
|
||||
++x64_struct;
|
||||
++arm_struct;
|
||||
--nbr;
|
||||
}
|
||||
}
|
||||
|
||||
struct __attribute__((packed)) x64_semid_ds {
|
||||
struct ipc_perm sem_perm;
|
||||
time_t sem_otime;
|
||||
unsigned long _reserved1;
|
||||
time_t sem_ctime;
|
||||
unsigned long _reserved2;
|
||||
unsigned long sem_nsems;
|
||||
unsigned long _reserved3;
|
||||
unsigned long _reserved4;
|
||||
};
|
||||
|
||||
void UnalignSemidDs(void *dest, const void* source)
|
||||
{
|
||||
struct x64_semid_ds *x64_struct = (struct x64_semid_ds*)dest;
|
||||
const struct semid_ds *arm_struct = (const struct semid_ds*)source;
|
||||
|
||||
x64_struct->sem_perm = arm_struct->sem_perm;
|
||||
x64_struct->sem_otime = arm_struct->sem_otime;
|
||||
x64_struct->sem_ctime = arm_struct->sem_ctime;
|
||||
x64_struct->sem_nsems = arm_struct->sem_nsems;
|
||||
}
|
||||
|
||||
void AlignSemidDs(void *dest, const void* source)
|
||||
{
|
||||
const struct x64_semid_ds *x64_struct = (const struct x64_semid_ds*)source;
|
||||
struct semid_ds *arm_struct = (struct semid_ds*)dest;
|
||||
|
||||
arm_struct->sem_perm = x64_struct->sem_perm;
|
||||
arm_struct->sem_otime = x64_struct->sem_otime;
|
||||
arm_struct->sem_ctime = x64_struct->sem_ctime;
|
||||
arm_struct->sem_nsems = x64_struct->sem_nsems;
|
||||
}
|
||||
@@ -93,7 +93,9 @@ EXPORT int32_t my2_emulated_write(SDL2_RWops_t *context, const void *ptr, int32_
|
||||
}
|
||||
EXPORT int32_t my2_emulated_close(SDL2_RWops_t *context)
|
||||
{
|
||||
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
|
||||
int ret = (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
|
||||
context->hidden.my.custom_free(context);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops)
|
||||
|
||||
+55
-24
@@ -376,7 +376,7 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
|
||||
|
||||
void my_sighandler(int32_t sig)
|
||||
{
|
||||
pthread_mutex_unlock(&my_context->mutex_trace); // just in case
|
||||
int Locks = unlockMutex();
|
||||
printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
|
||||
// save values
|
||||
x64emu_t *emu = thread_get_emu();
|
||||
@@ -400,11 +400,14 @@ void my_sighandler(int32_t sig)
|
||||
emu->eflags.x64 = old_flags;
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->regs[i].q[0] = old_regs[i];
|
||||
if(exits)
|
||||
if(exits) {
|
||||
relockMutex(Locks);
|
||||
exit(ret);
|
||||
}
|
||||
// what about the restored regs?
|
||||
if(restorer)
|
||||
RunFunctionHandler(&exits, restorer, 0);
|
||||
relockMutex(Locks);
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
@@ -449,6 +452,8 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
if(db) {
|
||||
frame = (uintptr_t*)p->uc_mcontext.regs[10+_SP];
|
||||
}
|
||||
#else
|
||||
(void)ucntx; (void)cur_db;
|
||||
#endif
|
||||
// stack tracking
|
||||
x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL;
|
||||
@@ -554,7 +559,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
|
||||
} else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue
|
||||
if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
|
||||
if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 12; // stack overflow probably
|
||||
else
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; // PAGE_FAULT
|
||||
@@ -638,13 +643,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
|
||||
GO(FS);
|
||||
#undef GO
|
||||
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing longjmp to resume emu\n");
|
||||
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
|
||||
if(used_stack) // release stack
|
||||
new_ss->ss_flags = 0;
|
||||
relockMutex(Locks);
|
||||
longjmp(ejb->jmpbuf, 1);
|
||||
siglongjmp(ejb->jmpbuf, 1);
|
||||
}
|
||||
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":"");
|
||||
}
|
||||
@@ -717,14 +722,12 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
|
||||
// access error, unprotect the block (and mark them dirty)
|
||||
if(prot&PROT_DYNAREC) // on heavy multi-thread program, the protection can already be gone...
|
||||
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
|
||||
// check if SMC inside block
|
||||
if(!db_searched) {
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
}
|
||||
if(db && (addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size))) {
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x\n", pc, addr, db, db?((void*)db->x64_addr):NULL, prot);
|
||||
if(db && ((addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) || db->need_test)) {
|
||||
// dynablock got auto-dirty! need to get out of it!!!
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
if(ejb->jmpbuf_ok) {
|
||||
@@ -746,9 +749,13 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
ejb->emu->regs[_R15].q[0] = p->uc_mcontext.regs[25];
|
||||
ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc);
|
||||
ejb->emu->eflags.x64 = p->uc_mcontext.regs[26];
|
||||
dynarec_log(LOG_DEBUG, "Auto-SMC detected, getting out of current Dynablock!\n");
|
||||
if(addr>=db->x64_addr && addr<(db->x64_addr+db->x64_size)) {
|
||||
dynarec_log(LOG_INFO, "Auto-SMC detected, getting out of current Dynablock!\n");
|
||||
} else {
|
||||
dynarec_log(LOG_INFO, "Dynablock unprotected, getting out!\n");
|
||||
}
|
||||
relockMutex(Locks);
|
||||
longjmp(ejb->jmpbuf, 2);
|
||||
siglongjmp(ejb->jmpbuf, 2);
|
||||
}
|
||||
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
|
||||
}
|
||||
@@ -764,11 +771,23 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) {
|
||||
dynarec_log(LOG_INFO, "Warning, addr inside current dynablock!\n");
|
||||
}
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
if(addr && pc && db) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
|
||||
relockMutex(Locks);
|
||||
return; // try again
|
||||
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x, retrying\n", pc, addr, db, prot);
|
||||
glitch_pc = pc;
|
||||
glitch_addr = addr;
|
||||
glitch_prot = prot;
|
||||
relockMutex(Locks);
|
||||
return; // try again
|
||||
}
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot);
|
||||
glitch_pc = NULL;
|
||||
glitch_addr = NULL;
|
||||
glitch_prot = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -838,13 +857,15 @@ exit(-1);
|
||||
uint32_t hash = 0;
|
||||
if(db)
|
||||
hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
|
||||
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x) handler=%p",
|
||||
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp,
|
||||
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_RBP,
|
||||
addr, info->si_code,
|
||||
prot, db, db?db->block:0, db?(db->block+db->size):0,
|
||||
db?db->x64_addr:0, db?(db->x64_addr+db->x64_size):0,
|
||||
getAddrFunctionName((uintptr_t)(db?db->x64_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
getAddrFunctionName((uintptr_t)(db?db->x64_addr:0)),
|
||||
(db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash,
|
||||
(void*)my_context->signals[sig]);
|
||||
#else
|
||||
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code);
|
||||
#endif
|
||||
@@ -865,8 +886,9 @@ exit(-1);
|
||||
}
|
||||
// no handler (or double identical segfault)
|
||||
// set default and that's it, instruction will restart and default segfault handler will be called...
|
||||
if(my_context->signals[sig]!=1)
|
||||
signal(sig, SIG_DFL);
|
||||
if(my_context->signals[sig]!=1 || sig==SIGSEGV || sig==SIGILL || sig==SIGFPE) {
|
||||
signal(sig, (void*)my_context->signals[sig]);
|
||||
}
|
||||
}
|
||||
|
||||
void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
@@ -891,7 +913,16 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
|
||||
info.si_errno = 0;
|
||||
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_RIP, addr, code);
|
||||
const char* x64name = NULL;
|
||||
const char* elfname = NULL;
|
||||
if(box64_log>LOG_NONE) {
|
||||
x64name = getAddrFunctionName(R_RIP);
|
||||
elfheader_t* elf = FindElfAddress(my_context, R_RIP);
|
||||
if(elf)
|
||||
elfname = ElfName(elf);
|
||||
}
|
||||
|
||||
printf_log(LOG_INFO, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=%d\n", sig, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr, code);
|
||||
my_sigactionhandler_oldcode(sig, &info, &ctx, NULL, db);
|
||||
}
|
||||
|
||||
@@ -954,7 +985,7 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x
|
||||
}
|
||||
int ret = 0;
|
||||
if(signum!=SIGSEGV && signum!=SIGBUS && signum!=SIGILL)
|
||||
sigaction(signum, act?&newact:NULL, oldact?&old:NULL);
|
||||
ret = sigaction(signum, act?&newact:NULL, oldact?&old:NULL);
|
||||
if(oldact) {
|
||||
oldact->sa_flags = old.sa_flags;
|
||||
oldact->sa_mask = old.sa_mask;
|
||||
|
||||
+174
-95
@@ -245,6 +245,7 @@ pthread_attr_t* getAlignedAttr(pthread_attr_t* m) {
|
||||
return m;
|
||||
}
|
||||
void freeAlignedAttr(void* attr) {
|
||||
(void)attr;
|
||||
}
|
||||
#else
|
||||
typedef struct aligned_attr_s {
|
||||
@@ -313,6 +314,7 @@ EXPORT int my_pthread_attr_setstack(x64emu_t* emu, void* attr, void* stackaddr,
|
||||
|
||||
EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacksize)
|
||||
{
|
||||
(void)emu;
|
||||
//aarch64 have an PTHREAD_STACK_MIN of 131072 instead of 16384 on x86_64!
|
||||
if(stacksize<PTHREAD_STACK_MIN)
|
||||
stacksize = PTHREAD_STACK_MIN;
|
||||
@@ -322,70 +324,86 @@ EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacks
|
||||
#ifndef NOALIGN
|
||||
EXPORT int my_pthread_attr_getdetachstate(x64emu_t* emu, pthread_attr_t* attr, int *state)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getdetachstate(getAlignedAttr(attr), state);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getguardsize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getinheritsched(x64emu_t* emu, pthread_attr_t* attr, int* sched)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getinheritsched(getAlignedAttr(attr), sched);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getschedparam(getAlignedAttr(attr), param);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int* policy)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getschedpolicy(getAlignedAttr(attr), policy);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getscope(x64emu_t* emu, pthread_attr_t* attr, int* scope)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_getscope(getAlignedAttr(attr), scope);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
|
||||
{
|
||||
(void)emu;
|
||||
size_t size;
|
||||
return pthread_attr_getstack(getAlignedAttr(attr), addr, &size);
|
||||
//return pthread_attr_getstackaddr(getAlignedAttr(attr), addr);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getstacksize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
|
||||
{
|
||||
(void)emu;
|
||||
void* addr;
|
||||
return pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
|
||||
//return pthread_attr_getstacksize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_init(getAlignedAttrWithInit(attr, 0));
|
||||
}
|
||||
EXPORT int my_pthread_attr_setaffinity_np(x64emu_t* emu, pthread_attr_t* attr, size_t cpusize, void* cpuset)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setaffinity_np(getAlignedAttr(attr), cpusize, cpuset);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setdetachstate(x64emu_t* emu, pthread_attr_t* attr, int state)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setdetachstate(getAlignedAttr(attr), state);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t size)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setguardsize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setinheritsched(x64emu_t* emu, pthread_attr_t* attr, int sched)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setinheritsched(getAlignedAttr(attr), sched);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setschedparam(getAlignedAttr(attr), param);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int policy)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setschedpolicy(getAlignedAttr(attr), policy);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setscope(x64emu_t* emu, pthread_attr_t* attr, int scope)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_attr_setscope(getAlignedAttr(attr), scope);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
|
||||
@@ -495,6 +513,7 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
|
||||
|
||||
EXPORT void my___pthread_unregister_cancel(x64emu_t* emu, x64_unwind_buff_t* buff)
|
||||
{
|
||||
(void)emu;
|
||||
__pthread_unwind_buf_t * pbuff = GetCancelThread(buff);
|
||||
__pthread_unregister_cancel(pbuff);
|
||||
|
||||
@@ -504,6 +523,7 @@ EXPORT void my___pthread_unregister_cancel(x64emu_t* emu, x64_unwind_buff_t* buf
|
||||
|
||||
EXPORT void my___pthread_unwind_next(x64emu_t* emu, x64_unwind_buff_t* buff)
|
||||
{
|
||||
(void)emu;
|
||||
__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?)
|
||||
@@ -599,17 +619,17 @@ static __thread uintptr_t my_once_callback_fct = 0;
|
||||
static void my_once_callback()
|
||||
{
|
||||
if(my_once_callback_fct) {
|
||||
if(GetNativeFnc((uintptr_t)my_once_callback_fct)) {
|
||||
vFv_t f = (vFv_t)GetNativeFnc((uintptr_t)my_once_callback_fct);
|
||||
f();
|
||||
return;
|
||||
}
|
||||
RunFunction(my_context, my_once_callback_fct, 0, 0);
|
||||
EmuCall(thread_get_emu(), my_once_callback_fct); // avoid DynaCall for now
|
||||
//RunFunction(my_context, my_once_callback_fct, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int EXPORT my_pthread_once(x64emu_t* emu, void* once, void* cb)
|
||||
int EXPORT my_pthread_once(x64emu_t* emu, int* once, void* cb)
|
||||
{
|
||||
(void)emu;
|
||||
void * n = GetNativeFnc((uintptr_t)cb);
|
||||
if(n)
|
||||
return pthread_once(once, n);
|
||||
my_once_callback_fct = (uintptr_t)cb;
|
||||
return pthread_once(once, my_once_callback);
|
||||
}
|
||||
@@ -617,6 +637,7 @@ EXPORT int my___pthread_once(x64emu_t* emu, void* once, void* cb) __attribute__(
|
||||
|
||||
EXPORT int my_pthread_key_create(x64emu_t* emu, void* key, void* dtor)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_key_create(key, findkey_destructorFct(dtor));
|
||||
}
|
||||
EXPORT int my___pthread_key_create(x64emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
|
||||
@@ -626,64 +647,64 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
|
||||
|
||||
EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, pthread_cond_t* cond, void* mutex, void* abstime)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_cond_timedwait(cond, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
|
||||
}
|
||||
EXPORT int my_pthread_cond_wait(x64emu_t* emu, pthread_cond_t* cond, void* mutex)
|
||||
{
|
||||
(void)emu;
|
||||
return pthread_cond_wait(cond, getAlignedMutex((pthread_mutex_t*)mutex));
|
||||
}
|
||||
|
||||
//EXPORT int my_pthread_attr_setscope(x64emu_t* emu, void* at*tr, int scope)
|
||||
//{
|
||||
// if(scope!=PTHREAD_SCOPE_SYSTEM) printf_log(LOG_INFO, "Warning, scope of call to pthread_attr_setscope(...) changed from %d to PTHREAD_SCOPE_SYSTEM\n", scope);
|
||||
// return pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
|
||||
// //The scope is either PTHREAD_SCOPE_SYSTEM or PTHREAD_SCOPE_PROCESS
|
||||
// // but PTHREAD_SCOPE_PROCESS doesn't seem supported on ARM linux, and PTHREAD_SCOPE_SYSTEM is default
|
||||
//}
|
||||
|
||||
EXPORT void my__pthread_cleanup_push_defer(x64emu_t* emu, void* buffer, void* routine, void* arg)
|
||||
{
|
||||
(void)emu;
|
||||
_pthread_cleanup_push_defer(buffer, findcleanup_routineFct(routine), arg);
|
||||
}
|
||||
|
||||
EXPORT void my__pthread_cleanup_push(x64emu_t* emu, void* buffer, void* routine, void* arg)
|
||||
{
|
||||
(void)emu;
|
||||
_pthread_cleanup_push(buffer, findcleanup_routineFct(routine), arg);
|
||||
}
|
||||
|
||||
EXPORT void my__pthread_cleanup_pop_restore(x64emu_t* emu, void* buffer, int exec)
|
||||
{
|
||||
(void)emu;
|
||||
_pthread_cleanup_pop_restore(buffer, exec);
|
||||
}
|
||||
|
||||
EXPORT void my__pthread_cleanup_pop(x64emu_t* emu, void* buffer, int exec)
|
||||
{
|
||||
(void)emu;
|
||||
_pthread_cleanup_pop(buffer, exec);
|
||||
}
|
||||
|
||||
//EXPORT int my_pthread_getaffinity_np(x64emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset)
|
||||
//{
|
||||
// int ret = pthread_getaffinity_np(thread, cpusetsize, cpuset);
|
||||
// if(ret<0) {
|
||||
// printf_log(LOG_INFO, "Warning, pthread_getaffinity_np(%p, %d, %p) errored, with errno=%d\n", (void*)thread, cpusetsize, cpuset, errno);
|
||||
// }
|
||||
//
|
||||
// return ret;
|
||||
//}
|
||||
EXPORT int my_pthread_getaffinity_np(x64emu_t* emu, pthread_t thread, size_t cpusetsize, void* cpuset)
|
||||
{
|
||||
(void)emu;
|
||||
int ret = pthread_getaffinity_np(thread, cpusetsize, cpuset);
|
||||
if(ret<0) {
|
||||
printf_log(LOG_INFO, "Warning, pthread_getaffinity_np(%p, %zd, %p) errored, with errno=%d\n", (void*)thread, cpusetsize, cpuset, errno);
|
||||
}
|
||||
|
||||
//EXPORT int my_pthread_setaffinity_np(x64emu_t* emu, pthread_t thread, int cpusetsize, void* cpuset)
|
||||
//{
|
||||
// int ret = pthread_setaffinity_np(thread, cpusetsize, cpuset);
|
||||
// if(ret<0) {
|
||||
// printf_log(LOG_INFO, "Warning, pthread_setaffinity_np(%p, %d, %p) errored, with errno=%d\n", (void*)thread, cpusetsize, cpuset, errno);
|
||||
// }
|
||||
//
|
||||
// return ret;
|
||||
//}
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT int my_pthread_setaffinity_np(x64emu_t* emu, pthread_t thread, size_t cpusetsize, void* cpuset)
|
||||
{
|
||||
(void)emu;
|
||||
int ret = pthread_setaffinity_np(thread, cpusetsize, cpuset);
|
||||
if(ret<0) {
|
||||
printf_log(LOG_INFO, "Warning, pthread_setaffinity_np(%p, %zd, %p) errored, with errno=%d\n", (void*)thread, cpusetsize, cpuset, errno);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//EXPORT int my_pthread_attr_setaffinity_np(x64emu_t* emu, void* attr, uint32_t cpusetsize, void* cpuset)
|
||||
//{
|
||||
//
|
||||
// (void)emu;
|
||||
// int ret = pthread_attr_setaffinity_np(attr, cpusetsize, cpuset);
|
||||
// if(ret<0) {
|
||||
// printf_log(LOG_INFO, "Warning, pthread_attr_setaffinity_np(%p, %d, %p) errored, with errno=%d\n", attr, cpusetsize, cpuset, errno);
|
||||
@@ -694,14 +715,16 @@ EXPORT void my__pthread_cleanup_pop(x64emu_t* emu, void* buffer, int exec)
|
||||
|
||||
EXPORT int my_pthread_kill(x64emu_t* emu, void* thread, int sig)
|
||||
{
|
||||
// check for old "is everything ok?"
|
||||
if(thread==NULL && sig==0)
|
||||
return pthread_kill(pthread_self(), 0);
|
||||
return pthread_kill((pthread_t)thread, sig);
|
||||
(void)emu;
|
||||
// check for old "is everything ok?"
|
||||
if(thread==NULL && sig==0)
|
||||
return pthread_kill(pthread_self(), 0);
|
||||
return pthread_kill((pthread_t)thread, sig);
|
||||
}
|
||||
|
||||
//EXPORT void my_pthread_exit(x64emu_t* emu, void* retval)
|
||||
//{
|
||||
// (void)emu;
|
||||
// pthread_exit(retval);
|
||||
//}
|
||||
|
||||
@@ -710,17 +733,89 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m) {
|
||||
return m;
|
||||
}
|
||||
#else
|
||||
//#define TRACK_MUTEX
|
||||
// mutex alignment
|
||||
#ifdef TRACK_MUTEX
|
||||
KHASH_MAP_INIT_INT(mutex, pthread_mutex_t*)
|
||||
#define MUTEXES_SIZE 64
|
||||
typedef struct mutexes_block_s {
|
||||
pthread_mutex_t mutexes[MUTEXES_SIZE];
|
||||
uint8_t taken[MUTEXES_SIZE];
|
||||
struct mutexes_block_s* next;
|
||||
int n_free, pad;
|
||||
} mutexes_block_t;
|
||||
|
||||
static kh_mutex_t* unaligned_mutex = NULL;
|
||||
#endif
|
||||
static mutexes_block_t *mutexes = NULL;
|
||||
static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static mutexes_block_t* NewMutexesBlock()
|
||||
{
|
||||
mutexes_block_t* ret = (mutexes_block_t*)calloc(1, sizeof(mutexes_block_t));
|
||||
ret->n_free = MUTEXES_SIZE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int NewMutex() {
|
||||
pthread_mutex_lock(&mutex_mutexes);
|
||||
if(!mutexes) {
|
||||
mutexes = NewMutexesBlock();
|
||||
}
|
||||
int j = 0;
|
||||
mutexes_block_t* m = mutexes;
|
||||
while(!m->n_free) {
|
||||
if(!m->next) {
|
||||
m->next = NewMutexesBlock();
|
||||
}
|
||||
++j;
|
||||
m = m->next;
|
||||
}
|
||||
--m->n_free;
|
||||
for (int i=0; i<MUTEXES_SIZE; ++i)
|
||||
if(!m->taken[i]) {
|
||||
m->taken[i] = 1;
|
||||
pthread_mutex_unlock(&mutex_mutexes);
|
||||
return j*MUTEXES_SIZE + i;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_mutexes);
|
||||
printf_log(LOG_NONE, "Error: NewMutex unreachable part reached\n");
|
||||
return (int)-1; // error!!!!
|
||||
}
|
||||
|
||||
void FreeMutex(int k)
|
||||
{
|
||||
if(!mutexes)
|
||||
return; //???
|
||||
pthread_mutex_lock(&mutex_mutexes);
|
||||
mutexes_block_t* m = mutexes;
|
||||
for(int i=0; i<k/MUTEXES_SIZE; ++i)
|
||||
m = m->next;
|
||||
m->taken[k%MUTEXES_SIZE] = 0;
|
||||
++m->n_free;
|
||||
pthread_mutex_unlock(&mutex_mutexes);
|
||||
}
|
||||
|
||||
void FreeAllMutexes(mutexes_block_t* m)
|
||||
{
|
||||
if(!m)
|
||||
return;
|
||||
FreeAllMutexes(m->next);
|
||||
// should destroy all mutexes also?
|
||||
free(m);
|
||||
}
|
||||
|
||||
pthread_mutex_t* GetMutex(int k)
|
||||
{
|
||||
if(!mutexes)
|
||||
return NULL; //???
|
||||
mutexes_block_t* m = mutexes;
|
||||
for(int i=0; i<k/MUTEXES_SIZE; ++i)
|
||||
m = m->next;
|
||||
return &m->mutexes[k%MUTEXES_SIZE];
|
||||
}
|
||||
|
||||
// x86_64 pthread_mutex_t is 40 bytes (ARM64 one is 48)
|
||||
typedef struct aligned_mutex_s {
|
||||
struct aligned_mutex_s *self;
|
||||
uint64_t dummy;
|
||||
pthread_mutex_t *m;
|
||||
int kind; // kind position on x86_64
|
||||
int k;
|
||||
pthread_mutex_t* m;
|
||||
uint64_t sign;
|
||||
} aligned_mutex_t;
|
||||
#define SIGNMTX *(uint64_t*)"BOX64MTX"
|
||||
@@ -730,23 +825,28 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
if(!m)
|
||||
return NULL;
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
if(init && (am->sign==SIGNMTX))
|
||||
if(init && (am->sign==SIGNMTX && am->self==am))
|
||||
return am->m;
|
||||
int k = NewMutex();
|
||||
// check again, it might be created now becayse NewMutex is under mutex
|
||||
if(init && (am->sign==SIGNMTX && am->self==am)) {
|
||||
FreeMutex(k);
|
||||
return am->m;
|
||||
#ifdef TRACK_MUTEX
|
||||
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
|
||||
if(k!=kh_end(unaligned_mutex))
|
||||
return kh_value(unaligned_mutex, k);
|
||||
int r;
|
||||
k = kh_put(mutex, unaligned_mutex, (uintptr_t)m, &r);
|
||||
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
|
||||
#else
|
||||
pthread_mutex_t* ret = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
|
||||
#endif
|
||||
if(init) {
|
||||
int kind = ((int*)m)[4]; // extract kind from original mutex
|
||||
((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind; // inject in new one (i.e. "init" it)
|
||||
}
|
||||
pthread_mutex_t* ret = GetMutex(k);
|
||||
|
||||
if(init) {
|
||||
if(am->sign == SIGNMTX) {
|
||||
int kind = ((int*)am->m)[3+__PTHREAD_MUTEX_HAVE_PREV]; // extract kind from original mutex
|
||||
((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind; // inject in new one (i.e. "init" it)
|
||||
} else {
|
||||
int kind = am->kind; // extract kind from original mutex
|
||||
((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind; // inject in new one (i.e. "init" it)
|
||||
}
|
||||
}
|
||||
am->self = am;
|
||||
am->sign = SIGNMTX;
|
||||
am->k = k;
|
||||
am->m = ret;
|
||||
return ret;
|
||||
}
|
||||
@@ -758,28 +858,13 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
|
||||
EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
|
||||
{
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
#ifdef TRACK_MUTEX
|
||||
if(am->sign==SIGNMTX) {
|
||||
am->sign = 0;
|
||||
am->m = NULL;
|
||||
}
|
||||
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
|
||||
if(k!=kh_end(unaligned_mutex)) {
|
||||
pthread_mutex_t *n = kh_value(unaligned_mutex, k);
|
||||
kh_del(mutex, unaligned_mutex, k);
|
||||
int ret = pthread_mutex_destroy(n);
|
||||
free(n);
|
||||
return ret;
|
||||
}
|
||||
return pthread_mutex_destroy(m);
|
||||
#else
|
||||
if(am->sign!=SIGNMTX) {
|
||||
return 1; //???
|
||||
}
|
||||
int ret = pthread_mutex_destroy(am->m);
|
||||
free(am->m);
|
||||
FreeMutex(am->k);
|
||||
am->sign = 0;
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
typedef union my_mutexattr_s {
|
||||
int x86;
|
||||
@@ -804,6 +889,14 @@ EXPORT int my_pthread_mutexattr_getkind_np(x64emu_t* emu, my_mutexattr_t *attr,
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_getprotocol(x64emu_t* emu, my_mutexattr_t *attr, void* p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_getprotocol(&mattr.nat, p);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_gettype(x64emu_t* emu, my_mutexattr_t *attr, void* p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
@@ -1031,11 +1124,6 @@ void init_pthread_helper()
|
||||
{
|
||||
InitCancelThread();
|
||||
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
|
||||
#ifndef NOALIGN
|
||||
#ifdef TRACK_MUTEX
|
||||
unaligned_mutex = kh_init(mutex);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void fini_pthread_helper(box64context_t* context)
|
||||
@@ -1043,14 +1131,8 @@ void fini_pthread_helper(box64context_t* context)
|
||||
FreeCancelThread(context);
|
||||
CleanStackSize(context);
|
||||
#ifndef NOALIGN
|
||||
#ifdef TRACK_MUTEX
|
||||
pthread_mutex_t *m;
|
||||
kh_foreach_value(unaligned_mutex, m,
|
||||
pthread_mutex_destroy(m);
|
||||
free(m);
|
||||
);
|
||||
kh_destroy(mutex, unaligned_mutex);
|
||||
#endif
|
||||
FreeAllMutexes(mutexes);
|
||||
mutexes = NULL;
|
||||
#endif
|
||||
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
|
||||
if(ejb) {
|
||||
@@ -1064,15 +1146,12 @@ void fini_pthread_helper(box64context_t* context)
|
||||
}
|
||||
}
|
||||
|
||||
int checkMutex(void* m)
|
||||
int checkUnlockMutex(void* m)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
|
||||
int ret = pthread_mutex_trylock(mutex);
|
||||
int ret = pthread_mutex_unlock(mutex);
|
||||
if(ret==0) {
|
||||
pthread_mutex_unlock(mutex);
|
||||
return 0;
|
||||
}
|
||||
if(ret==EDEADLK)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+95
-74
@@ -23,9 +23,11 @@
|
||||
#include "x64trace.h"
|
||||
#include "librarian.h"
|
||||
#include "x64run.h"
|
||||
#include "symbols.h"
|
||||
|
||||
box64context_t *my_context = NULL;
|
||||
int box64_log = LOG_INFO; //LOG_NONE;
|
||||
int box64_dump = 0;
|
||||
int box64_nobanner = 0;
|
||||
int box64_dynarec_log = LOG_NONE;
|
||||
int box64_pagesize;
|
||||
@@ -33,7 +35,6 @@ int box64_pagesize;
|
||||
int box64_dynarec = 1;
|
||||
int box64_dynarec_dump = 0;
|
||||
int box64_dynarec_forced = 0;
|
||||
int box64_dynarec_largest = 0;
|
||||
uintptr_t box64_nodynarec_start = 0;
|
||||
uintptr_t box64_nodynarec_end = 0;
|
||||
#else //DYNAREC
|
||||
@@ -88,13 +89,17 @@ void openFTrace()
|
||||
ftrace_has_pid = 1;
|
||||
}
|
||||
if(p) {
|
||||
ftrace = fopen(p, "w");
|
||||
if(!ftrace) {
|
||||
ftrace = stdout;
|
||||
printf_log(LOG_INFO, "Cannot open trace file \"%s\" for writing (error=%s)\n", p, strerror(errno));
|
||||
} else {
|
||||
if(!box64_nobanner)
|
||||
printf("BOX64 Trace redirected to \"%s\"\n", p);
|
||||
if(!strcmp(p, "stderr"))
|
||||
ftrace = stderr;
|
||||
else {
|
||||
ftrace = fopen(p, "w");
|
||||
if(!ftrace) {
|
||||
ftrace = stdout;
|
||||
printf_log(LOG_INFO, "Cannot open trace file \"%s\" for writing (error=%s)\n", p, strerror(errno));
|
||||
} else {
|
||||
if(!box64_nobanner)
|
||||
printf("BOX64 Trace redirected to \"%s\"\n", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,15 +121,20 @@ void LoadLogEnv()
|
||||
const char *p = getenv("BOX64_NOBANNER");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='1')
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_nobanner = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_LOG");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0'+LOG_NONE && p[1]<='0'+LOG_DEBUG)
|
||||
if(p[0]>='0'+LOG_NONE && p[0]<='0'+LOG_NEVER) {
|
||||
box64_log = p[0]-'0';
|
||||
if(box64_log == LOG_NEVER) {
|
||||
--box64_log;
|
||||
box64_dump = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!strcasecmp(p, "NONE"))
|
||||
box64_log = LOG_NONE;
|
||||
@@ -132,17 +142,28 @@ void LoadLogEnv()
|
||||
box64_log = LOG_INFO;
|
||||
else if(!strcasecmp(p, "DEBUG"))
|
||||
box64_log = LOG_DEBUG;
|
||||
else if(!strcasecmp(p, "DUMP"))
|
||||
box64_log = LOG_DUMP;
|
||||
else if(!strcasecmp(p, "DUMP")) {
|
||||
box64_log = LOG_DEBUG;
|
||||
box64_dump = 1;
|
||||
}
|
||||
}
|
||||
if(!box64_nobanner)
|
||||
printf_log(LOG_INFO, "Debug level is %d\n", box64_log);
|
||||
}
|
||||
p = getenv("BOX64_DUMP");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_dump = p[0]-'0';
|
||||
}
|
||||
}
|
||||
if(!box64_nobanner && box64_dump)
|
||||
printf_log(LOG_INFO, "Elf Dump if ON\n");
|
||||
#ifdef DYNAREC
|
||||
p = getenv("BOX64_DYNAREC_DUMP");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='1')
|
||||
if(p[0]>='0' && p[0]<='2')
|
||||
box64_dynarec_dump = p[0]-'0';
|
||||
}
|
||||
if (box64_dynarec_dump) printf_log(LOG_INFO, "Dynarec blocks are dumped%s\n", (box64_dynarec_dump>1)?" in color":"");
|
||||
@@ -150,7 +171,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_DYNAREC_LOG");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if((p[0]>='0'+LOG_NONE) && (p[0]<='0'+LOG_DUMP))
|
||||
if((p[0]>='0'+LOG_NONE) && (p[0]<='0'+LOG_NEVER))
|
||||
box64_dynarec_log = p[0]-'0';
|
||||
} else {
|
||||
if(!strcasecmp(p, "NONE"))
|
||||
@@ -160,14 +181,14 @@ void LoadLogEnv()
|
||||
else if(!strcasecmp(p, "DEBUG"))
|
||||
box64_dynarec_log = LOG_DEBUG;
|
||||
else if(!strcasecmp(p, "VERBOSE"))
|
||||
box64_dynarec_log = LOG_DUMP;
|
||||
box64_dynarec_log = LOG_VERBOSE;
|
||||
}
|
||||
printf_log(LOG_INFO, "Dynarec log level is %d\n", box64_dynarec_log);
|
||||
}
|
||||
p = getenv("BOX64_DYNAREC");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='1')
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_dynarec = p[0]-'0';
|
||||
}
|
||||
printf_log(LOG_INFO, "Dynarec is %s\n", box64_dynarec?"On":"Off");
|
||||
@@ -175,7 +196,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_DYNAREC_FORCED");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='1')
|
||||
if(p[0]>='0' && p[0]<='1')
|
||||
box64_dynarec_forced = p[0]-'0';
|
||||
}
|
||||
if(box64_dynarec_forced)
|
||||
@@ -197,21 +218,21 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_TRACE_XMM");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
trace_xmm = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_TRACE_EMM");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
trace_emm = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_TRACE_COLOR");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
trace_regsdiff = p[0]-'0';
|
||||
}
|
||||
}
|
||||
@@ -225,7 +246,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_DYNAREC_TRACE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box64_dynarec_trace = p[0]-'0';
|
||||
if(box64_dynarec_trace)
|
||||
printf_log(LOG_INFO, "Dynarec generated code will also print a trace\n");
|
||||
@@ -239,14 +260,14 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_DLSYM_ERROR");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
dlsym_error = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_X11THREADS");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
x11threads = p[0]-'0';
|
||||
}
|
||||
if(x11threads)
|
||||
@@ -255,7 +276,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_X11GLX");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
x11glx = p[0]-'0';
|
||||
}
|
||||
if(x11glx)
|
||||
@@ -277,7 +298,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_ALLOWMISSINGLIBS");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
allow_missing_libs = p[0]-'0';
|
||||
}
|
||||
if(allow_missing_libs)
|
||||
@@ -286,7 +307,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_NOPULSE");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box64_nopulse = p[0]-'0';
|
||||
}
|
||||
if(box64_nopulse)
|
||||
@@ -295,7 +316,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_NOGTK");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box64_nogtk = p[0]-'0';
|
||||
}
|
||||
if(box64_nogtk)
|
||||
@@ -304,7 +325,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_NOVULKAN");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
box64_novulkan = p[0]-'0';
|
||||
}
|
||||
if(box64_novulkan)
|
||||
@@ -313,7 +334,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_FIX_64BIT_INODES");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
fix_64bit_inodes = p[0]-'0';
|
||||
}
|
||||
if(fix_64bit_inodes)
|
||||
@@ -322,7 +343,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_JITGDB");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
jit_gdb = p[0]-'0';
|
||||
}
|
||||
if(jit_gdb)
|
||||
@@ -426,7 +447,8 @@ void PrintHelp() {
|
||||
printf("You can also set some environment variables:\n");
|
||||
printf(" BOX64_PATH is the box64 version of PATH (default is '.:bin')\n");
|
||||
printf(" BOX64_LD_LIBRARY_PATH is the box64 version LD_LIBRARY_PATH (default is '.:lib')\n");
|
||||
printf(" BOX64_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info\n");
|
||||
printf(" BOX64_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info (level 3 is level 2 + BOX64_DUMP)\n");
|
||||
printf(" BOX64_DUMP with 0/1 to dump elf infos\n");
|
||||
printf(" BOX64_NOBANNER with 0/1 to enable/disable the printing of box64 version and build at start\n");
|
||||
#ifdef DYNAREC
|
||||
printf(" BOX64_DYNAREC_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed dynarec info\n");
|
||||
@@ -446,7 +468,7 @@ void PrintHelp() {
|
||||
printf(" BOX64_DYNAREC_TRACE with 0/1 to disable or enable Trace on generated code too\n");
|
||||
#endif
|
||||
#endif
|
||||
printf(" BOX64_TRACE_FILE with FileName to redirect logs in a file");
|
||||
printf(" BOX64_TRACE_FILE with FileName to redirect logs in a file (or stderr to use stderr instead of stdout)");
|
||||
printf(" BOX64_DLSYM_ERROR with 1 to log dlsym errors\n");
|
||||
printf(" BOX64_LOAD_ADDR=0xXXXXXX try to load at 0xXXXXXX main binary (if binary is a PIE)\n");
|
||||
printf(" BOX64_NOSIGSEGV=1 to disable handling of SigSEGV\n");
|
||||
@@ -519,28 +541,28 @@ void LoadEnvVars(box64context_t *context)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
void setupTraceInit(box64context_t* context)
|
||||
void setupTraceInit()
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
char* p = getenv("BOX64_TRACE_INIT");
|
||||
if(p) {
|
||||
setbuf(stdout, NULL);
|
||||
uintptr_t trace_start=0, trace_end=0;
|
||||
uintptr_t s_trace_start=0, s_trace_end=0;
|
||||
if (strcmp(p, "1")==0)
|
||||
SetTraceEmu(0, 0);
|
||||
else if (strchr(p,'-')) {
|
||||
if(sscanf(p, "%ld-%ld", &trace_start, &trace_end)!=2) {
|
||||
if(sscanf(p, "0x%lX-0x%lX", &trace_start, &trace_end)!=2)
|
||||
sscanf(p, "%lx-%lx", &trace_start, &trace_end);
|
||||
if(sscanf(p, "%ld-%ld", &s_trace_start, &s_trace_end)!=2) {
|
||||
if(sscanf(p, "0x%lX-0x%lX", &s_trace_start, &s_trace_end)!=2)
|
||||
sscanf(p, "%lx-%lx", &s_trace_start, &s_trace_end);
|
||||
}
|
||||
if(trace_start || trace_end)
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
if(s_trace_start || s_trace_end)
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
} else {
|
||||
if (GetSymbolStartEnd(GetMapSymbol(my_context->maplib), p, &trace_start, &trace_end)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
if (GetSymbolStartEnd(GetMapSymbol(my_context->maplib), p, &s_trace_start, &s_trace_end, -1, NULL, -1)) {
|
||||
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 {
|
||||
printf_log(LOG_NONE, "Warning, symbol to Traced (\"%s\") not found, disabling trace\n", p);
|
||||
printf_log(LOG_NONE, "Warning, symbol to trace (\"%s\") not found, disabling trace\n", p);
|
||||
SetTraceEmu(0, 100); // disabling trace, mostly
|
||||
}
|
||||
}
|
||||
@@ -554,37 +576,37 @@ void setupTraceInit(box64context_t* context)
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
void setupTrace(box64context_t* context)
|
||||
void setupTrace()
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
char* p = getenv("BOX64_TRACE");
|
||||
if(p) {
|
||||
setbuf(stdout, NULL);
|
||||
uintptr_t trace_start=0, trace_end=0;
|
||||
uintptr_t s_trace_start=0, s_trace_end=0;
|
||||
if (strcmp(p, "1")==0)
|
||||
SetTraceEmu(0, 0);
|
||||
else if (strchr(p,'-')) {
|
||||
if(sscanf(p, "%ld-%ld", &trace_start, &trace_end)!=2) {
|
||||
if(sscanf(p, "0x%lX-0x%lX", &trace_start, &trace_end)!=2)
|
||||
sscanf(p, "%lx-%lx", &trace_start, &trace_end);
|
||||
if(sscanf(p, "%ld-%ld", &s_trace_start, &s_trace_end)!=2) {
|
||||
if(sscanf(p, "0x%lX-0x%lX", &s_trace_start, &s_trace_end)!=2)
|
||||
sscanf(p, "%lx-%lx", &s_trace_start, &s_trace_end);
|
||||
}
|
||||
if(trace_start || trace_end) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
if(!trace_start && trace_end==1) {
|
||||
if(s_trace_start || s_trace_end) {
|
||||
SetTraceEmu(s_trace_start, s_trace_end);
|
||||
if(!s_trace_start && s_trace_end==1) {
|
||||
printf_log(LOG_INFO, "TRACE enabled but inactive\n");
|
||||
} else {
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)s_trace_start, (void*)s_trace_end);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
} else if(GetLocalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end, NULL)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &s_trace_start, &s_trace_end, NULL, -1, 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)) {
|
||||
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 {
|
||||
printf_log(LOG_NONE, "Warning, symbol to Traced (\"%s\") not found, trying to set trace later\n", p);
|
||||
printf_log(LOG_NONE, "Warning, symbol to trace (\"%s\") not found, trying to set trace later\n", p);
|
||||
SetTraceEmu(0, 1); // disabling trace, mostly
|
||||
trace_func = strdup(p);
|
||||
}
|
||||
@@ -673,6 +695,8 @@ int main(int argc, const char **argv, const char **env) {
|
||||
PrintHelp();
|
||||
return 1;
|
||||
}
|
||||
if(argc>1 && !strcmp(argv[1], "/usr/bin/gdb") && getenv("BOX64_TRACE_FILE"))
|
||||
exit(0);
|
||||
|
||||
// init random seed
|
||||
srandom(time(NULL));
|
||||
@@ -744,9 +768,9 @@ int main(int argc, const char **argv, const char **env) {
|
||||
// allocate extra space for new environment variables such as BOX64_PATH
|
||||
my_context->envv = (char**)calloc(my_context->envc+4, sizeof(char*));
|
||||
GatherEnv(&my_context->envv, environ?environ:env, my_context->box64path);
|
||||
if(box64_log>=LOG_DUMP) {
|
||||
if(box64_dump) {
|
||||
for (int i=0; i<my_context->envc; ++i)
|
||||
printf_log(LOG_DUMP, " Env[%02d]: %s\n", i, my_context->envv[i]);
|
||||
printf_dump(LOG_NEVER, " Env[%02d]: %s\n", i, my_context->envv[i]);
|
||||
}
|
||||
|
||||
path_collection_t ld_preload = {0};
|
||||
@@ -800,16 +824,16 @@ int main(int argc, const char **argv, const char **env) {
|
||||
AddPath("libSDL2-2.0.so.0", &my_context->box64_emulated_libs, 0);
|
||||
}
|
||||
// special case for steam that somehow seems to alter libudev opaque pointer (udev_monitor)
|
||||
if(strstr(prgname, "steam")==prgname) {
|
||||
if(!strcmp(prgname, "steam")) {
|
||||
printf_log(LOG_INFO, "steam detected, forcing emulated libudev\n");
|
||||
AddPath("libudev.so.0", &my_context->box64_emulated_libs, 0);
|
||||
box64_steam = 1;
|
||||
}
|
||||
/*// special case for steam-runtime-check-requirements to fake 64bits suport
|
||||
// special case for steam-runtime-check-requirements to fake 64bits suport
|
||||
if(strstr(prgname, "steam-runtime-check-requirements")==prgname) {
|
||||
printf_log(LOG_INFO, "steam-runtime-check-requirements detected, faking All is good!\n");
|
||||
exit(0); // exiting, not testing anything
|
||||
}*/
|
||||
}
|
||||
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
|
||||
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
|
||||
free(my_context->argv[0]);
|
||||
@@ -966,13 +990,13 @@ int main(int argc, const char **argv, const char **env) {
|
||||
|
||||
thread_set_emu(emu);
|
||||
|
||||
setupTraceInit(my_context);
|
||||
setupTraceInit();
|
||||
// export symbols
|
||||
AddSymbols(my_context->maplib, GetMapSymbol(my_context->maplib), GetWeakSymbol(my_context->maplib), GetLocalSymbol(my_context->maplib), elf_header);
|
||||
if(wine_preloaded) {
|
||||
uintptr_t wineinfo = FindSymbol(GetMapSymbol(my_context->maplib), "wine_main_preload_info");
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbol(my_context->maplib), "wine_main_preload_info");
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbol(my_context->maplib), "wine_main_preload_info");
|
||||
uintptr_t wineinfo = FindSymbol(GetMapSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
|
||||
if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
|
||||
if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");}
|
||||
else {
|
||||
*(void**)wineinfo = get_wine_prereserve();
|
||||
@@ -984,11 +1008,8 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
// pre-load lib if needed
|
||||
if(ld_preload.size) {
|
||||
for (int i=0; i<ld_preload.size; ++i) {
|
||||
if(AddNeededLib(NULL, NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
|
||||
if(!strstr(ld_preload.paths[i], "vgpreload_"))
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]);
|
||||
}
|
||||
if(AddNeededLib(NULL, NULL, NULL, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) {
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load a lib\n");
|
||||
}
|
||||
}
|
||||
FreeCollection(&ld_preload);
|
||||
@@ -1012,7 +1033,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
// do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
|
||||
ResetSpecialCaseMainElf(elf_header);
|
||||
// init...
|
||||
setupTrace(my_context);
|
||||
setupTrace();
|
||||
// get entrypoint
|
||||
my_context->ep = GetEntryPoint(my_context->maplib, elf_header);
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
|
||||
Loaded 100 of 253 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user