mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-09 04:09:46 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
716ac9e041 | ||
|
|
fb835fbe66 | ||
|
|
4aac3444bd | ||
|
|
0a343b72f2 | ||
|
|
ab9178f638 | ||
|
|
1b8d952d88 | ||
|
|
e8e966cd80 | ||
|
|
8b80cc328f | ||
|
|
72986e8ba3 | ||
|
|
3df01a153d | ||
|
|
5d5ef75337 | ||
|
|
c3ef6380a7 | ||
|
|
c2782b269f | ||
|
|
1cb55b2633 | ||
|
|
823c6a138a | ||
|
|
e10a78d671 | ||
|
|
04b9195cd2 | ||
|
|
3aa12a52eb | ||
|
|
5f31e0e093 | ||
|
|
39f2b508f8 | ||
|
|
5b5285940f | ||
|
|
c49da85606 | ||
|
|
5cc3512a59 | ||
|
|
cbd1d3781b | ||
|
|
5bca9b52b3 | ||
|
|
fd21d6a8da | ||
|
|
c8ebce5732 | ||
|
|
fce5aa5a6b | ||
|
|
2ac2996abd | ||
|
|
53fb83487a | ||
|
|
3597284e8d | ||
|
|
4e8f387f79 | ||
|
|
305e6326a6 | ||
|
|
e98c7eaa0f | ||
|
|
02462b2c12 | ||
|
|
4d9559f345 | ||
|
|
ed63000e23 | ||
|
|
cc307df592 | ||
|
|
2d321bbd33 | ||
|
|
5b5f7c133e | ||
|
|
69484d7f3c | ||
|
|
43f5438d93 | ||
|
|
2b920d6936 | ||
|
|
01bf3e741e | ||
|
|
f014d4580a | ||
|
|
1f02ab17e3 | ||
|
|
e1d8f1d7e5 | ||
|
|
c8640caba3 | ||
|
|
f4ea86378e | ||
|
|
16011f4b34 | ||
|
|
5a3316b872 | ||
|
|
9f50a19856 | ||
|
|
6207b3fa38 | ||
|
|
35d2103189 | ||
|
|
84626f065c | ||
|
|
eaedda8ceb | ||
|
|
4e9c25893c | ||
|
|
eb5bebb344 | ||
|
|
296ee1baca | ||
|
|
58b5c6ded9 | ||
|
|
ecc07a235c | ||
|
|
fc4f0e3bae | ||
|
|
e00d35f5bf | ||
|
|
790022483b | ||
|
|
100cdd329a | ||
|
|
9c441df959 | ||
|
|
a8ae44a881 | ||
|
|
2f5fe43955 | ||
|
|
86820cf1b1 | ||
|
|
e511e1bf96 | ||
|
|
5fb1c6c497 | ||
|
|
607bb28677 | ||
|
|
36e5fb50ec | ||
|
|
74405a8b00 | ||
|
|
4b1ecc16ff | ||
|
|
139d5128a0 | ||
|
|
7b8bd8a285 | ||
|
|
445d232ee7 | ||
|
|
8ad472c118 | ||
|
|
fd6895782f | ||
|
|
abdd03cdfa | ||
|
|
ba3359353f | ||
|
|
ca473b06dc | ||
|
|
2ee0230793 | ||
|
|
35119f8db2 | ||
|
|
c95af7c81b | ||
|
|
a9aa474884 | ||
|
|
259fe4a238 | ||
|
|
f73bbfc0af | ||
|
|
e7478f3390 | ||
|
|
9be89e8ba2 | ||
|
|
5287e42b02 | ||
|
|
e0a7f775c9 | ||
|
|
f1d238b78d | ||
|
|
41ebdc7604 | ||
|
|
e3fde0807f | ||
|
|
4007ff2610 | ||
|
|
27d79eddec | ||
|
|
0e5bc91a14 | ||
|
|
c715141bf0 | ||
|
|
3d656b5008 | ||
|
|
d84afba7c8 | ||
|
|
7559df965b | ||
|
|
10702c160a | ||
|
|
a66bb7453b | ||
|
|
5406a040fb | ||
|
|
77421d2eed | ||
|
|
78b9b0cec8 | ||
|
|
16a3d46193 | ||
|
|
2976bf5e6a | ||
|
|
b370540447 | ||
|
|
6d7c0f75e7 | ||
|
|
81a7eca5ef | ||
|
|
2711a7e522 | ||
|
|
cc8f926d66 | ||
|
|
486aa58b15 | ||
|
|
8711693698 | ||
|
|
e6f615a1f8 | ||
|
|
813ed6f9a1 | ||
|
|
85dba348a7 | ||
|
|
a7422d11ed | ||
|
|
b39fbc0cfd | ||
|
|
f000951fc9 | ||
|
|
edeac868d0 | ||
|
|
a618dee15c | ||
|
|
8b48773176 | ||
|
|
9a17d9a35e | ||
|
|
a2ca22972c | ||
|
|
b05c449dd0 | ||
|
|
bdb918c9c2 | ||
|
|
7ae9dca562 | ||
|
|
005e3ddf7d | ||
|
|
c5fbc5efd3 | ||
|
|
4b06a0126e | ||
|
|
f8ef852b46 | ||
|
|
741b03761a | ||
|
|
8ccde3ed4a | ||
|
|
b6ce8efa20 | ||
|
|
2bf49e8a11 | ||
|
|
0cfb48f3c7 | ||
|
|
fcd9eba0da | ||
|
|
6d7e729563 | ||
|
|
102744665c | ||
|
|
dd885a694e | ||
|
|
ecf8ffbbdc | ||
|
|
c1e67c31bc | ||
|
|
6eccdc1baf | ||
|
|
7aa7ef6baf | ||
|
|
66ed68ca48 | ||
|
|
d20d007933 | ||
|
|
a91d2d0841 | ||
|
|
649b7772f1 | ||
|
|
fe6304b7cd | ||
|
|
e9b6f3559b | ||
|
|
53b2578b8e | ||
|
|
9507601ee6 | ||
|
|
52e4edd147 | ||
|
|
acc3ed85cb | ||
|
|
dbbda60d9e | ||
|
|
401071c40a | ||
|
|
928eb2a32b | ||
|
|
1c0b1721cd | ||
|
|
15a7d0b9b5 | ||
|
|
6670e924bf | ||
|
|
5b5b974341 | ||
|
|
ad85b7c4c6 | ||
|
|
a5490dc6f2 | ||
|
|
5c52fa6007 | ||
|
|
f8ecf14763 | ||
|
|
d2f7e15fcd | ||
|
|
66ac772585 | ||
|
|
dd365e0b14 | ||
|
|
d612656978 | ||
|
|
91787c4dbf | ||
|
|
c534a9d78c | ||
|
|
06053027a9 | ||
|
|
9291d15215 | ||
|
|
d07036b8ec | ||
|
|
cb73eaf776 | ||
|
|
bb38d8d1ca | ||
|
|
cc269337f2 | ||
|
|
a2aa5fc650 | ||
|
|
26d4f21fa7 | ||
|
|
7f390a5499 | ||
|
|
b9f38bcefd | ||
|
|
81b1f61aec | ||
|
|
ab83d86300 | ||
|
|
450cad7a4d | ||
|
|
c1ee744205 | ||
|
|
f21afb3277 | ||
|
|
7948a25945 | ||
|
|
7711131d5c | ||
|
|
c6119efb04 | ||
|
|
d0dee6cb50 | ||
|
|
e3bbfe3052 | ||
|
|
85a460afb7 | ||
|
|
28a2dba9f7 | ||
|
|
4e7f86979d | ||
|
|
303390bf00 | ||
|
|
623e81a422 | ||
|
|
13e574db3f | ||
|
|
7bd4aae433 | ||
|
|
69382682c4 | ||
|
|
7535b4ac61 | ||
|
|
3bab7d6c53 | ||
|
|
a8a45aede3 | ||
|
|
28c6d72110 | ||
|
|
c3cd14f3c5 | ||
|
|
2010f8dcce | ||
|
|
abcb12f9ed | ||
|
|
283a4dda20 | ||
|
|
3355f39e9f | ||
|
|
a4cd4c0745 | ||
|
|
3834546100 | ||
|
|
a3d7f9cd85 | ||
|
|
10247fcf85 | ||
|
|
b1183e55fd | ||
|
|
b6c9377551 | ||
|
|
c9a4b94efe | ||
|
|
04658cafcc | ||
|
|
27b3a3f33c | ||
|
|
d60a0ef58d | ||
|
|
fff2effd5b | ||
|
|
bb7e473e7b | ||
|
|
908641a414 | ||
|
|
69bd28cc65 | ||
|
|
0126a0d575 | ||
|
|
6cee821138 | ||
|
|
bbed3403e8 | ||
|
|
9a0824af69 | ||
|
|
53375ca728 | ||
|
|
f0503b67eb | ||
|
|
9c0daf0ed5 | ||
|
|
796e6d3a87 | ||
|
|
6112505757 | ||
|
|
9b547c7884 | ||
|
|
1687c48c1b | ||
|
|
f5981c4dca | ||
|
|
6f183aa1cc | ||
|
|
56f6ad84bb | ||
|
|
ed9a29b25f | ||
|
|
20ba6261b6 | ||
|
|
905b27f216 | ||
|
|
c218631c56 | ||
|
|
bd600a6135 | ||
|
|
67c80f683e | ||
|
|
1fb65cbce2 | ||
|
|
7aa5705400 | ||
|
|
bd21214467 | ||
|
|
de8b4da6b5 |
No files matched your search
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: ptitSeb
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: paypal.me/0ptitSeb
|
||||
@@ -59,3 +59,8 @@ build*/
|
||||
src/git_head.h
|
||||
backup/
|
||||
|
||||
# LLVMprivateGenerator
|
||||
/LLVMprivateGenerator/*
|
||||
!/LLVMprivateGenerator/Makefile
|
||||
!/LLVMprivateGenerator/main.cpp
|
||||
!/LLVMprivateGenerator/registered_structs.cpp
|
||||
+78
-11
@@ -5,11 +5,12 @@ 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})
|
||||
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326)
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -50,18 +51,20 @@ if(RPI4ARM64)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
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)
|
||||
elseif(RK3326)
|
||||
add_definitions(-DRK3326)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto")
|
||||
endif()
|
||||
|
||||
if(RK3399)
|
||||
elseif(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
|
||||
elseif(TEGRAX1)
|
||||
add_definitions(-DTEGRAX1)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
|
||||
elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
|
||||
if(NOGIT)
|
||||
@@ -69,7 +72,7 @@ if(NOGIT)
|
||||
endif()
|
||||
|
||||
if(HAVE_TRACE)
|
||||
set(BOX64 box64t)
|
||||
set(BOX64 box64)
|
||||
else()
|
||||
set(BOX64 box64)
|
||||
endif()
|
||||
@@ -200,6 +203,9 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
@@ -208,6 +214,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
|
||||
@@ -217,6 +224,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpcre.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
|
||||
@@ -230,6 +238,14 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbglx.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbimage.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshape.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcomposite.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcursor.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxdamage.c"
|
||||
@@ -248,6 +264,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedmpg123.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
@@ -274,6 +291,8 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
|
||||
)
|
||||
|
||||
@@ -339,7 +358,7 @@ if(ARM_DYNAREC)
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
|
||||
@@ -403,17 +422,30 @@ endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--image-base=${BOX64_ELF_ADDRESS}")
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
if(NOT NOLOADADDR)
|
||||
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
|
||||
else()
|
||||
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
|
||||
if(_x86_64 OR _aarch64)
|
||||
add_definitions(-DCONFIG_64BIT)
|
||||
endif()
|
||||
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX64}
|
||||
@@ -434,6 +466,36 @@ if(NOT TARGET uninstall)
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
|
||||
set(CPACK_PACKAGE_CONTACT "[email protected]")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Box64 - Linux Userspace x86_64 Emulator with a twist")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MAJOR\\s*")
|
||||
string(REGEX REPLACE "BOX64_MAJOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_MAJOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MINOR\\s*")
|
||||
string(REGEX REPLACE "BOX64_MINOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_MINOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_REVISION\\s*")
|
||||
string(REGEX REPLACE "BOX64_REVISION" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_REVISION ${TEMP_STRING})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX64_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${BOX64_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
|
||||
if(_aarch64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
elseif(_x86_64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
|
||||
else()
|
||||
#probably wrong...
|
||||
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||
endif()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
INCLUDE(CPack)
|
||||
|
||||
add_test(test01 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
|
||||
@@ -519,6 +581,11 @@ add_test(test17 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.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)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
all: dumpSigs
|
||||
|
||||
dumpSigs: main.o registered_structs.o
|
||||
g++ -g3 -std=gnu++17 -fno-rtti main.o registered_structs.o -o dumpSigs "-L$(LLVM_install_dir)/lib" -lclang-cpp -lclangTooling -Wl,-rpath "-Wl,$(LLVM_install_dir)/lib"
|
||||
|
||||
main.o: main.cpp
|
||||
g++ -g3 -std=gnu++17 -fno-rtti -c main.cpp -Wfatal-errors "-I$(LLVM_install_dir)/include" -o main.o
|
||||
registered_structs.o: registered_structs.cpp
|
||||
g++ -g3 -std=gnu++17 -fno-rtti -c registered_structs.cpp -Wfatal-errors -o registered_structs.o
|
||||
|
||||
clean:
|
||||
$(RM) dumpSigs main.o registered_structs.o
|
||||
@@ -0,0 +1,458 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/Decl.h>
|
||||
#include <clang/AST/Mangle.h>
|
||||
#include <clang/AST/PrettyPrinter.h>
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Frontend/FrontendActions.h>
|
||||
#include <clang/Tooling/CommonOptionsParser.h>
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
|
||||
clang::MangleContext *mangler = nullptr;
|
||||
|
||||
std::unordered_map<std::string, std::pair<std::string, bool>> funMap;
|
||||
std::vector<std::string> funList;
|
||||
|
||||
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig);
|
||||
clang::QualType getPointedType(const clang::QualType q) {
|
||||
if (const clang::PointerType *p = q->getAs<clang::PointerType>())
|
||||
return getPointedType(p->getPointeeType());
|
||||
else if (const clang::ReferenceType *r = q->getAs<clang::ReferenceType>())
|
||||
return getPointedType(r->getPointeeType());
|
||||
else
|
||||
return q;
|
||||
}
|
||||
|
||||
std::string record2name(const clang::RecordDecl &q, const clang::QualType *qorig) {
|
||||
std::string s = q.getNameAsString();
|
||||
if (s == "") {
|
||||
if (!qorig) return "????.!";
|
||||
if (const clang::TypedefType *tt = (*qorig)->getAs<clang::TypedefType>()) {
|
||||
// Typedef
|
||||
if (clang::TypedefNameDecl *td = tt->getDecl()) {
|
||||
return td->getNameAsString();
|
||||
} else {
|
||||
return "<typedef with no declaration>";
|
||||
}
|
||||
} else {
|
||||
return std::string("<unknown type ") + (*qorig)->getTypeClassName() + ">";
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
char ptr2char(const std::string &str) __attribute__((const));
|
||||
const char *ptr2str(const std::string &str) __attribute__((const));
|
||||
char type2char(const clang::QualType &qual /* Canonical */, const clang::QualType *qorig) {
|
||||
if (qual->isBuiltinType()) {
|
||||
switch (static_cast<const clang::BuiltinType&>(*qual).getKind()) {
|
||||
case clang::BuiltinType::Kind::Void:
|
||||
return 'v';
|
||||
case clang::BuiltinType::Kind::Bool:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::Char_U:
|
||||
return 'C';
|
||||
case clang::BuiltinType::Kind::Char_S:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::Char8:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::UChar:
|
||||
return 'C';
|
||||
case clang::BuiltinType::Kind::SChar:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::WChar_U:
|
||||
return 'W';
|
||||
case clang::BuiltinType::Kind::UShort:
|
||||
return 'W';
|
||||
case clang::BuiltinType::Kind::WChar_S:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::Char16:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::Short:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::UInt:
|
||||
return 'u';
|
||||
case clang::BuiltinType::Kind::Char32:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::Int:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::ULong:
|
||||
return 'L';
|
||||
case clang::BuiltinType::Kind::Long:
|
||||
return 'l';
|
||||
case clang::BuiltinType::Kind::ULongLong:
|
||||
return 'U';
|
||||
case clang::BuiltinType::Kind::LongLong:
|
||||
return 'I';
|
||||
case clang::BuiltinType::Kind::UInt128:
|
||||
return 'H';
|
||||
case clang::BuiltinType::Kind::Int128:
|
||||
return 'H';
|
||||
case clang::BuiltinType::Kind::Float:
|
||||
return 'f';
|
||||
case clang::BuiltinType::Kind::Double:
|
||||
return 'd';
|
||||
case clang::BuiltinType::Kind::LongDouble:
|
||||
return 'D';
|
||||
case clang::BuiltinType::Kind::NullPtr:
|
||||
return 'p'; // nullptr_t
|
||||
|
||||
case clang::BuiltinType::Kind::Half:
|
||||
case clang::BuiltinType::Kind::BFloat16:
|
||||
case clang::BuiltinType::Kind::ShortAccum:
|
||||
case clang::BuiltinType::Kind::Accum:
|
||||
case clang::BuiltinType::Kind::LongAccum:
|
||||
case clang::BuiltinType::Kind::UShortAccum:
|
||||
case clang::BuiltinType::Kind::UAccum:
|
||||
case clang::BuiltinType::Kind::ULongAccum:
|
||||
case clang::BuiltinType::Kind::ShortFract:
|
||||
case clang::BuiltinType::Kind::Fract:
|
||||
case clang::BuiltinType::Kind::LongFract:
|
||||
case clang::BuiltinType::Kind::UShortFract:
|
||||
case clang::BuiltinType::Kind::UFract:
|
||||
case clang::BuiltinType::Kind::ULongFract:
|
||||
case clang::BuiltinType::Kind::SatShortAccum:
|
||||
case clang::BuiltinType::Kind::SatAccum:
|
||||
case clang::BuiltinType::Kind::SatLongAccum:
|
||||
case clang::BuiltinType::Kind::SatUShortAccum:
|
||||
case clang::BuiltinType::Kind::SatUAccum:
|
||||
case clang::BuiltinType::Kind::SatULongAccum:
|
||||
case clang::BuiltinType::Kind::SatShortFract:
|
||||
case clang::BuiltinType::Kind::SatFract:
|
||||
case clang::BuiltinType::Kind::SatLongFract:
|
||||
case clang::BuiltinType::Kind::SatUShortFract:
|
||||
case clang::BuiltinType::Kind::SatUFract:
|
||||
case clang::BuiltinType::Kind::SatULongFract:
|
||||
case clang::BuiltinType::Kind::Float16:
|
||||
case clang::BuiltinType::Kind::Float128:
|
||||
case clang::BuiltinType::Kind::Overload:
|
||||
case clang::BuiltinType::Kind::BoundMember:
|
||||
case clang::BuiltinType::Kind::PseudoObject:
|
||||
case clang::BuiltinType::Kind::Dependent:
|
||||
case clang::BuiltinType::Kind::UnknownAny:
|
||||
case clang::BuiltinType::Kind::ARCUnbridgedCast:
|
||||
case clang::BuiltinType::Kind::BuiltinFn:
|
||||
case clang::BuiltinType::Kind::ObjCId:
|
||||
case clang::BuiltinType::Kind::ObjCClass:
|
||||
case clang::BuiltinType::Kind::ObjCSel:
|
||||
#define IMAGE_TYPE(it, id, si, a, s) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/OpenCLImageTypes.def>
|
||||
#undef IMAGE_TYPE
|
||||
case clang::BuiltinType::Kind::OCLSampler:
|
||||
case clang::BuiltinType::Kind::OCLEvent:
|
||||
case clang::BuiltinType::Kind::OCLClkEvent:
|
||||
case clang::BuiltinType::Kind::OCLQueue:
|
||||
case clang::BuiltinType::Kind::OCLReserveID:
|
||||
case clang::BuiltinType::Kind::IncompleteMatrixIdx:
|
||||
case clang::BuiltinType::Kind::OMPArraySection:
|
||||
case clang::BuiltinType::Kind::OMPArrayShaping:
|
||||
case clang::BuiltinType::Kind::OMPIterator:
|
||||
#define EXT_OPAQUE_TYPE(et, id, e) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/OpenCLExtensionTypes.def>
|
||||
#define SVE_TYPE(n, id, si) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/AArch64SVEACLETypes.def>
|
||||
#define PPC_VECTOR_TYPE(n, id, s) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/PPCTypes.def>
|
||||
#undef EXT_OPAQUE_TYPE
|
||||
#undef SVE_TYPE
|
||||
#undef PPC_VECTOR_TYPE
|
||||
return '!';
|
||||
default:
|
||||
return ':';
|
||||
}
|
||||
} else if (qual->isEnumeralType()) {
|
||||
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
|
||||
if (!ed) {
|
||||
return 'i';
|
||||
} else {
|
||||
return type2char(ed->getIntegerType().getCanonicalType(), qorig);
|
||||
}
|
||||
} else if (qual->isFunctionPointerType()) {
|
||||
return '@';
|
||||
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
|
||||
const clang::QualType &pointed = getPointedType(qual);
|
||||
if (isTypeTrivial(pointed, qorig)) {
|
||||
return 'p';
|
||||
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return '!';
|
||||
} else if (!rc->isCompleteDefinition()) {
|
||||
return 'p';
|
||||
} else {
|
||||
std::string str;
|
||||
if (qorig) {
|
||||
const clang::QualType qpted = getPointedType(*qorig);
|
||||
str = record2name(*rc, &qpted);
|
||||
} else {
|
||||
str = record2name(*rc, nullptr);
|
||||
}
|
||||
char ret = ptr2char(str);
|
||||
if (ret) return ret;
|
||||
else {
|
||||
return '!';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return '!';
|
||||
}
|
||||
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return '?';
|
||||
} else if (rc->getNameAsString() == "__builtin_va_list") {
|
||||
// va_list
|
||||
return 'A';
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig) {
|
||||
const char c = type2char(q, qorig);
|
||||
#define GO(chr) || (c == chr)
|
||||
return (c == 'v')
|
||||
GO('i') GO('u')
|
||||
GO('I') GO('U')
|
||||
GO('l') GO('L')
|
||||
GO('f') GO('d')
|
||||
GO('D') GO('K')
|
||||
GO('0') GO('1')
|
||||
GO('C') GO('c')
|
||||
GO('W') GO('w')
|
||||
GO('H')
|
||||
GO('p');
|
||||
#undef GO
|
||||
}
|
||||
bool isTypeValid(const clang::QualType &q, const clang::QualType *qorig) {
|
||||
const char c = type2char(q, qorig);
|
||||
if (c == 'A') return false;
|
||||
if (c == 'V') return false;
|
||||
return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
|
||||
}
|
||||
|
||||
const std::string type2string(const clang::QualType &qual, const clang::QualType *qorig) {
|
||||
if (qual->isBuiltinType()) {
|
||||
return std::string("(builtin) ") + static_cast<const clang::BuiltinType&>(*qual).getName(clang::PrintingPolicy{{}}).data();
|
||||
} else if (qual->isFunctionPointerType()) {
|
||||
return "Callback (function pointer)";
|
||||
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
|
||||
std::string prefix = qual->isAnyPointerType() ? "Pointer to " : "Reference to ";
|
||||
const clang::QualType &pointed = getPointedType(qual);
|
||||
if (isTypeTrivial(pointed, qorig)) {
|
||||
return prefix + "trivial object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
|
||||
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return prefix + "unknown record";
|
||||
} else if (!rc->isCompleteDefinition()) {
|
||||
return prefix + "incomplete record " + rc->getNameAsString();
|
||||
} else {
|
||||
std::string str;
|
||||
if (qorig) {
|
||||
const clang::QualType qpted = getPointedType(*qorig);
|
||||
str = record2name(*rc, &qpted);
|
||||
} else {
|
||||
str = record2name(*rc, nullptr);
|
||||
}
|
||||
const char *ret = ptr2str(str);
|
||||
if (ret[0] != '\0') {
|
||||
return prefix + ret;
|
||||
} else {
|
||||
if (mangler && mangler->shouldMangleDeclName(rc)) {
|
||||
std::string mangled;
|
||||
{
|
||||
llvm::raw_string_ostream strstr{mangled};
|
||||
mangler->mangleName(rc, strstr);
|
||||
}
|
||||
return prefix + "unknown record " + str + " (=== " + mangled + ")";
|
||||
} else {
|
||||
return prefix + "unknown record " + str;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return prefix + "non-trivial or typedef'ed object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
|
||||
//return "Pointer (maybe to callback)";
|
||||
}
|
||||
} else if (qual->isEnumeralType()) {
|
||||
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
|
||||
if (!ed) {
|
||||
return "Enumeration with unknown underlying integer type (assuming int)";
|
||||
} else {
|
||||
return "Enumeration with underlying type " + type2string(ed->getIntegerType().getCanonicalType(), nullptr);
|
||||
}
|
||||
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return "Unknown record";
|
||||
} else if (rc->getNameAsString() == "__builtin_va_list") {
|
||||
return "va_list";
|
||||
} else {
|
||||
return "Unknown record " + std::string(rc->getName().data());
|
||||
}
|
||||
} else {
|
||||
return std::string("??? ") + qual->getTypeClassName();
|
||||
}
|
||||
}
|
||||
|
||||
class Visitor : public clang::RecursiveASTVisitor<Visitor> {
|
||||
public:
|
||||
clang::ASTContext &context;
|
||||
|
||||
bool shouldVisitTemplateInstantiations() const /* override */ { return true; }
|
||||
|
||||
Visitor(clang::CompilerInstance &ci) : context(ci.getASTContext()) {
|
||||
if (!mangler) {
|
||||
mangler = clang::ItaniumMangleContext::create(context, ci.getDiagnostics());
|
||||
}
|
||||
}
|
||||
|
||||
~Visitor() {
|
||||
if (mangler) {
|
||||
delete mangler;
|
||||
mangler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool VisitDecl(clang::Decl *decl) /* override */ {
|
||||
std::cerr << std::flush;
|
||||
if (!decl) return true;
|
||||
|
||||
if ((decl->getKind() >= clang::Decl::Kind::firstFunction) && (decl->getKind() <= clang::Decl::Kind::lastFunction)) {
|
||||
clang::DeclaratorDecl *ddecl = static_cast<clang::DeclaratorDecl*>(decl);
|
||||
std::cout << "Function detected!\n";
|
||||
|
||||
std::string funName{ddecl->getName()};
|
||||
|
||||
auto niceprint = [](const std::string &infotype, const auto &dat){ std::cout << " " << infotype << ": " << dat << "\n"; };
|
||||
niceprint("Function name", funName);
|
||||
if (mangler && mangler->shouldMangleDeclName(ddecl)) {
|
||||
std::string mangled;
|
||||
{
|
||||
llvm::raw_string_ostream strstr{mangled};
|
||||
mangler->mangleName(ddecl, strstr);
|
||||
}
|
||||
niceprint("Function mangled name", mangled);
|
||||
funName = std::move(mangled);
|
||||
}
|
||||
|
||||
bool valid;
|
||||
std::string funTypeStr{""};
|
||||
if (ddecl->getFunctionType()->isFunctionNoProtoType()) {
|
||||
const clang::FunctionNoProtoType *funType = static_cast<const clang::FunctionNoProtoType*>(ddecl->getFunctionType());
|
||||
const auto &retType = funType->getReturnType();
|
||||
|
||||
niceprint("Function return type", type2string(retType, &retType));
|
||||
niceprint("Canonical function return type",
|
||||
type2string(retType.getCanonicalType(), &retType) +
|
||||
" (" + type2char(retType.getCanonicalType(), &retType) + ")");
|
||||
niceprint("Is sugared", funType->isSugared());
|
||||
if (funType->isSugared()) {
|
||||
clang::QualType qft{funType, 0};
|
||||
niceprint("Desugared", type2string(funType->desugar(), &qft));
|
||||
}
|
||||
|
||||
funTypeStr = type2char(retType.getCanonicalType(), &retType) + std::string("Fv");
|
||||
valid = isTypeValid(retType.getCanonicalType(), &retType);
|
||||
} else {
|
||||
const clang::FunctionProtoType *funType = static_cast<const clang::FunctionProtoType*>(ddecl->getFunctionType());
|
||||
const auto &retType = funType->getReturnType();
|
||||
|
||||
niceprint("Function return type", type2string(retType, &retType));
|
||||
niceprint("Canonical function return type",
|
||||
type2string(retType.getCanonicalType(), &retType)
|
||||
+ " (" + type2char(retType.getCanonicalType(), &retType) + ")");
|
||||
niceprint("Parameter count", funType->getNumParams());
|
||||
for (const clang::QualType &type : funType->getParamTypes()) {
|
||||
niceprint(" " + type2string(type, &type),
|
||||
type2string(type.getCanonicalType(), &type) + " (" + type2char(type.getCanonicalType(), &type) + ")");
|
||||
}
|
||||
niceprint("Variadic function", funType->isVariadic() ? "yes" : "no");
|
||||
|
||||
funTypeStr =
|
||||
type2char(retType.getCanonicalType(), &retType) +
|
||||
((funType->getNumParams() == 0)
|
||||
? std::string("Fv") : std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), std::string("F"),
|
||||
[](const std::string &acc, const clang::QualType &qual){ return acc + type2char(qual.getCanonicalType(), &qual); }));
|
||||
if (funType->isVariadic()) funTypeStr += "V";
|
||||
valid = !funType->isVariadic() &&
|
||||
std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), isTypeValid(retType.getCanonicalType(), &retType),
|
||||
[](bool acc, const clang::QualType &qual){ return acc && isTypeValid(qual.getCanonicalType(), &qual); });
|
||||
}
|
||||
|
||||
niceprint("Conclusion", "");
|
||||
niceprint("Function final name", funName);
|
||||
niceprint("Function type", funTypeStr);
|
||||
niceprint("Valid function type", valid ? "yes" : "no");
|
||||
std::cout << "\n";
|
||||
|
||||
funMap[funName] = std::make_pair(funTypeStr, valid);
|
||||
funList.push_back(funName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Consumer : public clang::ASTConsumer {
|
||||
public:
|
||||
Visitor visitor;
|
||||
|
||||
Consumer(clang::CompilerInstance &ci) : visitor(ci) {
|
||||
}
|
||||
|
||||
void HandleTranslationUnit(clang::ASTContext &context) override {
|
||||
visitor.TraverseDecl(context.getTranslationUnitDecl());
|
||||
}
|
||||
};
|
||||
|
||||
class Action : public clang::ASTFrontendAction {
|
||||
public:
|
||||
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef inFile) override {
|
||||
return std::make_unique<Consumer>(ci);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " (filenames) -- [-I...]" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*int fakeargc = argc + 1;
|
||||
const char **fakeargv = new const char*[fakeargc];
|
||||
memcpy(fakeargv, argv, argc * sizeof(char*));
|
||||
fakeargv[fakeargc - 1] = "--";*/
|
||||
llvm::cl::OptionCategory opcat{""};
|
||||
clang::tooling::CommonOptionsParser op{argc, argv, opcat};
|
||||
std::vector<std::string> paths; for (int i = 1; i < argc; ++i) paths.push_back(argv[i]);
|
||||
|
||||
clang::tooling::ClangTool tool{op.getCompilations(), paths};
|
||||
|
||||
tool.run(clang::tooling::newFrontendActionFactory<Action>().get());
|
||||
|
||||
std::cout << "Done, outputing output.h" << std::endl;
|
||||
std::sort(funList.begin(), funList.end());
|
||||
std::fstream file{"output.h", std::ios_base::out};
|
||||
for (const std::string &funName : funList) {
|
||||
if (!funMap[funName].second) {
|
||||
file << "//";
|
||||
}
|
||||
file << "GO(" << funName << ", " << funMap[funName].first << ")\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
#include <string>
|
||||
|
||||
#define ALL START() \
|
||||
/* libc */ \
|
||||
STRUCT("_IO_FILE", "a FILE") \
|
||||
STRUCT("_G_fpos_t", "a file position") \
|
||||
STRUCT("sockaddr", "a socket address") \
|
||||
STRUCT("itimerspec", "an itimerspec") \
|
||||
STRUCT("timespec", "a timespec") \
|
||||
STRUCT("itimerval", "an itimerval") \
|
||||
STRUCT("timeval", "a timeval") \
|
||||
STRUCT("timex", "a timex") \
|
||||
STRUCT("timezone", "a timezone") \
|
||||
STRUCT("dirent", "a dirent") \
|
||||
STRUCT("dirent64", "a dirent64") \
|
||||
STRUCT("__dirstream", "a dir stream") \
|
||||
STRUCT("tm", "a time structure (tm)") \
|
||||
STRUCT("cmsghdr", "a cmsghdr") \
|
||||
STRUCT("msghdr", "a msghdr") \
|
||||
STRUCT("rpcent", "an rpcent") \
|
||||
STRUCT("random_data", "a random_data structure") \
|
||||
STRUCT("drand48_data", "a drand48_data structure") \
|
||||
STRUCT("termios", "a termios") \
|
||||
STRUCT("iovec", "an iovec") \
|
||||
STRUCT("file_handle", "a file handle") \
|
||||
STRUCT("lconv", "an lconv") \
|
||||
STRUCT("__locale_struct", "a locale structure") \
|
||||
STRUCT("aliasent", "an alias") \
|
||||
STRUCT("fstab", "an fstab") \
|
||||
STRUCT("group", "a group") \
|
||||
STRUCT("hostent", "a hostent") \
|
||||
STRUCT("protoent", "a protoent") \
|
||||
STRUCT("passwd", "a password") \
|
||||
STRUCT("spwd", "an spwd") \
|
||||
STRUCT("ttyent", "a ttyent") \
|
||||
STRUCT("utmp", "an utmp structure") \
|
||||
STRUCT("utmpx", "an utmpx structure") \
|
||||
STRUCT("ifaddrs", "an ifaddrs structure") \
|
||||
STRUCT("statfs", "a statfs structure") \
|
||||
STRUCT("statfs64", "a statfs64 structure") \
|
||||
STRUCT("statvfs", "a statvfs structure") \
|
||||
STRUCT("statvfs64", "a statvfs64 structure") \
|
||||
STRUCT("timeb", "a timeb structure") \
|
||||
STRUCT("_ftsent", "an _ftsent structure") \
|
||||
STRUCT("sysinfo", "a sysinfo structure") \
|
||||
STRUCT("rlimit", "an rlimit structure") \
|
||||
STRUCT("rlimit64", "an rlimit64 structure") \
|
||||
STRUCT("rusage", "an rusage structure") \
|
||||
STRUCT("entry", "an entry structure") \
|
||||
STRUCT("pollfd", "a pollfd structure") \
|
||||
STRUCT("re_pattern_buffer", "a re_pattern_buffer structure") \
|
||||
STRUCT("sembuf", "a sembuf structure") \
|
||||
STRUCT("tms", "a tms structure") \
|
||||
STRUCT("utsname", "an utsname structure") \
|
||||
STRUCT("utimbuf", "an utimbuf structure") \
|
||||
STRUCT2("__va_list_tag", "__va_list_tag (aka, a va_list)", 'A') \
|
||||
/* ncurses */ \
|
||||
STRUCT("_win_st", "a _win_st structure") \
|
||||
STRUCT("MEVENT", "an MEVENT structure") \
|
||||
TYPEDEF("cchar_t", "a cchar_t") \
|
||||
/* zlib */ \
|
||||
STRUCT("gz_header_s", "a gz_header_s structure") \
|
||||
STRUCT("gzFile_s", "a gzFile_s structure") \
|
||||
STRUCT("z_stream_s", "a z_stream_s structure") \
|
||||
\
|
||||
END()
|
||||
|
||||
#define START()
|
||||
#define STRUCT(s, ret) if (str == s) { return 'p'; } else
|
||||
#define STRUCT2(s, ret, c) if (str == s) { return c; } else
|
||||
#define TYPEDEF(s, ret) if (str == s) { return 'p'; } else
|
||||
#define END() { return 0; }
|
||||
char ptr2char(const std::string &str) {
|
||||
/*if ((str == "_IO_FILE")
|
||||
|| (str == "_G_fpos_t")
|
||||
|| (str == "sockaddr")
|
||||
|| (str == "itimerspec")
|
||||
|| (str == "timespec")
|
||||
|| (str == "itimerval")
|
||||
|| (str == "timeval")
|
||||
|| (str == "timex")
|
||||
|| (str == "timezone")
|
||||
|| (str == "dirent")
|
||||
|| (str == "dirent64")
|
||||
|| (str == "__dirstream")
|
||||
|| (str == "tm")
|
||||
|| (str == "cmsghdr")
|
||||
|| (str == "msghdr")
|
||||
|| (str == "rpcent")
|
||||
|| (str == "random_data")
|
||||
|| (str == "drand48_data")
|
||||
|| (str == "termios")
|
||||
|| (str == "iovec")
|
||||
|| (str == "file_handle")
|
||||
|| (str == "lconv")
|
||||
|| (str == "__locale_struct")
|
||||
|| (str == "aliasent")
|
||||
|| (str == "fstab")
|
||||
|| (str == "group")
|
||||
|| (str == "hostent")
|
||||
|| (str == "protoent")
|
||||
|| (str == "passwd")
|
||||
|| (str == "spwd")
|
||||
|| (str == "ttyent")
|
||||
|| (str == "utmp")
|
||||
|| (str == "utmpx")
|
||||
|| (str == "ifaddrs")
|
||||
|| (str == "statfs")
|
||||
|| (str == "statfs64")
|
||||
|| (str == "statvfs")
|
||||
|| (str == "timeb")
|
||||
|| (str == "_ftsent")
|
||||
|| (str == "sysinfo")
|
||||
|| (str == "rlimit")
|
||||
|| (str == "rlimit64")
|
||||
|| (str == "rusage")
|
||||
|| (str == "entry")
|
||||
|| (str == "pollfd")
|
||||
|| (str == "re_pattern_buffer")
|
||||
|| (str == "sembuf")
|
||||
|| (str == "tms")
|
||||
|| (str == "utsname")
|
||||
|| (str == "utimbuf")
|
||||
// ncurses
|
||||
|| (str == "_win_st")
|
||||
|
||||
|| (str == "cchar_t")
|
||||
) {
|
||||
// FILE*, fpos_t*, ...
|
||||
return 'p';
|
||||
} else if (str == "__va_list_tag") {
|
||||
return 'A';
|
||||
} else {
|
||||
return 0;
|
||||
}*/
|
||||
ALL
|
||||
}
|
||||
#undef END
|
||||
#undef TYPEDEF
|
||||
#undef STRUCT2
|
||||
#undef STRUCT
|
||||
#undef START
|
||||
|
||||
#define START()
|
||||
#define STRUCT(s, ret) if (str == s) { return ret; } else
|
||||
#define STRUCT2(s, ret, c) if (str == s) { return ret; } else
|
||||
#define TYPEDEF(s, ret) if (str == s) { return ret; } else
|
||||
#define END() return "";
|
||||
const char *ptr2str(const std::string &str) {
|
||||
/*if (str == "_IO_FILE") {
|
||||
return "a FILE";
|
||||
} else if (str == "_G_fpos_t") {
|
||||
return "a file position";
|
||||
} else if (str == "sockaddr") {
|
||||
return "a socket address";
|
||||
} else if (str == "itimerspec") {
|
||||
return "an itimerspec";
|
||||
} else if (str == "timespec") {
|
||||
return "a timespec";
|
||||
} else if (str == "itimerval") {
|
||||
return "an itimerval";
|
||||
} else if (str == "timeval") {
|
||||
return "a timeval";
|
||||
} else if (str == "timex") {
|
||||
return "a timex";
|
||||
} else if (str == "timezone") {
|
||||
return "a timezone";
|
||||
} else if (str == "dirent") {
|
||||
return "a dirent";
|
||||
} else if (str == "dirent64") {
|
||||
return "a dirent64";
|
||||
} else if (str == "__dirstream") {
|
||||
return "a dir stream";
|
||||
} else if (str == "tm") {
|
||||
return "a time structure (tm)";
|
||||
} else if (str == "cmsghdr") {
|
||||
return "a cmsghdr";
|
||||
} else if (str == "msghdr") {
|
||||
return "a msghdr";
|
||||
} else if (str == "rpcent") {
|
||||
return "an rpcent";
|
||||
} else if (str == "random_data") {
|
||||
return "a random_data structure";
|
||||
} else if (str == "drand48_data") {
|
||||
return "a drand48_data structure";
|
||||
} else if (str == "termios") {
|
||||
return "a termios";
|
||||
} else if (str == "iovec") {
|
||||
return "an iovec";
|
||||
} else if (str == "file_handle") {
|
||||
return "a file handle";
|
||||
} else if (str == "lconv") {
|
||||
return "an lconv";
|
||||
} else if (str == "__locale_struct") {
|
||||
return "a locale structure";
|
||||
} else if (str == "aliasent") {
|
||||
return "an alias";
|
||||
} else if (str == "fstab") {
|
||||
return "an fstab";
|
||||
} else if (str == "group") {
|
||||
return "a group";
|
||||
} else if (str == "hostent") {
|
||||
return "a hostent";
|
||||
} else if (str == "protoent") {
|
||||
return "a protoent";
|
||||
} else if (str == "passwd") {
|
||||
return "a password";
|
||||
} else if (str == "spwd") {
|
||||
return "an spwd";
|
||||
} else if (str == "ttyent") {
|
||||
return "a ttyent";
|
||||
} else if (str == "utmp") {
|
||||
return "an utmp structure";
|
||||
} else if (str == "utmpx") {
|
||||
return "an utmpx structure";
|
||||
} else if (str == "ifaddrs") {
|
||||
return "an ifaddrs structure";
|
||||
} else if (str == "statfs") {
|
||||
return "a statfs structure";
|
||||
} else if (str == "statfs64") {
|
||||
return "a statfs64 structure";
|
||||
} else if (str == "statvfs") {
|
||||
return "a statvfs structure";
|
||||
} else if (str == "statvfs64") {
|
||||
return "a statvfs64 structure";
|
||||
} else if (str == "timeb") {
|
||||
return "a timeb structure";
|
||||
} else if (str == "_ftsent") {
|
||||
return "an _ftsent structure";
|
||||
} else if (str == "sysinfo") {
|
||||
return "a sysinfo structure";
|
||||
} else if (str == "rlimit") {
|
||||
return "an rlimit structure";
|
||||
} else if (str == "rlimit64") {
|
||||
return "an rlimit64 structure";
|
||||
} else if (str == "rusage") {
|
||||
return "an rusage structure";
|
||||
} else if (str == "entry") {
|
||||
return "an entry structure";
|
||||
} else if (str == "pollfd") {
|
||||
return "a pollfd structure";
|
||||
} else if (str == "re_pattern_buffer") {
|
||||
return "a re_pattern_buffer structure";
|
||||
} else if (str == "sembuf") {
|
||||
return "a sembuf structure";
|
||||
} else if (str == "tms") {
|
||||
return "a tms structure";
|
||||
} else if (str == "utsname") {
|
||||
return "an utsname structure";
|
||||
} else if (str == "utimbuf") {
|
||||
return "an utimbuf structure";
|
||||
} else if (str == "__va_list_tag") {
|
||||
return "__va_list_tag (aka, a va_list)";
|
||||
// ncurses
|
||||
} else if (str == "_win_st") {
|
||||
return "a _win_st structure";
|
||||
|
||||
} else if (str == "cchar_t") {
|
||||
return "a cchar_t";
|
||||
} else return "";*/
|
||||
ALL
|
||||
}
|
||||
#undef END
|
||||
#undef TYPEDEF
|
||||
#undef STRUCT2
|
||||
#undef STRUCT
|
||||
#undef START
|
||||
@@ -1,51 +0,0 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
----
|
||||
|
||||
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
|
||||
|
||||
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
|
||||
|
||||
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/emu/x86primop.c) for copyright details
|
||||
|
||||
<img src="Box64Icon.png" width="96" height="96">
|
||||
|
||||
Logo and Icon made by @grayduck, thanks!
|
||||
|
||||
----
|
||||
|
||||
Usage
|
||||
----
|
||||
|
||||
There are a few environment variables to control the behaviour of Box64.
|
||||
|
||||
See [here](USAGE.md) for all environment variables and what they do.
|
||||
|
||||
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
|
||||
|
||||
----
|
||||
|
||||
Compiling/Installation
|
||||
----
|
||||
> Compilation instructions can be found [here](COMPILE.md)
|
||||
|
||||
----
|
||||
|
||||
Version history
|
||||
----
|
||||
|
||||
The change log is available [here](CHANGELOG.md)
|
||||
|
||||
----
|
||||
|
||||
Final words
|
||||
----
|
||||
|
||||
(If you use Box64 in your project, please don't forget to mention Box64!)
|
||||
@@ -1,3 +1,6 @@
|
||||
Current Version
|
||||
======
|
||||
|
||||
v0.1.2
|
||||
======
|
||||
* OpenSource!
|
||||
@@ -31,6 +31,22 @@ If it's the first install, you also need:
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for TEGRA X1
|
||||
|
||||
Using a 64bits OS:
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
If it's the first install, you also need:
|
||||
```
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for Other ARM64 Linux platforms
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
@@ -57,11 +73,11 @@ The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both opti
|
||||
|
||||
*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 a trace enabled build ( ***the interpretor will be slightly 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*
|
||||
|
||||
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).
|
||||
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`.
|
||||
|
||||
*Not building from a git clone*
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
----
|
||||
|
||||
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
|
||||
|
||||
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
|
||||
|
||||
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](../src/emu/x64primop.c) for copyright details
|
||||
|
||||
<img src="img/Box64Icon.png" width="96" height="96">
|
||||
|
||||
Logo and Icon made by @grayduck, thanks!
|
||||
|
||||
----
|
||||
|
||||
Usage
|
||||
----
|
||||
|
||||
There are a few environment variables to control the behaviour of Box64.
|
||||
|
||||
See [here](USAGE.md) for all environment variables and what they do.
|
||||
|
||||
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
|
||||
|
||||
----
|
||||
|
||||
Compiling/Installation
|
||||
----
|
||||
> Compilation instructions can be found [here](COMPILE.md)
|
||||
|
||||
----
|
||||
|
||||
Version history
|
||||
----
|
||||
|
||||
The change log is available [here](CHANGELOG.md)
|
||||
|
||||
----
|
||||
|
||||
Notes about 32-bit platforms
|
||||
----
|
||||
|
||||
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bits libraries. Box64 doesn't include any 64-bits <-> 32-bits translation.
|
||||
|
||||
So understand that box64 will only runs 64bits linux binaries. For 32bits binaries, you need box86 (with all the multiarch or proot trickery it imply on 64bits OS).
|
||||
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when argument is "-m"
|
||||
|
||||
----
|
||||
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not always emulated in a 100% accurate way).
|
||||
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
So, not all Unity games work and can require a high OpenGL profile, but many actualy works now
|
||||
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game start then quit before showing anything.
|
||||
|
||||
----
|
||||
|
||||
Notes about GTK programs
|
||||
----
|
||||
|
||||
GTK libraries are not wrapped yet on box64 (contrary to box86). Many games use gtk (setup too), like Unity game for the Screen Selection dialog. While Unity game can run without that dialog (using default setup), many just can't. For now, you'll need o put the set of gtk x86_64 libraries in the game folder (or some other folder known by box64) to get gtk support. GTK Wrapping is planned on box64.
|
||||
|
||||
----
|
||||
|
||||
Notes about Steam
|
||||
----
|
||||
|
||||
Not that Steam is an hybrid 32buts / 64bits. You NEED box86 to run steam, as the client app is a 32bits binaries. It also use a 64bits local server binaries, but like most stuff using libsef/chromium. it's not working correctly on box64 for now.
|
||||
So: no Steam for now on box64.
|
||||
|
||||
----
|
||||
|
||||
Notes about Wine
|
||||
----
|
||||
|
||||
Wine 64bits is supported on box64. Be aware that 64bits wine also include 32bits componant, to be able to run 32bits windws programs. The 32bits will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64bits setup can run both 32bits and 64bits windows program (just use `wine` and `wine64` respectivelly)
|
||||
|
||||
----
|
||||
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
Box64 Does not wrap Vulkan libraries yet. It's planned, but for now, vulkan program will not run on box64.
|
||||
|
||||
----
|
||||
|
||||
Final word
|
||||
----
|
||||
|
||||
I want to thank everyone who has contributed to box64 developpement.
|
||||
There are many ways to contribute: code contribution, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
|
||||
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
And I also thank the many other people who participated even once in the project.
|
||||
|
||||
(If you use Box64 in your project, please don't forget to mention it!)
|
||||
@@ -134,6 +134,11 @@ Allow Box64 to continue even if a library is missing.
|
||||
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
|
||||
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
|
||||
|
||||
#### BOX64_NOPULSE
|
||||
Disables the load of pulseaudio libraries.
|
||||
* 0 : Load pulseaudio libraries if found. (Default.)
|
||||
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
|
||||
|
||||
#### BOX64_JITGDB
|
||||
|
||||
* 0 : Just print the Segfault message on segfault (default)
|
||||
File renamed without changes.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
File renamed without changes.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-arm64-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rk3399-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rk3399-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-rpi-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rpi-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-tegra-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-x64-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-x64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-x64-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-x64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-x64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# The directory containing all PKGBUILDs for BOX64
|
||||
## FAQ
|
||||
### 1. How to use it?
|
||||
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
|
||||
```sh
|
||||
mv ./PKGBUILD-<your-platform> ./PKGBUILD
|
||||
cd ..
|
||||
makepkg -si
|
||||
```
|
||||
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 64-bit Archlinux ARM.
|
||||
|
||||
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
|
||||
|
||||
### 2. What platforms are currently supported.
|
||||
All specified in [COMPILE.md](../COMPILE.md).
|
||||
|
||||
### 3. Any advantages with that sollution?
|
||||
This might give you some advantages like those:
|
||||
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
|
||||
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
|
||||
- your `box64` installation is recognized as a package (where it wasn't when installing with `make install`).
|
||||
|
||||
|
||||
### Note: You can use [makedeb](https://github.com/makedeb/makedeb) (or) [pkgbuild2spec](https://github.com/prozum/pkgbuild2spec) to compile box64 to .deb or .rpm installer files.
|
||||
+675
-325
File diff suppressed because it is too large.
Load diff
+14
-1
@@ -88,6 +88,7 @@ int unlockMutex()
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
|
||||
return ret;
|
||||
@@ -110,6 +111,7 @@ void relockMutex(int locks)
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
}
|
||||
|
||||
@@ -128,6 +130,7 @@ static void init_mutexes(box64context_t* context)
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
@@ -160,7 +163,16 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
|
||||
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
|
||||
// create the vsyscalls
|
||||
context->vsyscalls[0] = AddVSyscall(context->system, 96);
|
||||
context->vsyscalls[1] = AddVSyscall(context->system, 201);
|
||||
context->vsyscalls[2] = AddVSyscall(context->system, 309);
|
||||
// create the alternate to map at address
|
||||
addAlternate((void*)context->vsyscalls[0], (void*)0xffffffffff600000);
|
||||
addAlternate((void*)context->vsyscalls[1], (void*)0xffffffffff600400);
|
||||
addAlternate((void*)context->vsyscalls[2], (void*)0xffffffffff600800);
|
||||
// get handle to box64 itself
|
||||
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
|
||||
context->dlprivate = NewDLPrivate();
|
||||
|
||||
@@ -268,6 +280,7 @@ void FreeBox64Context(box64context_t** context)
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 1
|
||||
#define BOX64_REVISION 2
|
||||
#define BOX64_REVISION 4
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+9
-6
@@ -432,10 +432,11 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
if(!size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
#ifndef USE_MMAP
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -443,6 +444,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
#else
|
||||
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
@@ -708,11 +710,12 @@ void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
}
|
||||
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))
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,8 +754,8 @@ void unprotectDB(uintptr_t addr, size_t size)
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
|
||||
if(prot&PROT_DYNAREC) {
|
||||
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
}
|
||||
|
||||
@@ -230,13 +230,16 @@
|
||||
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
|
||||
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
|
||||
|
||||
#define LDRSH_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSHxw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSBx_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, 0b10, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
#define LDRSBw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, 0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
#define LDRSBxw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSHxw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRSBx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, 0b10, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
#define LDRSBw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, 0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
#define LDRSBxw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
|
||||
|
||||
#define LDRS_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRSW_REG(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
|
||||
|
||||
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
|
||||
#define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
|
||||
@@ -628,9 +631,11 @@
|
||||
|
||||
// REV
|
||||
#define REV_gen(sf, opc, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | (opc)<<10 | (Rn)<<5 | (Rd))
|
||||
#define REVx(Rd, Rn) EMIT(REV_gen(1, 0b11, Rn, Rd))
|
||||
#define REVw(Rd, Rn) EMIT(REV_gen(0, 0b10, Rn, Rd))
|
||||
#define REV64x(Rd, Rn) EMIT(REV_gen(1, 0b11, Rn, Rd))
|
||||
#define REV32w(Rd, Rn) EMIT(REV_gen(0, 0b10, Rn, Rd))
|
||||
#define REVxw(Rd, Rn) EMIT(REV_gen(rex.w, 0b10|rex.w, Rn, Rd))
|
||||
#define REV16w(Rd, Rn) EMIT(REV_gen(0, 0b01, Rn, Rd))
|
||||
#define REV16x(Rd, Rn) EMIT(REV_gen(1, 0b01, Rn, Rd))
|
||||
|
||||
// MRS
|
||||
#define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
|
||||
@@ -992,6 +997,11 @@
|
||||
#define FMULS(Sd, Sn, Sm) EMIT(FMUL_scalar(0b00, Sm, Sn, Sd))
|
||||
#define FMULD(Dd, Dn, Dm) EMIT(FMUL_scalar(0b01, Dm, Dn, Dd))
|
||||
|
||||
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFMLAS(Sd, Sn, Sm) EMIT(FMLA_vector(0, 0, 0, Sm, Sn, Sd))
|
||||
#define VFMLAQS(Sd, Sn, Sm) EMIT(FMLA_vector(1, 0, 0, Sm, Sn, Sd))
|
||||
#define CFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
|
||||
|
||||
// DIV
|
||||
#define FDIV_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFDIVS(Sd, Sn, Sm) EMIT(FDIV_vector(0, 0, Sm, Sn, Sd))
|
||||
@@ -1419,6 +1429,25 @@
|
||||
#define VCHIQQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b10, 0, Rm, Rn, Rd))
|
||||
#define VCHIQQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b11, 0, Rm, Rn, Rd))
|
||||
|
||||
// Less Than 0
|
||||
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
|
||||
#define CMLT_0_16(Rd, Rn) EMIT(CMLT_0_vector(0, 0b01, Rn, Rd))
|
||||
#define CMLT_0_32(Rd, Rn) EMIT(CMLT_0_vector(0, 0b10, Rn, Rd))
|
||||
#define CMLTQ_0_8(Rd, Rn) EMIT(CMLT_0_vector(1, 0b00, Rn, Rd))
|
||||
#define CMLTQ_0_16(Rd, Rn) EMIT(CMLT_0_vector(1, 0b01, Rn, Rd))
|
||||
#define CMLTQ_0_32(Rd, Rn) EMIT(CMLT_0_vector(1, 0b10, Rn, Rd))
|
||||
#define CMLTQ_0_64(Rd, Rn) EMIT(CMLT_0_vector(1, 0b11, Rn, Rd))
|
||||
// Equal 0
|
||||
#define CMEQ_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b0100<<13 | 1<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define CMEQ_0_8(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b00, Rn, Rd))
|
||||
#define CMEQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b01, Rn, Rd))
|
||||
#define CMEQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b10, Rn, Rd))
|
||||
#define CMEQQ_0_8(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b00, Rn, Rd))
|
||||
#define CMEQQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b01, Rn, Rd))
|
||||
#define CMEQQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b10, Rn, Rd))
|
||||
#define CMEQQ_0_64(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b11, Rn, Rd))
|
||||
|
||||
// Vector Float CMP
|
||||
// EQual
|
||||
#define FCMP_vector(Q, U, E, sz, Rm, ac, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (E)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b1110<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -1698,4 +1727,13 @@
|
||||
#define SQDMULHQ_16(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQDMULHQ_32(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b10, Vm, Vn, Vd))
|
||||
|
||||
// AES extensions
|
||||
#define AES_gen(D, Rn, Rd) (0b01001110<<24 | 0b00<<22 | 0b10100<<17 | 0b0010<<13 | (D)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define AESD(Vd, Vn) EMIT(AES_gen(1, Vn, Vd))
|
||||
#define AESE(Vd, Vn) EMIT(AES_gen(0, Vn, Vd))
|
||||
|
||||
#define AESMC_gen(D, Rn, Rd) (0b01001110<<24 | 0b00<<22 | 0b10100<<17 | 0b0011<<13 | (D)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define AESIMC(Vd, Vn) EMIT(AESMC_gen(1, Vn, Vd))
|
||||
#define AESMC(Vd, Vn) EMIT(AESMC_gen(0, Vn, Vd))
|
||||
|
||||
#endif //__ARM64_EMITTER_H__
|
||||
@@ -1312,6 +1312,15 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
// AES
|
||||
if(isMask(opcode, "0100111000101000010f10nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "AES%c V%d.16B, V%d.16B", sf?'D':'E', Rd, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0100111000101000011f10nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "AES%sMC V%d.16B, V%d.16B", sf?"I":"", Rd, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
|
||||
|
||||
@@ -139,7 +139,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
|
||||
@@ -422,6 +422,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i64 = F32S;
|
||||
emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4);
|
||||
break;
|
||||
case 0x36:
|
||||
INST_NAME("SS:");
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
INST_NAME("CMP Eb, Gb");
|
||||
@@ -967,7 +970,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8C:
|
||||
INST_NAME("MOV Ed, Seg");
|
||||
nextop=F8;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= seg
|
||||
LDRH_U12(xRAX+(nextop&7)+(rex.b<<3), xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
|
||||
} else { // mem <= seg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_U12(x3, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x8D:
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -985,6 +998,24 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP1(xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else {
|
||||
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
if(ed==xRSP) {
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
} else {
|
||||
// complicated to just allow a segfault that can be recovered correctly
|
||||
SUBx_U12(xRSP, xRSP, 8);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
ADDx_U12(xRSP, xRSP, 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
@@ -1357,49 +1388,61 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEB(x1, 1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
LSLw(ed, ed, u8);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl8);
|
||||
if(u8) {
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
LSLw(ed, ed, u8);
|
||||
EBBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl8);
|
||||
} else {
|
||||
NOP;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEB(x1, 1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
LSRw(ed, ed, u8);
|
||||
EBBACK;
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
LSRw(ed, ed, u8);
|
||||
EBBACK;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr8);
|
||||
} else {
|
||||
NOP;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr8);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEB(x1, 1);
|
||||
u8 = (F8)&0x1f;
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
ASRw(ed, ed, u8);
|
||||
EBBACK;
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF{
|
||||
MOV32w(x4, u8); UFLAG_OP2(x4);
|
||||
};
|
||||
UFLAG_OP1(ed);
|
||||
if(u8) {
|
||||
ASRw(ed, ed, u8);
|
||||
EBBACK;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar8);
|
||||
} else {
|
||||
NOP;
|
||||
}
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1914,7 +1957,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xDB:
|
||||
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xDC:
|
||||
addr = dynarec64_DC(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
case 0xDD:
|
||||
addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
@@ -88,12 +88,42 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MAYUSE(d1);
|
||||
MAYUSE(s0);
|
||||
MAYUSE(j64);
|
||||
#if 0//STEP == 3
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x01:
|
||||
INST_NAME("FAKE xgetbv");
|
||||
nextop = F8;
|
||||
addr = fakeed(dyn, addr, ninst, nextop);
|
||||
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 0x05:
|
||||
INST_NAME("SYSCALL");
|
||||
GETIP(addr);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL_S(x64Syscall, -1);
|
||||
LOAD_XEMU_CALL(xRIP);
|
||||
TABLE64(x3, addr); // expected return address
|
||||
CMPSx_REG(xRIP, x3);
|
||||
B_MARK(cNE);
|
||||
LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit));
|
||||
CBZw_NEXT(w1);
|
||||
MARK;
|
||||
LOAD_XEMU_REM();
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("WBINVD");
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
@@ -1307,11 +1337,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8&=(rex.w?0x3f:0x1f);
|
||||
if(u8) {
|
||||
LSRxw(x4, ed, u8);
|
||||
} else {
|
||||
MOVw_REG(x4, ed);
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction
|
||||
MOV32w(x4, 1);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
@@ -1330,11 +1365,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8&=(rex.w?0x3f:0x1f);
|
||||
if(u8) {
|
||||
LSRxw(x4, ed, u8);
|
||||
} else {
|
||||
MOVw_REG(x4, ed);
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction
|
||||
//MOVW(x14, 1); // already 0x01
|
||||
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
@@ -1353,10 +1393,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8&=(rex.w?0x3f:0x1f);
|
||||
if(u8) {
|
||||
LSRxw(x4, ed, u8);
|
||||
} else {
|
||||
MOVw_REG(x4, ed);
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
@@ -1496,7 +1541,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break; // not NaN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC3:
|
||||
INST_NAME("MOVNTI Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
STRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gm,Ed,Ib");
|
||||
nextop = F8;
|
||||
@@ -1586,6 +1641,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMUL_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
INST_NAME("PMOVMSKB Gd, Em");
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
GETEM(q0, 0);
|
||||
GETGD;
|
||||
TABLE64(x1, (uintptr_t)&mask_shift8);
|
||||
VLDR64_U12(v0, x1, 0); // load shift
|
||||
MOVI_8(v1, 0x80); // load mask
|
||||
VAND(q1, v1, q0);
|
||||
USHL_8(q1, q1, v0); // shift
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(gd, q1, 0);
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gm, Em");
|
||||
nextop = F8;
|
||||
|
||||
@@ -32,7 +32,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t nextop;
|
||||
uint8_t u8;
|
||||
uint8_t gd, ed, eb1, eb2;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t wback, wb1, wb2, wb;
|
||||
int64_t i64, j64;
|
||||
int v0;
|
||||
int q0;
|
||||
@@ -199,6 +199,20 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("CMP Seg:Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5);
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x1, seg);
|
||||
@@ -625,6 +639,206 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF7:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("TEST Ed, Id");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
GETEDO(x6, 4);
|
||||
MVNxw_REG(ed, ed);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("NEG Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, 0);
|
||||
emit_neg32(dyn, ninst, rex, ed, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("MUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
GETEDO(x6, 0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
UMULH(gd, xRAX, ed);
|
||||
MULx(xRAX, xRAX, ed);
|
||||
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
|
||||
} else {
|
||||
UMULL(xRDX, xRAX, ed); //64 <- 32x32
|
||||
MOVw_REG(xRAX, xRDX);
|
||||
LSRx(xRDX, xRDX, 32);
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("IMUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
|
||||
GETEDO(x6, 0);
|
||||
if(rex.w) {
|
||||
if(ed==xRDX) gd=x3; else gd=xRDX;
|
||||
SMULH(gd, xRAX, ed);
|
||||
MULx(xRAX, xRAX, ed);
|
||||
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
|
||||
} else {
|
||||
SMULL(xRDX, xRAX, ed); //64 <- 32x32
|
||||
MOVw_REG(xRAX, xRDX);
|
||||
LSRx(xRDX, xRDX, 32);
|
||||
}
|
||||
UFLAG_RES(xRAX);
|
||||
UFLAG_OP1(xRDX);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if(!rex.w) {
|
||||
SET_DFNONE(x2);
|
||||
GETEDO(x6, 0);
|
||||
MOVw_REG(x3, xRAX);
|
||||
ORRx_REG_LSL(x3, x3, xRDX, 32);
|
||||
if(MODREG) {
|
||||
MOVw_REG(x4, ed);
|
||||
ed = x4;
|
||||
}
|
||||
UDIVx(x2, x3, ed);
|
||||
MSUBx(x4, x2, ed, xRAX);
|
||||
MOVw_REG(xRAX, x2);
|
||||
MOVw_REG(xRDX, x4);
|
||||
} else {
|
||||
if(ninst && dyn->insts
|
||||
&& dyn->insts[ninst-1].x64.addr
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
|
||||
SET_DFNONE(x2);
|
||||
GETEDO(x6, 0);
|
||||
UDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
} else {
|
||||
GETEDO(x6, 0);
|
||||
CBZxw_MARK(xRDX);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL(div64, -1);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
UDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
SET_DFNONE(x2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if(!rex.w) {
|
||||
SET_DFNONE(x2)
|
||||
GETSEDOw(x6, 0);
|
||||
MOVw_REG(x3, xRAX);
|
||||
ORRx_REG_LSL(x3, x3, xRDX, 32);
|
||||
SDIVx(x2, x3, wb);
|
||||
MSUBx(x4, x2, wb, x3);
|
||||
MOVw_REG(xRAX, x2);
|
||||
MOVw_REG(xRDX, x4);
|
||||
} else {
|
||||
if(ninst && dyn->insts
|
||||
&& dyn->insts[ninst-1].x64.addr
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
|
||||
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
|
||||
SET_DFNONE(x2)
|
||||
GETEDO(x6, 0);
|
||||
SDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
} else {
|
||||
GETEDO(x6, 0);
|
||||
CBZxw_MARK(xRDX);
|
||||
MVNx_REG(x2, xRDX);
|
||||
CBZxw_MARK(x2);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL((void*)idiv64, -1);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
SDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
SET_DFNONE(x2)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: // INC Ed
|
||||
INST_NAME("INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
GETEDO(x6, 0);
|
||||
emit_inc32(dyn, ninst, rex, ed, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
GETEDO(x6, 0);
|
||||
emit_dec32(dyn, ninst, rex, ed, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF(dyn->insts &&
|
||||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|
||||
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
|
||||
{
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDOx(x6, 0);
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
if(!dyn->insts || ninst==dyn->size-1) {
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
GETIP(addr);
|
||||
PUSH1(xRIP);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
break;
|
||||
case 4: // JMP Ed
|
||||
INST_NAME("JMP Ed");
|
||||
BARRIER(1);
|
||||
GETEDOx(x6, 0);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH Ed");
|
||||
GETEDOx(x6, 0);
|
||||
PUSH1(ed);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
|
||||
if(rex.w && opcode!=0x0f) // rex.w cancels "66", but not for 66 0f type of prefix
|
||||
return dynarec64_00(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
|
||||
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
|
||||
|
||||
switch(opcode) {
|
||||
case 0x01:
|
||||
@@ -454,8 +454,23 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
INST_NAME("NOP");
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
gd = xRAX+(opcode&0x07)+(rex.b<<3);
|
||||
if(gd==xRAX) {
|
||||
INST_NAME("NOP");
|
||||
} else {
|
||||
INST_NAME("XCHG AX, Reg");
|
||||
MOVw_REG(x2, xRAX);
|
||||
BFIx(xRAX, gd, 0, 16);
|
||||
BFIx(gd, x2, 0, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x98:
|
||||
|
||||
@@ -66,7 +66,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j64);
|
||||
#if 0//STEP > 1
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
@@ -256,6 +256,51 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQXTN2_16(q0, v0);
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
INST_NAME("PSIGNB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
NEGQ_8(v0, q0); // get NEG
|
||||
CMLTQ_0_8(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
CMEQQ_0_8(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
case 0x09:
|
||||
INST_NAME("PSIGNW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
NEGQ_16(v0, q0); // get NEG
|
||||
CMLTQ_0_16(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
CMEQQ_0_16(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
case 0x0A:
|
||||
INST_NAME("PSIGND Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
NEGQ_32(v0, q0); // get NEG
|
||||
CMLTQ_0_32(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
CMEQQ_0_32(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
case 0x0B:
|
||||
INST_NAME("PMULHRSW Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -264,6 +309,31 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQRDMULHQ_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x1C:
|
||||
INST_NAME("PABSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETG;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
ABSQ_8(q0, q1);
|
||||
break;
|
||||
case 0x1D:
|
||||
INST_NAME("PABSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETG;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
ABSQ_16(q0, q1);
|
||||
break;
|
||||
case 0x1E:
|
||||
INST_NAME("PABSD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETG;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
ABSQ_32(q0, q1);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
@@ -311,6 +381,107 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
|
||||
case 0xDB:
|
||||
INST_NAME("AESIMC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm64_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
AESIMC(q0, q1);
|
||||
} else {
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
if(q0!=q1) {
|
||||
VMOVQ(q0, q1);
|
||||
}
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd);
|
||||
CALL(arm_aesimc, -1);
|
||||
}
|
||||
break;
|
||||
case 0xDC:
|
||||
INST_NAME("AESENC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm64_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESE(v0, q1);
|
||||
AESMC(v0, v0);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd);
|
||||
CALL(arm_aese, -1);
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDD:
|
||||
INST_NAME("AESENCLAST Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm64_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESE(v0, q1);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd);
|
||||
CALL(arm_aeselast, -1);
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDE:
|
||||
INST_NAME("AESDEC Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm64_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESD(v0, q1);
|
||||
AESIMC(v0, v0);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd);
|
||||
CALL(arm_aesd, -1);
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0xDF:
|
||||
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
|
||||
nextop = F8;
|
||||
if(arm64_aes) {
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
|
||||
VEORQ(v0, q0, q1);
|
||||
AESD(v0, q1);
|
||||
VEORQ(q0, v0, q1);
|
||||
} else {
|
||||
GETG;
|
||||
sse_forget_reg(dyn, ninst, gd);
|
||||
MOV32w(x1, gd);
|
||||
CALL(arm_aesdlast, -1);
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -354,6 +525,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEXTQ_8(q0, q1, q0, u8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
INST_NAME("PINSRD Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETED(1);
|
||||
u8 = F8;
|
||||
VMOVQSfrom(q0, (u8&3), ed);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -377,6 +558,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GOCOND(0x40, "CMOV", "Gw, Ew");
|
||||
#undef GO
|
||||
|
||||
case 0x50:
|
||||
nextop = F8;
|
||||
INST_NAME("PMOVMSKD Gd, Ex");
|
||||
GETEX(q0, 0);
|
||||
GETGD;
|
||||
VMOVQDto(x1, q0, 1);
|
||||
VMOVQDto(gd, q0, 0);
|
||||
LSRx(x1, x1, 63);
|
||||
LSRx(gd, gd, 63);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
break;
|
||||
|
||||
case 0x54:
|
||||
INST_NAME("ANDPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -465,7 +658,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
VFMINQD(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x5E:
|
||||
INST_NAME("DIVPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFDIVQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x5F:
|
||||
INST_NAME("MAXPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1090,6 +1289,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
|
||||
BFIx(gd, x1, 0, 16); // insert in Gw
|
||||
break;
|
||||
case 0xB7:
|
||||
INST_NAME("MOVZX Gw, Ew");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UBFXxw(x1, eb1, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff>>1, 1, rex, 0, 0);
|
||||
LDRH_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");
|
||||
@@ -1175,6 +1388,38 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
switch(u8&7) {
|
||||
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
|
||||
case 0: FCMEQQD(v0, v0, v1); break; // Equal
|
||||
case 1: FCMGTQD(v0, v1, v0); break; // Less than
|
||||
case 2: FCMGEQD(v0, v1, v0); break; // Less or equal
|
||||
case 3: FCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
VMVNQ(v0, v0);
|
||||
break; // NaN (NaN is not equal to himself)
|
||||
case 4: FCMEQQD(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 5: FCMGTQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
|
||||
case 6: FCMGEQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
|
||||
case 7: FCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
break; // not NaN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gx,Ed,Ib");
|
||||
nextop = F8;
|
||||
@@ -1224,7 +1469,37 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* BSWAP reg */
|
||||
INST_NAME("BSWAP Reg");
|
||||
gd = xRAX+(opcode&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
REV64x(gd, gd);
|
||||
} else {
|
||||
REV16w(x1, gd);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0xD2:
|
||||
INST_NAME("PSRLD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
SQSHRN_32(v0, q1, 0); // S64x1->S32x1
|
||||
VMOVeS(v0, 1, v0, 0); // S32x1->S32x2
|
||||
NEG_32(v0, v0); // neg, because SHR
|
||||
VMOVeD(v0, 1, v0, 0); // S32x2->S32x4
|
||||
USHLQ_32(q0, q0, v0); // SHR x4
|
||||
break;
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1262,7 +1537,29 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
INST_NAME("PMOVMSKB Gd, Ex");
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
GETEX(q0, 0);
|
||||
GETGD;
|
||||
TABLE64(x1, (uintptr_t)&mask_shift8);
|
||||
VLDR64_U12(v0, x1, 0); // load shift
|
||||
MOVI_8(v1, 0x80); // load mask
|
||||
VAND(q1, v1, q0);
|
||||
USHL_8(q1, q1, v0); // shift
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(gd, q1, 0);
|
||||
// and now the high part
|
||||
VMOVeD(q1, 0, q0, 1);
|
||||
VAND(q1, v1, q1); // keep highest bit
|
||||
USHL_8(q1, q1, v0); // shift
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(x1, q1, 0);
|
||||
BFIx(gd, x1, 8, 8);
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1443,7 +1740,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
SQADDQ_16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEE:
|
||||
INST_NAME("PMAXSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SMAXQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gx,Ex");
|
||||
nextop = F8;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -30,6 +31,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int v0, v1;
|
||||
int64_t fixedaddress;
|
||||
|
||||
// REX prefix before the 66 are ignored
|
||||
@@ -46,10 +48,56 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0xD6:
|
||||
INST_NAME("MOVQ Ex, Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
FMOVD(v1, v0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VSTR64_REG(v0, ed, x4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ew, Gw");
|
||||
nextop = F8;
|
||||
GETGD; // don't need GETGW here
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
MOVx_REG(ed, gd);
|
||||
} else {
|
||||
if(ed!=gd) {
|
||||
BFIx(ed, gd, 0, 16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(rex.w) {
|
||||
STRx_REG(gd, ed, x4);
|
||||
} else {
|
||||
STRH_REG(gd, ed, x4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
@@ -62,6 +110,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
}
|
||||
} else { // mem <= reg
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(rex.w) {
|
||||
LDRx_REG(gd, ed, x4);
|
||||
|
||||
@@ -157,6 +157,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
case 0xE8:
|
||||
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("FNINIT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_purgecache(dyn, ninst, x1, x2, x3);
|
||||
CALL(reset_fpu, -1);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "dynarec.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_arm64.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "arm64_printer.h"
|
||||
#include "emu/x87emu_private.h"
|
||||
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
|
||||
uintptr_t dynarec64_DC(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 wback;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FADD STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FADDD(v1, v1, v2);
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FMUL STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FMULD(v1, v1, v2);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCOM ST0, STx"); //yep
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FSUBR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FSUB STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FDIVR STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
INST_NAME("FDIV STx, ST0");
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FADD ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FADDD(v1, v1, v2);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FMULD(v1, v1, v2);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
@@ -285,6 +285,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -206,7 +206,9 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
LSRxw_REG(s3, s1, c-1);
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
@@ -252,7 +254,9 @@ 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);
|
||||
if(c>1) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
ASRxw(s1, s1, c);
|
||||
@@ -359,11 +363,13 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
LSRxw_REG(s3, s1, c-1);
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
ORRxw_REG_LSL(s1, s1, s2, (rex.w?64:32)-c);
|
||||
LSRxw(s3, s1, c);
|
||||
ORRxw_REG_LSL(s1, s3, s2, (rex.w?64:32)-c);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
@@ -413,8 +419,8 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
|
||||
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);
|
||||
LSLxw(s3, s1, c);
|
||||
ORRxw_REG_LSR(s1, s3, s2, (rex.w?64:32)-c);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
|
||||
@@ -296,7 +296,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
IFX(X_PF) {
|
||||
ANDw_mask(s3, s3, 0b011011, 000010); // 0xE0
|
||||
ANDw_mask(s3, s3, 0b011011, 0b000010); // 0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
MOV64x(s4, (uintptr_t)GetParityTab());
|
||||
LDRw_REG_LSL2(s4, s4, s3);
|
||||
|
||||
@@ -29,7 +29,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
uint8_t gd, ed, u8;
|
||||
uint8_t wback, wb1, wb2, gb1, gb2;
|
||||
int32_t i32;
|
||||
int64_t i64, j64;
|
||||
@@ -96,6 +96,24 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("LOCK OR Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
@@ -436,6 +454,167 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEB(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;
|
||||
|
||||
@@ -288,19 +288,31 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FCMPD(v0, v1);
|
||||
}
|
||||
switch(u8&7) {
|
||||
case 0: CSETMx(x2, cEQ); break; // Equal
|
||||
case 1: CSETMx(x2, cMI); break; // Less than
|
||||
case 2: //CSETMx(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
|
||||
CSETMx(x2, cPL); CSINVx(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
|
||||
case 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal
|
||||
case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than
|
||||
case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); break; // Less or equal
|
||||
case 3: CSETMx(x2, cVS); break; // NaN
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal
|
||||
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
|
||||
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 7: CSETMx(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQDfrom(v0, 0, x2);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
INST_NAME("ADDSUBPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
|
||||
MAYUSE(addsubps);
|
||||
TABLE64(x2, (uintptr_t)&addsubps);
|
||||
VLDR128_U12(q0, x2, 0);
|
||||
VFMLAQS(v0, v1, q0);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("LDDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
|
||||
@@ -184,17 +184,28 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
GETGX_empty(v0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
|
||||
// and want 1.0f = 0x3f800000
|
||||
// so 00111111 10000000 00000000 00000000
|
||||
// a = 0, b = 1, c = 1, d = 1, efgh=0
|
||||
// 0b01110000
|
||||
FMOVS_8(d0, 0b01110000);
|
||||
FSQRTS(v0, v1);
|
||||
FDIVS(d0, d0, v0);
|
||||
FSQRTS(d1, v1);
|
||||
FDIVS(d0, d0, d1);
|
||||
VMOVeS(v0, 0, d0, 0);
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMOVS_8(d0, 0b01110000); //1.0f
|
||||
FDIVS(d0, d0, v1);
|
||||
VMOVeS(v0, 0, d0, 0);
|
||||
break;
|
||||
|
||||
@@ -352,6 +363,20 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
CSETw(x1, cEQ);
|
||||
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("LZCNT Gd, Ed");
|
||||
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
TSTxw_REG(ed, ed);
|
||||
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
|
||||
CLZxw(gd, x1); // x2 gets leading 0 == LZCNT
|
||||
TSTxw_REG(gd, gd);
|
||||
CSETw(x1, cEQ);
|
||||
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSS Gx, Ex, Ib");
|
||||
@@ -365,14 +390,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FCMPS(v0, v1);
|
||||
}
|
||||
switch(u8&7) {
|
||||
case 0: CSETMw(x2, cEQ); break; // Equal
|
||||
case 1: CSETMw(x2, cMI); break; // Less than
|
||||
case 2: //CSETMw(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
|
||||
CSETMw(x2, cPL); CSINVw(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
|
||||
case 0: CSETMw(x2, cEQ); CSELw(x2, xZR, x2, cVS); break; // Equal
|
||||
case 1: CSETMw(x2, cMI); CSELw(x2, xZR, x2, cVS); break; // Less than
|
||||
case 2: CSETMw(x2, cLE); CSELw(x2, xZR, x2, cVS); break; // Less or equal
|
||||
case 3: CSETMw(x2, cVS); break; // NaN
|
||||
case 4: CSETMw(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 4: CSETMw(x2, cNE); break; // Not Equal
|
||||
case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered
|
||||
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 7: CSETMw(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQSfrom(v0, 0, x2);
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
#include "dynarec_arm64.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "custommem.h"
|
||||
|
||||
void arm_fstp(x64emu_t* emu, void* p)
|
||||
{
|
||||
if(ST0.q!=STld(0).ref)
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, p);
|
||||
else
|
||||
memcpy(p, &STld(0).ld, 10);
|
||||
@@ -51,6 +52,7 @@ void arm_fyl2x(x64emu_t* emu)
|
||||
void arm_ftan(x64emu_t* emu)
|
||||
{
|
||||
ST0.d = tan(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_fpatan(x64emu_t* emu)
|
||||
{
|
||||
@@ -79,6 +81,7 @@ void arm_fyl2xp1(x64emu_t* emu)
|
||||
void arm_fsincos(x64emu_t* emu)
|
||||
{
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_frndint(x64emu_t* emu)
|
||||
{
|
||||
@@ -92,10 +95,12 @@ void arm_fscale(x64emu_t* emu)
|
||||
void arm_fsin(x64emu_t* emu)
|
||||
{
|
||||
ST0.d = sin(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_fcos(x64emu_t* emu)
|
||||
{
|
||||
ST0.d = cos(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
|
||||
void arm_fbld(x64emu_t* emu, uint8_t* ed)
|
||||
@@ -108,8 +113,8 @@ void arm_fild64(x64emu_t* emu, int64_t* ed)
|
||||
int64_t tmp;
|
||||
memcpy(&tmp, ed, sizeof(tmp));
|
||||
ST0.d = tmp;
|
||||
STll(0).ll = tmp;
|
||||
STll(0).ref = ST0.q;
|
||||
STll(0).sq = tmp;
|
||||
STll(0).sref = ST0.sq;
|
||||
}
|
||||
|
||||
void arm_fbstp(x64emu_t* emu, uint8_t* ed)
|
||||
@@ -120,8 +125,8 @@ 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((uint64_t)STll(0).ref==ST(0).q) {
|
||||
memcpy(ed, &STll(0).ll, sizeof(int64_t));
|
||||
if(STll(0).sref==ST(0).sq) {
|
||||
memcpy(ed, &STll(0).sq, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
@@ -143,7 +148,7 @@ void arm_fld(x64emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
memcpy(&STld(0).ld, ed, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
STld(0).ref = ST0.q;
|
||||
STld(0).uref = ST0.q;
|
||||
}
|
||||
|
||||
void arm_ud(x64emu_t* emu)
|
||||
@@ -185,6 +190,125 @@ void arm_fprem1(x64emu_t* emu)
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
|
||||
}
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if((b & 1) == 1)
|
||||
retval ^= a;
|
||||
|
||||
if((a & 0x80)) {
|
||||
a <<= 1;
|
||||
a ^= 0x1b;
|
||||
} else {
|
||||
a <<= 1;
|
||||
}
|
||||
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void arm_aesimc(x64emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesmc(x64emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesdlast(x64emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A N K H E B O L I F C P M J G D
|
||||
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
|
||||
const uint8_t invsubbytes[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
|
||||
|
||||
}
|
||||
void arm_aeselast(x64emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A F K P E J O D I N C H M B G L
|
||||
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
|
||||
const uint8_t subbytes[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
|
||||
}
|
||||
void arm_aesd(x64emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aesdlast(emu, xmm);
|
||||
arm_aesimc(emu, xmm);
|
||||
}
|
||||
void arm_aese(x64emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aeselast(emu, xmm);
|
||||
arm_aesmc(emu, xmm);
|
||||
}
|
||||
|
||||
|
||||
#define XMM0 0
|
||||
#define XMM8 16
|
||||
#define X870 8
|
||||
@@ -320,13 +444,13 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(int32_t*)(addr+a)
|
||||
|
||||
if(!addr)
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
|
||||
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = *(uintptr_t*)a1;
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
|
||||
|
||||
@@ -29,6 +29,13 @@ void arm_fsave(x64emu_t* emu, uint8_t* ed);
|
||||
void arm_frstor(x64emu_t* emu, uint8_t* ed);
|
||||
void arm_fprem1(x64emu_t* emu);
|
||||
|
||||
void arm_aesd(x64emu_t* emu, int xmm);
|
||||
void arm_aese(x64emu_t* emu, int xmm);
|
||||
void arm_aesdlast(x64emu_t* emu, int xmm);
|
||||
void arm_aeselast(x64emu_t* emu, int xmm);
|
||||
void arm_aesimc(x64emu_t* emu, int xmm);
|
||||
|
||||
|
||||
void arm_ud(x64emu_t* emu);
|
||||
|
||||
// Get an FPU scratch reg
|
||||
|
||||
@@ -462,12 +462,20 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
MOVZw(x1, 0);
|
||||
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
|
||||
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
|
||||
// POP EFLAGS
|
||||
POP1(xFlags);
|
||||
MOV32w(x1, 0x3F7FD7);
|
||||
ANDx_REG(xFlags, xFlags, x1);
|
||||
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0);
|
||||
SET_DFNONE(x1);
|
||||
// POP RSP
|
||||
POP1(x3);
|
||||
// POP SS
|
||||
POP1(x2);
|
||||
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS]));
|
||||
// set new RSP
|
||||
MOVx_REG(xRSP, x3);
|
||||
// Ret....
|
||||
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
|
||||
BR(x2);
|
||||
@@ -741,7 +749,7 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
if(ret!=0) {
|
||||
// --- set values
|
||||
// prepare offset to fpu => s1
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
// Get top
|
||||
// loop all cache entries
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -772,7 +780,7 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
if(!ret) // nothing to do
|
||||
return;
|
||||
// prepare offset to fpu => s1
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
// Get top
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
// loop all cache entries
|
||||
@@ -806,7 +814,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
// found, setup and grab the value
|
||||
dyn->x87cache[ret] = st;
|
||||
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a) {
|
||||
@@ -851,7 +859,7 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
|
||||
// prepare offset to fpu => s1
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
// Get top
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
// Update
|
||||
@@ -879,7 +887,7 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
|
||||
// prepare offset to fpu => s1
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
// Get top
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
// Update
|
||||
@@ -908,7 +916,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
if(dyn->x87cache[i]==st) {
|
||||
// refresh the value
|
||||
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a<0) {
|
||||
@@ -932,7 +940,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
// found, setup and grab the value
|
||||
dyn->x87cache[ret] = st;
|
||||
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
int a = st - dyn->x87stack;
|
||||
if(a<0) {
|
||||
@@ -953,9 +961,9 @@ 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));
|
||||
RBITw(s2, s1); // round is on bits 10-11 on x86,
|
||||
LSRw(s2, s2, 20); // but we want the reverse of that
|
||||
LDRw_U12(s1, xEmu, offsetof(x64emu_t, round));
|
||||
UBFXw(s2, s1, 1, 1); // bit 1 of round in bit 0 (zero extented) of s2
|
||||
BFIw(s2, s1, 1, 1); // bit 0 of round in bit 1 of s2
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
@@ -1006,7 +1014,7 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
|
||||
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx87[a]));
|
||||
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx[a]));
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
@@ -1039,7 +1047,7 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
|
||||
++old;
|
||||
}
|
||||
VSTR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
|
||||
VSTR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
fpu_free_reg(dyn, dyn->mmxcache[i]);
|
||||
dyn->mmxcache[i] = -1;
|
||||
}
|
||||
@@ -1057,7 +1065,7 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int 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]));
|
||||
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
@@ -1106,6 +1114,21 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// forget neon register for a SSE reg, create the entry if needed
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a)
|
||||
{
|
||||
(void) ninst;
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]==-1)
|
||||
return;
|
||||
VSTR128_U12(dyn->ssecache[a], xEmu, offsetof(x64emu_t, xmm[a]));
|
||||
fpu_free_reg(dyn, dyn->ssecache[a]);
|
||||
dyn->ssecache[a] = -1;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// purge the SSE cache for XMM0..XMM7 (to use before function native call)
|
||||
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
LDRw_U12(x1, wback, fixedaddress); \
|
||||
LDRSW_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
|
||||
@@ -106,6 +106,25 @@
|
||||
ed = x1; \
|
||||
}
|
||||
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O);}
|
||||
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDOx(O, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
|
||||
LDRx_REG(x1, wback, O); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define GETSEDOw(O, 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, 0, 0, rex, 0, D); \
|
||||
LDRSW_REG(x1, wback, O); \
|
||||
wb = ed = x1; \
|
||||
}
|
||||
//FAKEELike GETED, but doesn't get anything
|
||||
#define FAKEED if(!MODREG) { \
|
||||
addr = fakeed(dyn, addr, ninst, nextop); \
|
||||
@@ -725,6 +744,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
|
||||
#define sse_get_reg STEPNAME(sse_get_reg)
|
||||
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
|
||||
#define sse_forget_reg STEPNAME(sse_forget_reg)
|
||||
#define sse_purge07cache STEPNAME(sse_purge07cache)
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
@@ -865,6 +885,8 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// forget neon register for a SSE reg, create the entry if needed
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// purge the XMM0..XMM7 cache (before function call)
|
||||
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
@@ -893,7 +915,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
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);
|
||||
//uintptr_t dynarec64_DA(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_DB(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_DC(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_DC(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_DD(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_DE(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_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
|
||||
@@ -100,7 +100,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
}
|
||||
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
|
||||
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3)&~PROT_CUSTOM)
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
|
||||
+58
-31
@@ -124,7 +124,9 @@ int CalcLoadAddr(elfheader_t* head)
|
||||
head->stackalign = head->PHEntries[i].p_align;
|
||||
}
|
||||
if(head->PHEntries[i].p_type == PT_TLS) {
|
||||
head->tlsaddr = head->PHEntries[i].p_vaddr;
|
||||
head->tlssize = head->PHEntries[i].p_memsz;
|
||||
head->tlsfilesize = head->PHEntries[i].p_filesz;
|
||||
head->tlsalign = head->PHEntries[i].p_align;
|
||||
// force alignement...
|
||||
if(head->tlsalign>1)
|
||||
@@ -369,21 +371,24 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
|
||||
int t = ELF64_R_TYPE(rel[i].r_info);
|
||||
Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel[i].r_info)];
|
||||
const char* symname = SymName(h, sym);
|
||||
int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2) && t==R_X86_64_COPY) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
|
||||
return 1;
|
||||
if(t==R_X86_64_COPY && symname && !strcmp(symname, name)) {
|
||||
int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
|
||||
if(version2!=-1) version2 &= 0x7fff;
|
||||
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
|
||||
const char* vername2 = GetSymbolVersion(h, version2);
|
||||
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rel *rel)
|
||||
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rel *rel)
|
||||
{
|
||||
int ret_ok = 0;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF64_R_TYPE(rel[i].r_info);
|
||||
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)];
|
||||
@@ -425,6 +430,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
case R_X86_64_PC32:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
ret_ok = 1;
|
||||
}
|
||||
offs = (offs - (uintptr_t)p);
|
||||
if(!offs)
|
||||
@@ -451,7 +457,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
end = globend;
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__"))
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
@@ -493,6 +499,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
case R_X86_64_64:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
ret_ok = 1;
|
||||
// return -1;
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint64_t*)p));
|
||||
@@ -533,7 +540,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
printf_log(LOG_INFO, "Warning, don't know how to handle rel #%d %s (%p)\n", i, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), p);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return bindnow?ret_ok:0;
|
||||
}
|
||||
|
||||
struct tlsdesc
|
||||
@@ -551,8 +558,9 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu)
|
||||
}
|
||||
|
||||
|
||||
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
|
||||
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
|
||||
{
|
||||
int ret_ok = 0;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
int t = ELF64_R_TYPE(rela[i].r_info);
|
||||
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
|
||||
@@ -642,7 +650,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
end = globend;
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__"))
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
@@ -659,12 +667,14 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
|| !tmp
|
||||
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
|
||||
|| !need_resolv
|
||||
|| bindnow
|
||||
) {
|
||||
if (!offs) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
ret_ok = 1;
|
||||
}
|
||||
// return -1;
|
||||
} else {
|
||||
@@ -686,6 +696,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
case R_X86_64_64:
|
||||
if (!offs) {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
ret_ok = 1;
|
||||
// return -1;
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (ver=%d/%s) addend=0x%lx (%p -> %p)\n",
|
||||
@@ -696,9 +707,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
case R_X86_64_TPOFF64:
|
||||
// Negated offset in static TLS block
|
||||
{
|
||||
if(h_tls)
|
||||
if(!symname || !symname[0]) {
|
||||
h_tls = head;
|
||||
offs = sym->st_value;
|
||||
else {
|
||||
} else {
|
||||
h_tls = NULL;
|
||||
if(local_maplib)
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
|
||||
if(!h_tls)
|
||||
@@ -706,7 +719,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int64_t*)p;
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
|
||||
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs);
|
||||
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs);
|
||||
@@ -770,42 +783,42 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), symname);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return bindnow?ret_ok:0;
|
||||
}
|
||||
int RelocateElf(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
|
||||
{
|
||||
if(head->rel) {
|
||||
int cnt = head->relsz / head->relent;
|
||||
DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel");
|
||||
printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
|
||||
if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->rel + head->delta)))
|
||||
printf_dump(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
|
||||
if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->rel + head->delta)))
|
||||
return -1;
|
||||
}
|
||||
if(head->rela) {
|
||||
int cnt = head->relasz / head->relaent;
|
||||
DumpRelATable(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA");
|
||||
printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL))
|
||||
printf_dump(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
|
||||
{
|
||||
int need_resolver = 0;
|
||||
if(head->pltrel) {
|
||||
int cnt = head->pltsz / head->pltent;
|
||||
if(head->pltrel==DT_REL) {
|
||||
DumpRelTable(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT");
|
||||
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
|
||||
if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta)))
|
||||
printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
|
||||
if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta)))
|
||||
return -1;
|
||||
} else if(head->pltrel==DT_RELA) {
|
||||
DumpRelATable(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT");
|
||||
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver))
|
||||
printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
|
||||
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver))
|
||||
return -1;
|
||||
}
|
||||
if(need_resolver) {
|
||||
@@ -815,11 +828,11 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
if(head->pltgot) {
|
||||
*(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver;
|
||||
*(uintptr_t*)(head->pltgot+head->delta+8) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16));
|
||||
printf_dump(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16));
|
||||
} else if(head->got) {
|
||||
*(uintptr_t*)(head->got+head->delta+16) = pltResolver;
|
||||
*(uintptr_t*)(head->got+head->delta+8) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16));
|
||||
printf_dump(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1018,7 +1031,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
|
||||
uname(1) man page description of the -i option). For more details of this token
|
||||
expansion, see “System Specific Shared Objects”
|
||||
*/
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu)
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu)
|
||||
{
|
||||
DumpDynamicRPath(h);
|
||||
// update RPATH first
|
||||
@@ -1079,7 +1092,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib
|
||||
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, nlibs, cnt, box64, emu)) {
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, bindnow, nlibs, cnt, box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading one of needed lib\n");
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
@@ -1118,6 +1131,20 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
|
||||
context->deferedInitList[context->deferedInitSz++] = h;
|
||||
return;
|
||||
}
|
||||
// Refresh no-file part of TLS in case default value changed
|
||||
if(h->tlsfilesize) {
|
||||
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
|
||||
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
|
||||
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
|
||||
tlsdatasize_t* ptr;
|
||||
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL)
|
||||
if(ptr->tlssize==my_context->tlssize) {
|
||||
// refresh in tlsdata too
|
||||
dest = (char*)(ptr->tlsdata+ptr->tlssize+h->tlsbase);
|
||||
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
|
||||
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
|
||||
}
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
|
||||
|
||||
@@ -73,7 +73,9 @@ struct elfheader_s {
|
||||
uint64_t memsz;
|
||||
uint64_t stacksz;
|
||||
size_t stackalign;
|
||||
uintptr_t tlsaddr;
|
||||
uint64_t tlssize;
|
||||
uint64_t tlsfilesize;
|
||||
size_t tlsalign;
|
||||
|
||||
int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
|
||||
+9
-7
@@ -218,12 +218,12 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
|
||||
newemu->old_ip = emu->old_ip;
|
||||
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
|
||||
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
|
||||
memcpy(newemu->mmx87, emu->mmx87, sizeof(emu->mmx87));
|
||||
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
|
||||
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
|
||||
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->cw = emu->cw;
|
||||
newemu->cw_mask_all = emu->cw_mask_all;
|
||||
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
@@ -327,14 +327,15 @@ uint64_t GetRBP(x64emu_t *emu)
|
||||
{
|
||||
return R_RBP;
|
||||
}
|
||||
void SetFS(x64emu_t *emu, uint16_t v)
|
||||
/*void SetFS(x64emu_t *emu, uint16_t v)
|
||||
{
|
||||
emu->segs[_FS] = v;
|
||||
emu->segs_serial[_FS] = 0;
|
||||
}
|
||||
uint16_t GetFS(x64emu_t *emu)
|
||||
{
|
||||
return emu->segs[_FS];
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
void ResetFlags(x64emu_t *emu)
|
||||
@@ -353,7 +354,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
if(trace_emm) {
|
||||
// do emm reg if needed
|
||||
for(int i=0; i<8; ++i) {
|
||||
sprintf(tmp, "mm%d:%016lx", i, emu->mmx87[i].q);
|
||||
sprintf(tmp, "mm%d:%016lx", i, emu->mmx[i].q);
|
||||
strcat(buff, tmp);
|
||||
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
|
||||
}
|
||||
@@ -370,7 +371,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
// start with FPU regs...
|
||||
if(emu->fpu_stack) {
|
||||
for (int i=0; i<emu->fpu_stack; i++) {
|
||||
sprintf(tmp, "ST%d=%f", i, emu->mmx87[(emu->top+i)&7].d);
|
||||
sprintf(tmp, "ST%d=%f", i, ST(i).d);
|
||||
strcat(buff, tmp);
|
||||
int c = 10-strlen(tmp);
|
||||
if(c<1) c=1;
|
||||
@@ -465,7 +466,8 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
|
||||
@@ -33,8 +33,9 @@ typedef struct x64emu_s {
|
||||
// sse
|
||||
sse_regs_t xmm[16];
|
||||
// fpu / mmx
|
||||
mmx87_regs_t mmx87[8];
|
||||
uint16_t cw,cw_mask_all;
|
||||
mmx87_regs_t x87[8];
|
||||
mmx87_regs_t mmx[8];
|
||||
uint16_t cw;
|
||||
x87flags_t sw;
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
|
||||
+76
-12
@@ -46,6 +46,11 @@ int Run(x64emu_t *emu, int step)
|
||||
|
||||
if(emu->quit)
|
||||
return 0;
|
||||
if(R_RIP==0) {
|
||||
emu->quit = 1;
|
||||
printf_log(LOG_INFO, "Ask to run at NULL, quit silently\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//ref opcode: http://ref.x64asm.net/geek32.html#xA1
|
||||
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, (void*)R_RSP);
|
||||
@@ -158,6 +163,9 @@ x64emurun:
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x36: /* SS: (ignored) */
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
@@ -299,6 +307,15 @@ x64emurun:
|
||||
else
|
||||
GD->q[0] = imul32(emu, ED->dword[0], (uint32_t)tmp64s);
|
||||
break;
|
||||
case 0x6C: /* INSB DX */
|
||||
case 0x6D: /* INSL DX */
|
||||
case 0x6E: /* OUTSB DX */
|
||||
case 0x6F: /* OUTSL DX */
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
|
||||
GOCOND(0x70
|
||||
, tmp8s = F8S; CHECK_FLAGS(emu);
|
||||
@@ -496,7 +513,10 @@ x64emurun:
|
||||
case 0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
if(MODREG)
|
||||
ED->q[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
else
|
||||
ED->word[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
break;
|
||||
case 0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
@@ -1004,7 +1024,12 @@ x64emurun:
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC2: /* RETN Iw */
|
||||
tmp16u = F16;
|
||||
R_RIP = Pop(emu);
|
||||
R_RSP += tmp16u;
|
||||
STEP
|
||||
break;
|
||||
case 0xC3: /* RET */
|
||||
R_RIP = Pop(emu);
|
||||
STEP
|
||||
@@ -1050,12 +1075,23 @@ x64emurun:
|
||||
x64Int3(emu);
|
||||
if(emu->quit) goto fini;
|
||||
break;
|
||||
case 0xCD: /* INT n */
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
|
||||
|
||||
case 0xCF: /* IRET */
|
||||
R_RIP = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu)&0xffff;
|
||||
emu->segs_serial[_CS] = 0;
|
||||
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
tmp64u = Pop(emu); //RSP
|
||||
emu->segs[_SS] = Pop(emu)&0xffff;
|
||||
emu->segs_serial[_SS] = 0;
|
||||
R_RSP= tmp64u;
|
||||
RESET_FLAGS(emu);
|
||||
goto fini; // exit, to recompute CS if needed
|
||||
break;
|
||||
@@ -1213,7 +1249,15 @@ x64emurun:
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
|
||||
case 0xE4: /* IN AL, XX */
|
||||
case 0xE5: /* IN EAX, XX */
|
||||
case 0xE6: /* OUT XX, AL */
|
||||
case 0xE7: /* OUT XX, EAX */
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, R_RIP);
|
||||
@@ -1231,7 +1275,15 @@ x64emurun:
|
||||
R_RIP += tmp32s;
|
||||
STEP
|
||||
break;
|
||||
|
||||
case 0xEC: /* IN AL, DX */
|
||||
case 0xED: /* IN EAX, DX */
|
||||
case 0xEE: /* OUT DX, AL */
|
||||
case 0xEF: /* OUT DX, EAX */
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
case 0xF0: /* LOCK prefix */
|
||||
if(RunF0(emu, rex)) {
|
||||
unimp = 1;
|
||||
@@ -1241,6 +1293,12 @@ x64emurun:
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0xF4: /* HLT */
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
case 0xF5: /* CMC */
|
||||
CHECK_FLAGS(emu);
|
||||
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
|
||||
@@ -1354,10 +1412,16 @@ x64emurun:
|
||||
SET_FLAG(F_CF);
|
||||
break;
|
||||
case 0xFA: /* CLI */
|
||||
CLEAR_FLAG(F_IF); //not really handled...
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
case 0xFB: /* STI */
|
||||
SET_FLAG(F_IF);
|
||||
// this is a privilege opcode...
|
||||
--R_RIP;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
STEP;
|
||||
break;
|
||||
case 0xFC: /* CLD */
|
||||
CLEAR_FLAG(F_DF);
|
||||
@@ -1411,16 +1475,16 @@ x64emurun:
|
||||
STEP
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xC0) {
|
||||
if(MODREG) {
|
||||
R_RIP = emu->old_ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, R_CS);
|
||||
Push(emu, R_RIP);
|
||||
R_RIP = ED->dword[0];
|
||||
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]); // check CS?
|
||||
R_CS = (ED+1)->word[0];
|
||||
goto fini; // exit loop to recompute new CS...
|
||||
}
|
||||
@@ -1430,14 +1494,14 @@ x64emurun:
|
||||
STEP
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
if(MODREG) {
|
||||
R_RIP = emu->old_ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
} else {
|
||||
R_RIP = ED->q[0];
|
||||
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]); //check CS?
|
||||
R_CS = (ED+1)->word[0];
|
||||
goto fini; // exit loop to recompute CS...
|
||||
}
|
||||
|
||||
+45
-4
@@ -48,6 +48,18 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
case 0x05: /* SYSCALL */
|
||||
x64Syscall(emu);
|
||||
break;
|
||||
case 0x06: /* CLTS */
|
||||
// this is a privilege opcode...
|
||||
R_RIP-=2;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
break;
|
||||
|
||||
case 0x08: /* INVD */
|
||||
case 0x09: /* WBINVD */
|
||||
// this is a privilege opcode...
|
||||
R_RIP-=2;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
break;
|
||||
|
||||
case 0x0B: /* UD2 */
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
@@ -69,13 +81,13 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
memcpy(GX, EX, 16); // unaligned, so carreful
|
||||
GX->u128 = EX->u128;
|
||||
break;
|
||||
case 0x11: /* MOVUPS Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
memcpy(EX, GX, 16); // unaligned, so carreful
|
||||
EX->u128 = GX->u128;
|
||||
break;
|
||||
case 0x12:
|
||||
nextop = F8;
|
||||
@@ -142,6 +154,14 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
break;
|
||||
case 0x20: /* MOV REG, crX */
|
||||
case 0x21: /* MOV REG, drX */
|
||||
case 0x22: /* MOV cxR, REG */
|
||||
case 0x23: /* MOV drX, REG */
|
||||
// this is a privilege opcode...
|
||||
R_RIP-=2;
|
||||
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
|
||||
break;
|
||||
|
||||
case 0x28: /* MOVAPS Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -1156,8 +1176,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GX->ud[i]=(tmp8s)?0xffffffff:0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4: /* PINSRW Gm,Ew,Ib */
|
||||
case 0xC3: /* MOVNTI Ed, Gd */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
ED->q[0] = GD->q[0];
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = GD->dword[0];
|
||||
else
|
||||
ED->dword[0] = GD->dword[0];
|
||||
}
|
||||
break;
|
||||
case 0xC4: /* PINSRW Gm,Ew,Ib */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGM;
|
||||
@@ -1271,6 +1303,15 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD7: /* PMOVMSKB Gd,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGD;
|
||||
GD->dword[0] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(EM->ub[i]&0x80)
|
||||
GD->dword[0] |= (1<<i);
|
||||
break;
|
||||
case 0xD8: /* PSUBUSB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
|
||||
+152
-29
@@ -191,6 +191,13 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
|
||||
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gd,Eb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
GD->q[0] = EB->byte[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -224,34 +231,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
|
||||
|
||||
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
|
||||
while(opcode>=0x40 && opcode<=0x4F) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
switch(opcode) {
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0xD6: /* MOVQ Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
if(MODREG)
|
||||
EX->q[1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
return Run6664(emu, rex);
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
@@ -406,7 +386,150 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0xF7: /* GRP3 Ed(,Id) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
GETED_OFFS((tmp8u<2)?4:0, tlsdata);
|
||||
if(rex.w) {
|
||||
switch(tmp8u) {
|
||||
case 0:
|
||||
case 1: /* TEST Ed,Id */
|
||||
tmp64u = F32S64;
|
||||
test64(emu, ED->q[0], tmp64u);
|
||||
break;
|
||||
case 2: /* NOT Ed */
|
||||
ED->q[0] = not64(emu, ED->q[0]);
|
||||
break;
|
||||
case 3: /* NEG Ed */
|
||||
ED->q[0] = neg64(emu, ED->q[0]);
|
||||
break;
|
||||
case 4: /* MUL RAX,Ed */
|
||||
mul64_rax(emu, ED->q[0]);
|
||||
break;
|
||||
case 5: /* IMUL RAX,Ed */
|
||||
imul64_rax(emu, ED->q[0]);
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
div64(emu, ED->q[0]);
|
||||
break;
|
||||
case 7: /* IDIV Ed */
|
||||
idiv64(emu, ED->q[0]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(tmp8u) {
|
||||
case 0:
|
||||
case 1: /* TEST Ed,Id */
|
||||
tmp32u = F32;
|
||||
test32(emu, ED->dword[0], tmp32u);
|
||||
break;
|
||||
case 2: /* NOT Ed */
|
||||
if(MODREG)
|
||||
ED->q[0] = not32(emu, ED->dword[0]);
|
||||
else
|
||||
ED->dword[0] = not32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 3: /* NEG Ed */
|
||||
if(MODREG)
|
||||
ED->q[0] = neg32(emu, ED->dword[0]);
|
||||
else
|
||||
ED->dword[0] = neg32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 4: /* MUL EAX,Ed */
|
||||
mul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
break;
|
||||
case 5: /* IMUL EAX,Ed */
|
||||
imul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
div32(emu, ED->dword[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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
if(rex.w)
|
||||
ED->q[0] = inc64(emu, ED->q[0]);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = inc32(emu, ED->dword[0]);
|
||||
else
|
||||
ED->dword[0] = inc32(emu, ED->dword[0]);
|
||||
}
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
if(rex.w)
|
||||
ED->q[0] = dec64(emu, ED->q[0]);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = dec32(emu, ED->dword[0]);
|
||||
else
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
}
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
|
||||
Push(emu, R_RIP);
|
||||
R_RIP = tmp64u;
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xC0) {
|
||||
R_RIP = emu->old_ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, R_RIP);
|
||||
R_RIP = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
return 0; // exit loop to recompute new CS...
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]);
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
R_RIP = emu->old_ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
} else {
|
||||
R_RIP = ED->q[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
return 0; // exit loop to recompute CS...
|
||||
}
|
||||
break;
|
||||
case 6: /* Push Ed */
|
||||
tmp64u = ED->q[0]; // rex.w ignored
|
||||
Push(emu, tmp64u); // avoid potential issue with push [esp+...]
|
||||
break;
|
||||
default:
|
||||
R_RIP = emu->old_ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+30
-3
@@ -47,7 +47,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
// REX prefix before the F0 are ignored
|
||||
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
@@ -225,7 +225,14 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
else
|
||||
GW->word[0] = EW->word[0];
|
||||
break;
|
||||
|
||||
case 0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
if(rex.w)
|
||||
EW->q[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
else
|
||||
EW->word[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
break;
|
||||
case 0x8D: /* LEA Gw,M */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -236,7 +243,27 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
GD->word[0] = (uint16_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
case 0x90: /* NOP */
|
||||
case 0x90: /* NOP or XCHG R8d, AX*/
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97: /* XCHG reg,AX */
|
||||
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 {
|
||||
tmp16u = R_AX;
|
||||
R_AX = emu->regs[tmp8u].word[0];
|
||||
emu->regs[tmp8u].word[0] = tmp16u;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x98: /* CBW */
|
||||
|
||||
+448
-1
@@ -22,6 +22,27 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if((b & 1) == 1)
|
||||
retval ^= a;
|
||||
|
||||
if((a & 0x80)) {
|
||||
a <<= 1;
|
||||
a ^= 0x1b;
|
||||
} else {
|
||||
a <<= 1;
|
||||
}
|
||||
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Run660F(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
@@ -33,9 +54,53 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
float tmpf;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1, *opex2;
|
||||
mmx87_regs_t *opem, *opgm;
|
||||
// AES opcodes constants
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A F K P E J O D I N C H M B G L
|
||||
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
|
||||
const uint8_t subbytes[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A N K H E B O L I F C P M J G D
|
||||
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
|
||||
const uint8_t invsubbytes[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -248,6 +313,27 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: /* PSIGNB Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<16; ++i)
|
||||
GX->sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
|
||||
break;
|
||||
case 0x09: /* PSIGNW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<8; ++i)
|
||||
GX->sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
|
||||
break;
|
||||
case 0x0A: /* PSIGND Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
|
||||
break;
|
||||
case 0x0B: /* PMULHRSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
@@ -258,6 +344,49 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x14: /* BLENDVPS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
if(emu->xmm[0].ud[i]&0x80000000)
|
||||
GX->ud[i] = EX->ud[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17: // PTEST GX, EX
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
CONDITIONAL_SET_FLAG(!(GX->u128&EX->u128), F_ZF);
|
||||
CONDITIONAL_SET_FLAG(!((~GX->u128)&EX->u128), F_CF);
|
||||
break;
|
||||
|
||||
case 0x1C: /* PABSB Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<16; ++i) {
|
||||
GX->sb[i] = abs(EX->sb[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1D: /* PABSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
GX->sw[i] = abs(EX->sw[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1E: /* PABSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
GX->sd[i] = abs(EX->sd[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x20: /* PMOVSXBW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
@@ -301,14 +430,140 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->sq[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0xDB: /* AESIMC Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
//STATE ← InvMixColumns( STATE );
|
||||
if (EX == GX) {
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = EX->ub[i];
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX->ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
GX->ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
GX->ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
GX->ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
} else {
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX->ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
|
||||
GX->ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
|
||||
GX->ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
|
||||
GX->ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xDC: /* AESENC Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← ShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX->ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = subbytes[eax1.ub[i]];
|
||||
//STATE ← MixColumns( STATE );
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX->ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
|
||||
GX->ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
|
||||
GX->ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
|
||||
GX->ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
|
||||
}
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX->q[0] ^= EX->q[0];
|
||||
GX->q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDD: /* AESENCLAST Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← ShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX->ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
GX->ub[i] = subbytes[eax1.ub[i]];
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX->q[0] ^= EX->q[0];
|
||||
GX->q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDE: /* AESDEC Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← InvShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX->ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = invsubbytes[eax1.ub[i]];
|
||||
//STATE ← InvMixColumns( STATE );
|
||||
for(int j=0; j<4; ++j) {
|
||||
GX->ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
GX->ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
GX->ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
GX->ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX->q[0] ^= EX->q[0];
|
||||
GX->q[1] ^= EX->q[1];
|
||||
break;
|
||||
case 0xDF: /* AESDECLAST Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
//STATE ← SRC1;
|
||||
//RoundKey ← SRC2;
|
||||
//STATE ← InvShiftRows( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = GX->ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
GX->ub[i] = invsubbytes[eax1.ub[i]];
|
||||
//DEST[127:0] ← STATE XOR RoundKey;
|
||||
GX->q[0] ^= EX->q[0];
|
||||
GX->q[1] ^= EX->q[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3A: // these are some SSE3 opcodes
|
||||
case 0x3A: // these are some SSE3 & SSE4.x opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0A: // ROUNDSS 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->f[0] = floor(EX->f[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->f[0] = floor(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->f[0] = ceil(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->f[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0B: // ROUNDSD Gx, Ex, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -334,6 +589,16 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0E: /* PBLENDW Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
for (int i=0; i<8; ++i) {
|
||||
if(tmp8u&(1<<i))
|
||||
GX->uw[i] = EX->uw[i];
|
||||
}
|
||||
break;
|
||||
case 0x0F: // PALIGNR GX, EX, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -350,6 +615,75 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17: // EXTRACTPS ED, GX, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
ED->dword[0] = GX->ud[tmp8u&3];
|
||||
if(MODREG && rex.w) ED->dword[1] = 0;
|
||||
break;
|
||||
|
||||
case 0x20: // PINSRB GX, ED, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->ub[tmp8u&0xf] = ED->byte[0];
|
||||
break;
|
||||
case 0x21: // INSERTPS GX, EX, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
|
||||
GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<i))
|
||||
GX->ud[i] = 0;
|
||||
break;
|
||||
case 0x22: // PINSRD GX, ED, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->ud[tmp8u&0x3] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x40: /* DPPS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
tmpf = 0.0f;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<(i+4)))
|
||||
tmpf += GX->f[i]*EX->f[i];
|
||||
for(int i=0; i<4; ++i)
|
||||
GX->f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
|
||||
break;
|
||||
|
||||
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp32u = F8;
|
||||
for (int i = 4; i < 8; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
for (int i = 12; i < 16; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
GX->ud[0] = GX->ud[1];
|
||||
tmp8u = GX->ub[4];
|
||||
GX->ud[1] = GX->ud[1] >> 8;
|
||||
GX->ub[7] = tmp8u;
|
||||
GX->ud[1] ^= tmp32u;
|
||||
GX->ud[2] = GX->ud[3];
|
||||
tmp8u = GX->ub[12];
|
||||
GX->ud[3] = GX->ud[3] >> 8;
|
||||
GX->ub[15] = tmp8u;
|
||||
GX->ud[3] ^= tmp32u;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -965,7 +1299,104 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GETGW;
|
||||
GW->word[0] = EB->byte[0];
|
||||
break;
|
||||
case 0xB7: /* MOVZX Gw,Ew */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
GW->word[0] = EW->word[0];
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* BT Ew,Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
case 5: /* BTS Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: /* BTR Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
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&=15;
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
case 7: /* BTC Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
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&=15;
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0xBB: /* BTC Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
@@ -1116,6 +1547,22 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[1] = eax1.q[1];
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* BSWAP reg16 */
|
||||
tmp8u = (opcode&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
emu->regs[tmp8u].q[0] = __builtin_bswap64(emu->regs[tmp8u].q[0]);
|
||||
} else {
|
||||
emu->regs[tmp8u].word[0] = __builtin_bswap16(emu->regs[tmp8u].word[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD1: /* PSRLW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
|
||||
@@ -27,6 +27,7 @@ int Run6664(x64emu_t *emu, rex_t rex)
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
|
||||
opcode = F8;
|
||||
@@ -39,6 +40,33 @@ int Run6664(x64emu_t *emu, rex_t rex)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0xD6: /* MOVQ Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
if(MODREG)
|
||||
EX->q[1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV Ew,Gw */
|
||||
nextop = F8;
|
||||
GETEW_OFFS(0, tlsdata);
|
||||
GETGW;
|
||||
if(rex.w)
|
||||
EW->q[0] = GW->q[0];
|
||||
else
|
||||
EW->word[0] = GW->word[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
nextop = F8;
|
||||
GETEW_OFFS(0, tlsdata);
|
||||
|
||||
+65
-52
@@ -27,10 +27,11 @@ int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint16_t tmp16u2;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int32_t tmp32s;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped;
|
||||
reg64_t *oped, *opgd;
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
@@ -40,7 +41,45 @@ int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
if(rex.w) return RunF0(emu, rex);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
case 0xB1: /* CMPXCHG Ew,Gw */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp16u = arm64_lock_read_h(EW);
|
||||
cmp16(emu, R_AX, tmp16u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_h(EW, GW->word[0]);
|
||||
} else {
|
||||
R_AX = tmp16u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp16(emu, R_AX, EW->word[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EW->word[0] = GW->word[0];
|
||||
} else {
|
||||
R_AX = EW->word[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x81: /* GRP Ew,Iw */
|
||||
case 0x83: /* GRP Ew,Ib */
|
||||
@@ -49,55 +88,7 @@ int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
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 {
|
||||
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;
|
||||
@@ -106,8 +97,30 @@ int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
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;
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -29,6 +29,7 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
|
||||
@@ -237,6 +238,12 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
R_RIP += tmp8s;
|
||||
break;
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, R_RIP);
|
||||
R_RIP += tmp32s;
|
||||
break;
|
||||
|
||||
case 0xF7: /* GRP3 Ed(,Id) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
|
||||
@@ -55,9 +55,11 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
|
||||
|
||||
DynaRun(emu);
|
||||
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 1; // finished!
|
||||
if(!emu->quit) {
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 1; // finished!
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1000,6 +1002,11 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
}
|
||||
#endif
|
||||
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
|
||||
if(R_RIP==0) {
|
||||
printf_log(LOG_NONE, "Running at NULL address\n");
|
||||
pthread_mutex_unlock(&my_context->mutex_trace);
|
||||
return;
|
||||
}
|
||||
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
|
||||
uint64_t a = *(uint64_t*)(ip+3);
|
||||
if(a==0) {
|
||||
@@ -1241,7 +1248,7 @@ mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->mmx87[m&0x07];
|
||||
return &emu->mmx[m&0x07];
|
||||
} else return (mmx87_regs_t*)GetECommon(emu, rex, m, delta);
|
||||
}
|
||||
|
||||
@@ -1289,7 +1296,7 @@ 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];
|
||||
return &emu->mmx[m&7];
|
||||
}
|
||||
|
||||
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
@@ -185,6 +185,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
|
||||
case 0xFB: /* FSINCOS */
|
||||
fpu_do_push(emu);
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
case 0xFC: /* FRNDINT */
|
||||
ST0.d = fpu_round(emu, ST0.d);
|
||||
@@ -196,9 +197,11 @@ int RunD9(x64emu_t *emu, rex_t rex)
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
ST0.d = sin(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
case 0xFF: /* FCOS */
|
||||
ST0.d = cos(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -163,11 +163,11 @@ int RunDB(x64emu_t *emu, rex_t rex)
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
STld(0).ref = ST0.q;
|
||||
STld(0).uref = ST0.q;
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GETED(0);
|
||||
if(ST0.q!=STld(0).ref)
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, ED);
|
||||
else
|
||||
memcpy(ED, &STld(0).ld, 10);
|
||||
|
||||
+4
-4
@@ -152,8 +152,8 @@ int RunDF(x64emu_t *emu, rex_t rex)
|
||||
tmp64s = ED->sq[0];
|
||||
fpu_do_push(emu);
|
||||
ST0.d = tmp64s;
|
||||
STll(0).ll = tmp64s;
|
||||
STll(0).ref = ST0.q;
|
||||
STll(0).sq = tmp64s;
|
||||
STll(0).sref = ST0.sq;
|
||||
break;
|
||||
case 6: /* FBSTP tbytes, ST0 */
|
||||
GETED(0);
|
||||
@@ -162,8 +162,8 @@ int RunDF(x64emu_t *emu, rex_t rex)
|
||||
break;
|
||||
case 7: /* FISTP i64 */
|
||||
GETED(0);
|
||||
if(STll(0).ref==ST(0).sq)
|
||||
ED->sq[0] = STll(0).ll;
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
ED->sq[0] = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
ED->sq[0] = 0x8000000000000000LL;
|
||||
|
||||
+212
-1
@@ -30,7 +30,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
uint8_t tmp8u, tmp8u2; (void)tmp8u2;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int64_t tmp64s;
|
||||
@@ -405,6 +405,187 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* BT Ed,Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
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
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
case 5: /* BTS Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
if(tmp64u & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
} else {
|
||||
tmp64u ^= (1LL<<tmp8u);
|
||||
tmp32s = arm64_lock_write_dd(ED, tmp64u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
} else {
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp32u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} while(tmp32s);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 6: /* BTR Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp8u&=63;
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
if(tmp64u & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp64u ^= (1LL<<tmp8u);
|
||||
tmp32s = arm64_lock_write_dd(ED, tmp64u);
|
||||
} else {
|
||||
tmp32s = 0;
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp32u);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
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);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 7: /* BTC Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
if(tmp64u & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp64u ^= (1LL<<tmp8u);
|
||||
tmp32s = arm64_lock_write_dd(ED, tmp64u);
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp32u);
|
||||
} while(tmp32s);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
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
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC1: /* XADD Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -523,6 +704,36 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
case 0x66:
|
||||
return Run66F0(emu, rex); // more opcode F0 66 and 66 F0 is the same
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB(1);
|
||||
tmp8u = F8;
|
||||
#ifdef DYNAREC
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = add8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 1: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = or8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 2: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = adc8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 3: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = sbb8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 4: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = and8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 5: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = sub8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 6: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = xor8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
|
||||
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
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;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
|
||||
+11
-1
@@ -212,7 +212,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
|
||||
case 0xC2: /* CMPSD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
tmp8s = 0;
|
||||
@@ -229,6 +229,16 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
|
||||
break;
|
||||
|
||||
case 0xD0: /* ADDSUBPS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->f[0] -= EX->f[0];
|
||||
GX->f[1] += EX->f[1];
|
||||
GX->f[2] -= EX->f[2];
|
||||
GX->f[3] += EX->f[3];
|
||||
break;
|
||||
|
||||
case 0xD6: /* MOVDQ2Q Gm, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
|
||||
@@ -238,6 +238,24 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
memcpy(EX, GX, 16); // unaligned...
|
||||
break;
|
||||
|
||||
case 0xB8: /* POPCNT Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = __builtin_popcountl(ED->q[0]);
|
||||
else
|
||||
GD->q[0] = __builtin_popcount(ED->dword[0]);
|
||||
RESET_FLAGS(emu);
|
||||
CLEAR_FLAG(F_OF);
|
||||
CLEAR_FLAG(F_SF);
|
||||
CLEAR_FLAG(F_ZF);
|
||||
CLEAR_FLAG(F_AF);
|
||||
CLEAR_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_PF);
|
||||
CONDITIONAL_SET_FLAG(GD->q[0]==0, F_ZF);
|
||||
break;
|
||||
|
||||
case 0xBC: /* TZCNT Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
@@ -273,6 +291,24 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xBD: /* LZCNT Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
tmp64u = ED->q[0];
|
||||
tmp8u = (tmp64u)?__builtin_clzl(tmp64u):64;
|
||||
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u==64, F_CF);
|
||||
} else {
|
||||
tmp32u = ED->dword[0];
|
||||
tmp8u = (tmp32u)?__builtin_clz(tmp32u):32;
|
||||
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u==32, F_CF);
|
||||
}
|
||||
GD->q[0] = tmp8u;
|
||||
break;
|
||||
|
||||
case 0xC2: /* CMPSS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
|
||||
+102
-33
@@ -36,13 +36,16 @@
|
||||
typedef struct x64_sigaction_s x64_sigaction_t;
|
||||
typedef struct x64_stack_s x64_stack_t;
|
||||
|
||||
int mkdir(const char *path, mode_t mode);
|
||||
extern int mkdir(const char *path, mode_t mode);
|
||||
extern int fchmodat (int __fd, const char *__file, mode_t __mode, int __flag);
|
||||
|
||||
//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_lstat(x64emu_t *emu, void* filename, void* buf);
|
||||
int my_fstat(x64emu_t *emu, int fd, 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);
|
||||
@@ -72,10 +75,13 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 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
|
||||
//{ 5, __NR_fstat, 2},
|
||||
//{ 6, __NR_lstat, 2},
|
||||
{ 8, __NR_lseek, 3},
|
||||
//{ 9, __NR_mmap, 6}, // wrapped to track mmap
|
||||
//{ 10, __NR_mprotect, 3}, // same
|
||||
//{ 11, __NR_munmap, 2}, // same
|
||||
{ 5, __NR_fstat, 2},
|
||||
{ 12, __NR_brk, 1},
|
||||
//{ 13, __NR_rt_sigaction, 4}, // wrapped to use my_ version
|
||||
{ 14, __NR_rt_sigprocmask, 4},
|
||||
{ 16, __NR_ioctl, 3},
|
||||
@@ -90,18 +96,32 @@ scwrap_t syscallwrap[] = {
|
||||
{ 23, __NR_select, 5},
|
||||
#endif
|
||||
//{ 25, __NR_mremap, 5}, // wrapped to track protection
|
||||
{ 35, __NR_nanosleep, 2},
|
||||
{ 39, __NR_getpid, 0},
|
||||
{ 41, __NR_socket, 3},
|
||||
{ 42, __NR_connect, 3},
|
||||
{ 43, __NR_accept, 3},
|
||||
{ 44, __NR_sendto, 6},
|
||||
{ 45, __NR_recvfrom, 6},
|
||||
{ 46, __NR_sendmsg, 3},
|
||||
{ 47, __NR_recvmsg, 3},
|
||||
{ 53, __NR_socketpair, 4},
|
||||
#ifdef __NR_vfork
|
||||
{56, __NR_vfork, 0},
|
||||
#endif
|
||||
#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},
|
||||
{ 73, __NR_flock, 2},
|
||||
#ifdef __NR_getdents
|
||||
{ 78, __NR_getdents, 3},
|
||||
#endif
|
||||
{ 79, __NR_getcwd, 2},
|
||||
#ifdef __NR_rename
|
||||
{ 82, __NR_rename, 2},
|
||||
#endif
|
||||
#ifdef __NR_mkdir
|
||||
{ 83, __NR_mkdir, 2},
|
||||
#endif
|
||||
@@ -124,6 +144,8 @@ scwrap_t syscallwrap[] = {
|
||||
{ 201, __NR_time, 1},
|
||||
#endif
|
||||
{ 202, __NR_futex, 6},
|
||||
{ 203, __NR_sched_setaffinity, 3},
|
||||
{ 204, __NR_sched_getaffinity, 3},
|
||||
{ 217, __NR_getdents64, 3},
|
||||
{ 220, __NR_semtimedop, 4},
|
||||
{ 228, __NR_clock_gettime, 2},
|
||||
@@ -135,10 +157,21 @@ scwrap_t syscallwrap[] = {
|
||||
#endif
|
||||
{ 254, __NR_inotify_add_watch, 3},
|
||||
{ 255, __NR_inotify_rm_watch, 2},
|
||||
{ 257, __NR_openat, 4},
|
||||
{ 274, __NR_get_robust_list, 3},
|
||||
{ 294, __NR_inotify_init1, 1},
|
||||
{ 298, __NR_perf_event_open, 5},
|
||||
{ 309, __NR_getcpu, 3}, // need wrapping?
|
||||
{ 315, __NR_sched_getattr, 4},
|
||||
{ 318, __NR_getrandom, 3},
|
||||
{ 319, __NR_memfd_create, 2},
|
||||
#ifdef __NR_statx
|
||||
// TODO: implement fallback if __NR_statx is not defined
|
||||
{ 332, __NR_statx, 4},
|
||||
#endif
|
||||
#ifdef __NR_fchmodat4
|
||||
{ 434, __NR_fchmodat4, 4},
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mmap_arg_struct {
|
||||
@@ -248,42 +281,48 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
}
|
||||
switch (s) {
|
||||
case 0: // sys_read
|
||||
R_EAX = (uint32_t)read((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
*(int64_t*)&R_RAX = read((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
break;
|
||||
case 1: // sys_write
|
||||
R_EAX = (uint32_t)write((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
*(int64_t*)&R_RAX = write((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
break;
|
||||
case 2: // sys_open
|
||||
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_RDI, of_convert(R_ESI), R_EDX);};
|
||||
//R_EAX = (uint32_t)open((void*)R_EDI, of_convert(R_ESI), R_EDX);
|
||||
R_EAX = (uint32_t)my_open(emu, (void*)R_RDI, of_convert(R_ESI), R_EDX);
|
||||
//*(int64_t*)&R_RAX = open((void*)R_EDI, of_convert(R_ESI), R_EDX);
|
||||
*(int64_t*)&R_RAX = my_open(emu, (void*)R_RDI, of_convert(R_ESI), R_EDX);
|
||||
break;
|
||||
case 3: // sys_close
|
||||
R_EAX = (uint32_t)close((int)R_EDI);
|
||||
*(int64_t*)&R_RAX = close((int)R_EDI);
|
||||
break;
|
||||
case 4: // sys_stat
|
||||
R_EAX = (uint32_t)my_stat(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
*(int64_t*)&R_RAX = my_stat(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
case 5: // sys_fstat
|
||||
*(int64_t*)&R_RAX = my_fstat(emu, (int)R_EDI, (void*)R_RSI);
|
||||
break;
|
||||
case 6: // sys_lstat
|
||||
*(int64_t*)&R_RAX = my_lstat(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;
|
||||
case 10: // sys_mprotect
|
||||
R_EAX = (uint32_t)my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
|
||||
*(int64_t*)&R_RAX = my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
|
||||
break;
|
||||
case 11: // sys_munmap
|
||||
R_EAX = (uint32_t)my_munmap(emu, (void*)R_RDI, R_RSI);
|
||||
*(int64_t*)&R_RAX = my_munmap(emu, (void*)R_RDI, R_RSI);
|
||||
break;
|
||||
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*/);
|
||||
*(int64_t*)&R_RAX = 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);
|
||||
*(int64_t*)&R_RAX = access((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
R_EAX = (uint32_t)pipe((void*)R_RDI);
|
||||
*(int64_t*)&R_RAX = pipe((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
@@ -294,6 +333,14 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
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_vfork
|
||||
case 56: // vfork
|
||||
{
|
||||
int64_t r = vfork();
|
||||
R_RAX = r;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
R_RAX = fork();
|
||||
@@ -310,24 +357,29 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_rename
|
||||
case 82: // sys_rename
|
||||
*(int64_t*)&R_RAX = rename((void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
R_EAX = (uint32_t)mkdir((void*)R_RDI, R_ESI);
|
||||
*(int64_t*)&R_RAX = mkdir((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
R_EAX = (uint32_t)unlink((void*)R_RDI);
|
||||
*(int64_t*)&R_RAX = 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);
|
||||
*(int64_t*)&R_RAX = 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);
|
||||
*(int64_t*)&R_RAX = my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 201: // sys_time
|
||||
@@ -339,13 +391,18 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
R_EAX = (int)syscall(__NR_inotify_init1, 0);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_fchmodat4
|
||||
case 434:
|
||||
*(int64_t*)R_RAX = fchmodat((int)R_EDI, (void*)R_RSI, (mode_t)R_RDX, (int)R_R10d);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
emu->error |= ERR_UNIMPL;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
printf_log(LOG_DEBUG, " => 0x%lx\n", R_RAX);
|
||||
}
|
||||
|
||||
#define stack(n) (R_RSP+8+n)
|
||||
@@ -357,7 +414,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
|
||||
uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
{
|
||||
uint32_t s = R_EDI;;
|
||||
uint32_t s = R_EDI;
|
||||
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);
|
||||
@@ -381,37 +438,45 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
}
|
||||
switch (s) {
|
||||
case 0: // sys_read
|
||||
return (uint32_t)read(R_ESI, (void*)R_RDX, R_ECX);
|
||||
return (uint64_t)read(R_ESI, (void*)R_RDX, R_ECX);
|
||||
case 1: // sys_write
|
||||
return (uint32_t)write(R_ESI, (void*)R_RDX, R_ECX);
|
||||
return (uint64_t)write(R_ESI, (void*)R_RDX, R_ECX);
|
||||
case 2: // sys_open
|
||||
return my_open(emu, (char*)R_RSI, of_convert(R_EDX), R_ECX);
|
||||
case 3: // sys_close
|
||||
return (uint32_t)close(R_ESI);
|
||||
return (uint64_t)(int64_t)close(R_ESI);
|
||||
case 4: // sys_stat
|
||||
return (uint32_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
|
||||
return (uint64_t)(int64_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
|
||||
case 5: // sys_fstat
|
||||
return (uint64_t)(int64_t)my_fstat(emu, (int)R_ESI, (void*)R_RDX);
|
||||
case 6: // sys_lstat
|
||||
return (uint64_t)(int64_t)my_lstat(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
|
||||
return (uint32_t)my_mprotect(emu, (void*)R_RSI, R_RDX, (int)R_ECX);
|
||||
return (uint64_t)(int64_t)my_mprotect(emu, (void*)R_RSI, R_RDX, (int)R_ECX);
|
||||
case 11: // sys_munmap
|
||||
return (uint32_t)my_munmap(emu, (void*)R_RSI, R_RDX);
|
||||
return (uint64_t)(int64_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*/);
|
||||
return (uint64_t)(int64_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);
|
||||
return (uint64_t)(int64_t)access((void*)R_RSI, R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
return (uint32_t)pipe((void*)R_RSI);
|
||||
return (uint64_t)(int64_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);
|
||||
return (uint64_t)(int64_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_vfork
|
||||
case 56: // vfork
|
||||
return vfork();
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
return fork();
|
||||
@@ -428,18 +493,18 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
return (uint32_t)mkdir((void*)R_RSI, R_EDX);
|
||||
return (uint64_t)(int64_t)mkdir((void*)R_RSI, R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
return (uint32_t)unlink((void*)R_RSI);
|
||||
return (uint64_t)(int64_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);
|
||||
return (uint64_t)(int64_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);
|
||||
return (uint64_t)(int64_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);
|
||||
@@ -448,6 +513,10 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
case 253:
|
||||
return (int)syscall(__NR_inotify_init1, 0);
|
||||
#endif
|
||||
#ifndef __NR_fchmodat4
|
||||
case 434:
|
||||
return (int)fchmodat((int)R_ESI, (void*)R_RDX, (mode_t)R_RCX, (int)R_R8d);
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
|
||||
+6
-6
@@ -136,18 +136,18 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
|
||||
int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
{
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_SET_FS 0x1002
|
||||
#define ARCH_GET_FS 0x1003
|
||||
#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;
|
||||
}
|
||||
pthread_once(&thread_key_once3, thread_key_alloc3);
|
||||
if(emu->segs[_GS]!=(0xa<<3))
|
||||
emu->segs[_GS] = 0xa<<3; // should not move!
|
||||
emu->segs_serial[_GS] = 0;
|
||||
my_context->segtls[3].base = (uintptr_t)addr;
|
||||
my_context->segtls[3].limit = 0;
|
||||
my_context->segtls[3].present = 1;
|
||||
|
||||
@@ -21,7 +21,7 @@ void fpu_do_free(x64emu_t* emu, int i)
|
||||
|
||||
void reset_fpu(x64emu_t* emu)
|
||||
{
|
||||
memset(emu->mmx87, 0, sizeof(emu->mmx87));
|
||||
memset(emu->x87, 0, sizeof(emu->x87));
|
||||
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
|
||||
emu->cw = 0x37F;
|
||||
emu->sw.x16 = 0x0000;
|
||||
@@ -177,8 +177,8 @@ void D2LD(void* d, void* ld)
|
||||
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
|
||||
int32_t exp80 = s.ud[1]&0x7ff00000;
|
||||
int32_t exp80final = (exp80>>20);
|
||||
int64_t mant80 = s.q&0x000fffffffffffffL;
|
||||
int64_t mant80final = (mant80 << 11);
|
||||
uint64_t mant80 = s.q&0x000fffffffffffffL;
|
||||
uint64_t mant80final = (mant80 << 11);
|
||||
if(exp80final==0x7ff) {
|
||||
// NaN and Infinite
|
||||
exp80final = 0x7fff;
|
||||
@@ -294,7 +294,11 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
|
||||
{
|
||||
xsave32_t *p = (xsave32_t*)ed;
|
||||
// should save flags & all
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
uint8_t tags = 0;
|
||||
@@ -310,7 +314,7 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
|
||||
p->MxCsr_Mask = 0;
|
||||
// copy FPU/MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
|
||||
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
|
||||
}
|
||||
@@ -319,7 +323,11 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
|
||||
{
|
||||
xsave64_t *p = (xsave64_t*)ed;
|
||||
// should save flags & all
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
uint8_t tags = 0;
|
||||
@@ -333,7 +341,7 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
|
||||
p->MxCsr_Mask = 0;
|
||||
// copy FPU/MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
|
||||
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
|
||||
}
|
||||
@@ -347,9 +355,13 @@ void fpu_fxrstor32(x64emu_t* emu, void* ed)
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
|
||||
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
|
||||
}
|
||||
@@ -363,9 +375,13 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed)
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
|
||||
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
|
||||
}
|
||||
@@ -14,9 +14,9 @@ typedef struct x64emu_s x64emu_t;
|
||||
#define LN2 0.69314718055994531
|
||||
#define LG2 0.3010299956639812
|
||||
|
||||
#define ST0 emu->mmx87[emu->top]
|
||||
#define ST1 emu->mmx87[(emu->top+1)&7]
|
||||
#define ST(a) emu->mmx87[(emu->top+(a))&7]
|
||||
#define ST0 emu->x87[emu->top]
|
||||
#define ST1 emu->x87[(emu->top+1)&7]
|
||||
#define ST(a) emu->x87[(emu->top+(a))&7]
|
||||
|
||||
#define STld(a) emu->fpu_ld[(emu->top+(a))&7]
|
||||
#define STll(a) emu->fpu_ll[(emu->top+(a))&7]
|
||||
|
||||
@@ -82,6 +82,7 @@ typedef struct box64context_s {
|
||||
|
||||
char* fullpath;
|
||||
char* box64path; // path of current box64 executable
|
||||
char* box86path; // path of box86 executable (if present)
|
||||
|
||||
uint64_t stacksz;
|
||||
size_t stackalign;
|
||||
@@ -103,6 +104,7 @@ typedef struct box64context_s {
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
uintptr_t vsyscall; // vsyscall bridge value
|
||||
uintptr_t vsyscalls[3]; // the 3 x86 VSyscall pseudo bridges (mapped at 0xffffffffff600000+)
|
||||
dlprivate_t *dlprivate; // dlopen library map
|
||||
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
|
||||
kh_symbolmap_t *glmymap; // link to the mysymbolmap of libGL
|
||||
@@ -121,6 +123,7 @@ typedef struct box64context_s {
|
||||
#endif
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
pthread_mutex_t mutex_bridge;
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
|
||||
|
||||
@@ -17,6 +17,8 @@ uintptr_t AddAutomaticBridge(x64emu_t* emu, bridge_t* bridge, wrapper_t w, void*
|
||||
void* GetNativeFnc(uintptr_t fnc);
|
||||
void* GetNativeFncOrFnc(uintptr_t fnc);
|
||||
|
||||
uintptr_t AddVSyscall(bridge_t* bridge, int num);
|
||||
|
||||
int hasAlternate(void* addr);
|
||||
void* getAlternate(void* addr);
|
||||
void addAlternate(void* addr, void* alt);
|
||||
|
||||
@@ -13,6 +13,12 @@ extern int box64_dynarec_dump;
|
||||
extern int box64_dynarec_trace;
|
||||
extern int box64_dynarec_forced;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
#ifdef ARM64
|
||||
extern int arm64_asimd;
|
||||
extern int arm64_aes;
|
||||
extern int arm64_pmull;
|
||||
extern int arm64_crc32;
|
||||
#endif
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -23,6 +29,7 @@ extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
#endif
|
||||
extern int allow_missing_libs;
|
||||
extern int box64_prefer_wrapped;
|
||||
extern int box64_steam;
|
||||
extern int box64_wine;
|
||||
extern int box64_nopulse; // disabling the use of wrapped pulseaudio
|
||||
|
||||
@@ -24,13 +24,13 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
|
||||
void FreeElfMemory(elfheader_t* head);
|
||||
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);
|
||||
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, 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);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu);
|
||||
uintptr_t GetElfInit(elfheader_t* h);
|
||||
uintptr_t GetElfFini(elfheader_t* h);
|
||||
void RunElfInit(elfheader_t* h, x64emu_t *emu);
|
||||
|
||||
@@ -14,6 +14,7 @@ int FileExist(const char* filename, int flags);
|
||||
char* ResolveFile(const char* filename, path_collection_t* paths);
|
||||
|
||||
// 1: if file is an x86 elf, 0: if not (or not found)
|
||||
int FileIsX86ELF(const char* filename);
|
||||
int FileIsX64ELF(const char* filename);
|
||||
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
|
||||
@@ -24,7 +24,7 @@ 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** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, 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 version, const char* vername);
|
||||
|
||||
@@ -12,7 +12,7 @@ typedef struct needed_libs_s needed_libs_t;
|
||||
|
||||
library_t *NewLibrary(const char* path, box64context_t* box64);
|
||||
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu);
|
||||
int ReloadLibrary(library_t* lib, x64emu_t* emu);
|
||||
void InactiveLibrary(library_t* lib);
|
||||
void Free1Library(library_t **lib, x64emu_t* emu);
|
||||
|
||||
+35
-6
@@ -35,6 +35,20 @@ typedef struct {
|
||||
sysv_varargs->reg_save_area=A->reg_save_area; \
|
||||
sysv_varargs->overflow_arg_area=A->overflow_arg_area;
|
||||
|
||||
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs->gp_offset=(6-((N<6)?N:6))*8;\
|
||||
sysv_varargs->fp_offset=(6*8); \
|
||||
sysv_varargs->reg_save_area=SCRATCH; \
|
||||
sysv_varargs->overflow_arg_area=STACK; \
|
||||
{ \
|
||||
uint64_t *p = (uint64_t*)SCRATCH; \
|
||||
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
|
||||
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
|
||||
memcpy(&p[6], emu->xmm, 8*16); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
// aarch64: 8 64bits general regs and 8 128bits float regs
|
||||
@@ -54,14 +68,28 @@ typedef struct va_list {
|
||||
sysv_varargs.__vr_offs=(8*16); \
|
||||
sysv_varargs.__stack=A;
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
|
||||
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
|
||||
sysv_varargs.__stack=A->overflow_arg_area; \
|
||||
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
|
||||
#define CONVERT_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
|
||||
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
|
||||
sysv_varargs.__stack=A->overflow_arg_area; \
|
||||
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
|
||||
sysv_varargs.__vr_top=A->reg_save_area + X64_VA_MAX_XMM;
|
||||
|
||||
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs.__gr_offs=(8*(2+((N<6)?N:6))); \
|
||||
sysv_varargs.__vr_offs=0; \
|
||||
sysv_varargs.__stack=STACK; \
|
||||
sysv_varargs.__gr_top=SCRATCH + X64_VA_MAX_REG; \
|
||||
sysv_varargs.__vr_top=SCRATCH + X64_VA_MAX_XMM; \
|
||||
{ \
|
||||
uint64_t *p = (uint64_t*)SCRATCH; \
|
||||
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
|
||||
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
|
||||
memcpy(&p[6], emu->xmm, 8*16); \
|
||||
}
|
||||
|
||||
#elif defined(__powerpc64__)
|
||||
// TODO, is this correct?
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
@@ -109,6 +137,7 @@ struct x64_stat64 { /* x86_64 arm64 */
|
||||
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
|
||||
} __attribute__((packed)); /* 144 */ /* 128 */
|
||||
|
||||
void AlignStat64(const void* source, void* dest);
|
||||
void UnalignStat64(const void* source, void* dest);
|
||||
|
||||
// defined in wrapperlibc.c
|
||||
|
||||
+3
-3
@@ -150,12 +150,12 @@ typedef struct {
|
||||
#else
|
||||
longdouble_t ld;
|
||||
#endif
|
||||
uint64_t ref;
|
||||
uint64_t uref;
|
||||
} fpu_ld_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t ll;
|
||||
int64_t ref;
|
||||
int64_t sq;
|
||||
int64_t sref;
|
||||
} fpu_ll_t;
|
||||
|
||||
typedef union {
|
||||
|
||||
@@ -34,8 +34,8 @@ void SetRSI(x64emu_t *emu, uint64_t v);
|
||||
void SetRBP(x64emu_t *emu, uint64_t v);
|
||||
void SetRSP(x64emu_t *emu, uint64_t v);
|
||||
void SetRIP(x64emu_t *emu, uint64_t v);
|
||||
void SetFS(x64emu_t *emu, uint16_t v);
|
||||
uint16_t GetFS(x64emu_t *emu);
|
||||
//void SetFS(x64emu_t *emu, uint16_t v);
|
||||
//uint16_t GetFS(x64emu_t *emu);
|
||||
uint64_t GetRSP(x64emu_t *emu);
|
||||
uint64_t GetRBP(x64emu_t *emu);
|
||||
void ResetFlags(x64emu_t *emu);
|
||||
|
||||
@@ -46,7 +46,7 @@ static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *free
|
||||
if (lib->depended.libs[i] == maplib->libraries[j]) break;
|
||||
}
|
||||
if (j == maplib->libsz) {
|
||||
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
|
||||
printf_log(LOG_DEBUG, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
|
||||
continue;
|
||||
}
|
||||
if (freed[j] == 1) {
|
||||
@@ -288,7 +288,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
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)
|
||||
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
@@ -300,22 +300,22 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// load dependancies and launch init sequence
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, 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")) {
|
||||
const char* libs[] = {"libGL.so.1"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box64, emu);
|
||||
}
|
||||
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
|
||||
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box64, emu);
|
||||
}
|
||||
|
||||
// finalize the lib
|
||||
if(FinalizeLibrary(lib, local?maplib:NULL, emu)) {
|
||||
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -327,7 +327,7 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
|
||||
}
|
||||
|
||||
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)
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!neededlibs) {
|
||||
neededlibs = alloca(sizeof(needed_libs_t));
|
||||
@@ -344,7 +344,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
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)) {
|
||||
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, 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;
|
||||
}
|
||||
|
||||
+86
-9
@@ -26,7 +26,7 @@
|
||||
#include "wrappedlibs.h"
|
||||
// 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);\
|
||||
void wrapped##N##_fini(library_t* lib); \
|
||||
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"
|
||||
@@ -79,12 +79,52 @@ int NbDot(const char* name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void NativeLib_CommonInit(library_t *lib) {
|
||||
lib->priv.w.bridge = NewBridge();
|
||||
|
||||
lib->symbolmap = kh_init(symbolmap);
|
||||
lib->wsymbolmap = kh_init(symbolmap);
|
||||
lib->mysymbolmap = kh_init(symbolmap);
|
||||
lib->wmysymbolmap = kh_init(symbolmap);
|
||||
lib->stsymbolmap = kh_init(symbolmap);
|
||||
lib->symbol2map = kh_init(symbol2map);
|
||||
lib->datamap = kh_init(datamap);
|
||||
lib->wdatamap = kh_init(datamap);
|
||||
lib->mydatamap = kh_init(datamap);
|
||||
}
|
||||
|
||||
void EmuLib_Fini(library_t* lib)
|
||||
{
|
||||
kh_destroy(mapsymbols, lib->priv.n.mapsymbols);
|
||||
kh_destroy(mapsymbols, lib->priv.n.localsymbols);
|
||||
}
|
||||
void NativeLib_FinishFini(library_t* lib)
|
||||
{
|
||||
if(lib->priv.w.lib)
|
||||
dlclose(lib->priv.w.lib);
|
||||
lib->priv.w.lib = NULL;
|
||||
if(lib->priv.w.altprefix)
|
||||
free(lib->priv.w.altprefix);
|
||||
if(lib->priv.w.neededlibs) {
|
||||
for(int i=0; i<lib->priv.w.needed; ++i)
|
||||
free(lib->priv.w.neededlibs[i]);
|
||||
free(lib->priv.w.neededlibs);
|
||||
}
|
||||
FreeBridge(&lib->priv.w.bridge);
|
||||
}
|
||||
|
||||
int WrappedLib_defget(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) {
|
||||
uintptr_t addr = 0;
|
||||
uintptr_t size = 0;
|
||||
if (!getSymbolInMaps(lib, name, 0, &addr, &size, version, vername, local)) {
|
||||
return 0;
|
||||
}
|
||||
if(!addr && !size)
|
||||
return 0;
|
||||
*offs = addr;
|
||||
*sz = size;
|
||||
return 1;
|
||||
}
|
||||
int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
// symbols...
|
||||
@@ -104,6 +144,18 @@ int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int WrappedLib_defgetnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) {
|
||||
uintptr_t addr = 0;
|
||||
uintptr_t size = 0;
|
||||
if (!getSymbolInMaps(lib, name, 1, &addr, &size, version, vername, local)) {
|
||||
return 0;
|
||||
}
|
||||
if(!addr && !size)
|
||||
return 0;
|
||||
*offs = addr;
|
||||
*sz = size;
|
||||
return 1;
|
||||
}
|
||||
int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
|
||||
{
|
||||
uintptr_t start, end;
|
||||
@@ -151,7 +203,7 @@ static void initNativeLib(library_t *lib, box64context_t* context) {
|
||||
lib->getlocal = NativeLib_GetLocal;
|
||||
lib->type = 0;
|
||||
// Call librarian to load all dependant elf
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, thread_get_emu())) {
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, 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;
|
||||
}
|
||||
@@ -265,18 +317,19 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
}
|
||||
}
|
||||
int notwrapped = FindInCollection(lib->name, &context->box64_emulated_libs);
|
||||
int precise = (path && path[0]=='/')?1:0;
|
||||
// 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)
|
||||
if(!notwrapped && !precise)
|
||||
initNativeLib(lib, context);
|
||||
// then look for a native one
|
||||
if(lib->type==-1)
|
||||
initEmulatedLib(path, lib, context);
|
||||
// still not loaded but notwrapped indicated: use wrapped...
|
||||
if(lib->type==-1 && notwrapped)
|
||||
if(lib->type==-1 && notwrapped && !precise)
|
||||
initNativeLib(lib, context);
|
||||
// nothing loaded, so error...
|
||||
if(lib->type==-1)
|
||||
@@ -303,7 +356,7 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu)
|
||||
{
|
||||
if(!lib)
|
||||
return 0;
|
||||
@@ -313,11 +366,14 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
lib->priv.n.finalized = 1;
|
||||
elfheader_t *elf_header = my_context->elfs[lib->priv.n.elf_index];
|
||||
// finalize relocations
|
||||
if(RelocateElf(my_context->maplib, local_maplib, elf_header)) {
|
||||
if(RelocateElf(my_context->maplib, local_maplib, bindnow, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
|
||||
return 1;
|
||||
}
|
||||
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
|
||||
if(RelocateElfPlt(my_context->maplib, local_maplib, bindnow, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: relocating Plt symbols in elf %s\n", lib->name);
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_func) {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
|
||||
@@ -371,11 +427,12 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu)
|
||||
}
|
||||
// can close the file now
|
||||
fclose(f);
|
||||
if(RelocateElf(lib->context->maplib, lib->maplib, elf_header)) {
|
||||
// should bindnow be store in a per/library basis?
|
||||
if(RelocateElf(lib->context->maplib, lib->maplib, 0, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
|
||||
return 1;
|
||||
}
|
||||
RelocateElfPlt(lib->context->maplib, lib->maplib, elf_header);
|
||||
RelocateElfPlt(lib->context->maplib, lib->maplib, 0, elf_header);
|
||||
// init (will use PltRelocator... because some other libs are not yet resolved)
|
||||
RunElfInit(elf_header, emu);
|
||||
}
|
||||
@@ -425,6 +482,8 @@ void Free1Library(library_t **lib, x64emu_t* emu)
|
||||
kh_destroy(datamap, (*lib)->mydatamap);
|
||||
if((*lib)->mysymbolmap)
|
||||
kh_destroy(symbolmap, (*lib)->mysymbolmap);
|
||||
if((*lib)->wmysymbolmap)
|
||||
kh_destroy(symbolmap, (*lib)->wmysymbolmap);
|
||||
if((*lib)->stsymbolmap)
|
||||
kh_destroy(symbolmap, (*lib)->stsymbolmap);
|
||||
if((*lib)->symbol2map)
|
||||
@@ -648,6 +707,24 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
|
||||
return 1;
|
||||
}
|
||||
if(!noweak) {
|
||||
// check in wmysymbolmap
|
||||
khint_t k = kh_get(symbolmap, lib->wmysymbolmap, name);
|
||||
if (k!=kh_end(lib->wmysymbolmap)) {
|
||||
char buff[200];
|
||||
if(lib->altmy)
|
||||
strcpy(buff, lib->altmy);
|
||||
else
|
||||
strcpy(buff, "my_");
|
||||
strcat(buff, name);
|
||||
symbol = dlsym(lib->priv.w.box64lib, buff);
|
||||
if(!symbol) {
|
||||
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
|
||||
} else
|
||||
AddOffsetSymbol(lib->context->maplib, symbol, name);
|
||||
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->wmysymbolmap, k), symbol, 0, name);
|
||||
*size = sizeof(void*);
|
||||
return 1;
|
||||
}
|
||||
k = kh_get(symbolmap, lib->wsymbolmap, name);
|
||||
if (k!=kh_end(lib->wsymbolmap)) {
|
||||
symbol = dlsym(lib->priv.w.lib, name);
|
||||
|
||||
@@ -68,6 +68,7 @@ typedef struct library_s {
|
||||
kh_symbolmap_t *symbolmap;
|
||||
kh_symbolmap_t *wsymbolmap;
|
||||
kh_symbolmap_t *mysymbolmap;
|
||||
kh_symbolmap_t *wmysymbolmap;
|
||||
kh_symbolmap_t *stsymbolmap;
|
||||
kh_symbol2map_t *symbol2map;
|
||||
kh_datamap_t *datamap;
|
||||
|
||||
+16
-10
@@ -52,13 +52,14 @@ GO("libXau.so.6", libxau)
|
||||
GO("libXdmcp.so.6", libxdmcp)
|
||||
GO("libX11-xcb.so.1", libx11xcb)
|
||||
GO("libxcb.so.1", libxcb)
|
||||
//GO("libxcb-xfixes.so.0", libxcbxfixes)
|
||||
//GO("libxcb-shape.so.0", libxcbshape)
|
||||
//GO("libxcb-shm.so.0", libxcbshm)
|
||||
//GO("libxcb-randr.so.0", libxcbrandr)
|
||||
//GO("libxcb-image.so.0", libxcbimage)
|
||||
//GO("libxcb-keysyms.so.1", libxcbkeysyms)
|
||||
//GO("libxcb-xtest.so.0", libxcbxtest)
|
||||
GO("libxcb-xfixes.so.0", libxcbxfixes)
|
||||
GO("libxcb-shape.so.0", libxcbshape)
|
||||
GO("libxcb-shm.so.0", libxcbshm)
|
||||
GO("libxcb-randr.so.0", libxcbrandr)
|
||||
GO("libxcb-image.so.0", libxcbimage)
|
||||
GO("libxcb-keysyms.so.1", libxcbkeysyms)
|
||||
GO("libxcb-xtest.so.0", libxcbxtest)
|
||||
GO("libxcb-glx.so.0", libxcbglx)
|
||||
//GO("libxcb-dri2.so.0", libxcbdri2)
|
||||
//GO("libxcb-dri3.so.0", libxcbdri3)
|
||||
//GO("libxcb-present.so.0", libxcbpresent)
|
||||
@@ -67,6 +68,8 @@ GO("libXt.so.6", libxt)
|
||||
GO("libXcomposite.so.1", libxcomposite)
|
||||
GO("libXdamage.so.1", libxdamage)
|
||||
GO("libXmu.so.6", libxmu)
|
||||
GO("libxkbcommon.so.0", xkbcommon)
|
||||
GO("libxkbcommon-x11.so.0", xkbcommonx11)
|
||||
GO("libz.so.1", libz)
|
||||
GO("libopenal.so.1", openal)
|
||||
GO("libopenal.so.0", openal)
|
||||
@@ -140,8 +143,9 @@ 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("libmpg123.so.0", mpg123)
|
||||
GO("libgnutls.so.30", gnutls)
|
||||
GO("libpcre.so.3", libpcre)
|
||||
GO("libcups.so.2", libcups)
|
||||
//GO("d3dadapter9.so.1", d3dadapter9)
|
||||
//GO("libvulkan.so.1", vulkan)
|
||||
@@ -153,9 +157,11 @@ GO("libxml2.so.2", xml2)
|
||||
//GO("liblber-2.4.so.2", lber)
|
||||
//GO("libnsl.so.1", nsl)
|
||||
//GO("liblcms2.so.2", lcms2)
|
||||
//GO("libkrb5.so.3", krb5)
|
||||
//GO("libgssapi_krb5.so.2", gssapikrb5)
|
||||
GO("libkrb5.so.3", krb5)
|
||||
GO("libgssapi_krb5.so.2", gssapikrb5)
|
||||
GO("libgssapi.so.3", gssapi)
|
||||
//GO("libtiff.so.5", libtiff)
|
||||
//GO("libfuse.so.2", libfuse)
|
||||
|
||||
GO("ld-linux-x86-64.so.2", ldlinux)
|
||||
|
||||
|
||||
@@ -710,6 +710,26 @@ void UnalignStat64(const void* source, void* dest)
|
||||
x64st->st_ctim = st->st_ctim;
|
||||
}
|
||||
|
||||
void AlignStat64(const void* source, void* dest)
|
||||
{
|
||||
struct stat *st = (struct stat*) dest;
|
||||
struct x64_stat64 *x64st = (struct x64_stat64*)source;
|
||||
|
||||
st->st_dev = x64st->st_dev;
|
||||
st->st_ino = x64st->st_ino;
|
||||
st->st_mode = x64st->st_mode;
|
||||
st->st_nlink = x64st->st_nlink;
|
||||
st->st_uid = x64st->st_uid;
|
||||
st->st_gid = x64st->st_gid;
|
||||
st->st_rdev = x64st->st_rdev;
|
||||
st->st_size = x64st->st_size;
|
||||
st->st_blksize = x64st->st_blksize;
|
||||
st->st_blocks = x64st->st_blocks;
|
||||
st->st_atim = x64st->st_atim;
|
||||
st->st_mtim = x64st->st_mtim;
|
||||
st->st_ctim = x64st->st_ctim;
|
||||
}
|
||||
|
||||
typedef union __attribute__((packed)) x64_epoll_data {
|
||||
void *ptr;
|
||||
int fd;
|
||||
|
||||
@@ -132,6 +132,7 @@ SDL1_RWops_t* RWNativeStart(x64emu_t* emu, SDL1_RWops_t* ops)
|
||||
SDL1_RWops_t* newrw = Alloc();
|
||||
newrw->type = BOX64RW;
|
||||
newrw->hidden.my.orig = ops;
|
||||
newrw->hidden.my.custom_free = (sdl1_freerw)emu->context->sdl1freerw;
|
||||
// create wrapper
|
||||
#define GO(A, W) \
|
||||
newrw->A = my_emulated_##A;
|
||||
|
||||
+87
-71
@@ -264,10 +264,14 @@ static void sigstack_key_alloc() {
|
||||
pthread_key_create(&sigstack_key, sigstack_destroy);
|
||||
}
|
||||
|
||||
uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
|
||||
uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
if(fnc==0 || fnc==1) {
|
||||
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
|
||||
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_IGN":"SIG_DFL");
|
||||
if(fnc==0) {
|
||||
printf_log(LOG_NONE, "Unhandled signal caught, aborting\n");
|
||||
abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -303,10 +307,45 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
|
||||
}
|
||||
va_end (va);
|
||||
|
||||
EmuCall(emu, fnc); // avoid DynaCall for now
|
||||
int oldquitonlongjmp = emu->quitonlongjmp;
|
||||
emu->quitonlongjmp = 2;
|
||||
|
||||
//EmuCall(emu, fnc); // avoid DynaCall for now
|
||||
DynaCall(emu, fnc);
|
||||
if(nargs>6)
|
||||
R_RSP+=((nargs-6)*4);
|
||||
|
||||
emu->quitonlongjmp = oldquitonlongjmp;
|
||||
|
||||
if(emu->longjmp) {
|
||||
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
|
||||
emu->longjmp = 0;
|
||||
if(sigcontext) {
|
||||
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
|
||||
sigcontext->uc_mcontext.gregs[X64_R9] = R_R9;
|
||||
sigcontext->uc_mcontext.gregs[X64_R10] = R_R10;
|
||||
sigcontext->uc_mcontext.gregs[X64_R11] = R_R11;
|
||||
sigcontext->uc_mcontext.gregs[X64_R12] = R_R12;
|
||||
sigcontext->uc_mcontext.gregs[X64_R13] = R_R13;
|
||||
sigcontext->uc_mcontext.gregs[X64_R14] = R_R14;
|
||||
sigcontext->uc_mcontext.gregs[X64_R15] = R_R15;
|
||||
sigcontext->uc_mcontext.gregs[X64_RAX] = R_RAX;
|
||||
sigcontext->uc_mcontext.gregs[X64_RCX] = R_RCX;
|
||||
sigcontext->uc_mcontext.gregs[X64_RDX] = R_RDX;
|
||||
sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI;
|
||||
sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI;
|
||||
sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP;
|
||||
sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
|
||||
sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
|
||||
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
|
||||
// flags
|
||||
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64;
|
||||
// get segments
|
||||
sigcontext->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, longjmp in signal but no sigcontext to change\n");
|
||||
}
|
||||
}
|
||||
if(exit)
|
||||
*exit = emu->exit;
|
||||
|
||||
@@ -374,42 +413,6 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
|
||||
}
|
||||
|
||||
|
||||
void my_sighandler(int32_t sig)
|
||||
{
|
||||
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();
|
||||
uintptr_t restorer = my_context->restorer[sig];
|
||||
uintptr_t old_regs[16] = {0};
|
||||
uintptr_t old_ip = emu->ip.q[0];
|
||||
uint64_t old_flags = emu->eflags.x64;
|
||||
for(int i=0; i<16; ++i)
|
||||
old_regs[i] = emu->regs[i].q[0];
|
||||
|
||||
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
|
||||
if(new_ss) {
|
||||
// no alternate stack, so signal RSP needs to match thread RSP!
|
||||
R_RSP = (uintptr_t)(new_ss->ss_sp+new_ss->ss_size-32);
|
||||
}
|
||||
|
||||
int exits = 0;
|
||||
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
|
||||
// restore regs
|
||||
emu->ip.q[0] = old_ip;
|
||||
emu->eflags.x64 = old_flags;
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->regs[i].q[0] = old_regs[i];
|
||||
if(exits) {
|
||||
relockMutex(Locks);
|
||||
exit(ret);
|
||||
}
|
||||
// what about the restored regs?
|
||||
if(restorer)
|
||||
RunFunctionHandler(&exits, restorer, 0);
|
||||
relockMutex(Locks);
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
|
||||
{
|
||||
@@ -435,7 +438,7 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
|
||||
void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
|
||||
{
|
||||
int Locks = unlockMutex();
|
||||
|
||||
@@ -444,13 +447,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
uintptr_t restorer = my_context->restorer[sig];
|
||||
// get that actual ESP first!
|
||||
x64emu_t *emu = thread_get_emu();
|
||||
uintptr_t *frame = (uintptr_t*)R_RSP;
|
||||
uintptr_t frame = R_RSP;
|
||||
#if defined(DYNAREC) && defined(__aarch64__)
|
||||
ucontext_t *p = (ucontext_t *)ucntx;
|
||||
void * pc = (void*)p->uc_mcontext.pc;
|
||||
dynablock_t* db = (dynablock_t*)cur_db;//FindDynablockFromNativeAddress(pc);
|
||||
if(db) {
|
||||
frame = (uintptr_t*)p->uc_mcontext.regs[10+_SP];
|
||||
frame = (uintptr_t)p->uc_mcontext.regs[10+_SP];
|
||||
}
|
||||
#else
|
||||
(void)ucntx; (void)cur_db;
|
||||
@@ -460,9 +463,9 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
int used_stack = 0;
|
||||
if(new_ss) {
|
||||
if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
|
||||
frame = (uintptr_t*)emu->regs[_SP].q[0];
|
||||
frame = (uintptr_t)emu->regs[_SP].q[0];
|
||||
} else {
|
||||
frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
|
||||
frame = (uintptr_t)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
|
||||
used_stack = 1;
|
||||
new_ss->ss_flags = SS_ONSTACK;
|
||||
}
|
||||
@@ -471,7 +474,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
// TODO: do I need to really setup 2 stack frame? That doesn't seems right!
|
||||
// setup stack frame
|
||||
// try to fill some sigcontext....
|
||||
frame -= sizeof(x64_ucontext_t)/sizeof(uintptr_t);
|
||||
frame -= sizeof(x64_ucontext_t);
|
||||
x64_ucontext_t *sigcontext = (x64_ucontext_t*)frame;
|
||||
// get general register
|
||||
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
|
||||
@@ -488,9 +491,9 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI;
|
||||
sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI;
|
||||
sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP;
|
||||
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
|
||||
sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
|
||||
sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
|
||||
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;//emu->old_ip; // old_ip should be more accurate as the "current" IP, but it's not always up-to-date
|
||||
// flags
|
||||
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64;
|
||||
// get segments
|
||||
@@ -555,8 +558,8 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17;
|
||||
else if(sig==SIGSEGV) {
|
||||
if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) {
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0010; // execution flag issue (probably)
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0)
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14;
|
||||
} else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue
|
||||
if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
|
||||
@@ -588,12 +591,16 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
GO(RBP);
|
||||
#undef GO
|
||||
// set stack pointer
|
||||
R_RSP = (uintptr_t)frame;
|
||||
R_RSP = frame;
|
||||
// set frame pointer
|
||||
R_RBP = sigcontext->uc_mcontext.gregs[X64_RBP];
|
||||
|
||||
int exits = 0;
|
||||
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
|
||||
int ret;
|
||||
if (simple)
|
||||
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig);
|
||||
else
|
||||
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info, sigcontext);
|
||||
// restore old value from emu
|
||||
#define GO(A) R_##A = old_##A
|
||||
GO(RAX);
|
||||
@@ -643,7 +650,7 @@ 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 siglongjmp to resume emu\n");
|
||||
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p\n", (void*)R_RIP);
|
||||
if(old_code)
|
||||
*old_code = -1; // re-init the value to allow another segfault at the same place
|
||||
if(used_stack) // release stack
|
||||
@@ -692,7 +699,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
exit(ret);
|
||||
}
|
||||
if(restorer)
|
||||
RunFunctionHandler(&exits, 0, restorer, 0);
|
||||
RunFunctionHandler(&exits, NULL, restorer, 0);
|
||||
if(used_stack) // release stack
|
||||
new_ss->ss_flags = 0;
|
||||
relockMutex(Locks);
|
||||
@@ -701,7 +708,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
{
|
||||
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
|
||||
int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_INFO:LOG_NONE;
|
||||
int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_DEBUG:LOG_INFO;
|
||||
ucontext_t *p = (ucontext_t *)ucntx;
|
||||
void* addr = (void*)info->si_addr; // address that triggered the issue
|
||||
void* rsp = NULL;
|
||||
@@ -791,7 +798,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
static void* glitch_pc = NULL;
|
||||
static void* glitch_addr = NULL;
|
||||
static int glitch_prot = 0;
|
||||
if(addr && pc && db) {
|
||||
if(addr && pc /*&& db*/) {
|
||||
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x, retrying\n", pc, addr, db, prot);
|
||||
@@ -834,6 +841,9 @@ exit(-1);
|
||||
const char* x64name = NULL;
|
||||
const char* elfname = NULL;
|
||||
x64emu_t* emu = thread_get_emu();
|
||||
// Adjust RIP for special case of NULL function run
|
||||
if(sig==SIGSEGV && R_RIP==0x1 && (uintptr_t)info->si_addr==0x0)
|
||||
R_RIP = 0x0;
|
||||
x64pc = R_RIP;
|
||||
rsp = (void*)R_RSP;
|
||||
#if defined(__aarch64__) && defined(DYNAREC)
|
||||
@@ -887,7 +897,7 @@ exit(-1);
|
||||
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
|
||||
if(sig==SIGILL)
|
||||
printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7]);
|
||||
printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X (%02X %02X %02X %02X %02X)\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7], ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4]);
|
||||
else if(sig==SIGBUS)
|
||||
printf_log(log_minimum, " x86opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4], ((uint8_t*)x64pc)[5], ((uint8_t*)x64pc)[6], ((uint8_t*)x64pc)[7]);
|
||||
else
|
||||
@@ -895,10 +905,7 @@ exit(-1);
|
||||
}
|
||||
relockMutex(Locks);
|
||||
if(my_context->signals[sig] && my_context->signals[sig]!=1) {
|
||||
if(my_context->is_sigaction[sig])
|
||||
my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
|
||||
else
|
||||
my_sighandler(sig);
|
||||
my_sigactionhandler_oldcode(sig, my_context->is_sigaction[sig]?0:1, info, ucntx, &old_code, db);
|
||||
return;
|
||||
}
|
||||
// no handler (or double identical segfault)
|
||||
@@ -918,7 +925,7 @@ void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
void* db = NULL;
|
||||
#endif
|
||||
|
||||
my_sigactionhandler_oldcode(sig, info, ucntx, NULL, db);
|
||||
my_sigactionhandler_oldcode(sig, 0, info, ucntx, NULL, db);
|
||||
}
|
||||
|
||||
void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
|
||||
@@ -927,7 +934,7 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
|
||||
void* db = NULL;
|
||||
siginfo_t info = {0};
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_errno = (sig==SIGSEGV)?0x1234:0; // MAark as a sign this is a #GP(0) (like privileged instruction)
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
const char* x64name = NULL;
|
||||
@@ -939,8 +946,8 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
|
||||
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);
|
||||
printf_log(/*LOG_INFO*/LOG_DEBUG, "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, 0, &info, &ctx, NULL, db);
|
||||
}
|
||||
|
||||
EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler)
|
||||
@@ -955,14 +962,20 @@ EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler)
|
||||
my_context->signals[signum] = (uintptr_t)handler;
|
||||
my_context->is_sigaction[signum] = 0;
|
||||
my_context->restorer[signum] = 0;
|
||||
if(handler!=NULL && handler!=(sighandler_t)1) {
|
||||
handler = my_sighandler;
|
||||
}
|
||||
my_context->onstack[signum] = 0;
|
||||
|
||||
if(signum==SIGSEGV || signum==SIGBUS || signum==SIGILL)
|
||||
return 0;
|
||||
|
||||
return signal(signum, handler);
|
||||
if(handler!=NULL && handler!=(sighandler_t)1) {
|
||||
struct sigaction newact = {0};
|
||||
struct sigaction oldact = {0};
|
||||
newact.sa_flags = 0x04;
|
||||
newact.sa_sigaction = my_sigactionhandler;
|
||||
sigaction(signum, &newact, &oldact);
|
||||
return oldact.sa_handler;
|
||||
} else
|
||||
return signal(signum, handler);
|
||||
}
|
||||
EXPORT sighandler_t my___sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal")));
|
||||
EXPORT sighandler_t my_sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal"))); // not completly exact
|
||||
@@ -993,7 +1006,8 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x
|
||||
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
|
||||
my_context->is_sigaction[signum] = 0;
|
||||
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
|
||||
newact.sa_handler = my_sighandler;
|
||||
newact.sa_flags|=0x04;
|
||||
newact.sa_sigaction = my_sigactionhandler;
|
||||
} else
|
||||
newact.sa_handler = act->_u._sa_handler;
|
||||
}
|
||||
@@ -1046,7 +1060,8 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio
|
||||
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
|
||||
my_context->is_sigaction[signum] = 0;
|
||||
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
|
||||
newact.k_sa_handler = my_sighandler;
|
||||
newact.sa_flags|=0x4;
|
||||
newact.k_sa_handler = (void*)my_sigactionhandler;
|
||||
} else {
|
||||
newact.k_sa_handler = act->_u._sa_handler;
|
||||
}
|
||||
@@ -1088,7 +1103,8 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio
|
||||
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
|
||||
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
|
||||
my_context->is_sigaction[signum] = 0;
|
||||
newact.sa_handler = my_sighandler;
|
||||
newact.sa_sigaction = my_sigactionhandler;
|
||||
newact.sa_flags|=0x4;
|
||||
} else {
|
||||
newact.sa_handler = act->_u._sa_handler;
|
||||
}
|
||||
@@ -1264,7 +1280,7 @@ void init_signal_helper(box64context_t* context)
|
||||
{
|
||||
// setup signal handling
|
||||
for(int i=0; i<MAX_SIGNAL; ++i) {
|
||||
context->signals[i] = 1; // SIG_DFL
|
||||
context->signals[i] = 0; // SIG_DFL
|
||||
}
|
||||
struct sigaction action = {0};
|
||||
action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
|
||||
|
||||
+11
-3
@@ -197,7 +197,8 @@ x64emu_t* thread_get_emu()
|
||||
size_t stack_size;
|
||||
void *stack_addr;
|
||||
if(!pthread_attr_getstack(&attr, &stack_addr, &stack_size))
|
||||
stacksize = stack_size;
|
||||
if(stack_size)
|
||||
stacksize = stack_size;
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
@@ -363,8 +364,11 @@ EXPORT int my_pthread_attr_getstacksize(x64emu_t* emu, pthread_attr_t* attr, siz
|
||||
{
|
||||
(void)emu;
|
||||
void* addr;
|
||||
return pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
|
||||
int ret = pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
|
||||
if(!*size)
|
||||
*size = 2*1024*1024;
|
||||
//return pthread_attr_getstacksize(getAlignedAttr(attr), size);
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr)
|
||||
{
|
||||
@@ -464,7 +468,7 @@ void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet
|
||||
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
|
||||
x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
|
||||
SetupX64Emu(emuthread);
|
||||
SetFS(emuthread, GetFS(emu));
|
||||
//SetFS(emuthread, GetFS(emu));
|
||||
et->emu = emuthread;
|
||||
et->fnc = (uintptr_t)f;
|
||||
et->arg = arg;
|
||||
@@ -835,6 +839,10 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
}
|
||||
pthread_mutex_t* ret = GetMutex(k);
|
||||
|
||||
#ifndef __PTHREAD_MUTEX_HAVE_PREV
|
||||
#define __PTHREAD_MUTEX_HAVE_PREV 1
|
||||
#endif
|
||||
|
||||
if(init) {
|
||||
if(am->sign == SIGNMTX) {
|
||||
int kind = ((int*)am->m)[3+__PTHREAD_MUTEX_HAVE_PREV]; // extract kind from original mutex
|
||||
|
||||
+93
-14
@@ -9,6 +9,12 @@
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/mman.h>
|
||||
#ifdef DYNAREC
|
||||
#ifdef ARM64
|
||||
#include <linux/auxvec.h>
|
||||
#include <asm/hwcap.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "build_info.h"
|
||||
#include "debug.h"
|
||||
@@ -38,6 +44,12 @@ int box64_dynarec_dump = 0;
|
||||
int box64_dynarec_forced = 0;
|
||||
uintptr_t box64_nodynarec_start = 0;
|
||||
uintptr_t box64_nodynarec_end = 0;
|
||||
#ifdef ARM64
|
||||
int arm64_asimd = 0;
|
||||
int arm64_aes = 0;
|
||||
int arm64_pmull = 0;
|
||||
int arm64_crc32 = 0;
|
||||
#endif
|
||||
#else //DYNAREC
|
||||
int box64_dynarec = 0;
|
||||
#endif
|
||||
@@ -56,6 +68,7 @@ int box64_dynarec_trace = 0;
|
||||
int x11threads = 0;
|
||||
int x11glx = 1;
|
||||
int allow_missing_libs = 0;
|
||||
int box64_prefer_wrapped = 0;
|
||||
int fix_64bit_inodes = 0;
|
||||
int box64_zoom = 0;
|
||||
int box64_steam = 0;
|
||||
@@ -66,7 +79,7 @@ int box64_novulkan = 0;
|
||||
char* libGL = NULL;
|
||||
uintptr_t fmod_smc_start = 0;
|
||||
uintptr_t fmod_smc_end = 0;
|
||||
uint32_t default_gs = 0;
|
||||
uint32_t default_gs = 0xa<<3;
|
||||
int jit_gdb = 0;
|
||||
int box64_tcmalloc_minimal = 0;
|
||||
|
||||
@@ -115,6 +128,39 @@ void my_child_fork()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
void GatherDynarecExtensions()
|
||||
{
|
||||
if(box64_dynarec==0) // no need to check if no dynarec
|
||||
return;
|
||||
#ifdef ARM64
|
||||
unsigned long hwcap = real_getauxval(AT_HWCAP);
|
||||
if(!hwcap) // no HWCap: provide a default...
|
||||
hwcap = HWCAP_ASIMD;
|
||||
// first, check all needed extensions, lif half, edsp and fastmult
|
||||
if((hwcap&HWCAP_ASIMD) == 0) {
|
||||
printf_log(LOG_INFO, "Missing ASMID cpu support, disabling Dynarec\n");
|
||||
box64_dynarec=0;
|
||||
return;
|
||||
}
|
||||
if(hwcap&HWCAP_CRC32)
|
||||
arm64_crc32 = 1;
|
||||
if(hwcap&HWCAP_PMULL)
|
||||
arm64_pmull = 1;
|
||||
if(hwcap&HWCAP_AES)
|
||||
arm64_aes = 1;
|
||||
printf_log(LOG_INFO, "Dynarec for ARM64, with extension: ASIMD");
|
||||
if(arm64_aes)
|
||||
printf_log(LOG_INFO, " AES");
|
||||
if(arm64_crc32)
|
||||
printf_log(LOG_INFO, " CRC32");
|
||||
if(arm64_pmull)
|
||||
printf_log(LOG_INFO, " PMULL");
|
||||
printf_log(LOG_INFO, " PageSize:%d\n", box64_pagesize);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
EXPORTDYN
|
||||
void LoadLogEnv()
|
||||
@@ -345,7 +391,7 @@ void LoadLogEnv()
|
||||
p = getenv("BOX64_JITGDB");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[0]<='0'+1)
|
||||
if(p[0]>='0' && p[0]<='0'+2)
|
||||
jit_gdb = p[0]-'0';
|
||||
}
|
||||
if(jit_gdb)
|
||||
@@ -354,6 +400,9 @@ void LoadLogEnv()
|
||||
box64_pagesize = sysconf(_SC_PAGESIZE);
|
||||
if(!box64_pagesize)
|
||||
box64_pagesize = 4096;
|
||||
#ifdef DYNAREC
|
||||
GatherDynarecExtensions();
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -423,7 +472,7 @@ int GatherEnv(char*** dest, const char** env, const char* prog)
|
||||
(*dest)[idx++] = strdup("BOX64_PATH=.:bin");
|
||||
}
|
||||
if(!ld_path) {
|
||||
(*dest)[idx++] = strdup("BOX64_LD_LIBRARY_PATH=.:lib");
|
||||
(*dest)[idx++] = strdup("BOX64_LD_LIBRARY_PATH=.:lib:lib64");
|
||||
}
|
||||
// add "_=prog" at the end...
|
||||
if(prog) {
|
||||
@@ -448,7 +497,8 @@ void PrintHelp() {
|
||||
printf(" '-h'|'--help' to print box64 help and quit\n");
|
||||
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_LD_LIBRARY_PATH is the box64 version LD_LIBRARY_PATH (default is '.:lib:lib64')\n");
|
||||
printf(" BOX64_PREFER_WRAPPED if box64 will use wrapped libs even if the lib is specified with absolute path\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");
|
||||
@@ -506,16 +556,24 @@ void LoadEnvVars(box64context_t *context)
|
||||
printf_log(LOG_INFO, "\n");
|
||||
}
|
||||
}
|
||||
if(getenv("BOX64_PREFER_WRAPPED")) {
|
||||
if (strcmp(getenv("BOX64_PREFER_WRAPPED"), "1")==0) {
|
||||
box64_prefer_wrapped = 1;
|
||||
printf_log(LOG_INFO, "BOX64: Prefer Wrapped libs\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(getenv("BOX64_NOSIGSEGV")) {
|
||||
if (strcmp(getenv("BOX64_NOSIGSEGV"), "1")==0)
|
||||
if (strcmp(getenv("BOX64_NOSIGSEGV"), "1")==0) {
|
||||
context->no_sigsegv = 1;
|
||||
printf_log(LOG_INFO, "BOX64: Disabling handling of SigSEGV\n");
|
||||
}
|
||||
}
|
||||
if(getenv("BOX64_NOSIGILL")) {
|
||||
if (strcmp(getenv("BOX64_NOSIGILL"), "1")==0)
|
||||
if (strcmp(getenv("BOX64_NOSIGILL"), "1")==0) {
|
||||
context->no_sigill = 1;
|
||||
printf_log(LOG_INFO, "BOX64: Disabling handling of SigILL\n");
|
||||
}
|
||||
}
|
||||
// check BOX64_PATH and load it
|
||||
LoadEnvPath(&context->box64_path, ".:bin", "BOX64_PATH");
|
||||
@@ -817,7 +875,16 @@ int main(int argc, const char **argv, const char **env) {
|
||||
my_context->argv[0] = strdup(prog);
|
||||
else
|
||||
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
|
||||
|
||||
// check if box86 is present
|
||||
{
|
||||
my_context->box86path = strdup(my_context->box64path);
|
||||
char* p = strrchr(my_context->box86path, '6'); // get the 6 of box64
|
||||
p[0] = '8'; p[1] = '6'; // change 64 to 86
|
||||
if(!FileExist(my_context->box86path, IS_FILE)) {
|
||||
free(my_context->box86path);
|
||||
my_context->box86path = NULL;
|
||||
}
|
||||
}
|
||||
const char* prgname = strrchr(prog, '/');
|
||||
if(!prgname)
|
||||
prgname = prog;
|
||||
@@ -894,12 +961,24 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->argv[0], 1);
|
||||
if(!elf_header) {
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch natively instead\n", my_context->argv[0]);
|
||||
int x86 = my_context->box86path?FileIsX86ELF(my_context->argv[0]):0;
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->argv[0], x86?"using box86":"natively");
|
||||
fclose(f);
|
||||
free_contextargv();
|
||||
FreeBox64Context(&my_context);
|
||||
FreeCollection(&ld_preload);
|
||||
return execvp(argv[1], (char * const*)(argv+1));
|
||||
if(x86) {
|
||||
// duplicate the array to change 1st arg as box86
|
||||
const char** newargv = (const char**)calloc(argc+1, sizeof(char*));
|
||||
newargv[0] = my_context->box86path;
|
||||
FreeBox64Context(&my_context);
|
||||
for(int i=1; i<argc; ++i)
|
||||
newargv[i] = argv[i];
|
||||
return execvp(newargv[0], (char * const*)newargv);
|
||||
} else {
|
||||
FreeBox64Context(&my_context);
|
||||
return execvp(argv[1], (char * const*)(argv+1));
|
||||
}
|
||||
printf_log(LOG_NONE, "Failed to execvp: error is %s\n", strerror(errno));
|
||||
}
|
||||
AddElfHeader(my_context, elf_header);
|
||||
|
||||
@@ -1018,26 +1097,26 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
// pre-load lib if needed
|
||||
if(ld_preload.size) {
|
||||
if(AddNeededLib(NULL, NULL, NULL, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) {
|
||||
if(AddNeededLib(NULL, NULL, NULL, 0, 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);
|
||||
// Call librarian to load all dependant elf
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, my_context, emu)) {
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, 0, my_context, emu)) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
|
||||
FreeBox64Context(&my_context);
|
||||
return -1;
|
||||
}
|
||||
// reloc...
|
||||
printf_log(LOG_DEBUG, "And now export symbols / relocation for %s...\n", ElfName(elf_header));
|
||||
if(RelocateElf(my_context->maplib, NULL, elf_header)) {
|
||||
if(RelocateElf(my_context->maplib, NULL, 0, elf_header)) {
|
||||
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", my_context->argv[0]);
|
||||
FreeBox64Context(&my_context);
|
||||
return -1;
|
||||
}
|
||||
// and handle PLT
|
||||
RelocateElfPlt(my_context->maplib, NULL, elf_header);
|
||||
RelocateElfPlt(my_context->maplib, NULL, 0, elf_header);
|
||||
// defered init
|
||||
RunDeferedElfInit(emu);
|
||||
// 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
|
||||
|
||||
@@ -167,7 +167,7 @@ void SetupInitialStack(x64emu_t *emu)
|
||||
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
|
||||
Push(emu, 0); Push(emu, 26); //AT_HWCAP2(26)=0
|
||||
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
|
||||
//Push(emu, ); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
|
||||
//Push(emu, 0); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
|
||||
if(!emu->context->auxval_start) // store auxval start if needed
|
||||
emu->context->auxval_start = (uintptr_t*)R_RSP;
|
||||
|
||||
|
||||
+49
-8
@@ -11,9 +11,9 @@
|
||||
#include "khash.h"
|
||||
#include "debug.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64context.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "box64context.h"
|
||||
#endif
|
||||
|
||||
KHASH_MAP_INIT_INT64(bridgemap, uintptr_t)
|
||||
@@ -30,7 +30,6 @@ typedef struct brick_s {
|
||||
typedef struct bridge_s {
|
||||
brick_t *head;
|
||||
brick_t *last; // to speed up
|
||||
pthread_mutex_t mutex;
|
||||
kh_bridgemap_t *bridgemap;
|
||||
} bridge_t;
|
||||
|
||||
@@ -48,7 +47,6 @@ bridge_t *NewBridge()
|
||||
bridge_t *b = (bridge_t*)calloc(1, sizeof(bridge_t));
|
||||
b->head = NewBrick();
|
||||
b->last = b->head;
|
||||
pthread_mutex_init(&b->mutex, NULL);
|
||||
b->bridgemap = kh_init(bridgemap);
|
||||
|
||||
return b;
|
||||
@@ -69,7 +67,6 @@ void FreeBridge(bridge_t** bridge)
|
||||
b = n;
|
||||
}
|
||||
kh_destroy(bridgemap, (*bridge)->bridgemap);
|
||||
pthread_mutex_destroy(&(*bridge)->mutex);
|
||||
free(*bridge);
|
||||
*bridge = NULL;
|
||||
}
|
||||
@@ -86,7 +83,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
int prot = 0;
|
||||
do {
|
||||
#endif
|
||||
pthread_mutex_lock(&bridge->mutex);
|
||||
pthread_mutex_lock(&my_context->mutex_bridge);
|
||||
b = bridge->last;
|
||||
if(b->sz == NBRICK) {
|
||||
b->next = NewBrick();
|
||||
@@ -95,7 +92,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
}
|
||||
sz = b->sz;
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_unlock(&bridge->mutex);
|
||||
pthread_mutex_unlock(&my_context->mutex_bridge);
|
||||
if(box64_dynarec) {
|
||||
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
|
||||
if(prot)
|
||||
@@ -104,7 +101,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
|
||||
}
|
||||
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
|
||||
pthread_mutex_lock(&bridge->mutex);
|
||||
pthread_mutex_lock(&my_context->mutex_bridge);
|
||||
#endif
|
||||
b->sz++;
|
||||
b->b[sz].CC = 0xCC;
|
||||
@@ -117,7 +114,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
int ret;
|
||||
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
|
||||
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
|
||||
pthread_mutex_unlock(&bridge->mutex);
|
||||
pthread_mutex_unlock(&my_context->mutex_bridge);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec)
|
||||
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||
@@ -206,6 +203,50 @@ void* GetNativeFncOrFnc(uintptr_t fnc)
|
||||
return (void*)b->f;
|
||||
}
|
||||
|
||||
// using the brdige mecanism for the VSyscall
|
||||
uintptr_t AddVSyscall(bridge_t* bridge, int num)
|
||||
{
|
||||
brick_t *b = NULL;
|
||||
int sz = -1;
|
||||
#ifdef DYNAREC
|
||||
int prot = 0;
|
||||
do {
|
||||
#endif
|
||||
pthread_mutex_lock(&my_context->mutex_bridge);
|
||||
b = bridge->last;
|
||||
if(b->sz == NBRICK) {
|
||||
b->next = NewBrick();
|
||||
b = b->next;
|
||||
bridge->last = b;
|
||||
}
|
||||
sz = b->sz;
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_unlock(&my_context->mutex_bridge);
|
||||
if(box64_dynarec) {
|
||||
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
|
||||
if(prot)
|
||||
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||
else // only add DB if there is no protection
|
||||
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
|
||||
}
|
||||
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
|
||||
pthread_mutex_lock(&my_context->mutex_bridge);
|
||||
#endif
|
||||
b->sz++;
|
||||
b->b[sz].B8 = 0xB8;
|
||||
b->b[sz].num = num;
|
||||
b->b[sz]._0F = 0x0F;
|
||||
b->b[sz]._05 = 0x05;
|
||||
b->b[sz]._C3 = 0xC3;
|
||||
pthread_mutex_unlock(&my_context->mutex_bridge);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec)
|
||||
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||
#endif
|
||||
|
||||
return (uintptr_t)&b->b[sz].CC;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
KHASH_MAP_INIT_INT64(bridgename, const char*)
|
||||
static kh_bridgename_t *bridgename;
|
||||
|
||||
@@ -15,6 +15,12 @@ typedef union onebridge_s {
|
||||
uint8_t C3; // C2 or C3 ret
|
||||
uint16_t N; // N in case of C2 ret
|
||||
};
|
||||
struct {
|
||||
uint8_t B8; // B8 00 11 22 33 mov rax, num
|
||||
uint32_t num;
|
||||
uint8_t _0F; uint8_t _05; // 0F 05 syscall
|
||||
uint8_t _C3; // C3 ret
|
||||
};
|
||||
uint64_t dummy[4];
|
||||
} onebridge_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
+29
-3
@@ -15,7 +15,10 @@
|
||||
#include "debug.h"
|
||||
#include "fileutils.h"
|
||||
|
||||
static const char* x86sign = "\x7f" "ELF" "\x01" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x03" "\x00";
|
||||
static const char* x64sign = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x3e" "\x00";
|
||||
static const char* x86lib = "\x7f" "ELF" "\x01" "\x01" "\x01" "\x03" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x03" "\x00" "\x03" "\x00";
|
||||
static const char* x64lib = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x03" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x03" "\x00" "\x3e" "\x00";
|
||||
|
||||
int FileExist(const char* filename, int flags)
|
||||
{
|
||||
@@ -65,14 +68,37 @@ int FileIsX64ELF(const char* filename)
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f)
|
||||
return 0;
|
||||
char head[sizeof(*x64sign)] = {0};
|
||||
int sz = fread(head, sizeof(*x64sign), 1, f);
|
||||
char head[20] = {0};
|
||||
int sz = fread(head, 20, 1, f);
|
||||
if(sz!=1) {
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
fclose(f);
|
||||
if(memcmp(head, x64sign, sizeof(*x64sign))==0)
|
||||
if(memcmp(head, x64sign, 20)==0)
|
||||
return 1;
|
||||
head[7] = x64lib[7]; // this one changes
|
||||
if(memcmp(head, x64lib, 20)==0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileIsX86ELF(const char* filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if(!f)
|
||||
return 0;
|
||||
char head[20] = {0};
|
||||
int sz = fread(head, 20, 1, f);
|
||||
if(sz!=1) {
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
fclose(f);
|
||||
if(memcmp(head, x86sign, 20)==0)
|
||||
return 1;
|
||||
head[7] = x64lib[7];
|
||||
if(memcmp(head, x86lib, 20)==0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
|
||||
| 1<<9 // SSSE3
|
||||
| 1<<12 // fma
|
||||
| 1<<13 // cx16 (cmpxchg16)
|
||||
| 1<<25 // aesni
|
||||
;
|
||||
break;
|
||||
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureDEFS_H_
|
||||
#define __wrappedalureDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedalureDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureTYPES_H_
|
||||
#define __wrappedalureTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedalureTYPES_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalureUNDEFS_H_
|
||||
#define __wrappedalureUNDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedalureUNDEFS_H_
|
||||
@@ -0,0 +1,8 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalutDEFS_H_
|
||||
#define __wrappedalutDEFS_H_
|
||||
|
||||
|
||||
#endif // __wrappedalutDEFS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedalutTYPES_H_
|
||||
#define __wrappedalutTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS()
|
||||
|
||||
#endif // __wrappedalutTYPES_H_
|
||||
Loaded 100 of 502 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user