mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-09 04:09:46 -10:00
Compare commits
354
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe90260cee | ||
|
|
841003bc47 | ||
|
|
27cf5c81b2 | ||
|
|
323783bf49 | ||
|
|
fbd9604dc1 | ||
|
|
5494d417c0 | ||
|
|
472037cba2 | ||
|
|
1b19d8b909 | ||
|
|
c2909c32ab | ||
|
|
a7c0c01bf4 | ||
|
|
d80226ec61 | ||
|
|
da81ba5be8 | ||
|
|
f81874277c | ||
|
|
d93b97ee92 | ||
|
|
4812d20da5 | ||
|
|
734e7cd47c | ||
|
|
d052b35c40 | ||
|
|
2bd3a3ccfa | ||
|
|
1886c454ca | ||
|
|
91ee1afe24 | ||
|
|
d867f578df | ||
|
|
b48ba048ed | ||
|
|
35a21d8932 | ||
|
|
81ec174e2a | ||
|
|
400ea800d9 | ||
|
|
0e1215268a | ||
|
|
a72d257443 | ||
|
|
6a99a4b359 | ||
|
|
b6764d1d6f | ||
|
|
d5e105ce62 | ||
|
|
45ee1e3c3c | ||
|
|
b1d0dde0b4 | ||
|
|
cb06d28383 | ||
|
|
36bfcd21d4 | ||
|
|
faa48276e5 | ||
|
|
8e5d32430a | ||
|
|
ac2d5b17dd | ||
|
|
0e2c63d9fb | ||
|
|
71b446774c | ||
|
|
dac71e9f7b | ||
|
|
e1a2230e9c | ||
|
|
82bd4431e6 | ||
|
|
7262288502 | ||
|
|
bcb0bdea77 | ||
|
|
4ca58d1f99 | ||
|
|
0c27b82ff3 | ||
|
|
289deb3655 | ||
|
|
8d69c17839 | ||
|
|
348cb57240 | ||
|
|
46f71f3947 | ||
|
|
0ba4b04078 | ||
|
|
5a5f572162 | ||
|
|
fb5bc122cc | ||
|
|
4c328d0fca | ||
|
|
dbce2758b2 | ||
|
|
837f7edd55 | ||
|
|
f054fb3a5f | ||
|
|
96831b144c | ||
|
|
d75116dab7 | ||
|
|
8da46ee305 | ||
|
|
4cac721e74 | ||
|
|
3fda41cbf6 | ||
|
|
053d5e9b8d | ||
|
|
40cb14bf31 | ||
|
|
27d18e4169 | ||
|
|
5403002a36 | ||
|
|
22f1a6c5ca | ||
|
|
783e9a4b74 | ||
|
|
202a067a61 | ||
|
|
f2d1a8bc70 | ||
|
|
b6bc7922b3 | ||
|
|
7e4af27ba7 | ||
|
|
06bbf93bf8 | ||
|
|
e08bdd644b | ||
|
|
1c5ddfafcd | ||
|
|
0f4db4c230 | ||
|
|
960ce86289 | ||
|
|
b2bd3103d8 | ||
|
|
745fd1b702 | ||
|
|
6df1b65249 | ||
|
|
510f8d45e8 | ||
|
|
c5d328a5da | ||
|
|
1430c811cd | ||
|
|
ec2eadd893 | ||
|
|
56c272c17a | ||
|
|
6f92db542b | ||
|
|
8531750631 | ||
|
|
9414ece323 | ||
|
|
c64cb5b92b | ||
|
|
2b1e12dafd | ||
|
|
b4ca2be9e0 | ||
|
|
203de52d71 | ||
|
|
c48333db44 | ||
|
|
e3552befe9 | ||
|
|
6141421f92 | ||
|
|
911ecc4489 | ||
|
|
63ab450d87 | ||
|
|
bcc29168cd | ||
|
|
4a9b0128d7 | ||
|
|
6cc56ac5f7 | ||
|
|
f53c967e18 | ||
|
|
b309933571 | ||
|
|
c7e8044f92 | ||
|
|
29720048e2 | ||
|
|
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
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
language: c
|
||||
arch:
|
||||
- amd64
|
||||
- arm64-graviton2
|
||||
os: linux
|
||||
dist: focal
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python3
|
||||
|
||||
#Build steps
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; else cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; fi
|
||||
|
||||
script:
|
||||
- make
|
||||
- ctest --output-on-failure
|
||||
+126
-12
@@ -2,14 +2,26 @@ cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
|
||||
|
||||
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(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
|
||||
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(LARCH64)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -50,18 +62,32 @@ 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(PHYTIUM)
|
||||
add_definitions(-DPHYSIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+crc+simd+crypto+aes")
|
||||
elseif(SD845)
|
||||
add_definitions(-DSD845)
|
||||
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
|
||||
elseif(LARCH64)
|
||||
add_definitions(-DLARCH64)
|
||||
add_definitions(-pipe -march=loongarch64)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=loongarch64")
|
||||
elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
|
||||
if(NOGIT)
|
||||
@@ -69,7 +95,7 @@ if(NOGIT)
|
||||
endif()
|
||||
|
||||
if(HAVE_TRACE)
|
||||
set(BOX64 box64t)
|
||||
set(BOX64 box64)
|
||||
else()
|
||||
set(BOX64 box64)
|
||||
endif()
|
||||
@@ -126,6 +152,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/box64context.c"
|
||||
"${BOX64_ROOT}/src/build_info.c"
|
||||
"${BOX64_ROOT}/src/custommem.c"
|
||||
"${BOX64_ROOT}/src/mailbox.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfloader.c"
|
||||
"${BOX64_ROOT}/src/elfs/elfparser.c"
|
||||
@@ -177,6 +204,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/tools/bridge.c"
|
||||
"${BOX64_ROOT}/src/tools/callback.c"
|
||||
"${BOX64_ROOT}/src/tools/my_cpuid.c"
|
||||
"${BOX64_ROOT}/src/tools/gtkclass.c"
|
||||
"${BOX64_ROOT}/src/tools/pathcoll.c"
|
||||
"${BOX64_ROOT}/src/tools/fileutils.c"
|
||||
"${BOX64_ROOT}/src/tools/wine_tools.c"
|
||||
@@ -195,11 +223,24 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgconf2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgdkx112.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgio2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedglib2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgmodule2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgobject2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.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 +249,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"
|
||||
@@ -215,12 +257,15 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw6.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"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibsndfile.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
|
||||
@@ -230,6 +275,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,10 +301,17 @@ 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/wrappednsl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappednspr4.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedplc4.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedplds4.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
|
||||
@@ -261,19 +321,25 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsecret1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedselinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
|
||||
)
|
||||
|
||||
@@ -339,7 +405,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"
|
||||
@@ -396,24 +462,37 @@ add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head
|
||||
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
|
||||
add_dependencies(${BOX64} WRAPPERS)
|
||||
#add_dependencies(${BOX64} PRINTER)
|
||||
target_link_libraries(${BOX64} m dl rt pthread)
|
||||
target_link_libraries(${BOX64} c m dl rt pthread)
|
||||
if(ARM_DYNAREC)
|
||||
target_link_libraries(${BOX64} dynarec)
|
||||
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 +513,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 +628,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,34 @@
|
||||
Current Version
|
||||
======
|
||||
* More functions wrapped
|
||||
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
|
||||
* Added a workaround for streamwebhelper to not load it
|
||||
* More opcodes added
|
||||
* More wrapped libraries, including gtk2
|
||||
* Added a fix for linking box64 on system using glibc 2.34+
|
||||
* Some residual fixes on thread attribute handling
|
||||
* Better handling of app that want 32bits jumps, like unity3d/mono (thanks mogery)
|
||||
* More ARM hardware option in CMake (Phytium, NX...)
|
||||
* Added loongarch64 support (interpretor only)
|
||||
* Some fixes to elfloader
|
||||
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
|
||||
|
||||
v0.1.4
|
||||
======
|
||||
* Reworked README a bit
|
||||
* Added some more wrapped libs
|
||||
* Added some SSE4x opcodes
|
||||
* Preliminary support for VSyscall (still missing VDSO)
|
||||
* Added support for AES-NI cpu extension, also in Dynarec (and using ARM extension if present)
|
||||
* Added some syscall
|
||||
* Added some more wrapped functions
|
||||
* Improvment to the handling of longjmp inside signal handlers
|
||||
* Improved wrapper helpers (from rajdakin)
|
||||
* Some fixes to opcodes (especially C2 flags for some x87 opcodes)
|
||||
* Handling of some specific opcode as privileged instruction (instead of NOP)
|
||||
* Fixed ELF signature detection
|
||||
* Some fixes to a few env. var. handling
|
||||
|
||||
v0.1.2
|
||||
======
|
||||
* OpenSource!
|
||||
@@ -31,6 +31,71 @@ 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 Snapdragon 845
|
||||
|
||||
Using a 64bits OS:
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DSD845=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 Phytium
|
||||
|
||||
Using a 64bits OS:
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DPHYTIUM=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 LoongArch
|
||||
|
||||
Using a 64bits OS:
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DLARCH64=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 +122,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*
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
----
|
||||

|
||||
|
||||
[中文](README_CN.md)
|
||||
|
||||
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 32bits / 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 libcef/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, mogery
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000
|
||||
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
|
||||
* 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!)
|
||||
@@ -0,0 +1,119 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux上用户空间的x86_64应用模拟器
|
||||
|
||||
----
|
||||

|
||||
|
||||
[English](README.md)
|
||||
|
||||
在ARM或其他非X86_64架构的Linux操作系统上,使用Box64可以运行x86_64 Linux程序(例如游戏),请注意,主机系统需要**64位小端**。
|
||||
|
||||
您可以在Youtube的[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)或[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)频道找到更多Box64视频。
|
||||
|
||||
Box64使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以它很容易与大多数应用程序集成和使用,并且在很多情况下性能会出奇的高。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看示例的基准测试分析。
|
||||
|
||||
Box64为ARM64平台集成了DynaRec(动态重编译器),比仅使用解释器提升5到10倍性能。关于Dynarec如何工作的更多信息,可以在[这里](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/)找到。
|
||||
|
||||
注:DynaRec需要针对不同平台编写一部分汇编代码,目前仅支持ARM64。
|
||||
|
||||
一些x64内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x64primop.c](../src/emu/x64primop.c)了解版权详情
|
||||
|
||||
<img src="img/Box64Icon.png" width="96" height="96">
|
||||
|
||||
Logo和图标由grayduck制作,感谢!
|
||||
|
||||
----
|
||||
|
||||
使用方法
|
||||
----
|
||||
|
||||
若干环境变量可以设置Box64的行为。
|
||||
|
||||
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
|
||||
|
||||
请注意:Box64的Dynarec提供了一种机制来处理JIT代码,包含内存保护和段错误信号处理程序。简单地说,如果您想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),您仍然会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的东西,不要在每个段错误时都停止,如果您想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
|
||||
|
||||
----
|
||||
|
||||
编译/安装
|
||||
----
|
||||
> 编译说明可以在[这里](COMPILE.md)查看。
|
||||
|
||||
----
|
||||
|
||||
版本历史
|
||||
----
|
||||
|
||||
版本日志在[这里](CHANGELOG.md)。
|
||||
|
||||
----
|
||||
|
||||
32位平台的注意事项
|
||||
----
|
||||
|
||||
Box64的工作原理是直接将函数调用从x86_64转换到主机系统,主机系统(Box64运行的系统)需要有64位的库。Box64并不包括任何64位<->32位的转换。
|
||||
|
||||
所以请理解,Box64只能运行64位的Linux二进制文件。对于32位的二进制文件,需要Box86(在64位的操作系统上需要所有的multiarch库或一些proot技巧)。
|
||||
|
||||
请注意,许多(基于mojo的)安装程序,即使存在x86_64版本,但在检测到架构为ARM64时会退回到"x86",这时会尝试使用(如果有)box86进行安装。这时你可以使用一个假的"uname",当它的参数为"-m"时返回"x86_64"。
|
||||
|
||||
----
|
||||
|
||||
关于Unity游戏模拟的注意事项
|
||||
----
|
||||
|
||||
当前Unity游戏模拟是一件碰运气的事情。Unity使用Mono(它的信号表示,并不总能100%成功模拟)。
|
||||
|
||||
您还应该注意,一些Unity3D游戏需要OpenGL 3+,目前在ARM SBC(单板计算机)上提供OpenGL 3+是很棘手的。
|
||||
|
||||
所以,并不是所有的Unity游戏都能工作,而且可能需要很高的OpenGL配置,但现在很多游戏都能工作。
|
||||
|
||||
提示:如果游戏开始后在显示任何东西之前退出,在Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
|
||||
|
||||
----
|
||||
|
||||
关于GTK程序的注意事项
|
||||
----
|
||||
|
||||
GTK库尚未封装在Box64内(与Box86相反)。许多游戏(包括设置)都使用gtk,例如Unity游戏的屏幕选择对话框。有些Unity游戏可以在没有该对话框的情况下运行(使用默认设置),还有一些不能。您需要将一套gtk x86_64库放在游戏目录(或其他一些Box64识别的目录)中以获得gtk支持。Box64有计划封装GTK原生库。
|
||||
|
||||
----
|
||||
|
||||
关于Steam的注意事项
|
||||
----
|
||||
|
||||
Steam并不是32位/64位混合的,而是32位的,因此您需要Box86才能运行Steam。Steam也使用64位的本地服务器程序,但像大多数使用libcef/chromium的程序一样,在box64上暂时无法正常工作。
|
||||
所以:目前在box64上无法运行Steam。
|
||||
----
|
||||
|
||||
关于Wine的注意事项
|
||||
----
|
||||
|
||||
box64支持64位Wine,但请注意,64位的Wine还包含32位的组件,以便能够运行32位的Windws程序。32位程序需要Box86,没有它就不能运行。在Box64和Box86共存的系统上,设置64位Wine可以同时运行32位和64位windows程序(只需分别使用 `wine` 和 `wine64`)。
|
||||
|
||||
----
|
||||
|
||||
关于Vulkan注意事项
|
||||
----
|
||||
|
||||
Box64尚未封装原生Vulkan库,有计划这么做,但目前,vulkan程序不能在box64上运行。
|
||||
|
||||
----
|
||||
|
||||
结语
|
||||
----
|
||||
|
||||
我要感谢所有为 box64 开发做出贡献的人。
|
||||
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
|
||||
以下感谢不分先后:
|
||||
* 代码贡献:rajdakin, mogery
|
||||
* 财务帮助:FlyingFathead, stormchaser3000
|
||||
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
|
||||
* 硬件捐赠和LoongArch迁移:[xiaoji](https://www.linuxgame.cn)
|
||||
* 为本项目持续的宣传: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/))
|
||||
|
||||
我还要感谢很多人,即使他们只参与了一次本项目。
|
||||
|
||||
(如果你的项目中使用了Box64,请不要忘记提及!)
|
||||
@@ -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=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=Debug
|
||||
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=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=Debug
|
||||
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-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=Debug
|
||||
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,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=Debug
|
||||
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,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=Debug
|
||||
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
+41
-11
@@ -6,6 +6,9 @@
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef DYNAREC
|
||||
#include "dynarec/arm64_lock.h"
|
||||
#endif
|
||||
#include "box64context.h"
|
||||
#include "debug.h"
|
||||
#include "elfloader.h"
|
||||
@@ -88,6 +91,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 +114,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
|
||||
}
|
||||
|
||||
@@ -121,21 +126,36 @@ static void init_mutexes(box64context_t* context)
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#else
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
#endif
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#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);
|
||||
}
|
||||
|
||||
void startMailbox(void);
|
||||
void haltMailbox(void);
|
||||
static void atfork_prepare_box64context(void)
|
||||
{
|
||||
// semaphores will go in undetermined state
|
||||
haltMailbox();
|
||||
}
|
||||
static void atfork_parent_box64context(void)
|
||||
{
|
||||
// reinit mailbox only
|
||||
init_mutexes(my_context);
|
||||
startMailbox();
|
||||
}
|
||||
static void atfork_child_box64context(void)
|
||||
{
|
||||
// (re)init mutex if it was lock before the fork
|
||||
// reinit mutexes and mailbox
|
||||
init_mutexes(my_context);
|
||||
startMailbox();
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -160,7 +180,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*)0xffffffffff600000, (void*)context->vsyscalls[0]);
|
||||
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
|
||||
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
|
||||
// get handle to box64 itself
|
||||
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
|
||||
context->dlprivate = NewDLPrivate();
|
||||
|
||||
@@ -168,7 +197,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
|
||||
|
||||
init_mutexes(context);
|
||||
pthread_atfork(NULL, NULL, atfork_child_box64context);
|
||||
pthread_atfork(atfork_prepare_box64context, atfork_parent_box64context, atfork_child_box64context);
|
||||
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
|
||||
@@ -261,13 +290,14 @@ void FreeBox64Context(box64context_t** context)
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#endif
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#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 5
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+204
-161
@@ -32,8 +32,9 @@
|
||||
KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
|
||||
static pthread_mutex_t mutex_mmap;
|
||||
static mmaplist_t *mmaplist;
|
||||
static size_t mmapsize;
|
||||
static mmaplist_t *mmaplist = NULL;
|
||||
static size_t mmapsize = 0;
|
||||
static size_t mmapcap = 0;
|
||||
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
|
||||
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
|
||||
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
|
||||
@@ -43,7 +44,6 @@ static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT];
|
||||
#define MEMPROT_SHIFT 12
|
||||
#define MEMPROT_SHIFT2 (32-MEMPROT_SHIFT)
|
||||
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
|
||||
static pthread_mutex_t mutex_prot;
|
||||
KHASH_MAP_INIT_INT(memprot, uint8_t*)
|
||||
static kh_memprot_t *memprot;
|
||||
static int inited = 0;
|
||||
@@ -62,8 +62,8 @@ static blocklist_t* p_blocks = NULL; // actual blocks for custom mallo
|
||||
|
||||
typedef union mark_s {
|
||||
struct {
|
||||
unsigned int fill:1;
|
||||
unsigned int size:31;
|
||||
unsigned int fill:1;
|
||||
};
|
||||
uint32_t x32;
|
||||
} mark_t;
|
||||
@@ -72,86 +72,123 @@ typedef struct blockmark_s {
|
||||
mark_t next;
|
||||
} blockmark_t;
|
||||
|
||||
#define NEXT_BLOCK(b) (blockmark_t*)((uintptr_t)(b) + (b)->next.size + sizeof(blockmark_t))
|
||||
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
|
||||
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
|
||||
|
||||
static void printBlock(blockmark_t* b, void* start)
|
||||
{
|
||||
printf_log(LOG_INFO, "========== Block is:\n");
|
||||
do {
|
||||
printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
|
||||
b = NEXT_BLOCK(b);
|
||||
} while(b->next.x32);
|
||||
printf_log(LOG_INFO, "===================\n");
|
||||
}
|
||||
|
||||
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size)
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
blockmark_t *m = (blockmark_t*)((start)?start:block);
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
|
||||
*size = m->next.size-sizeof(blockmark_t);
|
||||
if(!m->next.fill && m->next.size>=maxsize) {
|
||||
*size = m->next.size;
|
||||
return m;
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m + m->next.size);
|
||||
m = NEXT_BLOCK(m);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t getMaxFreeBlock(void* block, size_t block_size)
|
||||
static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
|
||||
if(start) {
|
||||
blockmark_t *m = (blockmark_t*)start;
|
||||
int maxsize = 0;
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>maxsize) {
|
||||
maxsize = m->next.size;
|
||||
}
|
||||
m = NEXT_BLOCK(m);
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
|
||||
} else {
|
||||
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0; // no block large enough left...
|
||||
}
|
||||
m = PREV_BLOCK(m);
|
||||
}
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
|
||||
}
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
|
||||
}
|
||||
|
||||
static void* allocBlock(void* block, void *sub, size_t size)
|
||||
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
|
||||
s->next.fill = 1;
|
||||
s->next.size = size+sizeof(blockmark_t);
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
|
||||
// check if a new mark is worth it
|
||||
if(s->next.size>size+2*sizeof(blockmark_t))
|
||||
s->next.size = size;
|
||||
blockmark_t *m = NEXT_BLOCK(s); // this is new n
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
if(n!=m) {
|
||||
// new mark
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
m->next.fill = 0;
|
||||
m->next.size = (uintptr_t)n - (uintptr_t)m;
|
||||
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
}
|
||||
|
||||
if(pstart && sub==*pstart) {
|
||||
// get the next free block
|
||||
m = (blockmark_t*)*pstart;
|
||||
while(m->next.fill)
|
||||
m = NEXT_BLOCK(m);
|
||||
*pstart = (void*)m;
|
||||
}
|
||||
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
|
||||
}
|
||||
static void freeBlock(void *block, void* sub)
|
||||
static size_t freeBlock(void *block, void* sub, void** pstart)
|
||||
{
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
if(block!=sub)
|
||||
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
|
||||
m = PREV_BLOCK(s);
|
||||
s->next.fill = 0;
|
||||
n->prev.fill = 0;
|
||||
// check if merge with previous
|
||||
if (s->prev.x32 && !s->prev.fill) {
|
||||
// remove s...
|
||||
m->next.size += s->next.size;
|
||||
m->next.size += s->next.size + sizeof(blockmark_t);
|
||||
n->prev.size = m->next.size;
|
||||
s = m;
|
||||
}
|
||||
// check if merge with next
|
||||
if(n->next.x32 && !n->next.fill) {
|
||||
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
|
||||
blockmark_t *n2 = NEXT_BLOCK(n);
|
||||
//remove n
|
||||
s->next.size += n->next.size;
|
||||
s->next.size += n->next.size + sizeof(blockmark_t);
|
||||
n2->prev.size = s->next.size;
|
||||
}
|
||||
if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) {
|
||||
*pstart = (void*)s;
|
||||
}
|
||||
// return free size at current block (might be bigger)
|
||||
return s->next.size;
|
||||
}
|
||||
// return 1 if block has been expanded to new size, 0 if not
|
||||
static int expandBlock(void* block, void* sub, size_t newsize)
|
||||
@@ -160,15 +197,21 @@ static int expandBlock(void* block, void* sub, size_t newsize)
|
||||
|
||||
newsize = (newsize+3)&~3;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
blockmark_t *n = NEXT_BLOCK(s);
|
||||
if(s->next.size>=newsize)
|
||||
// big enough, no shrinking...
|
||||
return 1;
|
||||
if(s->next.fill)
|
||||
return 0; // next block is filled
|
||||
// unsigned bitfield of this length gets "promoted" to *signed* int...
|
||||
if((size_t)(s->next.size + n->next.size) < newsize)
|
||||
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
|
||||
return 0; // free space too short
|
||||
// ok, doing the alloc!
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
|
||||
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
|
||||
s->next.size += n->next.size+sizeof(blockmark_t);
|
||||
else
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
blockmark_t *m = NEXT_BLOCK(s); // this is new n
|
||||
m->prev.fill = 1;
|
||||
m->prev.size = s->next.size;
|
||||
if(n!=m) {
|
||||
@@ -197,11 +240,11 @@ void* customMalloc(size_t size)
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if(p_blocks[i].maxfree>=size) {
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize, NULL);
|
||||
if(sub) {
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size);
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
|
||||
if(rsize==p_blocks[i].maxfree)
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
@@ -225,14 +268,14 @@ void* customMalloc(size_t size)
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
m->next.fill = 0;
|
||||
m->next.size = allocsize-sizeof(blockmark_t);
|
||||
m = (blockmark_t*)(p+allocsize-sizeof(blockmark_t));
|
||||
m->next.x32 = 0;
|
||||
m->prev.fill = 0;
|
||||
m->prev.size = allocsize-sizeof(blockmark_t);
|
||||
m->next.size = allocsize-2*sizeof(blockmark_t);
|
||||
blockmark_t* n = NEXT_BLOCK(m);
|
||||
n->next.x32 = 0;
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
// alloc 1st block
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
@@ -254,7 +297,7 @@ void* customRealloc(void* p, size_t size)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
if(expandBlock(p_blocks[i].block, sub, size)) {
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return p;
|
||||
}
|
||||
@@ -280,8 +323,8 @@ void customFree(void* p)
|
||||
if ((addr>(uintptr_t)p_blocks[i].block)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
freeBlock(p_blocks[i].block, sub);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
|
||||
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
|
||||
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return;
|
||||
}
|
||||
@@ -298,6 +341,8 @@ typedef struct mmaplist_s {
|
||||
size_t size;
|
||||
kh_dynablocks_t* dblist;
|
||||
uint8_t* helper;
|
||||
void* first; // first free block, to speed up things
|
||||
int locked; // don't try to add stuff on locked block
|
||||
} mmaplist_t;
|
||||
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
@@ -305,13 +350,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].maxfree>=size) {
|
||||
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
|
||||
mmaplist[i].locked = 1;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
|
||||
if(rsize==mmaplist[i].maxfree)
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
|
||||
if(rsize==mmaplist[i].maxfree) {
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
}
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(!blocks) {
|
||||
blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
@@ -321,9 +368,17 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
|
||||
int size255=(size<256)?size:255;
|
||||
for(size_t j=0; j<size255; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
|
||||
if(size!=size255)
|
||||
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
|
||||
mmaplist[i].locked = 0;
|
||||
return ret;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "BOX64: Warning, sub not found, corrupted mmaplist[%zu] info?\n", i);
|
||||
if(box64_log >= LOG_DEBUG)
|
||||
printBlock(mmaplist[i].block, mmaplist[i].first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,8 +388,11 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
size_t i = mmapsize++;
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
|
||||
if(mmapsize>mmapcap) {
|
||||
mmapcap += 32;
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
|
||||
}
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, MMAPSIZE)) {
|
||||
@@ -353,21 +411,23 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
|
||||
#endif
|
||||
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
mmaplist[i].locked = 1;
|
||||
mmaplist[i].block = p;
|
||||
mmaplist[i].size = MMAPSIZE;
|
||||
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
|
||||
mmaplist[i].first = p;
|
||||
// setup marks
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
m->next.fill = 0;
|
||||
m->next.size = MMAPSIZE-sizeof(blockmark_t);
|
||||
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
|
||||
m->next.x32 = 0;
|
||||
m->prev.fill = 0;
|
||||
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
|
||||
m->next.size = MMAPSIZE-2*sizeof(blockmark_t);
|
||||
blockmark_t* n = NEXT_BLOCK(m);
|
||||
n->next.x32 = 0;
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
// alloc 1st block
|
||||
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
kh_resize(dynablocks, blocks, 64);
|
||||
khint_t k;
|
||||
@@ -376,6 +436,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
|
||||
kh_value(blocks, k) = db;
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
|
||||
mmaplist[i].locked = 0;
|
||||
return sub;
|
||||
}
|
||||
|
||||
@@ -388,15 +449,18 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
if ((addr>(uintptr_t)mmaplist[i].block)
|
||||
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
freeBlock(mmaplist[i].block, sub);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
|
||||
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
|
||||
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(blocks) {
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
|
||||
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
|
||||
}
|
||||
if(mmaplist[i].locked) {
|
||||
printf_log(LOG_INFO, "BOX64: Warning, Free a chunk in a locked mmaplist[%zu]\n", i);
|
||||
++mmaplist[i].locked;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -432,10 +496,11 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
if(!size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
pthread_mutex_lock(&mutex_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 +508,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;
|
||||
}
|
||||
@@ -457,17 +523,17 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
|
||||
uintptr_t ret = FindFreeDynarecMap(db, size);
|
||||
if(!ret)
|
||||
ret = AddNewDynarecMap(db, size);
|
||||
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -477,7 +543,7 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
if(!addr || !size)
|
||||
return;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
#else
|
||||
@@ -489,12 +555,12 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
//pthread_mutex_lock(&mutex_mmap);
|
||||
ActuallyFreeDynarecMap(db, addr, size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
//pthread_mutex_unlock(&mutex_mmap);
|
||||
}
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx)
|
||||
@@ -524,17 +590,17 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
int idx1 = (i )&((1<<DYNAMAP_SHIFT)-1);
|
||||
if(!dynmap123[idx3]) {
|
||||
dynablocklist_t*** p = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3], (uint64_t)p)!=(uint64_t)p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2]) {
|
||||
dynablocklist_t** p = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], (uint64_t)p)!=(uint64_t)p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2][idx1]) {
|
||||
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], (uint64_t)p)!=(uint64_t)p)
|
||||
FreeDynablockList(&p);
|
||||
}
|
||||
}
|
||||
@@ -563,13 +629,13 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
if(destroy) {
|
||||
if(FreeRangeDynablock(dblist, addr, size) && 0) { // dblist is empty, check if we can delete more...
|
||||
// disabling this for now. It seems to cause random crash in Terraria
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], 0, (uint64_t)dblist)) {
|
||||
dynablocklist_t** p = dynmap123[idx3][idx2];
|
||||
if(dynmapempty((void**)p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], 0, (uint64_t)p)) {
|
||||
dynablocklist_t*** p2 = dynmap123[idx3];
|
||||
if(dynmapempty((void**)p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], 0, (uint64_t)p2)) {
|
||||
free(p2);
|
||||
}
|
||||
}
|
||||
@@ -601,25 +667,25 @@ void addJumpTableIfDefault64(void* addr, void* jmp)
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], (uint64_t)tbl, (uint64_t)box64_jmptbldefault2)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], (uint64_t)tbl, (uint64_t)box64_jmptbldefault1)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], (uint64_t)tbl, (uint64_t)box64_jmptbldefault0)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, arm64_next);
|
||||
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], (uint64_t)jmp, (uint64_t)arm64_next);
|
||||
}
|
||||
void setJumpTableDefault64(void* addr)
|
||||
{
|
||||
@@ -671,21 +737,21 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], (uint64_t)tbl, (uint64_t)box64_jmptbldefault2)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], (uint64_t)tbl, (uint64_t)box64_jmptbldefault1)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], (uint64_t)tbl, (uint64_t)box64_jmptbldefault0)!=(uint64_t)tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
@@ -693,9 +759,9 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
}
|
||||
|
||||
// Remove the Write flag from an adress range, so DB can be executed safely
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
void internalProtectDB(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalProtectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
@@ -708,40 +774,44 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void protectDB(uintptr_t addr, size_t size)
|
||||
int internalIsprotectedDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
protectDBnolock(addr, size);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void lockDB()
|
||||
{
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
}
|
||||
|
||||
void unlockDB()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Add the Write flag from an adress range, and mark all block as dirty
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void unprotectDB(uintptr_t addr, size_t size)
|
||||
void internalUnprotectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalUnprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -751,26 +821,24 @@ 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);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void internalUpdateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
dynarec_log(LOG_DEBUG, "internalUpdateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t last = idx<<MEMPROT_SHIFT;
|
||||
uint8_t oldprot = 0xff;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -801,16 +869,14 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
}
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void internalSetProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
dynarec_log(LOG_DEBUG, "internalSetProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -823,16 +889,14 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
void internalAllocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
dynarec_log(LOG_DEBUG, "internalAllocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -849,10 +913,9 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void loadProtectionFromMap()
|
||||
void internalLoadProtectionFromMap()
|
||||
{
|
||||
char buf[500];
|
||||
FILE *f = fopen("/proc/self/maps", "r");
|
||||
@@ -865,7 +928,7 @@ void loadProtectionFromMap()
|
||||
uintptr_t s, e;
|
||||
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
|
||||
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
|
||||
allocProtection(s, e-s, prot);
|
||||
internalAllocProtection(s, e-s, prot);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
@@ -879,12 +942,11 @@ static int blockempty(uint8_t* mem)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, size_t size)
|
||||
void internalFreeProtection(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "internalFreeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
@@ -900,21 +962,15 @@ void freeProtection(uintptr_t addr, size_t size)
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
uint32_t getProtection(uintptr_t addr)
|
||||
uint32_t internalGetProtection(uintptr_t addr)
|
||||
{
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return 0;
|
||||
}
|
||||
if (k == kh_end(memprot)) return 0;
|
||||
const uintptr_t idx = ((addr&0xffffffff)>>MEMPROT_SHIFT);
|
||||
uint32_t ret = kh_val(memprot, k)[idx];
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -966,20 +1022,14 @@ static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
|
||||
addr &= ~0xffffffffLL;
|
||||
} while(1);
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
return findBlockNearHint(LOWEST, size);
|
||||
}
|
||||
void* find47bitBlock(size_t size)
|
||||
void* internalFind47bitBlock(size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = 0x100000000LL;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
@@ -990,51 +1040,47 @@ void* find47bitBlock(size_t size)
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x100000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
void* find47bitBlockNearHint(void* hint, size_t size)
|
||||
void* internalFind47bitBlockNearHint(void* hint, size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = (uintptr_t)hint;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x800000000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
void* internalFindBlockNearHint(void* hint, size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
uintptr_t addr = (uintptr_t)hint;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
do {
|
||||
addr = nextFree(addr);
|
||||
uintptr_t sz = maxFree(addr, size);
|
||||
if(sz>=size) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return (void*)addr;
|
||||
}
|
||||
addr += sz;
|
||||
} while(addr<0x100000000LL);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
void* internalFind32bitBlock(size_t size)
|
||||
{
|
||||
return internalFindBlockNearHint(LOWEST, size);
|
||||
}
|
||||
#undef LOWEST
|
||||
|
||||
int unlockCustommemMutex()
|
||||
@@ -1047,7 +1093,6 @@ int unlockCustommemMutex()
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
@@ -1062,7 +1107,6 @@ void relockCustommemMutex(int locks)
|
||||
pthread_mutex_lock(&A); \
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
@@ -1075,7 +1119,6 @@ static void init_mutexes(void)
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
pthread_mutex_init(&mutex_prot, &attr);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&mutex_mmap, &attr);
|
||||
#endif
|
||||
@@ -1143,6 +1186,7 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
dblist_oversized = NULL;
|
||||
}
|
||||
mmapsize = 0;
|
||||
mmapcap = 0;
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
for (uintptr_t idx3=0; idx3<=0xffff; ++idx3)
|
||||
if(dynmap123[idx3]) {
|
||||
@@ -1185,6 +1229,5 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
free(p_blocks[i].block);
|
||||
#endif
|
||||
free(p_blocks);
|
||||
pthread_mutex_destroy(&mutex_prot);
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
}
|
||||
@@ -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__
|
||||
@@ -88,7 +88,7 @@ arm64_lock_xchg:
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0, return new [x0] value (so x1 or old value)
|
||||
ldaxr x2, [x0]
|
||||
cbnz x2, arm64_lock_storeifnull_exit
|
||||
mov x2, x1
|
||||
@@ -99,7 +99,7 @@ arm64_lock_storeifnull_exit:
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x2, return new [x0] value (so x1 or old value)
|
||||
ldaxr x3, [x0]
|
||||
cmp x2, x3
|
||||
bne arm64_lock_storeifref_exit
|
||||
|
||||
@@ -27,13 +27,13 @@ extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
|
||||
// STLXRD of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifnull(void*p, void* val);
|
||||
// Atomically store val to [p] only if [p] is 0. Return new [p] value (so val or old)
|
||||
extern uint64_t arm64_lock_storeifnull(void* p, uint64_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
|
||||
// Atomically store val to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint64_t arm64_lock_storeifref(void* p, uint64_t val, uint64_t ref);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
#endif //__ARM64_LOCK__H__
|
||||
@@ -18,9 +18,10 @@ arm64_next:
|
||||
stp x12, x13, [sp, (8 * 4)]
|
||||
stp x14, x15, [sp, (8 * 6)]
|
||||
stp x16, x17, [sp, (8 * 8)]
|
||||
str x18, [sp, (8 * 10)]
|
||||
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
|
||||
|
||||
mov x2, lr // "from" is in lr, so put in x2
|
||||
add x3, sp, 8*11 // x3 is address to change rip
|
||||
// call the function
|
||||
bl LinkNext
|
||||
// preserve return value
|
||||
@@ -31,7 +32,7 @@ arm64_next:
|
||||
ldp x12, x13, [sp, (8 * 4)]
|
||||
ldp x14, x15, [sp, (8 * 6)]
|
||||
ldp x16, x17, [sp, (8 * 8)]
|
||||
ldr x18, [sp, (8 * 10)]
|
||||
ldp x18, x27, [sp, (8 * 10)]
|
||||
add sp, sp, (8 * 12)
|
||||
// return offset is jump address
|
||||
br x3
|
||||
|
||||
@@ -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));
|
||||
|
||||
+24
-22
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
@@ -81,7 +82,9 @@ void FreeDynablock(dynablock_t* db)
|
||||
// only the father free the DynarecMap
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
@@ -269,7 +272,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
|
||||
if(arm64_lock_storeifnull(&dynablocks->direct, (uint64_t)p) != (uint64_t)p)
|
||||
free(p); // someone already create the direct array, too late...
|
||||
}
|
||||
|
||||
@@ -278,7 +281,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], (uint64_t)block);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
free(block);
|
||||
@@ -290,6 +293,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
return block;
|
||||
}
|
||||
|
||||
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
|
||||
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
|
||||
|
||||
void cancelFillBlock()
|
||||
{
|
||||
longjmp(&dynarec_jmpbuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
@@ -323,29 +334,26 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(!created)
|
||||
return block; // existing block...
|
||||
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// fill the block
|
||||
block->x64_addr = (void*)addr;
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock64(block, filladdr);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
if(old!=block && old) {// put it back in place, strange things are happening here!
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, (uint64_t)block);
|
||||
if(old != block && old) {
|
||||
// put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// doing nothing else, the block has not be writen
|
||||
// doing nothing else, the block has not been written
|
||||
}
|
||||
free(block);
|
||||
block = NULL;
|
||||
}
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// check size
|
||||
if(block && block->x64_size) {
|
||||
int blocksz = block->x64_size;
|
||||
@@ -358,8 +366,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
dblist->maxsz = blocksz;
|
||||
}
|
||||
}
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
|
||||
protectDB((uintptr_t)block->x64_addr, block->x64_size);
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault64(block->x64_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i) {
|
||||
@@ -367,7 +374,6 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
block->sons[i]->done = 1;
|
||||
}
|
||||
block->done = 1;
|
||||
unlockDB();
|
||||
}
|
||||
|
||||
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
|
||||
@@ -392,13 +398,11 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
|
||||
protectDB((uintptr_t)father->x64_addr, father->x64_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault64(father->x64_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
|
||||
unlockDB();
|
||||
}
|
||||
}
|
||||
return db;
|
||||
@@ -420,13 +424,11 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
lockDB();
|
||||
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
|
||||
protectDB((uintptr_t)father->x64_addr, father->x64_size);
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault64(father->x64_addr, father->block);
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
|
||||
unlockDB();
|
||||
}
|
||||
}
|
||||
return db;
|
||||
|
||||
+20
-6
@@ -19,6 +19,7 @@
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynablock_private.h"
|
||||
#include "bridge.h"
|
||||
#endif
|
||||
|
||||
#ifdef DYNAREC
|
||||
@@ -32,7 +33,7 @@ void arm64_epilog_fast() EXPORTDYN;
|
||||
#ifdef DYNAREC
|
||||
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
|
||||
|
||||
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
if(!addr) {
|
||||
@@ -45,10 +46,22 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
if(!block) {
|
||||
// no block, let link table as is...
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
//tableupdate(arm64_epilog, addr, table);
|
||||
return arm64_epilog;
|
||||
if(hasAlternate((void*)addr)) {
|
||||
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
|
||||
addr = (uintptr_t)getAlternate((void*)addr); // set new address
|
||||
R_RIP = addr; // but also new RIP!
|
||||
*x3 = addr; // and the RIP in x27 register
|
||||
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
|
||||
block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
}
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
#endif
|
||||
//tableupdate(arm64_epilog, addr, table);
|
||||
return arm64_epilog;
|
||||
}
|
||||
}
|
||||
if(!block->done) {
|
||||
// not finished yet... leave linker
|
||||
@@ -139,7 +152,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;
|
||||
|
||||
@@ -338,20 +338,23 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
// protect the 1st page
|
||||
protectDB(addr, 1);
|
||||
// init the helper
|
||||
dynarec_arm_t helper = {0};
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
if(!helper.size || !isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p) or write on purge on pass0\n", (void*)addr);
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
helper.cap = helper.size+3; // needs epilog handling
|
||||
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
@@ -422,7 +425,15 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
//TODO: Cancel block and return empty one
|
||||
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
free(helper.table64);
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
FreeDynarecMap(block, (uintptr_t)p, sz);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
// add table64 if needed
|
||||
if(helper.table64size) {
|
||||
@@ -453,7 +464,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->x64_size = end-start;
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
if(block->hash != hash || !isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
|
||||
@@ -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:
|
||||
@@ -172,9 +172,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
i16 = F16S;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i16);
|
||||
MOVZw(x2, i16);
|
||||
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
break;
|
||||
@@ -341,7 +341,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_add16(dyn, ninst, ed, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -350,7 +350,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_or16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -360,7 +360,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_adc16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -370,7 +370,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -379,7 +379,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_and16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -388,7 +388,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_sub16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -397,7 +397,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOVZw(x5, i16);
|
||||
emit_xor16(dyn, ninst, x1, x5, x2, x4);
|
||||
EWBACK;
|
||||
break;
|
||||
@@ -407,7 +407,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(i16) {
|
||||
MOV32w(x2, i16);
|
||||
MOVZw(x2, i16);
|
||||
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
} else
|
||||
emit_cmp16_0(dyn, ninst, x1, x3, x4);
|
||||
@@ -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,123 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
SMINQ_32(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x3D:
|
||||
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX(q0);
|
||||
SMAXQ_32(q0, q0, q1);
|
||||
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 +541,20 @@ 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;
|
||||
if(rex.w) {
|
||||
VMOVQDfrom(q0, (u8&1), ed);
|
||||
} else {
|
||||
VMOVQSfrom(q0, (u8&3), ed);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -377,6 +578,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 +678,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 +1309,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 +1408,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 +1489,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 +1557,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 +1760,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);
|
||||
|
||||
@@ -26,21 +26,29 @@
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
a = mmx_get_reg(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETGm gd = ((nextop&0x38)>>3)
|
||||
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
uint8_t gd, ed, wback, wb;
|
||||
int64_t fixedaddress;
|
||||
int8_t i8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int64_t j64;
|
||||
int v0, s0;
|
||||
int64_t j64, i64;
|
||||
int v0, v1, s0;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(s0);
|
||||
|
||||
// REX prefix before the 67 are ignored
|
||||
@@ -83,11 +91,51 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6F:
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
GETGm;
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7); // no rex.b on MMX
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVeD(v0, 0, v1, 0);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7F:
|
||||
INST_NAME("MOVQ Em, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOV(v1, v0);
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted32(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 0x8D:
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -103,6 +151,79 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ed, Ib");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETED32(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) { WBACK; }
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, Ib");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETED32(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) { WBACK; }
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETED32W(x4, x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, u8);
|
||||
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETED32W(x4, x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, u8);
|
||||
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETED32(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETED32(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) {
|
||||
WBACK;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETED32(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) {
|
||||
WBACK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
@@ -157,6 +278,151 @@ 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)
|
||||
|
||||
case 0xF7:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("TEST Ed, Id");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED32H(x1, 4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x2, i64);
|
||||
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
GETED32(4);
|
||||
MVNxw_REG(ed, ed);
|
||||
WBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("NEG Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED32(0);
|
||||
emit_neg32(dyn, ninst, rex, ed, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("MUL EAX, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
|
||||
GETED32(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);
|
||||
GETED32(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);
|
||||
GETED32(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);
|
||||
GETED32(0);
|
||||
UDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
} else {
|
||||
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
|
||||
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)
|
||||
GETSED32w(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)
|
||||
GETED32(0);
|
||||
SDIVx(x2, xRAX, ed);
|
||||
MSUBx(xRDX, x2, ed, xRAX);
|
||||
MOVx_REG(xRAX, x2);
|
||||
} else {
|
||||
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
|
||||
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;
|
||||
|
||||
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,8 +206,10 @@ 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);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
@@ -252,8 +254,10 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
if(c>1) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
|
||||
}
|
||||
ASRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
@@ -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);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 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,43 @@ 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 0xE6:
|
||||
INST_NAME("CVTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(v1, 0);
|
||||
GETGX_empty(v0);
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
FRINTXD(v0, v1);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
VFCVTNSQD(v0, v0); // convert double -> int64
|
||||
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
|
||||
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,12 @@
|
||||
#include "dynarec_arm64.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "custommem.h"
|
||||
#include "bridge.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 +53,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 +82,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 +96,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 +114,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 +126,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 +149,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 +191,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 +445,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;
|
||||
addr = (uintptr_t)getAlternate(*(void**)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,25 @@
|
||||
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; \
|
||||
}
|
||||
#define GETED32(D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
|
||||
LDRxw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define GETSED32w(D) if((nextop&0xC0)==0xC0) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
SXTWx(x1, ed); \
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
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
|
||||
@@ -78,8 +96,16 @@
|
||||
LDRxw_U12(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
}
|
||||
#define GETED32H(hint, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
|
||||
LDRxw_U12(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
}
|
||||
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDW(hint, ret, D) if(MODREG) { \
|
||||
#define GETEDW(hint, ret, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
MOVxw_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
@@ -88,6 +114,15 @@
|
||||
ed = ret; \
|
||||
LDRxw_U12(ed, wback, fixedaddress); \
|
||||
}
|
||||
#define GETED32W(hint, ret, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
MOVxw_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
|
||||
ed = ret; \
|
||||
LDRxw_U12(ed, wback, fixedaddress); \
|
||||
}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress);}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
@@ -106,6 +141,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 +779,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 +920,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 +950,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 && (
|
||||
|
||||
+80
-45
@@ -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)
|
||||
@@ -287,12 +289,20 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
Elf64_Phdr * e = &head->PHEntries[i];
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
printf_log(LOG_DEBUG, "Loading block #%zu @%p (0x%lx/0x%lx)\n", i, dest, e->p_filesz, e->p_memsz);
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(e->p_filesz) {
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%ld)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%lx/0x%lx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
|
||||
void* p = (void*)-1;
|
||||
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
|
||||
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
|
||||
mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
|
||||
}
|
||||
if(p!=dest) {
|
||||
printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
|
||||
fseeko64(f, e->p_offset, SEEK_SET);
|
||||
if(e->p_filesz) {
|
||||
if(fread(dest, e->p_filesz, 1, f)!=1) {
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
@@ -369,21 +379,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 +438,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)
|
||||
@@ -434,12 +448,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
case R_X86_64_GLOB_DAT:
|
||||
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
offs = sym->st_value;
|
||||
end = offs + sym->st_size;
|
||||
if(sym->st_size) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
|
||||
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
|
||||
if(sym->st_size && offs) {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
|
||||
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
AddWeakSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
|
||||
}
|
||||
@@ -451,7 +465,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 +507,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 +548,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 +566,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)];
|
||||
@@ -562,7 +578,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta);
|
||||
uintptr_t offs = 0;
|
||||
uintptr_t end = 0;
|
||||
elfheader_t* h_tls = head;
|
||||
elfheader_t* h_tls = NULL;//head;
|
||||
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
|
||||
if(version!=-1) version &=0x7fff;
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
@@ -642,7 +658,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 +675,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 +704,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 +715,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 +727,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);
|
||||
@@ -727,7 +748,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
offs = getElfIndex(my_context, h_tls);
|
||||
}
|
||||
if(p) {
|
||||
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_X86_64_DTPMOD64", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname);
|
||||
@@ -743,7 +764,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
}
|
||||
// return -1;
|
||||
} else {
|
||||
if(h_tls)
|
||||
if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
|
||||
offs = sym->st_value;
|
||||
if(p) {
|
||||
int64_t tlsoffset = offs; // it's not an offset in elf memory
|
||||
@@ -770,42 +791,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 +836,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 +1039,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 +1100,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 +1139,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)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
|
||||
#define GETGX opgx=GetGx(emu, rex, nextop)
|
||||
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
|
||||
#define GETEM32(D) opem=GetEm32O(emu, rex, nextop, D, 0)
|
||||
#define GETGM opgm=GetGm(emu, rex, nextop)
|
||||
#define ED oped
|
||||
#define GD opgd
|
||||
|
||||
+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;
|
||||
|
||||
+77
-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...
|
||||
}
|
||||
@@ -1462,6 +1526,7 @@ x64emurun:
|
||||
|
||||
|
||||
fini:
|
||||
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
|
||||
if(unimp) {
|
||||
R_RIP = emu->old_ip;
|
||||
emu->quit = 1;
|
||||
|
||||
+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 */
|
||||
|
||||
+481
-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,158 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->sq[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x39: /* PMINSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(GX->sd[i]>EX->sd[i])
|
||||
GX->sd[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x3A: /* PMAXSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(GX->sd[i]<EX->sd[i])
|
||||
GX->sd[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 +607,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 +633,78 @@ 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;
|
||||
if(rex.w)
|
||||
GX->q[tmp8u&0x1] = ED->q[0];
|
||||
else
|
||||
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;
|
||||
}
|
||||
@@ -798,6 +1153,18 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
|
||||
break;
|
||||
|
||||
case 0x7C: /* HADDPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->d[0] += GX->d[1];
|
||||
if(EX==GX) {
|
||||
GX->d[1] = GX->d[0];
|
||||
} else {
|
||||
GX->d[1] = EX->d[0] + EX->d[1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7E: /* MOVD Ed, Gx */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -965,7 +1332,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 +1580,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;
|
||||
|
||||
@@ -65,6 +65,20 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
|
||||
break;
|
||||
|
||||
case 0x6F: /* MOVQ Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
GM->q = EM->q;
|
||||
break;
|
||||
|
||||
case 0x7F: /* MOVQ Em, Gm */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
EM->q = GM->q;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -32,14 +32,21 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
|
||||
{
|
||||
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
|
||||
|
||||
// let's cheat and set all args...
|
||||
if(init) {
|
||||
Push64(emu, GetRBP(emu)); // set frame pointer
|
||||
SetRBP(emu, GetRSP(emu)); // save RSP
|
||||
SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP
|
||||
PushExit(emu);
|
||||
SetRDX(emu, (uint64_t)my_context->envv);
|
||||
SetRSI(emu, (uint64_t)my_context->argv);
|
||||
SetRDI(emu, (uint64_t)my_context->argc);
|
||||
R_RIP=(uint64_t)*init;
|
||||
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
|
||||
DynaRun(emu);
|
||||
if(emu->error) // any error, don't bother with more
|
||||
return 0;
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 0;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
|
||||
@@ -55,9 +62,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 +1009,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 +1255,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);
|
||||
}
|
||||
|
||||
@@ -1269,6 +1283,14 @@ sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr
|
||||
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->mmx[(m&0x07)];
|
||||
} else return (mmx87_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
|
||||
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
@@ -1289,7 +1311,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)
|
||||
|
||||
@@ -94,6 +94,7 @@ reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
#define GetGw GetGd
|
||||
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
|
||||
void UpdateFlags(x64emu_t *emu);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+104
-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
|
||||
@@ -112,6 +132,8 @@ scwrap_t syscallwrap[] = {
|
||||
{ 96, __NR_gettimeofday, 2},
|
||||
{ 97, __NR_getrlimit, 2},
|
||||
{ 101, __NR_ptrace, 4},
|
||||
{ 118, __NR_getresuid, 3},
|
||||
{ 120, __NR_getresgid, 3},
|
||||
{ 125, __NR_capget, 2},
|
||||
{ 126, __NR_capset, 2},
|
||||
{ 127, __NR_rt_sigpending, 2},
|
||||
@@ -124,6 +146,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 +159,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 +283,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 +335,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 +359,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 +393,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 +416,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 +440,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 +495,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 +515,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;
|
||||
|
||||
+9
-6
@@ -136,23 +136,26 @@ 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;
|
||||
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
|
||||
return 0;
|
||||
case ARCH_GET_FS:
|
||||
*(void**)addr = GetSegmentBase(emu->segs[_FS]);
|
||||
return 0;
|
||||
}
|
||||
// other are unsupported
|
||||
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -38,6 +38,7 @@ uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
#define PROT_ALLOC 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
|
||||
|
||||
// Implemented in mailbox.c
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
@@ -45,10 +46,8 @@ uint32_t getProtection(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void protectDBnolock(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size);
|
||||
void lockDB();
|
||||
void unlockDB();
|
||||
int isprotectedDB(uintptr_t addr, size_t size);
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
|
||||
+13
-3
@@ -1,6 +1,8 @@
|
||||
#ifndef __DEBUG_H_
|
||||
#define __DEBUG_H_
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
extern int box64_log; // log level
|
||||
@@ -13,6 +15,13 @@ 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;
|
||||
extern int arm64_atomics;
|
||||
#endif
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -23,6 +32,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
|
||||
@@ -53,4 +63,4 @@ extern FILE* ftrace;
|
||||
#define EXPORTDYN
|
||||
#endif
|
||||
|
||||
#endif //__DEBUG_H_
|
||||
#endif //__DEBUG_H__
|
||||
@@ -29,4 +29,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
// Create and Add an new dynablock in the list, handling direct/map
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
|
||||
|
||||
// for use in signal handler
|
||||
void cancelFillBlock();
|
||||
|
||||
#endif //__DYNABLOCK_H_
|
||||
@@ -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)
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
#define _GLOBAL_SYMBOLS_H_
|
||||
|
||||
//GTK stuff
|
||||
//void my_checkGlobalGdkDisplay();
|
||||
//void my_setGlobalGThreadsInit();
|
||||
void my_checkGlobalGdkDisplay();
|
||||
void my_setGlobalGThreadsInit();
|
||||
|
||||
//void** my_GetGTKDisplay();
|
||||
//void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
|
||||
void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
|
||||
|
||||
// NCurse / TInfo
|
||||
void my_checkGlobalTInfo();
|
||||
|
||||
Executable
+338
@@ -0,0 +1,338 @@
|
||||
#ifndef __GTKCLASS_H__
|
||||
#define __GTKCLASS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "globalsymbols.h"
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
typedef struct bridge_s bridge_t;
|
||||
|
||||
typedef struct my_GValue_s
|
||||
{
|
||||
size_t g_type;
|
||||
union {
|
||||
int v_int;
|
||||
int64_t v_int64;
|
||||
uint64_t v_uint64;
|
||||
float v_float;
|
||||
double v_double;
|
||||
void* v_pointer;
|
||||
} data[2];
|
||||
} my_GValue_t;
|
||||
|
||||
|
||||
typedef struct my_GObjectClass_s
|
||||
{
|
||||
size_t g_type_class;
|
||||
void* construct_properties;
|
||||
void* (*constructor) (int type, uint32_t n_construct_properties, void* construct_properties);
|
||||
void (*set_property) (void* object, uint32_t property_id, void* value, void* pspec);
|
||||
void (*get_property) (void* object, uint32_t property_id, void* value, void* pspec);
|
||||
void (*dispose) (void* object);
|
||||
void (*finalize) (void* object);
|
||||
void (*dispatch_properties_changed) (void* object, uint32_t n_pspecs, void* pspecs);
|
||||
void (*notify) (void* object, void* pspec);
|
||||
void (*constructed) (void* object);
|
||||
uint32_t flags;
|
||||
void* pdummy[6];
|
||||
} my_GObjectClass_t;
|
||||
|
||||
|
||||
typedef struct my_GtkObjectClass_s
|
||||
{
|
||||
my_GObjectClass_t parent_class;
|
||||
void (*set_arg) (void* object, void* arg, uint32_t arg_id);
|
||||
void (*get_arg) (void* object, void* arg, uint32_t arg_id);
|
||||
void (*destroy) (void* object);
|
||||
} my_GtkObjectClass_t;
|
||||
|
||||
typedef struct my_GtkWidgetClass_s
|
||||
{
|
||||
my_GtkObjectClass_t parent_class;
|
||||
uint32_t activate_signal;
|
||||
uint32_t set_scroll_adjustments_signal;
|
||||
void (*dispatch_child_properties_changed) (void* widget, uint32_t n_pspecs, void* pspecs);
|
||||
void (* show) (void* widget);
|
||||
void (* show_all) (void* widget);
|
||||
void (* hide) (void* widget);
|
||||
void (* hide_all) (void* widget);
|
||||
void (* map) (void* widget);
|
||||
void (* unmap) (void* widget);
|
||||
void (* realize) (void* widget);
|
||||
void (* unrealize) (void* widget);
|
||||
void (* size_request) (void* widget, void* requisition);
|
||||
void (* size_allocate) (void* widget, void* allocation);
|
||||
void (* state_changed) (void* widget, int previous_state);
|
||||
void (* parent_set) (void* widget, void* previous_parent);
|
||||
void (* hierarchy_changed) (void* widget, void* previous_toplevel);
|
||||
void (* style_set) (void* widget, void* previous_style);
|
||||
void (* direction_changed) (void* widget, int previous_direction);
|
||||
void (* grab_notify) (void* widget, int was_grabbed);
|
||||
void (* child_notify) (void* widget, void* pspec);
|
||||
int (* mnemonic_activate) (void* widget, int group_cycling);
|
||||
void (* grab_focus) (void* widget);
|
||||
int (* focus) (void* widget, int direction);
|
||||
int (* event) (void* widget, void* event);
|
||||
int (* button_press_event) (void* widget, void* event);
|
||||
int (* button_release_event) (void* widget, void* event);
|
||||
int (* scroll_event) (void* widget, void* event);
|
||||
int (* motion_notify_event) (void* widget, void* event);
|
||||
int (* delete_event) (void* widget, void* event);
|
||||
int (* destroy_event) (void* widget, void* event);
|
||||
int (* expose_event) (void* widget, void* event);
|
||||
int (* key_press_event) (void* widget, void* event);
|
||||
int (* key_release_event) (void* widget, void* event);
|
||||
int (* enter_notify_event) (void* widget, void* event);
|
||||
int (* leave_notify_event) (void* widget, void* event);
|
||||
int (* configure_event) (void* widget, void* event);
|
||||
int (* focus_in_event) (void* widget, void* event);
|
||||
int (* focus_out_event) (void* widget, void* event);
|
||||
int (* map_event) (void* widget, void* event);
|
||||
int (* unmap_event) (void* widget, void* event);
|
||||
int (* property_notify_event) (void* widget, void* event);
|
||||
int (* selection_clear_event) (void* widget, void* event);
|
||||
int (* selection_request_event) (void* widget, void* event);
|
||||
int (* selection_notify_event) (void* widget, void* event);
|
||||
int (* proximity_in_event) (void* widget, void* event);
|
||||
int (* proximity_out_event) (void* widget, void* event);
|
||||
int (* visibility_notify_event) (void* widget, void* event);
|
||||
int (* client_event) (void* widget, void* event);
|
||||
int (* no_expose_event) (void* widget, void* event);
|
||||
int (* window_state_event) (void* widget, void* event);
|
||||
void (* selection_get) (void* widget, void* selection_data, uint32_t info, uint32_t time_);
|
||||
void (* selection_received) (void* widget, void* selection_data, uint32_t time_);
|
||||
void (* drag_begin) (void* widget, void* context);
|
||||
void (* drag_end) (void* widget, void* context);
|
||||
void (* drag_data_get) (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_);
|
||||
void (* drag_data_delete) (void* widget, void* context);
|
||||
void (* drag_leave) (void* widget, void* context,uint32_t time_);
|
||||
int (* drag_motion) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
|
||||
int (* drag_drop) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
|
||||
void (* drag_data_received) (void* widget, void* context, int32_t x, int32_t y, void* selection_data, uint32_t info, uint32_t time_);
|
||||
int (* popup_menu) (void* widget);
|
||||
int (* show_help) (void* widget, int help_type);
|
||||
void*(*get_accessible) (void* widget);
|
||||
void (*screen_changed) (void* widget, void* previous_screen);
|
||||
int (*can_activate_accel) (void* widget, uint32_t signal_id);
|
||||
int (*grab_broken_event) (void* widget, void* event);
|
||||
void (* composited_changed) (void* widget);
|
||||
int (* query_tooltip) (void* widget, int32_t x, int32_t y, int keyboard_tooltip, void* tooltip);
|
||||
void (*_gtk_reserved5) (void);
|
||||
void (*_gtk_reserved6) (void);
|
||||
void (*_gtk_reserved7) (void);
|
||||
} my_GtkWidgetClass_t;
|
||||
|
||||
typedef struct my_GtkContainerClass_s
|
||||
{
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
void (*add) (void* container, void* widget);
|
||||
void (*remove) (void* container, void* widget);
|
||||
void (*check_resize) (void* container);
|
||||
void (*forall) (void* container, int include_internals, void* callback, void* callback_data);
|
||||
void (*set_focus_child) (void* container, void* widget);
|
||||
int (*child_type) (void* container);
|
||||
void* (*composite_name) (void* container, void* child);
|
||||
void (*set_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
|
||||
void (*get_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkContainerClass_t;
|
||||
|
||||
typedef struct my_GtkActionClass_s
|
||||
{
|
||||
my_GObjectClass_t parent_class;
|
||||
void (* activate) (void* action);
|
||||
int menu_item_type;
|
||||
int toolbar_item_type;
|
||||
void* (* create_menu_item) (void* action);
|
||||
void* (* create_tool_item) (void* action);
|
||||
void (* connect_proxy) (void* action, void* proxy);
|
||||
void (* disconnect_proxy) (void* action, void* proxy);
|
||||
void* (* create_menu) (void* action);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkActionClass_t;
|
||||
|
||||
typedef struct my_GtkMiscClass_s
|
||||
{
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
} my_GtkMiscClass_t;
|
||||
|
||||
typedef struct my_GtkLabelClass_s
|
||||
{
|
||||
my_GtkMiscClass_t parent_class;
|
||||
void (* move_cursor) (void* label, int step, int count, int extend_selection);
|
||||
void (* copy_clipboard) (void* label);
|
||||
void (* populate_popup) (void* label, void* menu);
|
||||
int (*activate_link) (void* label, void* uri);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
} my_GtkLabelClass_t;
|
||||
|
||||
typedef struct my_GtkTreeViewClass_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
|
||||
void (* row_activated) (void* tree_view, void* path, void* column);
|
||||
int (* test_expand_row) (void* tree_view, void* iter, void* path);
|
||||
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
|
||||
void (* row_expanded) (void* tree_view, void* iter, void* path);
|
||||
void (* row_collapsed) (void* tree_view, void* iter, void* path);
|
||||
void (* columns_changed) (void* tree_view);
|
||||
void (* cursor_changed) (void* tree_view);
|
||||
int (* move_cursor) (void* tree_view, int step, int count);
|
||||
int (* select_all) (void* tree_view);
|
||||
int (* unselect_all) (void* tree_view);
|
||||
int (* select_cursor_row) (void* tree_view, int start_editing);
|
||||
int (* toggle_cursor_row) (void* tree_view);
|
||||
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
|
||||
int (* select_cursor_parent) (void* tree_view);
|
||||
int (* start_interactive_search) (void* tree_view);
|
||||
void (*_gtk_reserved0) (void);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkTreeViewClass_t;
|
||||
|
||||
typedef struct my_GtkBinClass_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkBinClass_t;
|
||||
|
||||
typedef struct my_GtkWindowClass_s {
|
||||
my_GtkBinClass_t parent_class;
|
||||
void (* set_focus) (void* window, void* focus);
|
||||
int (* frame_event) (void* window, void* event);
|
||||
void (* activate_focus) (void* window);
|
||||
void (* activate_default) (void* window);
|
||||
void (* move_focus) (void* window, int direction);
|
||||
void (*keys_changed) (void* window);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkWindowClass_t;
|
||||
|
||||
typedef struct my_MetaFramesClass_s
|
||||
{
|
||||
my_GtkWindowClass_t parent_class;
|
||||
|
||||
} my_MetaFramesClass_t;
|
||||
|
||||
typedef struct my_GtkTableClass_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
} my_GtkTableClass_t;
|
||||
|
||||
typedef struct my_GtkFixedClass_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
} my_GtkFixedClass_t;
|
||||
|
||||
// GTypeValueTable
|
||||
typedef struct my_GTypeValueTable_s {
|
||||
void (*value_init) (void* value);
|
||||
void (*value_free) (void* value);
|
||||
void (*value_copy) (void* src_value, void* dest_value);
|
||||
void* (*value_peek_pointer) (void* value);
|
||||
void* collect_format;
|
||||
void* (*collect_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
|
||||
void* lcopy_format;
|
||||
void* (*lcopy_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
|
||||
} my_GTypeValueTable_t;
|
||||
|
||||
// GTypeInfo
|
||||
typedef void (*GBaseInitFunc) (void* g_class);
|
||||
typedef void (*GBaseFinalizeFunc) (void* g_class);
|
||||
typedef void (*GClassInitFunc) (void* g_class, void* class_data);
|
||||
typedef void (*GClassFinalizeFunc) (void* g_class, void* class_data);
|
||||
typedef void (*GInstanceInitFunc) (void* instance, void* g_class);
|
||||
|
||||
typedef struct my_GTypeInfo_s {
|
||||
uint16_t class_size;
|
||||
GBaseInitFunc base_init;
|
||||
GBaseFinalizeFunc base_finalize;
|
||||
GClassInitFunc class_init;
|
||||
GClassFinalizeFunc class_finalize;
|
||||
void* class_data;
|
||||
uint16_t instance_size;
|
||||
uint16_t n_preallocs;
|
||||
GInstanceInitFunc instance_init;
|
||||
my_GTypeValueTable_t* value_table;
|
||||
} my_GTypeInfo_t;
|
||||
|
||||
// GtkTypeInfo
|
||||
typedef GBaseInitFunc GtkClassInitFunc;
|
||||
typedef GInstanceInitFunc GtkObjectInitFunc;
|
||||
|
||||
typedef struct my_GtkTypeInfo_s {
|
||||
void* type_name;
|
||||
uint32_t object_size;
|
||||
uint32_t class_size;
|
||||
GtkClassInitFunc class_init_func;
|
||||
GtkObjectInitFunc object_init_func;
|
||||
void* reserved_1;
|
||||
void* reserved_2;
|
||||
GtkClassInitFunc base_class_init_func;
|
||||
} my_GtkTypeInfo_t ;
|
||||
|
||||
my_GTypeValueTable_t* findFreeGTypeValueTable(my_GTypeValueTable_t* fcts);
|
||||
my_GTypeInfo_t* findFreeGTypeInfo(my_GTypeInfo_t* fcts, size_t parent);
|
||||
my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, size_t parent);
|
||||
|
||||
void InitGTKClass(bridge_t *bridge);
|
||||
void FiniGTKClass();
|
||||
|
||||
#define GTKCLASSES() \
|
||||
GTKCLASS(GObject) \
|
||||
GTKCLASS(GtkObject) \
|
||||
GTKCLASS(GtkWidget) \
|
||||
GTKCLASS(GtkContainer) \
|
||||
GTKCLASS(GtkAction) \
|
||||
GTKCLASS(GtkLabel) \
|
||||
GTKCLASS(GtkMisc) \
|
||||
GTKCLASS(GtkTreeView) \
|
||||
GTKCLASS(GtkBin) \
|
||||
GTKCLASS(GtkWindow) \
|
||||
GTKCLASS(GtkTable) \
|
||||
GTKCLASS(GtkFixed) \
|
||||
GTKCLASS(MetaFrames) \
|
||||
|
||||
#define GTKCLASS(A) void Set##A##ID(size_t id);
|
||||
GTKCLASSES()
|
||||
#undef GTKCLASS
|
||||
|
||||
void SetGTypeName(void* f);
|
||||
void AutoBridgeGtk(void*(*ref)(size_t), void(*unref)(void*));
|
||||
|
||||
void* wrapCopyGTKClass(void* cl, size_t type);
|
||||
void* unwrapCopyGTKClass(void* klass, size_t type);
|
||||
|
||||
typedef struct my_signal_s {
|
||||
uint64_t sign; // signature
|
||||
void* data;
|
||||
uintptr_t c_handler;
|
||||
uintptr_t destroy;
|
||||
} my_signal_t;
|
||||
// some random sign to identify a my_signal_t
|
||||
#define SIGN 0xFB3405EB4510AA00LL
|
||||
|
||||
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
|
||||
void my_signal_delete(my_signal_t* sig);
|
||||
int my_signal_is_valid(void* sig);
|
||||
int my_signal_cb(void* a, void* b, void* c, void* d);
|
||||
|
||||
void my_add_signal_offset(size_t klass, uint32_t offset, int n);
|
||||
|
||||
#endif //__GTKCLASS_H__
|
||||
@@ -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);
|
||||
|
||||
+80
-19
@@ -21,19 +21,33 @@ typedef struct {
|
||||
void *reg_save_area;
|
||||
} va_list[1];
|
||||
*/
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs->gp_offset=X64_VA_MAX_REG; \
|
||||
sysv_varargs->fp_offset=X64_VA_MAX_XMM; \
|
||||
sysv_varargs->reg_save_area=A; \
|
||||
sysv_varargs->overflow_arg_area=A;
|
||||
sysv_varargs->reg_save_area=(A); \
|
||||
sysv_varargs->overflow_arg_area=A
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs->gp_offset=(A)->gp_offset; \
|
||||
sysv_varargs->fp_offset=(A)->fp_offset; \
|
||||
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); \
|
||||
}
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs->gp_offset=A->gp_offset; \
|
||||
sysv_varargs->fp_offset=A->fp_offset; \
|
||||
sysv_varargs->reg_save_area=A->reg_save_area; \
|
||||
sysv_varargs->overflow_arg_area=A->overflow_arg_area;
|
||||
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
@@ -52,15 +66,29 @@ typedef struct va_list {
|
||||
va_list sysv_varargs; \
|
||||
sysv_varargs.__gr_offs=(8*8); \
|
||||
sysv_varargs.__vr_offs=(8*16); \
|
||||
sysv_varargs.__stack=A;
|
||||
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; \
|
||||
sysv_varargs.__vr_top=A->reg_save_area + X64_VA_MAX_XMM;
|
||||
#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=-(6*8)+(8*(((N)<6)?(N):6)); \
|
||||
sysv_varargs.__vr_offs=-(8*16); \
|
||||
sysv_varargs.__stack=(STACK); \
|
||||
sysv_varargs.__gr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_REG); \
|
||||
sysv_varargs.__vr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_XMM); \
|
||||
{ \
|
||||
uintptr_t *p = (uintptr_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?
|
||||
@@ -72,6 +100,31 @@ typedef struct va_list {
|
||||
|
||||
#define CONVERT_VALIST(A) \
|
||||
#error TODO!
|
||||
#elif defined(__loongarch64)
|
||||
#define CREATE_SYSV_VALIST(A) \
|
||||
va_list sysv_varargs = (va_list)A
|
||||
// not creating CONVERT_VALIST(A) on purpose
|
||||
// this one will create a VA_LIST from x64_va_list using only GPRS and 100 stack element
|
||||
#define CREATE_VALIST_FROM_VALIST(VA, SCRATCH) \
|
||||
va_list sysv_varargs; \
|
||||
{ \
|
||||
uintptr_t *p = (uintptr_t*)(SCRATCH); \
|
||||
int n = (X64_VA_MAX_REG - (VA)->gp_offset)/8; \
|
||||
if(n) memcpy(&p[0], (VA)->reg_save_area, n*8); \
|
||||
memcpy(&p[n], (VA)->overflow_arg_area, 100*8); \
|
||||
sysv_varargs = (va_list)p; \
|
||||
}
|
||||
// this is an approximation, and if the va_list have some float/double, it will fail!
|
||||
// if the funciton needs more than 100 args, it will also fail
|
||||
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
|
||||
va_list sysv_varargs; \
|
||||
{ \
|
||||
uintptr_t *p = (uintptr_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], STACK, 100*8); \
|
||||
sysv_varargs = (va_list)&p[N]; \
|
||||
}
|
||||
#else
|
||||
#error Unknown architecture!
|
||||
#endif
|
||||
@@ -87,9 +140,14 @@ typedef struct x64emu_s x64emu_t;
|
||||
// 1st pos is of vaarg is 0, not 1!
|
||||
void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
|
||||
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
|
||||
void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
|
||||
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
|
||||
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
|
||||
#ifndef CONVERT_VALIST
|
||||
void myStackAlignValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
|
||||
void myStackAlignWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
|
||||
void myStackAlignScanfValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
|
||||
void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va);
|
||||
#endif
|
||||
|
||||
struct x64_stat64 { /* x86_64 arm64 */
|
||||
uint64_t st_dev; /* 0 */ /* 0 */
|
||||
@@ -109,6 +167,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
|
||||
@@ -120,3 +179,5 @@ void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm
|
||||
|
||||
void UnalignSemidDs(void *dest, const void* source);
|
||||
void AlignSemidDs(void *dest, const void* source);
|
||||
|
||||
uintptr_t getVArgs(x64emu_t* emu, int pos, uintptr_t* b, int N);
|
||||
+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);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
|
||||
// *********** GTK *****************
|
||||
#if 0
|
||||
EXPORT void* gdk_display = NULL; // in case it's used...
|
||||
|
||||
void my_checkGlobalGdkDisplay()
|
||||
@@ -38,7 +37,7 @@ void my_setGlobalGThreadsInit()
|
||||
int val = 1;
|
||||
uintptr_t globoffs, globend;
|
||||
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
|
||||
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
|
||||
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %d\n", (void*)globoffs, val);
|
||||
memcpy((void*)globoffs, &val, sizeof(val));
|
||||
}
|
||||
}
|
||||
@@ -50,14 +49,13 @@ void** my_GetGTKDisplay()
|
||||
return &gdk_display;
|
||||
|
||||
char* name = getGDKX11LibName();
|
||||
library_t * lib = GetLibInternal(name?name:"libgtk-1.2.so.0");
|
||||
library_t * lib = GetLibInternal(name?name:"libgdk-x11-2.0.so.0");
|
||||
if(!lib) return &gdk_display; // mmm, that will crash later probably
|
||||
void* s = dlsym(GetHandle(lib), "gdk_display");
|
||||
gdk_display = *(void**)s;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
// **************** NCurses ****************
|
||||
EXPORT int COLS;
|
||||
EXPORT int LINES;
|
||||
|
||||
Loaded 100 of 641 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user