mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 17:39:19 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
716ac9e041 | ||
|
|
fb835fbe66 | ||
|
|
4aac3444bd | ||
|
|
0a343b72f2 | ||
|
|
ab9178f638 | ||
|
|
1b8d952d88 | ||
|
|
e8e966cd80 | ||
|
|
8b80cc328f | ||
|
|
72986e8ba3 | ||
|
|
3df01a153d | ||
|
|
5d5ef75337 | ||
|
|
c3ef6380a7 | ||
|
|
c2782b269f | ||
|
|
1cb55b2633 | ||
|
|
823c6a138a | ||
|
|
e10a78d671 | ||
|
|
04b9195cd2 | ||
|
|
3aa12a52eb | ||
|
|
5f31e0e093 | ||
|
|
39f2b508f8 | ||
|
|
5b5285940f | ||
|
|
c49da85606 | ||
|
|
5cc3512a59 | ||
|
|
cbd1d3781b | ||
|
|
5bca9b52b3 | ||
|
|
fd21d6a8da | ||
|
|
c8ebce5732 | ||
|
|
fce5aa5a6b | ||
|
|
2ac2996abd | ||
|
|
53fb83487a | ||
|
|
3597284e8d | ||
|
|
4e8f387f79 | ||
|
|
305e6326a6 | ||
|
|
e98c7eaa0f | ||
|
|
02462b2c12 | ||
|
|
4d9559f345 | ||
|
|
ed63000e23 | ||
|
|
cc307df592 | ||
|
|
2d321bbd33 | ||
|
|
5b5f7c133e | ||
|
|
69484d7f3c | ||
|
|
43f5438d93 | ||
|
|
2b920d6936 | ||
|
|
01bf3e741e | ||
|
|
f014d4580a | ||
|
|
1f02ab17e3 | ||
|
|
e1d8f1d7e5 | ||
|
|
c8640caba3 | ||
|
|
f4ea86378e | ||
|
|
16011f4b34 | ||
|
|
5a3316b872 | ||
|
|
9f50a19856 | ||
|
|
6207b3fa38 | ||
|
|
35d2103189 | ||
|
|
84626f065c | ||
|
|
eaedda8ceb | ||
|
|
4e9c25893c | ||
|
|
eb5bebb344 | ||
|
|
296ee1baca | ||
|
|
58b5c6ded9 | ||
|
|
ecc07a235c | ||
|
|
fc4f0e3bae | ||
|
|
e00d35f5bf | ||
|
|
790022483b | ||
|
|
100cdd329a | ||
|
|
9c441df959 | ||
|
|
a8ae44a881 | ||
|
|
2f5fe43955 | ||
|
|
86820cf1b1 | ||
|
|
e511e1bf96 | ||
|
|
5fb1c6c497 | ||
|
|
607bb28677 | ||
|
|
36e5fb50ec | ||
|
|
74405a8b00 | ||
|
|
4b1ecc16ff | ||
|
|
139d5128a0 | ||
|
|
7b8bd8a285 | ||
|
|
445d232ee7 | ||
|
|
8ad472c118 | ||
|
|
fd6895782f | ||
|
|
abdd03cdfa | ||
|
|
ba3359353f | ||
|
|
ca473b06dc | ||
|
|
2ee0230793 | ||
|
|
35119f8db2 | ||
|
|
c95af7c81b | ||
|
|
a9aa474884 | ||
|
|
259fe4a238 | ||
|
|
f73bbfc0af | ||
|
|
e7478f3390 | ||
|
|
9be89e8ba2 | ||
|
|
5287e42b02 | ||
|
|
e0a7f775c9 | ||
|
|
f1d238b78d | ||
|
|
41ebdc7604 | ||
|
|
e3fde0807f | ||
|
|
4007ff2610 | ||
|
|
27d79eddec | ||
|
|
0e5bc91a14 | ||
|
|
c715141bf0 | ||
|
|
3d656b5008 | ||
|
|
d84afba7c8 | ||
|
|
7559df965b | ||
|
|
10702c160a | ||
|
|
a66bb7453b | ||
|
|
5406a040fb | ||
|
|
77421d2eed | ||
|
|
78b9b0cec8 | ||
|
|
16a3d46193 | ||
|
|
2976bf5e6a | ||
|
|
b370540447 | ||
|
|
6d7c0f75e7 | ||
|
|
81a7eca5ef | ||
|
|
2711a7e522 | ||
|
|
cc8f926d66 | ||
|
|
486aa58b15 | ||
|
|
8711693698 | ||
|
|
e6f615a1f8 | ||
|
|
813ed6f9a1 | ||
|
|
85dba348a7 | ||
|
|
a7422d11ed | ||
|
|
b39fbc0cfd | ||
|
|
f000951fc9 | ||
|
|
edeac868d0 | ||
|
|
a618dee15c | ||
|
|
8b48773176 | ||
|
|
9a17d9a35e | ||
|
|
a2ca22972c | ||
|
|
b05c449dd0 | ||
|
|
bdb918c9c2 | ||
|
|
7ae9dca562 | ||
|
|
005e3ddf7d | ||
|
|
c5fbc5efd3 | ||
|
|
4b06a0126e | ||
|
|
f8ef852b46 | ||
|
|
741b03761a | ||
|
|
8ccde3ed4a | ||
|
|
b6ce8efa20 | ||
|
|
2bf49e8a11 | ||
|
|
0cfb48f3c7 | ||
|
|
fcd9eba0da | ||
|
|
6d7e729563 | ||
|
|
102744665c | ||
|
|
dd885a694e | ||
|
|
ecf8ffbbdc | ||
|
|
c1e67c31bc | ||
|
|
6eccdc1baf | ||
|
|
7aa7ef6baf | ||
|
|
66ed68ca48 | ||
|
|
d20d007933 | ||
|
|
a91d2d0841 | ||
|
|
649b7772f1 | ||
|
|
fe6304b7cd | ||
|
|
e9b6f3559b | ||
|
|
53b2578b8e | ||
|
|
9507601ee6 | ||
|
|
52e4edd147 | ||
|
|
acc3ed85cb | ||
|
|
dbbda60d9e | ||
|
|
401071c40a | ||
|
|
928eb2a32b | ||
|
|
1c0b1721cd | ||
|
|
15a7d0b9b5 | ||
|
|
6670e924bf | ||
|
|
5b5b974341 | ||
|
|
ad85b7c4c6 | ||
|
|
a5490dc6f2 | ||
|
|
5c52fa6007 | ||
|
|
f8ecf14763 | ||
|
|
d2f7e15fcd | ||
|
|
66ac772585 | ||
|
|
dd365e0b14 | ||
|
|
d612656978 | ||
|
|
91787c4dbf | ||
|
|
c534a9d78c | ||
|
|
06053027a9 | ||
|
|
9291d15215 | ||
|
|
d07036b8ec | ||
|
|
cb73eaf776 | ||
|
|
bb38d8d1ca | ||
|
|
cc269337f2 | ||
|
|
a2aa5fc650 | ||
|
|
26d4f21fa7 | ||
|
|
7f390a5499 | ||
|
|
b9f38bcefd | ||
|
|
81b1f61aec | ||
|
|
ab83d86300 | ||
|
|
450cad7a4d | ||
|
|
c1ee744205 | ||
|
|
f21afb3277 | ||
|
|
7948a25945 | ||
|
|
7711131d5c | ||
|
|
c6119efb04 | ||
|
|
d0dee6cb50 | ||
|
|
e3bbfe3052 | ||
|
|
85a460afb7 | ||
|
|
28a2dba9f7 | ||
|
|
4e7f86979d | ||
|
|
303390bf00 | ||
|
|
623e81a422 | ||
|
|
13e574db3f | ||
|
|
7bd4aae433 | ||
|
|
69382682c4 | ||
|
|
7535b4ac61 | ||
|
|
3bab7d6c53 | ||
|
|
a8a45aede3 | ||
|
|
28c6d72110 | ||
|
|
c3cd14f3c5 | ||
|
|
2010f8dcce | ||
|
|
abcb12f9ed | ||
|
|
283a4dda20 | ||
|
|
3355f39e9f | ||
|
|
a4cd4c0745 | ||
|
|
3834546100 | ||
|
|
a3d7f9cd85 | ||
|
|
10247fcf85 | ||
|
|
b1183e55fd | ||
|
|
b6c9377551 | ||
|
|
c9a4b94efe | ||
|
|
04658cafcc | ||
|
|
27b3a3f33c | ||
|
|
d60a0ef58d | ||
|
|
fff2effd5b | ||
|
|
bb7e473e7b | ||
|
|
908641a414 | ||
|
|
69bd28cc65 | ||
|
|
0126a0d575 | ||
|
|
6cee821138 | ||
|
|
bbed3403e8 | ||
|
|
9a0824af69 | ||
|
|
53375ca728 | ||
|
|
f0503b67eb | ||
|
|
9c0daf0ed5 | ||
|
|
796e6d3a87 | ||
|
|
6112505757 | ||
|
|
9b547c7884 | ||
|
|
1687c48c1b | ||
|
|
f5981c4dca | ||
|
|
6f183aa1cc | ||
|
|
56f6ad84bb | ||
|
|
ed9a29b25f | ||
|
|
20ba6261b6 | ||
|
|
905b27f216 | ||
|
|
c218631c56 | ||
|
|
bd600a6135 | ||
|
|
67c80f683e | ||
|
|
1fb65cbce2 | ||
|
|
7aa5705400 | ||
|
|
bd21214467 | ||
|
|
de8b4da6b5 | ||
|
|
9243ea4ca1 | ||
|
|
2e871fc68a | ||
|
|
30eb08f8af | ||
|
|
7f51495877 | ||
|
|
112bc0d83f | ||
|
|
501a4a8956 | ||
|
|
bb4c06f107 | ||
|
|
65fae1077f | ||
|
|
e3a36591aa | ||
|
|
a597f6701f | ||
|
|
3b19a7fe1d | ||
|
|
ccf9775658 | ||
|
|
762a499648 | ||
|
|
aa56188e7e | ||
|
|
1d92e65fcc | ||
|
|
a6f132f6da | ||
|
|
cb75b670b6 | ||
|
|
7bb9dd18da | ||
|
|
140254f311 | ||
|
|
56401f6675 | ||
|
|
99ba7707f6 | ||
|
|
ea1ef4e602 | ||
|
|
78b6113d8b | ||
|
|
59ab48b99e | ||
|
|
a7a58b920f | ||
|
|
1c26df2a90 | ||
|
|
c60e4839eb | ||
|
|
b626fc5095 | ||
|
|
bcd504eb05 | ||
|
|
7057b7f929 | ||
|
|
6af070e25f | ||
|
|
af1a7bd6f4 | ||
|
|
dfd3d0ec93 | ||
|
|
1791c0937a | ||
|
|
c2dd6a0c6a | ||
|
|
f300e76c9b | ||
|
|
8f6f880b6a | ||
|
|
3dcef655c3 | ||
|
|
4c476de74b | ||
|
|
c9e277aee5 | ||
|
|
689d6906ef | ||
|
|
1712afdae9 | ||
|
|
8428fafd3a | ||
|
|
3074846477 | ||
|
|
6c1825ba65 | ||
|
|
bef0a5f793 | ||
|
|
8e694eac57 | ||
|
|
8622f9fdc3 | ||
|
|
6e6a8f47af | ||
|
|
7a57c70d81 | ||
|
|
b2a1af1029 | ||
|
|
c44961c063 | ||
|
|
aceb234c2e | ||
|
|
dd6b60818c | ||
|
|
1978b16581 | ||
|
|
0d079b8c0b | ||
|
|
913029f4c5 | ||
|
|
c667c71a99 | ||
|
|
3cd8b9a44e | ||
|
|
126119b1fb | ||
|
|
701bf913e8 | ||
|
|
00b5944271 | ||
|
|
196076f952 | ||
|
|
e350224157 | ||
|
|
730e129a80 | ||
|
|
883fc1681d | ||
|
|
6b2b672c5e | ||
|
|
1d31bf699f | ||
|
|
c62728f44f | ||
|
|
90efb1ff31 | ||
|
|
7625cc7ceb | ||
|
|
a074115bf5 | ||
|
|
c3aa068179 | ||
|
|
e07be95646 | ||
|
|
0777a568d7 | ||
|
|
f6ce622841 | ||
|
|
508545aa87 | ||
|
|
52d86177c5 | ||
|
|
979d1cfba9 | ||
|
|
31a01aceab | ||
|
|
3b39d1270d | ||
|
|
d5b286c050 | ||
|
|
1f23848e25 | ||
|
|
db1c033c7c | ||
|
|
489afcfb41 | ||
|
|
5519ddad0b | ||
|
|
e788589944 | ||
|
|
7a894540b9 | ||
|
|
30f0f3a5a1 | ||
|
|
debc7284b3 | ||
|
|
60f5dfabd8 | ||
|
|
dd2f209096 | ||
|
|
3b181576c8 | ||
|
|
409334ea56 | ||
|
|
71218a6f70 | ||
|
|
a5be3727e9 | ||
|
|
836b646e24 | ||
|
|
15e4830dff | ||
|
|
ac1156d165 | ||
|
|
370ec24987 | ||
|
|
3bdcae10c8 | ||
|
|
681df1604d | ||
|
|
05abd88ea5 | ||
|
|
42670c0130 | ||
|
|
f4c15979db | ||
|
|
8d97f13677 | ||
|
|
75c4c3d6b9 | ||
|
|
a71e81c842 | ||
|
|
add55f3cec | ||
|
|
c6f6a9ef72 | ||
|
|
1c1e39ef64 | ||
|
|
f5655d85a3 | ||
|
|
c31262d339 | ||
|
|
570798358c | ||
|
|
05c9644ea6 | ||
|
|
051bd2b10b | ||
|
|
b1b9d10656 | ||
|
|
506f78eb32 | ||
|
|
1336ddfad7 | ||
|
|
f3617f720b | ||
|
|
844a1f43ed | ||
|
|
8e42412490 | ||
|
|
2737180a20 | ||
|
|
57e9e55705 | ||
|
|
3f3f8b41e9 | ||
|
|
d3ea390983 | ||
|
|
2f1cc844fd | ||
|
|
543af50ff8 | ||
|
|
f6444c8d45 | ||
|
|
df96dd0060 | ||
|
|
956e2aace3 | ||
|
|
1951d525d1 | ||
|
|
3d4d678bdc | ||
|
|
b78d92d288 | ||
|
|
e5dc4d7e78 | ||
|
|
cd247ef6c1 | ||
|
|
104cf8a58b | ||
|
|
976f175aa9 | ||
|
|
81a06c47a1 | ||
|
|
46b8c6bc83 | ||
|
|
5f83a3f98a | ||
|
|
2f6129bfd5 | ||
|
|
26698b6449 | ||
|
|
61839151c0 | ||
|
|
b38c9ea253 | ||
|
|
25754a47e0 | ||
|
|
278888c912 | ||
|
|
7faa4704e6 | ||
|
|
ba48b6c793 | ||
|
|
f8a969d43e | ||
|
|
55720342ad | ||
|
|
085239ef4a | ||
|
|
df61d561f6 | ||
|
|
3cd8b5f48b | ||
|
|
2e21e46e86 | ||
|
|
cb73a9a6bc | ||
|
|
5199df9b61 | ||
|
|
537ca9f724 | ||
|
|
fc5f5dab29 | ||
|
|
4be307820b | ||
|
|
15227bbc06 | ||
|
|
d0da2c24fb | ||
|
|
152a8a4666 | ||
|
|
86669beb7a | ||
|
|
ba2a70a484 | ||
|
|
88ffcf6396 | ||
|
|
4d347f9ff0 | ||
|
|
252258d138 | ||
|
|
e35b25015b | ||
|
|
422844f842 | ||
|
|
61725c8b49 | ||
|
|
727178df57 | ||
|
|
66b3303f22 | ||
|
|
47c3fad83b | ||
|
|
3928222395 | ||
|
|
414d33a46c | ||
|
|
40a2c8393e | ||
|
|
48fe298a36 | ||
|
|
2865f0eab2 | ||
|
|
a5780632ca | ||
|
|
bd5d29a825 | ||
|
|
5255935a31 | ||
|
|
a31ee062b6 | ||
|
|
c56c991bf7 | ||
|
|
5ea4b796a5 | ||
|
|
8fe7378f86 | ||
|
|
1224ffa7cd | ||
|
|
56766df719 | ||
|
|
e505e5e466 | ||
|
|
4cdc3c62b2 | ||
|
|
4402f08245 | ||
|
|
954830032b | ||
|
|
6f3fad8a16 | ||
|
|
2bb956bb06 | ||
|
|
7fa2a273d0 | ||
|
|
52e125e35a | ||
|
|
57bea35004 | ||
|
|
890842286b | ||
|
|
aec0ad9128 | ||
|
|
4f5b5a995b | ||
|
|
bcd07ff6c7 | ||
|
|
68d7188f3e | ||
|
|
a924a74d82 | ||
|
|
a20b830379 | ||
|
|
12fe96b114 | ||
|
|
3432721379 | ||
|
|
b39b7fd374 | ||
|
|
406ddff9a1 | ||
|
|
d16d985a48 | ||
|
|
0a2ea72d72 | ||
|
|
3b4de7152c | ||
|
|
5520dae2e7 | ||
|
|
7a7f26c80e | ||
|
|
35f4944afb | ||
|
|
0a107d10eb | ||
|
|
2c56ccfabe | ||
|
|
d1497e98db | ||
|
|
7925a8e1b3 | ||
|
|
d529bf3c0c | ||
|
|
802c5a9d5b | ||
|
|
3a22c36d04 | ||
|
|
512ee40dbc | ||
|
|
d84e1f49ce | ||
|
|
c4abaf8c8d | ||
|
|
59fe5f3572 | ||
|
|
18320e19bc | ||
|
|
248cd2e749 | ||
|
|
3b550eeed3 | ||
|
|
097c0ac0b7 | ||
|
|
7a95dcd6b6 | ||
|
|
47d0c04b30 | ||
|
|
16be2bd305 | ||
|
|
7cf6ee06a1 | ||
|
|
dd4c413e41 | ||
|
|
08d2ac41f6 | ||
|
|
fd939c6fce | ||
|
|
82755b5ef2 | ||
|
|
7b4cbee8e7 | ||
|
|
5346f594d4 | ||
|
|
6f217d78da | ||
|
|
cdf71c4cbc | ||
|
|
e93a280d2c | ||
|
|
51fa96c44b | ||
|
|
48d6135106 | ||
|
|
0d38b1cd91 |
No files matched your search
@@ -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
|
||||
+131
-26
@@ -1,13 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
|
||||
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
|
||||
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
|
||||
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" ${NO_LOADAADR})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326)
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -36,7 +39,7 @@ project(box64 C ASM)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(default_build_type "RelwithDebInfo")
|
||||
set(default_build_type "RelWithDebInfo")
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
@@ -46,20 +49,22 @@ endif()
|
||||
if(RPI4ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8")
|
||||
endif()
|
||||
|
||||
if(RK3326)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
|
||||
elseif(RK3326)
|
||||
add_definitions(-DRK3326)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto")
|
||||
endif()
|
||||
|
||||
if(RK3399)
|
||||
elseif(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
|
||||
elseif(TEGRAX1)
|
||||
add_definitions(-DTEGRAX1)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
|
||||
elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
|
||||
if(NOGIT)
|
||||
@@ -67,12 +72,13 @@ if(NOGIT)
|
||||
endif()
|
||||
|
||||
if(HAVE_TRACE)
|
||||
set(BOX64 box64t)
|
||||
set(BOX64 box64)
|
||||
else()
|
||||
set(BOX64 box64)
|
||||
endif()
|
||||
|
||||
set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
|
||||
#set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
|
||||
set(BOX64_ELF_ADDRESS "0x64800000") #low address
|
||||
|
||||
if(LD80BITS)
|
||||
add_definitions(-DHAVE_LD80BITS)
|
||||
@@ -101,6 +107,8 @@ if(USE_CCACHE)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
else()
|
||||
message(SEND_ERROR "ccache not found!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -137,6 +145,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64run6664.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66f0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
@@ -158,6 +167,9 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64trace.c"
|
||||
"${BOX64_ROOT}/src/librarian/librarian.c"
|
||||
"${BOX64_ROOT}/src/librarian/library.c"
|
||||
"${BOX64_ROOT}/src/librarian/dictionnary.c"
|
||||
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
|
||||
"${BOX64_ROOT}/src/librarian/symbols.c"
|
||||
"${BOX64_ROOT}/src/libtools/auxval.c"
|
||||
"${BOX64_ROOT}/src/libtools/myalign.c"
|
||||
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
|
||||
@@ -177,42 +189,70 @@ set(ELFLOADER_SRC
|
||||
set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatk.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcrypt.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
|
||||
"${BOX64_ROOT}/src/wrapped/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/wrappedlibssl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibuuid.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibvorbis.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
|
||||
"${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"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxdmcp.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxext.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxfixes.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxft.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxmu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxpm.c"
|
||||
@@ -224,15 +264,19 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedmpg123.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1image.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1mixer.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
|
||||
@@ -241,11 +285,15 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
|
||||
)
|
||||
|
||||
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
|
||||
@@ -259,9 +307,9 @@ set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/w
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
"${BOX64_ROOT}"
|
||||
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
|
||||
${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
@@ -310,7 +358,7 @@ if(ARM_DYNAREC)
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
|
||||
@@ -338,9 +386,9 @@ if(ARM_DYNAREC)
|
||||
add_dependencies(arm64_pass2 WRAPPERS)
|
||||
add_dependencies(arm64_pass3 WRAPPERS)
|
||||
|
||||
add_library(dynarec STATIC
|
||||
$<TARGET_OBJECTS:dynarec_arm>
|
||||
$<TARGET_OBJECTS:arm64_pass0>
|
||||
add_library(dynarec STATIC
|
||||
$<TARGET_OBJECTS:dynarec_arm>
|
||||
$<TARGET_OBJECTS:arm64_pass0>
|
||||
$<TARGET_OBJECTS:arm64_pass1>
|
||||
$<TARGET_OBJECTS:arm64_pass2>
|
||||
$<TARGET_OBJECTS:arm64_pass3>
|
||||
@@ -364,6 +412,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
|
||||
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
|
||||
add_dependencies(${BOX64} WRAPPERS)
|
||||
#add_dependencies(${BOX64} PRINTER)
|
||||
target_link_libraries(${BOX64} m dl rt pthread)
|
||||
@@ -373,19 +422,30 @@ endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
if(NOT NOLOADADDR)
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
else()
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic")
|
||||
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()
|
||||
target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
if(NOT NOLOADADDR)
|
||||
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
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}
|
||||
@@ -406,6 +466,36 @@ if(NOT TARGET uninstall)
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
|
||||
set(CPACK_PACKAGE_CONTACT "[email protected]")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Box64 - Linux Userspace x86_64 Emulator with a twist")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MAJOR\\s*")
|
||||
string(REGEX REPLACE "BOX64_MAJOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_MAJOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MINOR\\s*")
|
||||
string(REGEX REPLACE "BOX64_MINOR" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_MINOR ${TEMP_STRING})
|
||||
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_REVISION\\s*")
|
||||
string(REGEX REPLACE "BOX64_REVISION" "" TEMP_STRING ${TEMP_STRING})
|
||||
string(REGEX MATCH "[0-9]" BOX64_REVISION ${TEMP_STRING})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX64_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${BOX64_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
|
||||
if(_aarch64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
|
||||
elseif(_x86_64)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
|
||||
else()
|
||||
#probably wrong...
|
||||
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
|
||||
endif()
|
||||
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
|
||||
INCLUDE(CPack)
|
||||
|
||||
add_test(test01 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
|
||||
@@ -481,6 +571,21 @@ add_test(test15 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(test16 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(test17 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile.txt
|
||||
-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,49 +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).
|
||||
|
||||
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 some cases.
|
||||
|
||||
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 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,31 @@
|
||||
Current Version
|
||||
======
|
||||
|
||||
v0.1.2
|
||||
======
|
||||
* OpenSource!
|
||||
* A few more opcode added to the Interpretor and the Dynarec
|
||||
* Improved Native Function calling
|
||||
* Added some function to limit allocated memory to 47bits space (for Wine)
|
||||
* Improved and Fixed the functions to limit allocated memory to 32bits space
|
||||
* Wine is starting now, but not everything and every version works
|
||||
|
||||
v0.1.0
|
||||
======
|
||||
* Improvement to ElfLoader
|
||||
* More opcode added to the Dynarec
|
||||
* More lib wrapping
|
||||
* Some fixes to a few function signature
|
||||
* Improvement to Signal handling, and internal mutex handling
|
||||
* A few fixes to some dynarec opcodes
|
||||
* A few fixes to some interpretor opcodes
|
||||
|
||||
v0.0.8
|
||||
======
|
||||
* Improvement to SSE/x87 handling
|
||||
* More opcode added to the Dynarec
|
||||
* More lib wrapping
|
||||
|
||||
v0.0.6
|
||||
======
|
||||
* Added Dynarec for ARM64
|
||||
@@ -31,6 +31,22 @@ If it's the first install, you also need:
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for TEGRA X1
|
||||
|
||||
Using a 64bits OS:
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
If it's the first install, you also need:
|
||||
```
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for Other ARM64 Linux platforms
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
@@ -39,29 +55,31 @@ sudo systemctl restart systemd-binfmt
|
||||
|
||||
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
|
||||
#### use ccmake
|
||||
If you encounter some linking errors, try activating `NOLOADADDR` (`cmake -DNOLOADADDR=ON; make -j$(nproc)`).
|
||||
|
||||
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
|
||||
### use ccmake
|
||||
|
||||
#### Customize your build
|
||||
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
|
||||
|
||||
*use ccache if you have it*
|
||||
### Customize your build
|
||||
|
||||
*Use ccache if you have it*
|
||||
|
||||
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
|
||||
|
||||
*have some debug info*
|
||||
*To have some debug info*
|
||||
|
||||
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
|
||||
|
||||
*to have a Trace Enabled build*
|
||||
*To have a Trace Enabled build*
|
||||
|
||||
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
|
||||
To have 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*
|
||||
*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*
|
||||
*Not building from a git clone*
|
||||
|
||||
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box64 print).
|
||||
|
||||
@@ -72,4 +90,3 @@ Testing
|
||||
A few tests are included.
|
||||
They can be launched with `ctest`
|
||||
They are very basic and don't test much for now.
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# box64
|
||||
|
||||

|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
|
||||
----
|
||||
|
||||
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
|
||||
|
||||
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
|
||||
|
||||
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
|
||||
|
||||
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](../src/emu/x64primop.c) for copyright details
|
||||
|
||||
<img src="img/Box64Icon.png" width="96" height="96">
|
||||
|
||||
Logo and Icon made by @grayduck, thanks!
|
||||
|
||||
----
|
||||
|
||||
Usage
|
||||
----
|
||||
|
||||
There are a few environment variables to control the behaviour of Box64.
|
||||
|
||||
See [here](USAGE.md) for all environment variables and what they do.
|
||||
|
||||
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
|
||||
|
||||
----
|
||||
|
||||
Compiling/Installation
|
||||
----
|
||||
> Compilation instructions can be found [here](COMPILE.md)
|
||||
|
||||
----
|
||||
|
||||
Version history
|
||||
----
|
||||
|
||||
The change log is available [here](CHANGELOG.md)
|
||||
|
||||
----
|
||||
|
||||
Notes about 32-bit platforms
|
||||
----
|
||||
|
||||
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bits libraries. Box64 doesn't include any 64-bits <-> 32-bits translation.
|
||||
|
||||
So understand that box64 will only runs 64bits linux binaries. For 32bits binaries, you need box86 (with all the multiarch or proot trickery it imply on 64bits OS).
|
||||
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when argument is "-m"
|
||||
|
||||
----
|
||||
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not always emulated in a 100% accurate way).
|
||||
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
So, not all Unity games work and can require a high OpenGL profile, but many actualy works now
|
||||
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game start then quit before showing anything.
|
||||
|
||||
----
|
||||
|
||||
Notes about GTK programs
|
||||
----
|
||||
|
||||
GTK libraries are not wrapped yet on box64 (contrary to box86). Many games use gtk (setup too), like Unity game for the Screen Selection dialog. While Unity game can run without that dialog (using default setup), many just can't. For now, you'll need o put the set of gtk x86_64 libraries in the game folder (or some other folder known by box64) to get gtk support. GTK Wrapping is planned on box64.
|
||||
|
||||
----
|
||||
|
||||
Notes about Steam
|
||||
----
|
||||
|
||||
Not that Steam is an hybrid 32buts / 64bits. You NEED box86 to run steam, as the client app is a 32bits binaries. It also use a 64bits local server binaries, but like most stuff using libsef/chromium. it's not working correctly on box64 for now.
|
||||
So: no Steam for now on box64.
|
||||
|
||||
----
|
||||
|
||||
Notes about Wine
|
||||
----
|
||||
|
||||
Wine 64bits is supported on box64. Be aware that 64bits wine also include 32bits componant, to be able to run 32bits windws programs. The 32bits will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64bits setup can run both 32bits and 64bits windows program (just use `wine` and `wine64` respectivelly)
|
||||
|
||||
----
|
||||
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
Box64 Does not wrap Vulkan libraries yet. It's planned, but for now, vulkan program will not run on box64.
|
||||
|
||||
----
|
||||
|
||||
Final word
|
||||
----
|
||||
|
||||
I want to thank everyone who has contributed to box64 developpement.
|
||||
There are many ways to contribute: code contribution, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
|
||||
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
|
||||
|
||||
And I also thank the many other people who participated even once in the project.
|
||||
|
||||
(If you use Box64 in your project, please don't forget to mention it!)
|
||||
@@ -31,6 +31,7 @@ Enables/Disables the logging of `dlsym` errors.
|
||||
#### BOX64_TRACE_FILE
|
||||
Send all log and trace to a file instead of `stdout`
|
||||
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
|
||||
Use `stderr` to use this instead of default `stdout`
|
||||
|
||||
#### BOX64_TRACE
|
||||
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
|
||||
@@ -133,6 +134,11 @@ Allow Box64 to continue even if a library is missing.
|
||||
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
|
||||
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
|
||||
|
||||
#### BOX64_NOPULSE
|
||||
Disables the load of pulseaudio libraries.
|
||||
* 0 : Load pulseaudio libraries if found. (Default.)
|
||||
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
|
||||
|
||||
#### BOX64_JITGDB
|
||||
|
||||
* 0 : Just print the Segfault message on segfault (default)
|
||||
File renamed without changes.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
File renamed without changes.
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-arm64-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-arm64-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-arm64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box86-rk3399-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rk3399-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-rk3399-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-rpi-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-rpi-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-rpi-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-tegra-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-tegra-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-tegra-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Maintainer: Jai-JAP <[email protected]>
|
||||
# Author: Sebastien Chevalier <[email protected]>
|
||||
pkgname=box64-x64-git
|
||||
pkgver=1116.9243ea4
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
|
||||
arch=('aarch64')
|
||||
url="https://github.com/ptitSeb/box64"
|
||||
license=('MIT')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
|
||||
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
|
||||
source=('git+https://github.com/ptitSeb/box64')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-x64-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-x64-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-x64-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-x64-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
# /usr/local/bin isn't in PATH by the default,
|
||||
# we should move it to /usr/bin
|
||||
cd ${pkgdir}
|
||||
mv usr/local/bin/ usr/bin/
|
||||
# cleanup when dir is empty
|
||||
rmdir usr/local || exit 0
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# The directory containing all PKGBUILDs for BOX64
|
||||
## FAQ
|
||||
### 1. How to use it?
|
||||
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
|
||||
```sh
|
||||
mv ./PKGBUILD-<your-platform> ./PKGBUILD
|
||||
cd ..
|
||||
makepkg -si
|
||||
```
|
||||
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 64-bit Archlinux ARM.
|
||||
|
||||
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
|
||||
|
||||
### 2. What platforms are currently supported.
|
||||
All specified in [COMPILE.md](../COMPILE.md).
|
||||
|
||||
### 3. Any advantages with that sollution?
|
||||
This might give you some advantages like those:
|
||||
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
|
||||
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
|
||||
- your `box64` installation is recognized as a package (where it wasn't when installing with `make install`).
|
||||
|
||||
|
||||
### Note: You can use [makedeb](https://github.com/makedeb/makedeb) (or) [pkgbuild2spec](https://github.com/prozum/pkgbuild2spec) to compile box64 to .deb or .rpm installer files.
|
||||
+1084
-427
File diff suppressed because it is too large.
Load diff
+24
-4
@@ -73,9 +73,8 @@ int unlockMutex()
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
|
||||
@@ -89,6 +88,7 @@ int unlockMutex()
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
|
||||
return ret;
|
||||
@@ -111,6 +111,7 @@ void relockMutex(int locks)
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
}
|
||||
|
||||
@@ -129,6 +130,7 @@ static void init_mutexes(box64context_t* context)
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
@@ -158,9 +160,19 @@ box64context_t *NewBox64Context(int argc)
|
||||
|
||||
context->maplib = NewLibrarian(context, 1);
|
||||
context->local_maplib = NewLibrarian(context, 1);
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
|
||||
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
|
||||
// create the vsyscalls
|
||||
context->vsyscalls[0] = AddVSyscall(context->system, 96);
|
||||
context->vsyscalls[1] = AddVSyscall(context->system, 201);
|
||||
context->vsyscalls[2] = AddVSyscall(context->system, 309);
|
||||
// create the alternate to map at address
|
||||
addAlternate((void*)context->vsyscalls[0], (void*)0xffffffffff600000);
|
||||
addAlternate((void*)context->vsyscalls[1], (void*)0xffffffffff600400);
|
||||
addAlternate((void*)context->vsyscalls[2], (void*)0xffffffffff600800);
|
||||
// get handle to box64 itself
|
||||
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
|
||||
context->dlprivate = NewDLPrivate();
|
||||
|
||||
@@ -175,7 +187,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
|
||||
for (int i=0; i<8; ++i) context->canary[i] = 1 + getrand(255);
|
||||
context->canary[getrand(4)] = 0;
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x14, value:%08X\n", *(uint32_t*)context->canary);
|
||||
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary);
|
||||
|
||||
initAllHelpers(context);
|
||||
|
||||
@@ -197,6 +209,7 @@ void FreeBox64Context(box64context_t** context)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
FreeLibrarian(&ctx->maplib, NULL);
|
||||
FreeDictionnary(&ctx->versym);
|
||||
|
||||
for(int i=0; i<ctx->elfsize; ++i) {
|
||||
FreeElfHeader(&ctx->elfs[i]);
|
||||
@@ -267,6 +280,7 @@ void FreeBox64Context(box64context_t** context)
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
@@ -311,6 +325,9 @@ void add_neededlib(needed_libs_t* needed, library_t* lib)
|
||||
{
|
||||
if(!needed)
|
||||
return;
|
||||
for(int i=0; i<needed->size; ++i)
|
||||
if(needed->libs[i] == lib)
|
||||
return;
|
||||
if(needed->size == needed->cap) {
|
||||
needed->cap += 8;
|
||||
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
|
||||
@@ -333,6 +350,9 @@ void add_dependedlib(needed_libs_t* depended, library_t* lib)
|
||||
{
|
||||
if(!depended)
|
||||
return;
|
||||
for(int i=0; i<depended->size; ++i)
|
||||
if(depended->libs[i] == lib)
|
||||
return;
|
||||
if(depended->size == depended->cap) {
|
||||
depended->cap += 8;
|
||||
depended->libs = (library_t**)realloc(depended->libs, depended->cap*sizeof(library_t*));
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
#define __BOX64_VERSION_H_
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 0
|
||||
#define BOX64_REVISION 8
|
||||
#define BOX64_MINOR 1
|
||||
#define BOX64_REVISION 4
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+283
-130
@@ -33,7 +33,7 @@ KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
|
||||
static pthread_mutex_t mutex_mmap;
|
||||
static mmaplist_t *mmaplist;
|
||||
static int mmapsize;
|
||||
static size_t mmapsize;
|
||||
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
|
||||
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
|
||||
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
|
||||
@@ -50,7 +50,7 @@ static int inited = 0;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t maxfree;
|
||||
size_t size;
|
||||
} blocklist_t;
|
||||
|
||||
@@ -73,14 +73,14 @@ typedef struct blockmark_s {
|
||||
} blockmark_t;
|
||||
|
||||
|
||||
// get first subblock free in block, stating at start (from block). return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, int maxsize, int* size)
|
||||
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)block;
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
|
||||
*size = m->next.size;
|
||||
*size = m->next.size-sizeof(blockmark_t);
|
||||
return m;
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m + m->next.size);
|
||||
@@ -89,24 +89,26 @@ static void* getFirstBlock(void* block, int maxsize, int* size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int getMaxFreeBlock(void* block, size_t block_size)
|
||||
static size_t getMaxFreeBlock(void* block, size_t block_size)
|
||||
{
|
||||
// get start of block
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // styart with the end
|
||||
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
|
||||
int maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
if((uintptr_t)block+maxsize>(uintptr_t)m)
|
||||
return maxsize; // no block large enough left...
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
|
||||
}
|
||||
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
|
||||
}
|
||||
return maxsize;
|
||||
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
|
||||
}
|
||||
|
||||
static void* allocBlock(void* block, void *sub, int size)
|
||||
static void* allocBlock(void* block, void *sub, size_t size)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
|
||||
@@ -152,14 +154,17 @@ static void freeBlock(void *block, void* sub)
|
||||
}
|
||||
}
|
||||
// return 1 if block has been expanded to new size, 0 if not
|
||||
static int expandBlock(void* block, void* sub, int newsize)
|
||||
static int expandBlock(void* block, void* sub, size_t newsize)
|
||||
{
|
||||
(void)block;
|
||||
|
||||
newsize = (newsize+3)&~3;
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
|
||||
if(s->next.fill)
|
||||
return 0; // next block is filled
|
||||
if(s->next.size + n->next.size < newsize)
|
||||
// unsigned bitfield of this length gets "promoted" to *signed* int...
|
||||
if((size_t)(s->next.size + n->next.size) < newsize)
|
||||
return 0; // free space too short
|
||||
// ok, doing the alloc!
|
||||
s->next.size = newsize+sizeof(blockmark_t);
|
||||
@@ -178,7 +183,7 @@ static int expandBlock(void* block, void* sub, int newsize)
|
||||
return 1;
|
||||
}
|
||||
// return size of block
|
||||
static int sizeBlock(void* sub)
|
||||
static size_t sizeBlock(void* sub)
|
||||
{
|
||||
blockmark_t *s = (blockmark_t*)sub;
|
||||
return s->next.size;
|
||||
@@ -191,7 +196,7 @@ void* customMalloc(size_t size)
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if(p_blocks[i].maxfree>=size) {
|
||||
int rsize = 0;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
|
||||
if(sub) {
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size);
|
||||
@@ -253,17 +258,16 @@ void* customRealloc(void* p, size_t size)
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
return p;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
if(n_blocks)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
|
||||
return customMalloc(size);
|
||||
}
|
||||
void customFree(void* p)
|
||||
@@ -290,19 +294,19 @@ void customFree(void* p)
|
||||
#ifdef DYNAREC
|
||||
typedef struct mmaplist_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t maxfree;
|
||||
size_t size;
|
||||
kh_dynablocks_t* dblist;
|
||||
uint8_t* helper;
|
||||
} mmaplist_t;
|
||||
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].maxfree>=size) {
|
||||
int rsize = 0;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
|
||||
@@ -317,7 +321,7 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
|
||||
return ret;
|
||||
}
|
||||
@@ -326,15 +330,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
int i = mmapsize++;
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
|
||||
size_t i = mmapsize++;
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, MMAPSIZE)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
@@ -342,7 +346,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
#else
|
||||
void* p = mmap(NULL, MMAPSIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
@@ -370,16 +374,17 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
|
||||
return sub;
|
||||
}
|
||||
|
||||
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
{
|
||||
(void)db;
|
||||
if(!addr || !size)
|
||||
return;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if ((addr>(uintptr_t)mmaplist[i].block)
|
||||
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
@@ -390,20 +395,20 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
for(int j=0; j<size; ++j)
|
||||
for(size_t j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(mmapsize)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
|
||||
dynarec_log(LOG_NONE, "Warning, block %p (size %zu) not found in mmaplist for Free\n", (void*)addr, size);
|
||||
}
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
{
|
||||
// look in actual list
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
for(size_t i=0; i<mmapsize; ++i) {
|
||||
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
|
||||
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) {
|
||||
if(!mmaplist[i].helper)
|
||||
@@ -422,23 +427,25 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
return FindDynablockDynablocklist(addr, dblist_oversized);
|
||||
}
|
||||
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
|
||||
{
|
||||
if(!size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
#ifndef USE_MMAP
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#else
|
||||
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -467,7 +474,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
|
||||
{
|
||||
if(!addr || !size)
|
||||
return;
|
||||
@@ -508,7 +515,7 @@ dynablocklist_t* getDB(uintptr_t idx)
|
||||
|
||||
// each dynmap is 64k of size
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
@@ -535,7 +542,15 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
}
|
||||
}
|
||||
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
static int dynmapempty(void** mem)
|
||||
{
|
||||
for (int i=0; i<(1<<DYNAMAP_SHIFT); ++i)
|
||||
if(mem[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
@@ -547,9 +562,26 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
if(dynmap123[idx3] && dynmap123[idx3][idx2]) {
|
||||
dynablocklist_t* dblist = dynmap123[idx3][idx2][idx1];
|
||||
if(dblist) {
|
||||
if(destroy)
|
||||
FreeRangeDynablock(dblist, addr, size);
|
||||
else
|
||||
if(destroy) {
|
||||
if(FreeRangeDynablock(dblist, addr, size) && 0) { // dblist is empty, check if we can delete more...
|
||||
// disabling this for now. It seems to cause random crash in Terraria
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
|
||||
dynablocklist_t** p = dynmap123[idx3][idx2];
|
||||
if(dynmapempty((void**)p)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
|
||||
dynablocklist_t*** p2 = dynmap123[idx3];
|
||||
if(dynmapempty((void**)p2)) {
|
||||
if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2)) {
|
||||
free(p2);
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
FreeDynablockList(&dblist);
|
||||
}
|
||||
}
|
||||
} else
|
||||
MarkRangeDynablock(dblist, addr, size);
|
||||
}
|
||||
}
|
||||
@@ -662,15 +694,13 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
return (uintptr_t)&box64_jmptbl3[idx3][idx2][idx1][idx0];
|
||||
}
|
||||
|
||||
// Remove the Write flag from an adress range, so DB can be executed
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void protectDB(uintptr_t addr, uintptr_t size)
|
||||
// Remove the Write flag from an adress range, so DB can be executed safely
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
@@ -680,36 +710,20 @@ void protectDB(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));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
void protectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
|
||||
if(!(prot&PROT_DYNAREC))
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
protectDBnolock(addr, size);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void lockDB()
|
||||
@@ -724,7 +738,7 @@ void unlockDB()
|
||||
|
||||
// Add the Write flag from an adress range, and mark all block as dirty
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
void unprotectDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
@@ -740,8 +754,8 @@ void unprotectDB(uintptr_t addr, uintptr_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);
|
||||
}
|
||||
@@ -751,12 +765,14 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
|
||||
#endif
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
uintptr_t last = idx<<MEMPROT_SHIFT;
|
||||
uint8_t oldprot = 0xff;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
@@ -765,16 +781,33 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
uint32_t dyn = kh_value(memprot, k)[ii]&PROT_DYNAREC;
|
||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC;
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t* block = kh_value(memprot, k);
|
||||
for(uintptr_t ii = start; ii<=finish; ++ii) {
|
||||
uint32_t dyn = block[ii]&PROT_DYNAREC;
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
if(oldprot!=prot) {
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i<<MEMPROT_SHIFT;
|
||||
oldprot = prot;
|
||||
}
|
||||
} else if(prot!=0xff) {
|
||||
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
last = i << MEMPROT_SHIFT;
|
||||
oldprot = 0xff;
|
||||
}
|
||||
block[ii] = prot|dyn|PROT_ALLOC;
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
if(oldprot!=0xff)
|
||||
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
@@ -788,15 +821,17 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = prot|PROT_ALLOC;
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "allocProtection %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;
|
||||
@@ -808,8 +843,65 @@ void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = 0;
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t* block = kh_value(memprot, k);
|
||||
for(uintptr_t ii = start; ii<=finish; ++ii) {
|
||||
if(!block[ii])
|
||||
block[ii] = prot;
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void loadProtectionFromMap()
|
||||
{
|
||||
char buf[500];
|
||||
FILE *f = fopen("/proc/self/maps", "r");
|
||||
if(!f)
|
||||
return;
|
||||
while(!feof(f)) {
|
||||
char* ret = fgets(buf, sizeof(buf), f);
|
||||
(void)ret;
|
||||
char r, w, x;
|
||||
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);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static int blockempty(uint8_t* mem)
|
||||
{
|
||||
for (int i=0; i<(MEMPROT_SIZE); ++i)
|
||||
if(mem[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
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);
|
||||
if(k!=kh_end(memprot)) {
|
||||
const uintptr_t start = i&(MEMPROT_SIZE-1);
|
||||
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
memset(block+start, 0, finish-start+1);
|
||||
if(blockempty(block)) {
|
||||
free(block);
|
||||
kh_del(memprot, memprot, k);
|
||||
}
|
||||
i+=finish-start; // +1 from the "for" loop
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -832,58 +924,118 @@ uint32_t getProtection(uintptr_t addr)
|
||||
#define LOWEST (void*)0x20000
|
||||
int availableBlock(uint8_t* p, size_t n)
|
||||
{
|
||||
for (int i=0; i<n; ++i, ++p)
|
||||
for (size_t i=0; i<n; ++i, ++p)
|
||||
if(*p)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
static uintptr_t nextFree(uintptr_t addr)
|
||||
{
|
||||
do {
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
return addr;
|
||||
}
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
|
||||
if(!block[i]) {
|
||||
return (addr&~0xffffffffLL)+(i<<MEMPROT_SHIFT);
|
||||
}
|
||||
addr += 0x100000000LL;
|
||||
addr &= ~0xffffffffLL;
|
||||
} while(1);
|
||||
}
|
||||
static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
|
||||
{
|
||||
uintptr_t mfree = 0;
|
||||
do {
|
||||
const uint32_t key = (addr>>32)&0xffffffff;
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
mfree+=0x100000000LL;
|
||||
if(mfree>sz) {
|
||||
return addr;
|
||||
}
|
||||
} else {
|
||||
uint8_t *block = kh_value(memprot, k);
|
||||
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
|
||||
if(!block[i]) {
|
||||
mfree+=1<<MEMPROT_SHIFT;
|
||||
} else
|
||||
return mfree;
|
||||
}
|
||||
addr += 0x100000000LL;
|
||||
addr &= ~0xffffffffLL;
|
||||
} while(1);
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
return findBlockNearHint(LOWEST, size);
|
||||
}
|
||||
void* find47bitBlock(size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
const uint32_t key = 0; // upper value is 0 by request
|
||||
uintptr_t addr = 0x100000000LL;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return LOWEST;
|
||||
}
|
||||
uint8_t *prot = kh_val(memprot, k);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
void* p = (void*)LOWEST;
|
||||
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
|
||||
do {
|
||||
const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT;
|
||||
if(availableBlock(prot+idx, pages))
|
||||
return p;
|
||||
p += 0x10000;
|
||||
} while(p!=(void*)0xffff0000);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
|
||||
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);
|
||||
// search in 32bits as a backup
|
||||
addr = (uintptr_t)LOWEST;
|
||||
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 47bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
void* find47bitBlockNearHint(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)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
if(!hint) hint=LOWEST;
|
||||
const uint32_t key = (((uintptr_t)hint)>>32)&0xffffffff;
|
||||
uintptr_t addr = (uintptr_t)hint;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
khint_t k = kh_get(memprot, memprot, key);
|
||||
if(k==kh_end(memprot)) {
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
return hint;
|
||||
}
|
||||
uint8_t *prot = kh_val(memprot, k);
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
void* p = hint;
|
||||
void* end = (void*)((uintptr_t)hint+0x100000000LL);
|
||||
uintptr_t step = (size+0xfff)&~0xfff;
|
||||
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
|
||||
do {
|
||||
const uintptr_t idx = (((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT;
|
||||
if(availableBlock(prot+idx, pages))
|
||||
return p;
|
||||
p += step;
|
||||
} while(p!=end);
|
||||
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", 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 32bits address space\n", size);
|
||||
return NULL;
|
||||
}
|
||||
#undef LOWEST
|
||||
@@ -893,9 +1045,8 @@ int unlockCustommemMutex()
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
@@ -943,6 +1094,7 @@ static void atfork_child_custommem(void)
|
||||
|
||||
void init_custommem_helper(box64context_t* ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
@@ -966,13 +1118,14 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
|
||||
void fini_custommem_helper(box64context_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(!inited)
|
||||
return;
|
||||
inited = 0;
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec) {
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
for (int i=0; i<mmapsize; ++i) {
|
||||
for (size_t i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(mmaplist[i].block, mmaplist[i].size);
|
||||
|
||||
+133
-24
@@ -110,8 +110,9 @@
|
||||
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
|
||||
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
|
||||
|
||||
// This macro will give a -Wsign-compare warning, probably bug #38341
|
||||
#define MOV32w(Rd, imm32) \
|
||||
if(~((uint32_t)(imm32))<0xffff) { \
|
||||
if(~((uint32_t)(imm32))<0xffffu) { \
|
||||
MOVNw(Rd, (~(uint32_t)(imm32))&0xffff); \
|
||||
} else { \
|
||||
MOVZw(Rd, (imm32)&0xffff); \
|
||||
@@ -210,14 +211,14 @@
|
||||
#define LDRSW_S9_preindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
|
||||
|
||||
#define LD_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
|
||||
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
|
||||
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)(imm12>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
|
||||
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
|
||||
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
|
||||
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
|
||||
#define LDS_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
|
||||
#define LDR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b01<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
|
||||
@@ -229,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))
|
||||
@@ -251,10 +255,10 @@
|
||||
#define STRH_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b01, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
|
||||
|
||||
#define ST_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
|
||||
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
|
||||
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
|
||||
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
|
||||
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
|
||||
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
|
||||
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
|
||||
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
|
||||
#define STRxw_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
|
||||
#define STR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b00<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
@@ -345,6 +349,8 @@
|
||||
#define PLD_L2_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00011))
|
||||
#define PLD_L3_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00101))
|
||||
|
||||
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
|
||||
|
||||
|
||||
// BR and Branches
|
||||
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
|
||||
@@ -430,11 +436,16 @@
|
||||
#define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
|
||||
#define ORRx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
|
||||
#define ORRxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORRw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define ORNx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
|
||||
#define ORNx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, lsl, Rn, Rd))
|
||||
#define EORx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define EORw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
#define EORxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
|
||||
@@ -447,6 +458,12 @@
|
||||
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
|
||||
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
|
||||
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
|
||||
#define LSLw_IMM(Rd, Rm, lsl) ORRw_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSLx_IMM(Rd, Rm, lsl) ORRx_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSLxw_IMM(Rd, Rm, lsl) ORRxw_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define LSRw_IMM(Rd, Rm, lsr) ORRw_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define LSRx_IMM(Rd, Rm, lsr) ORRx_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define LSRxw_IMM(Rd, Rm, lsr) ORRxw_REG_LSR(Rd, xZR, Rm, lsr)
|
||||
#define MVNx_REG(Rd, Rm) ORNx_REG(Rd, xZR, Rm)
|
||||
#define MVNx_REG_LSL(Rd, Rm, lsl) ORNx_REG_LSL(Rd, xZR, Rm, lsl)
|
||||
#define MVNw_REG(Rd, Rm) ORNw_REG(Rd, xZR, Rm)
|
||||
@@ -575,13 +592,27 @@
|
||||
#define UMULH(Xd, Xn, Xm) EMIT(MULH_gen(1, Xm, Xn, Xd))
|
||||
#define SMULH(Xd, Xn, Xm) EMIT(MULH_gen(0, Xm, Xn, Xd))
|
||||
|
||||
#define MADD_gen(sf, Rm, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (Ra)<<10 | (Rn)<<5 | (Rd))
|
||||
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, Ra, Rn, Rd))
|
||||
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, Ra, Rn, Rd))
|
||||
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, Ra, Rn, Rd))
|
||||
#define MADD_gen(sf, Rm, o0, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (o0)<<15 | (Ra)<<10 | (Rn)<<5 | (Rd))
|
||||
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 0, Ra, Rn, Rd))
|
||||
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 0, Ra, Rn, Rd))
|
||||
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 0, Ra, Rn, Rd))
|
||||
#define MULx(Rd, Rn, Rm) MADDx(Rd, Rn, Rm, xZR)
|
||||
#define MULw(Rd, Rn, Rm) MADDw(Rd, Rn, Rm, xZR)
|
||||
#define MULxw(Rd, Rn, Rm) MADDxw(Rd, Rn, Rm, xZR)
|
||||
#define MSUBx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 1, Ra, Rn, Rd))
|
||||
#define MSUBw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 1, Ra, Rn, Rd))
|
||||
#define MSUBxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 1, Ra, Rn, Rd))
|
||||
#define MNEGx(Rd, Rn, Rm) EMIT(MADD_gen(1, Rm, 1, xZR, Rn, Rd))
|
||||
#define MNEGw(Rd, Rn, Rm) EMIT(MADD_gen(0, Rm, 1, xZR, Rn, Rd))
|
||||
#define MNEGxw(Rd, Rn, Rm) EMIT(MADD_gen(rex.w, Rm, 1, xZR, Rn, Rd))
|
||||
|
||||
|
||||
// DIV
|
||||
#define DIV_gen(sf, Rm, o1, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b00001<<11 | (o1)<<10 | (Rn)<<5 | (Rd))
|
||||
#define UDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 0, Wn, Wd))
|
||||
#define UDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 0, Xn, Xd))
|
||||
#define SDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 1, Wn, Wd))
|
||||
#define SDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 1, Xn, Xd))
|
||||
|
||||
// CLZ
|
||||
#define CL_gen(sf, op, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | 0b00010<<11 | (op)<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -600,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))
|
||||
@@ -740,6 +773,7 @@
|
||||
|
||||
#define SHL_scalar(U, size, Rm, R, S, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b010<<13 | (R)<<12 | (S)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SSHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(0, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(1, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
|
||||
#define SHL_scalar_imm(U, immh, immb, Rn, Rd) (0b01<<30 | 0b111110<<23 | (immh)<<19 | (immb)<<16 | 0b01010<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SHL_64(Vd, Vn, shift) EMIT(SHL_scalar_imm(0, 0b1000 | (((shift)>>3)&7), (shift)&7, Vn, Vd))
|
||||
@@ -752,6 +786,13 @@
|
||||
#define SSHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define USHL_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define USHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b11, Vm, 0, 0, Vn, Vd))
|
||||
|
||||
#define SHR_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b00000<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VSHRQ_8(Vd, Vn, shift) EMIT(SHR_vector(1, 1, 0b0001, (8-(shift))&7, Vn, Vd))
|
||||
@@ -830,6 +871,10 @@
|
||||
#define ABSQ_32(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b10, Vn, Vd))
|
||||
#define ABSQ_64(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b11, Vn, Vd))
|
||||
|
||||
#define NEGABS_vector_scalar(U, size, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define NEG_64(Vd, Vn) EMIT(NEGABS_vector_scalar(1, 0b11, Vn, Vd))
|
||||
#define ABS_64(Vd, Vn) EMIT(NEGABS_vector_scalar(0, 0b11, Vn, Vd))
|
||||
|
||||
// FMOV
|
||||
#define FMOV_general(sf, type, mode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (mode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
|
||||
// 32-bit to single-precision
|
||||
@@ -952,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))
|
||||
@@ -962,6 +1012,16 @@
|
||||
#define FDIVS(Sd, Sn, Sm) EMIT(FDIV_scalar(0b00, Sm, Sn, Sd))
|
||||
#define FDIVD(Dd, Dn, Dm) EMIT(FDIV_scalar(0b01, Dm, Dn, Dd))
|
||||
|
||||
#define FRECPE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRECPES(Vd, Vn) EMIT(FRECPE_vector(0, 0, Vn, Vd))
|
||||
#define VFRECPEQS(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
|
||||
#define VFRECPEQD(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
|
||||
|
||||
#define FRECPS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 0<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRECPSS(Vd, Vn, Vm) EMIT(FRECPS_vector(0, 0, Vm, Vn, Vd))
|
||||
#define VFRECPSQS(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFRECPSQD(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
|
||||
|
||||
// SQRT
|
||||
#define FSQRT_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFSQRTS(Sd, Sn) EMIT(FSQRT_vector(0, 0, Sn, Sd))
|
||||
@@ -972,6 +1032,16 @@
|
||||
#define FSQRTS(Sd, Sn) EMIT(FSQRT_scalar(0b00, Sn, Sd))
|
||||
#define FSQRTD(Dd, Dn) EMIT(FSQRT_scalar(0b01, Dn, Dd))
|
||||
|
||||
#define FRSQRTE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRSQRTES(Vd, Vn) EMIT(FRSQRTE_vector(0, 0, Vn, Vd))
|
||||
#define VFRSQRTEQS(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
|
||||
#define VFRSQRTEQD(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
|
||||
|
||||
#define FRSQRTS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRSQRTSS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(0, 0, Vm, Vn, Vd))
|
||||
#define VFRSQRTSQS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFRSQRTSQD(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
|
||||
|
||||
// CMP
|
||||
#define FCMP_scalar(type, Rn, Rm, opc) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
|
||||
#define FCMPS(Sn, Sm) EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
|
||||
@@ -1173,10 +1243,18 @@
|
||||
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
|
||||
|
||||
#define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
// round toward 0 (truncate)
|
||||
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
|
||||
// round toward 0 (truncate)
|
||||
#define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
|
||||
// round with current FPCR mode
|
||||
#define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
|
||||
// round with current FPCR mode
|
||||
#define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
|
||||
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
|
||||
#define FRINTRRS(Sd, Sn, mode) EMIT(FRINT_scalar(0b00, ((mode)&3), Sn, Sd))
|
||||
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
|
||||
#define FRINTRRD(Dd, Dn, mode) EMIT(FRINT_scalar(0b01, ((mode)&3), Dn, Dd))
|
||||
|
||||
// FMAX / FMIN
|
||||
#define FMINMAX_vector(Q, U, o1, sz, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o1)<<23 | (sz)<<22 | 0b1<<21 | (Rm)<<16 | 0b11110<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
@@ -1342,12 +1420,34 @@
|
||||
#define VCMGTQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b01, 0, Rm, Rn, Rd))
|
||||
#define VCMGTQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b10, 0, Rm, Rn, Rd))
|
||||
#define VCMGTQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b11, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_8(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b00, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_16(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b01, 0, Rm, Rn, Rd))
|
||||
#define VCMGT_32(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b10, 0, Rm, Rn, Rd))
|
||||
// Unsigned Higher
|
||||
#define VCHIQQ_8(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b00, 0, Rm, Rn, Rd))
|
||||
#define VCHIQQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b01, 0, Rm, Rn, Rd))
|
||||
#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))
|
||||
@@ -1627,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__
|
||||
@@ -45,15 +45,12 @@ arm64_lock_write_h:
|
||||
arm64_lock_read_d:
|
||||
// address is x0, return is x0
|
||||
ldaxr w0, [x0]
|
||||
#ldx w0,[x0]
|
||||
ret
|
||||
|
||||
arm64_lock_write_d:
|
||||
// address is x0, value is w1, return is x0
|
||||
mov x2, x0
|
||||
stlxr w0, w1, [x2]
|
||||
#str w1, [x2]
|
||||
mov w0, 0
|
||||
ret
|
||||
|
||||
arm64_lock_read_dd:
|
||||
|
||||
@@ -19,6 +19,7 @@ arm64_next:
|
||||
stp x14, x15, [sp, (8 * 6)]
|
||||
stp x16, x17, [sp, (8 * 8)]
|
||||
str x18, [sp, (8 * 10)]
|
||||
|
||||
mov x2, lr // "from" is in lr, so put in x2
|
||||
// call the function
|
||||
bl LinkNext
|
||||
|
||||
@@ -278,12 +278,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "STR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "101110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
if(isMask(opcode, "1011100110iiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
int offset = imm<<2;
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn]);
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", Xt[Rt], XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], offset);
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", Xt[Rt], XtSp[Rn], offset);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "011110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
@@ -620,7 +620,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
else if(immr==0 && imms==0b001111)
|
||||
snprintf(buff, sizeof(buff), "SXTH %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
|
||||
else if(sf && immr==0 && imms==0b011111)
|
||||
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Xt[Rn]);
|
||||
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Wt[Rn]);
|
||||
else if(imms>=immr)
|
||||
snprintf(buff, sizeof(buff), "SBFX %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
|
||||
else
|
||||
@@ -777,6 +777,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "MADD %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "f0011011000mmmmm1aaaaannnnnddddd", &a)) {
|
||||
if(Ra==31)
|
||||
snprintf(buff, sizeof(buff), "MNEG %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "MSUB %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// DIV
|
||||
if(isMask(opcode, "f0011010110mmmmm00001onnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "%cDIV %s, %s, %s", option?'S':'U', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// MRS / MSR
|
||||
if(isMask(opcode, "110101010001opppnnnnmmmm222ttttt", &a)) {
|
||||
@@ -1299,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));
|
||||
|
||||
+35
-28
@@ -165,10 +165,10 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
if(dynablocks->direct) {
|
||||
dynablock_t* db;
|
||||
@@ -176,34 +176,38 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
khint_t k;
|
||||
kh_dynablocks_t *blocks = kh_init(dynablocks);
|
||||
// copy in a temporary list
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father;
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i) {
|
||||
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
|
||||
if(db) {
|
||||
if(db->father)
|
||||
db = db->father;
|
||||
if(db->parent==dynablocks) {
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
// check emptyness
|
||||
for(uintptr_t i=0; i<dynablocks->textsz; ++i)
|
||||
if(dynablocks->direct[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
@@ -214,7 +218,7 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
uintptr_t new_size = size + dynablocks->maxsz;
|
||||
MarkDirectDynablock(dynablocks, new_addr, new_size);
|
||||
// the blocks check before
|
||||
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
|
||||
MarkDirectDynablock(getDB(idx), new_addr, new_size);
|
||||
}
|
||||
}
|
||||
@@ -254,7 +258,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if(dynablocks->direct) {
|
||||
block = dynablocks->direct[addr-dynablocks->text];
|
||||
if(block) {
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
|
||||
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
@@ -270,7 +274,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
}
|
||||
|
||||
// create and add new block
|
||||
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
@@ -333,7 +337,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
if(old!=block && old) {// put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// doing nothing else, the block as not be writen
|
||||
// doing nothing else, the block has not be writen
|
||||
}
|
||||
free(block);
|
||||
block = NULL;
|
||||
@@ -347,7 +351,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
int blocksz = block->x64_size;
|
||||
if(dynablocks->maxsz<blocksz) {
|
||||
dynablocks->maxsz = blocksz;
|
||||
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
|
||||
dynablocklist_t* dblist;
|
||||
if((dblist = getDB(idx)))
|
||||
if(dblist->maxsz<blocksz)
|
||||
@@ -358,8 +362,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
|
||||
// fill-in jumptable
|
||||
addJumpTableIfDefault64(block->x64_addr, block->block);
|
||||
for(int i=0; i<block->sons_size; ++i)
|
||||
for(int i=0; i<block->sons_size; ++i) {
|
||||
addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
|
||||
block->sons[i]->done = 1;
|
||||
}
|
||||
block->done = 1;
|
||||
unlockDB();
|
||||
}
|
||||
|
||||
|
||||
+16
-8
@@ -30,9 +30,8 @@ void arm64_epilog_fast() EXPORTDYN;
|
||||
#endif
|
||||
|
||||
#ifdef DYNAREC
|
||||
#ifdef HAVE_TRACE
|
||||
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
|
||||
#endif
|
||||
|
||||
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -65,6 +64,11 @@ printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Disable "clobbered" warnings
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclobbered"
|
||||
#endif
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
@@ -76,7 +80,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_RIP; // not sure if it should still be inside DynaCall!
|
||||
}
|
||||
@@ -125,7 +129,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_RIP;
|
||||
}
|
||||
@@ -135,7 +139,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
emu->df = d_none;
|
||||
if(emu->quitonlongjmp && emu->longjmp) {
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
if(emu->quitonlongjmp==1)
|
||||
emu->longjmp = 0; // don't change anything because of the longjmp
|
||||
} else {
|
||||
R_RBX = old_rbx;
|
||||
R_RDI = old_rdi;
|
||||
@@ -166,7 +171,7 @@ int DynaRun(x64emu_t* emu)
|
||||
#ifdef DYNAREC
|
||||
jmpbuf_reset = 1;
|
||||
#endif
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
@@ -203,7 +208,7 @@ int DynaRun(x64emu_t* emu)
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
@@ -214,4 +219,7 @@ int DynaRun(x64emu_t* emu)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
+11
-13
@@ -351,8 +351,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
helper.cap = helper.size+3; // needs epilog handling
|
||||
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr+1);
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr+1);
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
// calculate barriers
|
||||
@@ -383,10 +383,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
// pass 2, instruction size
|
||||
arm_pass2(&helper, addr);
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
int sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
|
||||
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
|
||||
void* p = (void*)AllocDynarecMap(block, sz);
|
||||
if(p==NULL) {
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
|
||||
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
free(helper.table64);
|
||||
@@ -401,17 +401,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
// pass 3, emit (log emit arm opcode)
|
||||
if(box64_dynarec_dump) {
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
|
||||
printFunctionAddr(helper.start, " => ");
|
||||
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
int oldtable64size = helper.table64size;
|
||||
int oldarmsize = helper.arm_size;
|
||||
size_t oldarmsize = helper.arm_size;
|
||||
helper.arm_size = 0;
|
||||
helper.table64size = 0; // reset table64 (but not the cap)
|
||||
arm_pass3(&helper, addr);
|
||||
if((oldarmsize!=helper.arm_size) || (oldtable64size<helper.table64size)) {
|
||||
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size+helper.table64size*8);
|
||||
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.arm_size+helper.table64size*8);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
@@ -450,9 +450,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->block = p;
|
||||
block->need_test = 0;
|
||||
//block->x64_addr = (void*)start;
|
||||
block->x64_size = end-start+1;
|
||||
if(box64_dynarec_largest<block->x64_size)
|
||||
box64_dynarec_largest = block->x64_size;
|
||||
block->x64_size = end-start;
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
@@ -476,7 +474,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / ARM=%p)", son->x64_addr, son->block);}
|
||||
son->father = block;
|
||||
son->size = sz + son->block - block->block; // update size count, for debugging
|
||||
son->done = 1;
|
||||
//son->done = 1;
|
||||
if(!son->parent)
|
||||
son->parent = block->parent;
|
||||
sons[sons_size] = son;
|
||||
@@ -491,6 +489,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
block->done = 1;
|
||||
//block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
}
|
||||
+383
-168
File diff suppressed because it is too large.
Load diff
+381
-59
@@ -64,43 +64,87 @@
|
||||
|
||||
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, i32_, j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int32_t i32, i32_;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
MAYUSE(s0);
|
||||
uint64_t tmp64u;
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(u8);
|
||||
#if STEP == 3
|
||||
//static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
MAYUSE(s0);
|
||||
MAYUSE(j64);
|
||||
#if 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
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL(arm_ud, -1);
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
INST_NAME("PREFETCHW");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PST_L1_STREAM_U12(ed, fixedaddress);
|
||||
break;
|
||||
default: //???
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("MOVUPS Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -264,6 +308,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("MOVNTPS Ex,Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+(rex.b<<3);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -284,6 +343,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("RDTSC");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
CALL(ReadTSC, xRAX); // will return the u64 in xEAX
|
||||
LSRx(xRDX, xRAX, 32);
|
||||
MOVw_REG(xRAX, xRAX); // wipe upper part
|
||||
@@ -348,7 +408,39 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
GOCOND(0x40, "CMOV", "Gd, Ed");
|
||||
#undef GO
|
||||
|
||||
case 0x50:
|
||||
INST_NAME("MOVMSPKPS Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
MOV32w(gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
// EX is an xmm reg
|
||||
GETEX(q0, 0);
|
||||
VMOVQDto(x1, q0, 0);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 0, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
VMOVQDto(x1, q0, 1);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 2, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 3, 1);
|
||||
} else {
|
||||
// EX is memory
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, 0, 0);
|
||||
LDRx_U12(x1, ed, fixedaddress+0);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 0, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
LDRx_U12(x1, ed, fixedaddress+8);
|
||||
LSRx(x1, x1, 31);
|
||||
BFIx(gd, x1, 2, 1);
|
||||
LSRx(x1, x1, 32);
|
||||
BFIx(gd, x1, 3, 1);
|
||||
}
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -356,7 +448,36 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETGX_empty(v0);
|
||||
VFSQRTQS(v0, q0);
|
||||
break;
|
||||
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX_empty(q1);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
// more precise
|
||||
if(q1==q0)
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
VFRSQRTEQS(v0, q0);
|
||||
VFMULQS(v1, v0, q0);
|
||||
VFRSQRTSQS(v1, v1, v0);
|
||||
VFMULQS(q1, v1, v0);
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX_empty(q1);
|
||||
if(q0 == q1)
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
else
|
||||
v1 = q1;
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFRECPEQS(v0, q0);
|
||||
VFRECPSQS(v1, v0, q0);
|
||||
VFMULQS(q1, v0, v1);
|
||||
break;
|
||||
case 0x54:
|
||||
INST_NAME("ANDPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -479,7 +600,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
SQXTN_8(d0, q0);
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
INST_NAME("PCMPGTB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_8(v0, v0, v1);
|
||||
break;
|
||||
case 0x65:
|
||||
INST_NAME("PCMPGTW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_16(v0, v0, v1);
|
||||
break;
|
||||
case 0x66:
|
||||
INST_NAME("PCMPGTD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMGT_32(v0, v0, v1);
|
||||
break;
|
||||
case 0x67:
|
||||
INST_NAME("PACKUSWB Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -516,6 +657,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEM(q1, 1);
|
||||
VZIP2_32(q0, q0, q1);
|
||||
break;
|
||||
case 0x6B:
|
||||
INST_NAME("PACKSSDW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 1, v1, 0);
|
||||
} else {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VLD1_64(q0, 1, ed);
|
||||
}
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
SQXTN_16(v0, q0);
|
||||
break;
|
||||
|
||||
case 0x6E:
|
||||
INST_NAME("MOVD Gm, Ed");
|
||||
@@ -575,6 +732,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
VMOVeH(v0, 1, v1, 0);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
} else if(u8==0x55) {
|
||||
// dumplicate 16bits slot 1 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 1, v1, 1);
|
||||
}
|
||||
VMOVeH(v0, 0, v1, 1);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
} else if(u8==0xAA) {
|
||||
// dumplicate 16bits slot 2 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 2, v1, 2);
|
||||
}
|
||||
VMOVeH(v0, 3, v1, 2);
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
} else if(u8==0xFF) {
|
||||
// dumplicate 16bits slot 3 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 3, v1, 3);
|
||||
}
|
||||
VMOVeH(v0, 2, v1, 3);
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeH(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeH(v0, 1, v1, (u8>>(1*2))&3);
|
||||
@@ -663,7 +841,55 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x72:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>31) {
|
||||
VEOR(d0, d0, d0);
|
||||
} else if(u8) {
|
||||
VSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8>31) u8=31;
|
||||
if(u8) {
|
||||
VSSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLD Em, Ib");
|
||||
GETEM(d0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>31) {
|
||||
VEOR(d0, d0, d0);
|
||||
} else {
|
||||
VSHL_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x73:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -704,7 +930,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETEM(d1, 0);
|
||||
VCMEQ_8(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0x75:
|
||||
INST_NAME("PCMPEQW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(q0, 0);
|
||||
VCMEQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0x76:
|
||||
INST_NAME("PCMPEQD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VCMEQ_32(v0, v0, v1);
|
||||
break;
|
||||
case 0x77:
|
||||
INST_NAME("EMMS");
|
||||
// empty MMX, FPU now usable
|
||||
@@ -799,19 +1038,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("BT Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
@@ -821,10 +1059,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
break;
|
||||
|
||||
case 0xA4:
|
||||
nextop = F8;
|
||||
INST_NAME("SHLD Ed, Gd, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED(1);
|
||||
GETGD;
|
||||
u8 = F8;
|
||||
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xA5:
|
||||
nextop = F8;
|
||||
INST_NAME("SHLD Ed, Gd, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
UXTBw(x3, xRCX);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEDW(x4, x1, 0);
|
||||
@@ -836,7 +1084,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xAB:
|
||||
INST_NAME("BTS Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -844,8 +1093,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -870,10 +1119,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAC:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED(1);
|
||||
GETGD;
|
||||
u8 = F8;
|
||||
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xAD:
|
||||
nextop = F8;
|
||||
INST_NAME("SHRD Ed, Gd, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
UXTBw(x3, xRCX);
|
||||
GETEDW(x4, x1, 0);
|
||||
@@ -897,6 +1156,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FXSAVE Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
@@ -908,6 +1168,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FXRSTOR Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
@@ -972,7 +1233,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xB3:
|
||||
INST_NAME("BTR Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -980,8 +1242,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -1045,17 +1307,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
INST_NAME("BT Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
gd = x2;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8 = F8;
|
||||
u8&=rex.w?0x3f:0x1f;
|
||||
if(u8) {
|
||||
LSRxw(x1, ed, u8);
|
||||
@@ -1066,22 +1327,26 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 5:
|
||||
INST_NAME("BTS Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8 = F8;
|
||||
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);
|
||||
}
|
||||
@@ -1090,22 +1355,26 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 6:
|
||||
INST_NAME("BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8 = F8;
|
||||
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);
|
||||
}
|
||||
@@ -1114,21 +1383,25 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 7:
|
||||
INST_NAME("BTC Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
|
||||
u8 = F8;
|
||||
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);
|
||||
}
|
||||
@@ -1140,7 +1413,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xBB:
|
||||
INST_NAME("BTC Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -1148,8 +1422,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
UBFXw(x1, gd, 5+rex.w, 3-rex.w); // r1 = (gd>>5);
|
||||
ADDx_REG_LSL(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
LDRxw_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
@@ -1175,7 +1449,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xBC:
|
||||
INST_NAME("BSF Gd, Ed");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
@@ -1186,11 +1461,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("BSR Gd, Ed");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
@@ -1202,7 +1477,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBE:
|
||||
INST_NAME("MOVSX Gd, Eb");
|
||||
@@ -1267,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;
|
||||
@@ -1336,6 +1620,19 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
REVxw(gd, gd);
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
if(MODREG)
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
else
|
||||
q0 = d1;
|
||||
NEG_64(q0, d1);
|
||||
USHL_R_64(d0, d0, q0);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
INST_NAME("PMULLW Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -1344,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;
|
||||
@@ -1502,6 +1815,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SSHL_32(d0, d0, v0);
|
||||
break;
|
||||
|
||||
case 0xF5:
|
||||
INST_NAME("PMADDWD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VSMULL_16(q0, v0, v1);
|
||||
VADDPQ_32(q0, q0, q0); //ADDP from Q to non-Q?
|
||||
VMOVQ(v0, q0);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("PSADBW Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -1564,4 +1887,3 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
+654
-30
@@ -22,20 +22,30 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t u8;
|
||||
int32_t j32;
|
||||
uint8_t gd, ed, eb1, eb2;
|
||||
uint8_t wback;
|
||||
int64_t i64;
|
||||
int fixedaddress;
|
||||
MAYUSE(j32);
|
||||
uint8_t wback, wb1, wb2, wb;
|
||||
int64_t i64, j64;
|
||||
int v0;
|
||||
int q0;
|
||||
int d0;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(v0);
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
@@ -51,33 +61,244 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("ADD Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10:
|
||||
switch(rep) {
|
||||
case 1:
|
||||
INST_NAME("MOVSD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
VMOVeS(v0, 0, q0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR32_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 1:
|
||||
INST_NAME("MOVSD Ex, Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOVeD(d0, 0, v0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR64_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("MOVSS Ex, Gx");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
VMOVeS(q0, 0, v0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR32_U12(v0, x4, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAF:
|
||||
INST_NAME("IMUL Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
if(rex.w) {
|
||||
// 64bits imul
|
||||
UFLAG_IF {
|
||||
SMULH(x3, gd, ed);
|
||||
MULx(gd, gd, ed);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_RES(gd);
|
||||
UFLAG_DF(x3, d_imul64);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
} else {
|
||||
// 32bits imul
|
||||
UFLAG_IF {
|
||||
SMULL(gd, gd, ed);
|
||||
UFLAG_RES(gd);
|
||||
LSRx(x3, gd, 32);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
MOVw_REG(gd, gd);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("XOR Gd, Seg:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 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);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
|
||||
EBBACK;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEBO(x1, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
MOV32w(x2, u8);
|
||||
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
} else {
|
||||
emit_cmp8_0(dyn, ninst, x1, x3, x4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
|
||||
@@ -85,7 +306,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -94,7 +315,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
@@ -104,7 +325,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
@@ -113,7 +334,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -121,7 +342,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
|
||||
@@ -129,7 +350,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
|
||||
@@ -137,7 +358,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEDO(x6, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
if(i64) {
|
||||
@@ -150,8 +371,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ed, Gd");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Ed, Gd");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
@@ -163,8 +384,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Gd, Seg:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
@@ -176,8 +397,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0xC6:
|
||||
INST_NAME("MOV FS:Eb, Ib");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Eb, Ib");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
if(MODREG) { // reg <= u8
|
||||
u8 = F8;
|
||||
@@ -199,8 +420,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
INST_NAME("MOV FS:Ed, Id");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
INST_NAME("MOV Seg:Ed, Id");
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
nextop=F8;
|
||||
if(MODREG) { // reg <= i32
|
||||
i64 = F32S;
|
||||
@@ -214,9 +435,412 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD1:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ed, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETEDO(x6, 0);
|
||||
emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
GETEDO(x6, 0);
|
||||
emit_ror32c(dyn, ninst, rex, ed, 1, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOV32w(x2, 1);
|
||||
GETEDO(x6, 0);
|
||||
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
|
||||
if(ed!=x1) {MOVxw_REG(x1, ed);}
|
||||
CALL_(rcl32, ed, x6);
|
||||
WBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, 1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOV32w(x2, 1);
|
||||
GETEDO(x6, 0);
|
||||
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
|
||||
if(ed!=x1) {MOVxw_REG(x1, ed);}
|
||||
CALL_(rcr32, ed, x6);
|
||||
WBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO(x6, 0);
|
||||
emit_shl32c(dyn, ninst, rex, ed, 1, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO(x6, 0);
|
||||
emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO(x6, 0);
|
||||
emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xD3:
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x6, seg);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ed, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
MOV64xw(x4, (rex.w?64:32));
|
||||
SUBx_REG(x3, x4, x3);
|
||||
GETEDO(x6, 0);
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
RORxw_REG(ed, ed, x3);
|
||||
WBACKO(x6);
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPSw_U12(x3, rex.w?63:31);
|
||||
B_MARK(cNE);
|
||||
LSRxw(x4, ed, rex.w?63:31);
|
||||
ADDxw_REG(x4, x4, ed);
|
||||
BFIw(xFlags, x4, F_OF, 1);
|
||||
MARK;
|
||||
BFIw(xFlags, ed, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, CL");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
RORxw_REG(ed, ed, x3);
|
||||
WBACKO(x6);
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPSw_U12(x3, 1);
|
||||
B_MARK(cNE);
|
||||
LSRxw(x2, ed, rex.w?62:30); // x2 = d>>30
|
||||
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
|
||||
BFIw(xFlags, x2, F_OF, 1);
|
||||
MARK;
|
||||
LSRxw(x2, ed, rex.w?63:31);
|
||||
BFIw(xFlags, x2, F_CF, 1);
|
||||
UFLAG_DF(x2, d_none);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x6);
|
||||
WBACK;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, CL");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x6);
|
||||
WBACK;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
emit_shl32(dyn, ninst, rex, ed, x3, x5, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
emit_shr32(dyn, ninst, rex, ed, x3, x5, x4);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, CL");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
GETEDO(x6, 0);
|
||||
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
|
||||
B_NEXT(cEQ);
|
||||
UFLAG_OP12(ed, x3);
|
||||
ASRxw_REG(ed, ed, x3);
|
||||
WBACKO(x6);
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, rex.w?d_sar64:d_sar32);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
+101
-47
@@ -27,15 +27,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, j32;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
uint64_t u64;
|
||||
int32_t i32;
|
||||
int64_t j64;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
int fixedaddress;
|
||||
MAYUSE(u16);
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(u8);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(u16);
|
||||
MAYUSE(u64);
|
||||
MAYUSE(j64);
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
opcode = F8;
|
||||
@@ -52,12 +55,12 @@ 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:
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -66,7 +69,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -75,7 +78,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("ADD AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -85,7 +88,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x09:
|
||||
INST_NAME("OR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -94,7 +97,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x0B:
|
||||
INST_NAME("OR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -103,7 +106,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x0D:
|
||||
INST_NAME("OR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -117,7 +120,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x11:
|
||||
INST_NAME("ADC Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -127,7 +130,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x13:
|
||||
INST_NAME("ADC Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -137,7 +140,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x15:
|
||||
INST_NAME("ADC AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -148,7 +151,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x19:
|
||||
INST_NAME("SBB Ew, Gw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -158,7 +161,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x1B:
|
||||
INST_NAME("SBB Gw, Ew");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -168,7 +171,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x1D:
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i16 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i16);
|
||||
@@ -178,7 +181,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x21:
|
||||
INST_NAME("AND Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -187,7 +190,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x23:
|
||||
INST_NAME("AND Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -196,7 +199,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x25:
|
||||
INST_NAME("AND AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -206,7 +209,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("SUB Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -215,7 +218,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -224,7 +227,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("SUB AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -234,7 +237,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("XOR Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -243,7 +246,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -252,7 +255,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x35:
|
||||
INST_NAME("XOR AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
MOV32w(x2, i32);
|
||||
@@ -262,7 +265,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x39:
|
||||
INST_NAME("CMP Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x2);
|
||||
GETEW(x1, 0);
|
||||
@@ -270,7 +273,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gw, Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
GETEW(x2, 0);
|
||||
@@ -278,7 +281,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x3D:
|
||||
INST_NAME("CMP AX, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
i32 = F16;
|
||||
UXTHw(x1, xRAX);
|
||||
if(i32) {
|
||||
@@ -335,7 +338,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
INST_NAME("ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -344,7 +347,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -354,7 +357,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -364,7 +367,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -373,7 +376,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -382,7 +385,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -391,7 +394,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
@@ -400,7 +403,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(i16) {
|
||||
@@ -414,7 +417,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x85:
|
||||
INST_NAME("TEST Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETEW(x1, 0);
|
||||
GETGW(x2);
|
||||
@@ -451,8 +454,44 @@ 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:
|
||||
INST_NAME("CBW");
|
||||
SXTBw(x1, xRAX);
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,Od");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
LDRH_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od,EAX");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRH_U12(xRAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xA5:
|
||||
@@ -484,7 +523,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xA9:
|
||||
INST_NAME("TEST AX,Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
u16 = F16;
|
||||
MOV32w(x2, u16);
|
||||
UBFXx(x1, xRAX, 0, 16);
|
||||
@@ -534,6 +573,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("ROL Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
@@ -543,6 +583,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
@@ -552,6 +593,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
@@ -562,6 +604,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ew, Ib");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 1);
|
||||
@@ -573,24 +616,26 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4:
|
||||
case 6:
|
||||
INST_NAME("SHL Ew, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSLw_REG(ed, ed, x2);
|
||||
LSLw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shl16);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, Ib");
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
UFLAG_OP12(ed, x2)
|
||||
LSRw_REG(ed, ed, x2);
|
||||
LSRw_IMM(ed, ed, u8&0x1f);
|
||||
EWBACK;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_shr16);
|
||||
@@ -598,6 +643,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
GETSEW(x1, 0);
|
||||
u8 = F8;
|
||||
MOV32w(x2, (u8&0x1f));
|
||||
@@ -638,6 +684,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("ROL Ew, CL");
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL_(rol16, x1, x3);
|
||||
@@ -651,6 +698,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("ROR Ew, CL");
|
||||
ANDSw_mask(x2, xRCX, 0, 0b00100);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL_(ror16, x1, x3);
|
||||
@@ -658,6 +706,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
|
||||
@@ -667,6 +716,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
|
||||
@@ -683,6 +733,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SHL Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -699,6 +750,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SHR Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -715,6 +767,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SAR Ew, CL");
|
||||
ANDSw_mask(x4, xRCX, 0, 0b00100);
|
||||
}
|
||||
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
GETSEW(x1, 0);
|
||||
UFLAG_OP12(ed, x4)
|
||||
@@ -732,7 +785,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("TEST Ew, Iw");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, 2);
|
||||
u16 = F16;
|
||||
MOV32w(x2, u16);
|
||||
@@ -746,7 +799,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("NEG Ew");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x1, 0);
|
||||
emit_neg16(dyn, ninst, ed, x2, x4);
|
||||
EWBACK;
|
||||
@@ -775,12 +828,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("DIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL(div16, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("IDIV Ew");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, 0);
|
||||
CALL(idiv16, -1);
|
||||
@@ -800,7 +855,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SET);
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
GETEW(x1, 0);
|
||||
emit_dec16(dyn, ninst, x1, x2, x4);
|
||||
EWBACK;
|
||||
@@ -814,4 +869,3 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -44,17 +44,20 @@
|
||||
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, j32;
|
||||
int32_t i32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
@@ -62,8 +65,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j32);
|
||||
#if 0//STEP > 1
|
||||
MAYUSE(j64);
|
||||
#if STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
@@ -253,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;
|
||||
@@ -261,6 +309,179 @@ 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;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("PMOVSXBD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
break;
|
||||
case 0x22:
|
||||
INST_NAME("PMOVSXBQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_8(q0, q1); // 8bits->16bits
|
||||
SXTL_16(q0, q0); //16bits->32bits
|
||||
SXTL_32(q0, q0); //32bits->64bits
|
||||
break;
|
||||
case 0x23:
|
||||
INST_NAME("PMOVSXWD Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
break;
|
||||
case 0x24:
|
||||
INST_NAME("PMOVSXWQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_16(q0, q1); // 16bits->32bits
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
case 0x25:
|
||||
INST_NAME("PMOVSXDQ Gx, Ex"); // SSE4 opcode!
|
||||
nextop = F8;
|
||||
GETEX(q1, 0);
|
||||
GETGX_empty(q0);
|
||||
SXTL_32(q0, q1); // 32bits->64bits
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -269,6 +490,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x3A: // these are some more SSSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0B:
|
||||
INST_NAME("ROUNDSD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 1);
|
||||
u8 = F8;
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
if(u8&4) {
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
FRINTXD(v1, q1);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
} else {
|
||||
const uint8_t rounds[] = {0, 2, 1, 3};
|
||||
MAYUSE(rounds);
|
||||
FRINTRRD(v1, q1, rounds[u8&3]);
|
||||
}
|
||||
VMOVeD(q0, 0, v1, 0);
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
INST_NAME("PALIGNR Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -285,6 +525,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEXTQ_8(q0, q1, q0, u8);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
INST_NAME("PINSRD Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETED(1);
|
||||
u8 = F8;
|
||||
VMOVQSfrom(q0, (u8&3), ed);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -308,6 +558,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GOCOND(0x40, "CMOV", "Gw, Ew");
|
||||
#undef GO
|
||||
|
||||
case 0x50:
|
||||
nextop = F8;
|
||||
INST_NAME("PMOVMSKD Gd, Ex");
|
||||
GETEX(q0, 0);
|
||||
GETGD;
|
||||
VMOVQDto(x1, q0, 1);
|
||||
VMOVQDto(gd, q0, 0);
|
||||
LSRx(x1, x1, 63);
|
||||
LSRx(gd, gd, 63);
|
||||
BFIx(gd, x1, 1, 1);
|
||||
break;
|
||||
|
||||
case 0x54:
|
||||
INST_NAME("ANDPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -396,7 +658,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
VFMINQD(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x5E:
|
||||
INST_NAME("DIVPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFDIVQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x5F:
|
||||
INST_NAME("MAXPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -572,12 +840,33 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeD(v0, 1, v1, 0);
|
||||
}
|
||||
} else if(u8==0x00) {
|
||||
// dumplicate lower 32bits to all spot
|
||||
// duplicate lower 32bits to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, 0);
|
||||
}
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else if(u8==0x55) {
|
||||
// duplicate slot 1 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 1, v1, 1);
|
||||
}
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else if(u8==0xAA) {
|
||||
// duplicate slot 2 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 2, v1, 2);
|
||||
}
|
||||
VMOVeS(v0, 3, v1, 2);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
} else if(u8==0xFF) {
|
||||
// duplicate slot 3 to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeS(v0, 3, v1, 3);
|
||||
}
|
||||
VMOVeS(v0, 2, v1, 3);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
|
||||
@@ -594,9 +883,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
tmp64u = swp[(u8>>(0*2))&3] | (swp[(u8>>(1*2))&3]<<32);
|
||||
MOV64x(x2, tmp64u);
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
tmp64u = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
|
||||
MOV64x(x3, tmp64u);
|
||||
VMOVQDfrom(d0, 1, x3);
|
||||
tmp64u2 = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
|
||||
if(tmp64u2==tmp64u) {
|
||||
VMOVQDfrom(d0, 1, x2);
|
||||
} else {
|
||||
MOV64x(x3, tmp64u2);
|
||||
VMOVQDfrom(d0, 1, x3);
|
||||
}
|
||||
VTBLQ1_8(v0, v1, d0);
|
||||
}
|
||||
} else {
|
||||
@@ -613,7 +906,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VLD1_32(v0, i, x2);
|
||||
}
|
||||
} else {
|
||||
VLD1R_32(v0, ed);
|
||||
VLDQ1R_32(v0, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -847,10 +1140,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("BT Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -864,6 +1166,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("SHLD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xA4)?1:0);
|
||||
GETGW(x2);
|
||||
@@ -877,10 +1180,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xAB:
|
||||
INST_NAME("BTS Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -888,8 +1201,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cNE);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
@@ -900,6 +1215,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("SHRD Ew, Gw, CL");
|
||||
UXTBw(x3, xRCX);
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEWW(x4, x1, (opcode==0xAC)?1:0);
|
||||
GETGW(x2);
|
||||
@@ -925,10 +1241,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xB3:
|
||||
INST_NAME("BTR Ew, Gw");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
@@ -936,28 +1263,79 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
B_NEXT(cEQ);
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6:
|
||||
INST_NAME("MOVZX Gw, Eb");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
}
|
||||
UBFXxw(x1, eb1, eb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
|
||||
LDRB_U12(x1, ed, fixedaddress);
|
||||
}
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
|
||||
BFIx(gd, x1, 0, 16); // insert in Gw
|
||||
break;
|
||||
case 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");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
|
||||
GETEW(x4, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
LDRH_U12(x4, x3, fixedaddress);
|
||||
wback = x3;
|
||||
ed = x4;
|
||||
}
|
||||
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
|
||||
LSRw_REG(x1, ed, x2);
|
||||
BFIw(xFlags, x1, F_CF, 1);
|
||||
ANDw_mask(x1, x1, 0, 0); //mask=1
|
||||
MOV32w(x1, 1);
|
||||
LSLxw_REG(x1, x1, x2);
|
||||
EORxw_REG(ed, ed, x1);
|
||||
EWBACK;
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
INST_NAME("BSF Ew,Gw");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEW(x1, 0); // Get EW
|
||||
@@ -969,11 +1347,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("BSR Ew,Gw");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEW(x1, 0); // Get EW
|
||||
@@ -987,7 +1365,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MARK;
|
||||
CSETw(x1, cEQ); //ZF not set
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0xBE:
|
||||
INST_NAME("MOVSX Gw, Eb");
|
||||
@@ -1011,6 +1388,38 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
switch(u8&7) {
|
||||
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
|
||||
case 0: FCMEQQD(v0, v0, v1); break; // Equal
|
||||
case 1: FCMGTQD(v0, v1, v0); break; // Less than
|
||||
case 2: FCMGEQD(v0, v1, v0); break; // Less or equal
|
||||
case 3: FCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
VMVNQ(v0, v0);
|
||||
break; // NaN (NaN is not equal to himself)
|
||||
case 4: FCMEQQD(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 5: FCMGTQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
|
||||
case 6: FCMGEQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
|
||||
case 7: FCMEQQD(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQD(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
break; // not NaN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gx,Ed,Ib");
|
||||
nextop = F8;
|
||||
@@ -1060,7 +1469,47 @@ 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;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
NEG_64(v0, q1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
USHLQ_64(q0, q0, v0);
|
||||
break;
|
||||
case 0xD4:
|
||||
INST_NAME("PADDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1088,7 +1537,29 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
INST_NAME("PMOVMSKB Gd, Ex");
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
GETEX(q0, 0);
|
||||
GETGD;
|
||||
TABLE64(x1, (uintptr_t)&mask_shift8);
|
||||
VLDR64_U12(v0, x1, 0); // load shift
|
||||
MOVI_8(v1, 0x80); // load mask
|
||||
VAND(q1, v1, q0);
|
||||
USHL_8(q1, q1, v0); // shift
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(gd, q1, 0);
|
||||
// and now the high part
|
||||
VMOVeD(q1, 0, q0, 1);
|
||||
VAND(q1, v1, q1); // keep highest bit
|
||||
USHL_8(q1, q1, v0); // shift
|
||||
UADDLV_8(q1, q1); // accumalte
|
||||
VMOVBto(x1, q1, 0);
|
||||
BFIx(gd, x1, 8, 8);
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1208,31 +1679,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQSHRN2_16(v0, q1, 16);
|
||||
break;
|
||||
case 0xE6:
|
||||
INST_NAME("CVTPD2DQ Gx, Ex");
|
||||
INST_NAME("CVTTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(v1, 0);
|
||||
GETGX_empty(v0);
|
||||
#ifdef PRECISE_CVT
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
UBFXx(x1, x1, 13, 2); // extract round requested
|
||||
LSLx_REG(x1, x1, 3);
|
||||
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
|
||||
// Construct a "switch case", with each case 2 instructions, so 8 bytes
|
||||
BL(+4); // Branch with Link to next, so LR gets next PC address
|
||||
ADDx_REG(xLR, xLR, x1);
|
||||
B(xLR); // could use RET, but it's not really one
|
||||
VFCVTNSQD(v0, v1); // 0: Nearest (even)
|
||||
B_NEXT_nocond;
|
||||
VFCVTMSQD(v0, v1); // 1: Toward -inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTPSQD(v0, v1); // 2: Toward +inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTZSQD(v0, v1); // 3: Toward 0
|
||||
#else
|
||||
VFCVTNSQD(v0, v1);
|
||||
#endif
|
||||
VFCVTNSQD(v0, v1); // convert double -> int64
|
||||
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
|
||||
break;
|
||||
case 0xE7:
|
||||
INST_NAME("MOVNTDQ Ex, Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("PSUBSB Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1275,7 +1740,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
SQADDQ_16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEE:
|
||||
INST_NAME("PMAXSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SMAXQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1303,7 +1774,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SSHLQ_32(q0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xF3:
|
||||
INST_NAME("PSLLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVQ(v0, q1);
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
USHLQ_64(q0, q0, v0);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("PMULUDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1345,7 +1825,23 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
UADDLVQ_16(d1, d0);
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
break;
|
||||
|
||||
case 0xF7:
|
||||
INST_NAME("MASKMOVDQU Gx, Ex")
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VLDR128_U12(v0, xRDI, 0);
|
||||
if(MODREG)
|
||||
v1 = fpu_get_scratch(dyn); // need to preserve the register
|
||||
else
|
||||
v1 = q1;
|
||||
VSSHRQ_8(v1, q1, 7); // get the mask
|
||||
VBICQ(v0, v0, v1); // mask destination
|
||||
VANDQ(v1, q0, v1); // mask source
|
||||
VORRQ(v1, v1, v0); // combine
|
||||
VSTR128_U12(v1, xRDI, 0); // put back
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("PSUBB Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1401,4 +1897,3 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,17 @@
|
||||
#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)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int v0, v1;
|
||||
int64_t fixedaddress;
|
||||
|
||||
// REX prefix before the 66 are ignored
|
||||
rex.rex = 0;
|
||||
@@ -44,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
|
||||
@@ -60,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);
|
||||
@@ -76,4 +127,3 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,26 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
#define GETGX(a) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd)
|
||||
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int8_t i8;
|
||||
int32_t i32, j32;
|
||||
MAYUSE(j32);
|
||||
int32_t i32;
|
||||
int64_t j64;
|
||||
int v0, s0;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j64);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(s0);
|
||||
|
||||
// REX prefix before the 67 are ignored
|
||||
rex.rex = 0;
|
||||
@@ -40,9 +49,45 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
opcode=F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
if(rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
}
|
||||
FCMPS(v0, s0);
|
||||
FCOMI(x1, x2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8D:
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -112,9 +157,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
case 0xE8:
|
||||
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
@@ -228,4 +230,3 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
|
||||
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback, wb1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int i1, i2, i3;
|
||||
@@ -93,6 +95,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("FXAM");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_refresh(dyn, ninst, x1, x2, 0);
|
||||
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
|
||||
break;
|
||||
@@ -141,6 +144,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xFC:
|
||||
INST_NAME("FRNDINT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
// use C helper for now, nothing staightforward is available
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_frndint, -1);
|
||||
@@ -158,11 +162,13 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("F2XM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_f2xm1, -1);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("FYL2X");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2x, -1);
|
||||
@@ -170,6 +176,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FTAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_ftan, -1);
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
@@ -177,6 +184,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("FPATAN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fpatan, -1);
|
||||
@@ -184,12 +192,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fxtract, -1);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem1, -1);
|
||||
@@ -212,12 +222,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem, -1);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("FYL2XP1");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2xp1, -1);
|
||||
@@ -225,23 +237,27 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fsincos, -1);
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("FSCALE");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fscale, -1);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fsin, -1);
|
||||
break;
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fcos, -1);
|
||||
break;
|
||||
@@ -297,6 +313,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
@@ -314,6 +331,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
@@ -336,4 +354,3 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,19 +26,21 @@
|
||||
|
||||
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
uint8_t u8;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int j32;
|
||||
int64_t j64;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -115,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;
|
||||
@@ -184,17 +187,18 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTZD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
@@ -215,17 +219,18 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
@@ -246,29 +251,43 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
VSTR32_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDRx_U12(x5, ed, 0);
|
||||
LDRH_U12(x6, ed, 8);
|
||||
// no persistant scratch register, so unrool both instruction here...
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
STRx_U12(x5, ed, 0);
|
||||
STRH_U12(x6, ed, 8);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
CALL(arm_fld, -1);
|
||||
}
|
||||
CALL(arm_fld, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
@@ -286,4 +305,3 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -26,9 +26,11 @@
|
||||
|
||||
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
@@ -46,7 +48,11 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREE STx");
|
||||
break; // not handling Tag...
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_purgecache(dyn, ninst, x1, x2, x3);
|
||||
MOV32w(x1, nextop-0xC0);
|
||||
CALL(fpu_do_free, -1);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
@@ -168,6 +174,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
@@ -175,6 +182,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
@@ -195,4 +203,3 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,17 +26,19 @@
|
||||
|
||||
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed, wback, u8;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int j32;
|
||||
int s0;
|
||||
int64_t j64;
|
||||
int64_t fixedaddress;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -158,17 +160,18 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
VFCVTZSd(s0, v1);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
@@ -187,18 +190,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
@@ -217,18 +221,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
SQXTN_H_S(s0, s0);
|
||||
VSTR16_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
@@ -267,18 +272,20 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VFCVTZSd(s0, s0);
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTXD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
MSR_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV64x(x5, 0x8000000000000000LL);
|
||||
STRx_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
@@ -286,4 +293,3 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit OR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -89,9 +90,10 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
|
||||
}
|
||||
}
|
||||
|
||||
// emit XOR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -155,9 +157,10 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit AND32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -227,9 +230,10 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit OR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -292,9 +296,10 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit XOR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -357,9 +362,10 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
}
|
||||
|
||||
// emit AND8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -429,9 +435,10 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
}
|
||||
|
||||
|
||||
// emit OR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -507,9 +514,10 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit XOR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -585,9 +593,10 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit AND16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
// emit AND16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
|
||||
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -667,4 +676,4 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// IFX(X_PF) {
|
||||
// emit_pf(dyn, ninst, s1, s3, s4);
|
||||
// }
|
||||
//}
|
||||
//}
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit ADD32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADD32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -51,21 +52,17 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
Bcond(cCC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCS);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -76,9 +73,10 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADD32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
@@ -126,21 +124,17 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
Bcond(cCC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCS);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -151,9 +145,10 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -180,22 +175,18 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -206,9 +197,10 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
|
||||
{
|
||||
// special case when doing math on RSP and only PEND is needed: ignoring it!
|
||||
@@ -256,22 +248,18 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -282,9 +270,10 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -331,7 +320,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -383,9 +372,10 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SUB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -434,9 +424,10 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOV32w(s5, c&0xff);
|
||||
}
|
||||
@@ -491,9 +482,10 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -541,7 +533,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADD16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADD16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -608,9 +600,10 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SUB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SUB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -659,7 +652,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SUB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SUB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -756,17 +749,13 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, rex.w?63:31);
|
||||
@@ -777,7 +766,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
}
|
||||
}
|
||||
|
||||
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch
|
||||
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -822,7 +811,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit INC16 instruction, from s1 , store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
|
||||
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
@@ -900,17 +889,13 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, rex.w?63:31);
|
||||
@@ -1009,9 +994,10 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADC32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1062,7 +1048,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit ADC32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1132,9 +1118,10 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit ADC8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1185,9 +1172,10 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -1239,9 +1227,10 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1292,7 +1281,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit ADC16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit ADC16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1359,9 +1348,10 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SBB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1414,7 +1404,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1486,9 +1476,10 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
// }
|
||||
//}
|
||||
|
||||
// emit SBB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SBB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1540,9 +1531,10 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -1595,9 +1587,10 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
|
||||
// emit SBB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s2);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -1649,7 +1642,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit SBB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
// emit SBB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
//{
|
||||
// IFX(X_PEND) {
|
||||
@@ -1853,4 +1846,4 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,9 @@
|
||||
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
|
||||
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
MAYUSE(s2);
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -60,9 +61,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -71,9 +71,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
IFX(X_OF) {
|
||||
CMPSxw_U12(s2, 1); // if s2==1
|
||||
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
|
||||
Bcond(cNE, 4+3*4);
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
|
||||
CSELw(s4, s4, wZR, cEQ);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
@@ -101,7 +100,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
IFX(X_CF|X_OF) {
|
||||
LSRxw(s3, s1, (rex.w?64:32)-c);
|
||||
BFIxw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
@@ -112,9 +111,8 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -123,7 +121,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
|
||||
Bcond(cNE, +12);
|
||||
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
} else {
|
||||
@@ -138,8 +135,9 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit SHR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
|
||||
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
MAYUSE(s2);
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
@@ -167,9 +165,8 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -209,7 +206,9 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
LSRxw_REG(s3, s1, c-1);
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
@@ -218,9 +217,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -255,19 +253,20 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c>1) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
ASRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_REG(s1, s1);
|
||||
BFCx(xFlags, F_ZF, 1);
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
}
|
||||
IFX(X_CF) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
@@ -281,6 +280,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -312,6 +312,7 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -343,119 +344,106 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// c&=0x1f;
|
||||
// IFX(X_PEND) {
|
||||
// MOVW(s3, c);
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// // same flags calc as shr32
|
||||
// SET_DF(s4, d_shr32);
|
||||
// } else IFX(X_ALL) {
|
||||
// SET_DFNONE(s4);
|
||||
// }
|
||||
// if(!c) {
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// MOVS_REG_LSR_IMM5(s1, s1, c);
|
||||
// } else {
|
||||
// MOV_REG_LSR_IMM5(s1, s1, c);
|
||||
// }
|
||||
// IFX(X_ZF|X_CF) {
|
||||
// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
|
||||
// } else {
|
||||
// ORR_REG_LSL_IMM5(s1, s1, s2, 32-c);
|
||||
// }
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
// }
|
||||
// IFX(X_SF) {
|
||||
// MOV_REG_LSR_IMM5(s3, s1, 31);
|
||||
// BFI(xFlags, s3, F_SF, 1);
|
||||
// }
|
||||
// IFX(X_OF) {
|
||||
// if(c==1) {
|
||||
// MOV_REG_LSR_IMM5(s4, s1, 30);
|
||||
// XOR_REG_LSR_IMM8(s4, s4, s4, 1);
|
||||
// BFI(xFlags, s4, F_OF, 1);
|
||||
// }
|
||||
// }
|
||||
// IFX(X_PF) {
|
||||
// emit_pf(dyn, ninst, s1, s3, s4);
|
||||
// }
|
||||
//}
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// same flags computation as with shl64/shl32
|
||||
SET_DF(s4, rex.w?d_shl64:d_shl32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(!c) {
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
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));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
LSRxw(s4, s1, rex.w?62:30);
|
||||
EORw_REG_LSR(s4, s4, s4, 1);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
|
||||
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
|
||||
//{
|
||||
// c&=0x1f;
|
||||
// IFX(X_PEND) {
|
||||
// MOVW(s3, c);
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// // same flags computation as with shl32
|
||||
// SET_DF(s4, d_shl32);
|
||||
// } else IFX(X_ALL) {
|
||||
// SET_DFNONE(s4);
|
||||
// }
|
||||
// if(c==0) {
|
||||
// IFX(F_OF) {
|
||||
// BFC(xFlags, F_OF, 1);
|
||||
// }
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// IFX(X_CF) {
|
||||
// MOV_REG_LSR_IMM5(s3, s1, 32-c);
|
||||
// BFI(xFlags, s3, F_CF, 1);
|
||||
// }
|
||||
// IFX(X_OF) {
|
||||
// MOVS_REG_LSL_IMM5(s1, s1, c);
|
||||
// } else {
|
||||
// MOV_REG_LSL_IMM5(s1, s1, c);
|
||||
// }
|
||||
// IFX(X_OF) {
|
||||
// if(c==1) {
|
||||
// UBFX(s3, s2, 0, 1);
|
||||
// XOR_IMM8_COND(cCS, s3, s3, 1);
|
||||
// BFI(xFlags, s3, F_OF, 1);
|
||||
// } else {
|
||||
// BFC(xFlags, F_OF, 1);
|
||||
// }
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
|
||||
// } else {
|
||||
// ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
|
||||
// }
|
||||
//
|
||||
// IFX(X_PEND) {
|
||||
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
|
||||
// }
|
||||
// IFX(X_ZF) {
|
||||
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
|
||||
// }
|
||||
// IFX(X_SF) {
|
||||
// MOV_REG_LSR_IMM5(s3, s1, 31);
|
||||
// BFI(xFlags, s3, F_SF, 1);
|
||||
// }
|
||||
// IFX(X_PF) {
|
||||
// emit_pf(dyn, ninst, s1, s3, s4);
|
||||
// }
|
||||
//}
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
// same flags computation as with shl64/shl32
|
||||
SET_DF(s4, rex.w?d_shl64:d_shl32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c==0) {
|
||||
IFX(F_OF) {
|
||||
BFCx(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
return;
|
||||
}
|
||||
IFX(X_CF|X_OF) {
|
||||
LSRxw(s3, s1, (rex.w?64:32)-c);
|
||||
BFIxw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
LSLxw(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));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTxw_REG(s1, s1);
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s4, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s4, F_SF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
if(c==1) {
|
||||
UBFXxw(s3, s1, rex.w?63:31, 1);
|
||||
EORxw_REG(s3, s3, xFlags); // CF is set if OF is asked
|
||||
BFIw(xFlags, s3, F_OF, 1);
|
||||
} else {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,10 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -47,22 +48,18 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
LSRxw(s4, s3, 3);
|
||||
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
|
||||
BICx(xFlags, xFlags, s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
Bcond(cVC, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
|
||||
CSETw(s4, cVS);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s5, (rex.w)?63:31);
|
||||
@@ -88,18 +85,18 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
|
||||
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
|
||||
// and now the tricky ones (and mostly unused), PF and AF
|
||||
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
|
||||
IFX(X_ZF|X_CF|X_OF|X_AF) {
|
||||
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF)|(1<<F_AF));
|
||||
IFX(X_OF|X_AF) {
|
||||
MOV32w(s4, (1<<F_OF)|(1<<F_AF));
|
||||
BICw(xFlags, xFlags, s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
Bcond(cNE, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
Bcond(cCS, +8);
|
||||
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
@@ -110,9 +107,10 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
|
||||
}
|
||||
}
|
||||
|
||||
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -189,9 +187,10 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
}
|
||||
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
|
||||
// emit CMP8 instruction, from cmp s1, s2, using s3 and s4 as scratch
|
||||
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -252,8 +251,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
// bc = (res & (~d | s)) | (~d & s) = 0
|
||||
IFX(X_CF | X_AF | X_ZF | X_OF) {
|
||||
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
IFX(X_CF | X_AF | X_OF) {
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -270,9 +269,10 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, rex.w?d_tst64:d_tst32);
|
||||
} else {
|
||||
@@ -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);
|
||||
@@ -307,9 +307,10 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST16 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst16);
|
||||
} else {
|
||||
@@ -339,9 +340,10 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
}
|
||||
}
|
||||
|
||||
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
|
||||
// emit TEST8 instruction, from test s1, s2, using s3 and s4 as scratch
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst8);
|
||||
} else {
|
||||
|
||||
+471
-24
@@ -25,17 +25,20 @@
|
||||
|
||||
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
int32_t j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb2, gb1, gb2;
|
||||
int64_t i64;
|
||||
int fixedaddress;
|
||||
uint8_t gd, ed, u8;
|
||||
uint8_t wback, wb1, wb2, gb1, gb2;
|
||||
int32_t i32;
|
||||
int64_t i64, j64;
|
||||
int64_t fixedaddress;
|
||||
MAYUSE(gb1);
|
||||
MAYUSE(gb2);
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
@@ -51,7 +54,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
INST_NAME("LOCK ADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
@@ -77,7 +80,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("LOCK ADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
@@ -93,13 +96,31 @@ 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) {
|
||||
|
||||
case 0xB1:
|
||||
INST_NAME("LOCK CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -146,7 +167,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xC1:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -184,7 +205,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
@@ -212,7 +233,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("LOCK SUB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
@@ -228,6 +249,372 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
INST_NAME("LOCK ADD Ew, Iw");
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ew, Iw");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_add16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_add16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
}
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Iw");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_or16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_or16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ew, Iw");} else {INST_NAME("LOCK ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_adc16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ew, Iw");} else {INST_NAME("LOCK SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_and16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_and16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_sub16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIw(x1, x4, 0, 8); // re-inject
|
||||
emit_sub16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRH_U12(x1, wback, 0); // put the whole value
|
||||
}
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_xor16(dyn, ninst, x6, x5, x3, x4);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
MOV32w(x5, i32);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, wback);
|
||||
emit_xor16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ew, Iw");} else {INST_NAME("(LOCK) CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETEW(x6, (opcode==0x81)?2:1);
|
||||
(void)wb1;
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
if(i32) {
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
emit_cmp16_0(dyn, ninst, ed, x3, x4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 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;
|
||||
@@ -238,7 +625,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -248,7 +635,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
@@ -268,7 +655,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -288,7 +675,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -308,7 +695,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -327,7 +714,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -346,7 +733,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -356,7 +743,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
TSTx_mask(wback, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
@@ -376,7 +763,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
if(MODREG) {
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
@@ -395,8 +782,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETED(0);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETED((opcode==0x81)?4:1);
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
if(i64) {
|
||||
@@ -436,9 +823,69 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Ed
|
||||
INST_NAME("LOCK INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_inc32(dyn, ninst, rex, ed, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_inc32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8); // re-inject
|
||||
emit_inc32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("LOCK DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_dec32(dyn, ninst, rex, ed, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
emit_dec32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8); // re-inject
|
||||
emit_dec32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
@@ -51,7 +53,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int v0, v1;
|
||||
int q0;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int64_t fixedaddress;
|
||||
|
||||
#ifdef PRECISE_CVT
|
||||
int j32;
|
||||
@@ -73,7 +75,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOV(v0, d0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
@@ -88,7 +90,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed);
|
||||
VMOV(d0, v0);
|
||||
VMOVeD(d0, 0, v0, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
@@ -255,6 +257,9 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
if(v0!=v1) {
|
||||
VMOVeD(v0, 1, v1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7C:
|
||||
@@ -283,19 +288,31 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FCMPD(v0, v1);
|
||||
}
|
||||
switch(u8&7) {
|
||||
case 0: CSETMx(x2, cEQ); break; // Equal
|
||||
case 1: CSETMx(x2, cMI); break; // Less than
|
||||
case 2: //CSETMx(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
|
||||
CSETMx(x2, cPL); CSINVx(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
|
||||
case 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal
|
||||
case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than
|
||||
case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); break; // Less or equal
|
||||
case 3: CSETMx(x2, cVS); break; // NaN
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal
|
||||
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
|
||||
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
|
||||
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
|
||||
case 7: CSETMx(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQDfrom(v0, 0, x2);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
INST_NAME("ADDSUBPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
|
||||
MAYUSE(addsubps);
|
||||
TABLE64(x2, (uintptr_t)&addsubps);
|
||||
VLDR128_U12(q0, x2, 0);
|
||||
VFMLAQS(v0, v1, q0);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("LDDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -316,4 +333,3 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
|
||||
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
uint8_t gd, ed;
|
||||
@@ -50,8 +52,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int j32;
|
||||
int64_t fixedaddress;
|
||||
int64_t j64;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
@@ -59,7 +61,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -118,6 +120,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VTRNQ2_32(q0, q1, q1);
|
||||
break;
|
||||
|
||||
case 0x1E:
|
||||
INST_NAME("NOP / ENDBR32 / ENDBR64");
|
||||
nextop = F8;
|
||||
FAKEED;
|
||||
break;
|
||||
|
||||
case 0x2A:
|
||||
INST_NAME("CVTSI2SS Gx, Ed");
|
||||
nextop = F8;
|
||||
@@ -176,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;
|
||||
|
||||
@@ -295,6 +314,9 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 1, d0, 0);
|
||||
if(v0!=v1) {
|
||||
VMOVeD(v0, 0, v1, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7E:
|
||||
@@ -328,11 +350,11 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xBC:
|
||||
INST_NAME("TZCNT Gd, Ed");
|
||||
SETFLAGS(X_CF|X_ZF, SF_SET);
|
||||
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
SET_DFNONE(x1);
|
||||
TSTxw_REG(ed, ed);
|
||||
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
|
||||
RBITxw(x1, ed); // reverse
|
||||
@@ -341,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");
|
||||
@@ -354,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);
|
||||
@@ -396,4 +431,3 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
#include "dynarec_arm64.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "custommem.h"
|
||||
|
||||
void arm_fstp(x64emu_t* emu, void* p)
|
||||
{
|
||||
if(ST0.q!=STld(0).ref)
|
||||
if(ST0.q!=STld(0).uref)
|
||||
D2LD(&ST0.d, p);
|
||||
else
|
||||
memcpy(p, &STld(0).ld, 10);
|
||||
@@ -36,7 +37,8 @@ void arm_fstp(x64emu_t* emu, void* p)
|
||||
|
||||
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "R%ld=0x%lx (%ld)\n", n, reg, reg);
|
||||
(void)emu;
|
||||
dynarec_log(LOG_DEBUG, "R%lu=0x%lx (%lu)\n", n, reg, reg);
|
||||
}
|
||||
|
||||
void arm_f2xm1(x64emu_t* emu)
|
||||
@@ -50,6 +52,7 @@ void arm_fyl2x(x64emu_t* emu)
|
||||
void arm_ftan(x64emu_t* emu)
|
||||
{
|
||||
ST0.d = tan(ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_fpatan(x64emu_t* emu)
|
||||
{
|
||||
@@ -78,6 +81,7 @@ void arm_fyl2xp1(x64emu_t* emu)
|
||||
void arm_fsincos(x64emu_t* emu)
|
||||
{
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
}
|
||||
void arm_frndint(x64emu_t* emu)
|
||||
{
|
||||
@@ -85,15 +89,18 @@ void arm_frndint(x64emu_t* emu)
|
||||
}
|
||||
void arm_fscale(x64emu_t* emu)
|
||||
{
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
}
|
||||
void arm_fsin(x64emu_t* emu)
|
||||
{
|
||||
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)
|
||||
@@ -106,8 +113,8 @@ void arm_fild64(x64emu_t* emu, int64_t* ed)
|
||||
int64_t tmp;
|
||||
memcpy(&tmp, ed, sizeof(tmp));
|
||||
ST0.d = tmp;
|
||||
STll(0).ll = tmp;
|
||||
STll(0).ref = ST0.q;
|
||||
STll(0).sq = tmp;
|
||||
STll(0).sref = ST0.sq;
|
||||
}
|
||||
|
||||
void arm_fbstp(x64emu_t* emu, uint8_t* ed)
|
||||
@@ -118,8 +125,8 @@ void arm_fbstp(x64emu_t* emu, uint8_t* ed)
|
||||
void arm_fistp64(x64emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid aligments issues
|
||||
if(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))
|
||||
@@ -141,7 +148,7 @@ void arm_fld(x64emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
memcpy(&STld(0).ld, ed, 10);
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
STld(0).ref = ST0.q;
|
||||
STld(0).uref = ST0.q;
|
||||
}
|
||||
|
||||
void arm_ud(x64emu_t* emu)
|
||||
@@ -183,6 +190,125 @@ void arm_fprem1(x64emu_t* emu)
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
|
||||
}
|
||||
|
||||
static uint8_t ff_mult(uint8_t a, uint8_t b)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if((b & 1) == 1)
|
||||
retval ^= a;
|
||||
|
||||
if((a & 0x80)) {
|
||||
a <<= 1;
|
||||
a ^= 0x1b;
|
||||
} else {
|
||||
a <<= 1;
|
||||
}
|
||||
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void arm_aesimc(x64emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesmc(x64emu_t* emu, int xmm)
|
||||
{
|
||||
sse_regs_t eax1 = emu->xmm[xmm];
|
||||
|
||||
for(int j=0; j<4; ++j) {
|
||||
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
|
||||
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
|
||||
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
|
||||
}
|
||||
}
|
||||
void arm_aesdlast(x64emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A N K H E B O L I F C P M J G D
|
||||
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
|
||||
const uint8_t invsubbytes[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
|
||||
//STATE ← InvSubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
|
||||
|
||||
}
|
||||
void arm_aeselast(x64emu_t* emu, int xmm)
|
||||
{
|
||||
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
|
||||
// A F K P E J O D I N C H M B G L
|
||||
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
|
||||
const uint8_t subbytes[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
|
||||
sse_regs_t eax1;
|
||||
for(int i=0; i<16; ++i)
|
||||
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
|
||||
//STATE ← SubBytes( STATE );
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
|
||||
}
|
||||
void arm_aesd(x64emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aesdlast(emu, xmm);
|
||||
arm_aesimc(emu, xmm);
|
||||
}
|
||||
void arm_aese(x64emu_t* emu, int xmm)
|
||||
{
|
||||
arm_aeselast(emu, xmm);
|
||||
arm_aesmc(emu, xmm);
|
||||
}
|
||||
|
||||
|
||||
#define XMM0 0
|
||||
#define XMM8 16
|
||||
#define X870 8
|
||||
@@ -244,6 +370,7 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
|
||||
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
|
||||
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
|
||||
{
|
||||
(void)dyn; (void)ninst;
|
||||
|
||||
uint32_t tested = (1<<parity)-1;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
@@ -282,6 +409,8 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
|
||||
// Do the GETED, but don't emit anything...
|
||||
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
{
|
||||
(void)dyn; (void)addr; (void)ninst;
|
||||
|
||||
if((nextop&0xC0)==0xC0)
|
||||
return addr;
|
||||
if(!(nextop&0xC0)) {
|
||||
@@ -310,16 +439,18 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
|
||||
{
|
||||
(void)dyn;
|
||||
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(int32_t*)(addr+a)
|
||||
|
||||
if(!addr)
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
|
||||
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = *(uintptr_t*)a1;
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
if(!addr || !getProtection(addr))
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
|
||||
@@ -332,4 +463,3 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
|
||||
#undef PK32
|
||||
#undef PK
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x2;
|
||||
*fixaddress = 0;
|
||||
@@ -41,7 +43,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
uint8_t sib = F8;
|
||||
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
if((sib&0x7)==5) {
|
||||
uint64_t tmp = F32S64;
|
||||
int64_t tmp = F32S;
|
||||
if (sib_reg!=4) {
|
||||
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
|
||||
MOV64x(scratch, tmp);
|
||||
@@ -62,9 +64,21 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
}
|
||||
} else if((nextop&7)==5) {
|
||||
uint64_t tmp = F32S64;
|
||||
MOV64x(ret, tmp);
|
||||
GETIP(addr+delta);
|
||||
ADDx_REG(ret, ret, xRIP);
|
||||
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
|
||||
GETIP(addr+delta);
|
||||
ret = xRIP;
|
||||
*fixaddress = tmp;
|
||||
} else if(tmp<0x1000) {
|
||||
GETIP(addr+delta);
|
||||
ADDx_U12(ret, xRIP, tmp);
|
||||
} else if(tmp+addr+delta<0x1000000000000LL) { // 3 opcodes to load immediate is cheap enough
|
||||
tmp += addr+delta;
|
||||
MOV64x(ret, tmp);
|
||||
} else {
|
||||
MOV64x(ret, tmp);
|
||||
GETIP(addr+delta);
|
||||
ADDx_REG(ret, ret, xRIP);
|
||||
}
|
||||
} else {
|
||||
ret = xRAX+(nextop&7)+(rex.b<<3);
|
||||
}
|
||||
@@ -141,8 +155,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
}
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x2;
|
||||
*fixaddress = 0;
|
||||
@@ -156,17 +172,17 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
uint8_t sib = F8;
|
||||
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
if((sib&0x7)==5) {
|
||||
uint32_t tmp = F32;
|
||||
int64_t tmp = F32S;
|
||||
if (sib_reg!=4) {
|
||||
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
|
||||
MOV32w(scratch, tmp);
|
||||
MOV64x(scratch, tmp);
|
||||
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
LSLw(ret, xRAX+sib_reg, (sib>>6));
|
||||
*fixaddress = tmp;
|
||||
}
|
||||
} else {
|
||||
MOV32w(ret, tmp);
|
||||
MOV64x(ret, tmp);
|
||||
}
|
||||
} else {
|
||||
if (sib_reg!=4) {
|
||||
@@ -260,8 +276,10 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
}
|
||||
|
||||
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s)
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x3;
|
||||
*fixaddress = 0;
|
||||
@@ -270,7 +288,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
MAYUSE(scratch);
|
||||
uint32_t m = nextop&0xC7;
|
||||
uint32_t n = (m>>6)&3;
|
||||
int32_t offset = 0;
|
||||
int64_t offset = 0;
|
||||
int absmin = 0;
|
||||
if(s) absmin = -absmax;
|
||||
if(!n && m==6) {
|
||||
@@ -338,7 +356,9 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
|
||||
|
||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Jump to epilog\n");
|
||||
|
||||
if(reg) {
|
||||
if(reg!=xRIP) {
|
||||
MOVx_REG(xRIP, reg);
|
||||
@@ -352,6 +372,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
|
||||
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Jump to next\n");
|
||||
|
||||
if(reg) {
|
||||
@@ -387,7 +408,8 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
|
||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Ret next\n");
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Ret to epilog\n");
|
||||
POP1(xRIP);
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MOV64x(x2, tbl);
|
||||
@@ -405,7 +427,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Retn epilog\n");
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Retn to epilog\n");
|
||||
POP1(xRIP);
|
||||
if(n>0xfff) {
|
||||
MOV32w(w1, n);
|
||||
@@ -427,9 +450,11 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
BLR(x2); // save LR
|
||||
}
|
||||
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "IRet epilog\n");
|
||||
#warning TODO: is64bits
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "IRet to epilog\n");
|
||||
// POP IP
|
||||
POP1(xRIP);
|
||||
// POP CS
|
||||
@@ -437,12 +462,20 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
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);
|
||||
@@ -450,12 +483,13 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
|
||||
{
|
||||
MAYUSE(fnc);
|
||||
if(savereg==0)
|
||||
savereg = 7;
|
||||
if(saveflags) {
|
||||
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
|
||||
}
|
||||
fpu_pushcache(dyn, ninst, reg);
|
||||
fpu_pushcache(dyn, ninst, reg, 0);
|
||||
if(ret!=-2) {
|
||||
STPx_S7_preindex(xEmu, savereg, xSP, -16); // ARM64 stack needs to be 16byte aligned
|
||||
STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller
|
||||
@@ -485,17 +519,64 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
|
||||
GO(R8, R9);
|
||||
#undef GO
|
||||
}
|
||||
fpu_popcache(dyn, ninst, reg);
|
||||
fpu_popcache(dyn, ninst, reg, 0);
|
||||
if(saveflags) {
|
||||
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
|
||||
}
|
||||
SET_NODF();
|
||||
}
|
||||
|
||||
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
|
||||
{
|
||||
MAYUSE(fnc);
|
||||
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
|
||||
fpu_pushcache(dyn, ninst, x3, 1);
|
||||
// x9..x15, x16,x17,x18 those needs to be saved by caller
|
||||
// RDI, RSI, RDX, RCX, R8, R9 are used for function call
|
||||
STPx_S7_preindex(xEmu, xRBX, xSP, -16); // ARM64 stack needs to be 16byte aligned
|
||||
STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
|
||||
// float and double args
|
||||
if(abs(w)>1) {
|
||||
MESSAGE(LOG_DUMP, "Getting %d XMM args\n", abs(w)-1);
|
||||
for(int i=0; i<abs(w)-1; ++i) {
|
||||
sse_get_reg(dyn, ninst, x7, i);
|
||||
}
|
||||
}
|
||||
if(w<0) {
|
||||
MESSAGE(LOG_DUMP, "Return in XMM0\n");
|
||||
sse_get_reg_empty(dyn, ninst, x7, 0);
|
||||
}
|
||||
// prepare regs for native call
|
||||
MOVx_REG(0, xRDI);
|
||||
MOVx_REG(x1, xRSI);
|
||||
MOVx_REG(x2, xRDX);
|
||||
MOVx_REG(x3, xRCX);
|
||||
MOVx_REG(x4, xR8);
|
||||
MOVx_REG(x5, xR9);
|
||||
// native call
|
||||
TABLE64(16, (uintptr_t)fnc); // using x16 as scratch regs for call address
|
||||
BLR(16);
|
||||
// put return value in x86 regs
|
||||
if(w>0) {
|
||||
MOVx_REG(xRAX, 0);
|
||||
MOVx_REG(xRDX, x1);
|
||||
}
|
||||
// all done, restore all regs
|
||||
LDPx_S7_postindex(xEmu, xRBX, xSP, 16);
|
||||
#define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
GO(RSP, RBP);
|
||||
#undef GO
|
||||
|
||||
fpu_popcache(dyn, ninst, x3, 1);
|
||||
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
|
||||
SET_NODF();
|
||||
}
|
||||
|
||||
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
|
||||
{
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
(void)addr;
|
||||
int64_t j64;
|
||||
MAYUSE(j64);
|
||||
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
|
||||
int t1 = x1, t2 = x4;
|
||||
if(reg==t1) ++t1;
|
||||
@@ -519,16 +600,20 @@ void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int se
|
||||
// x87 stuffs
|
||||
static void x87_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->x87cache[i] = -1;
|
||||
dyn->x87stack = 0;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(scratch);
|
||||
if(!dyn->x87stack)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
|
||||
@@ -553,11 +638,14 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
// reset x87stack
|
||||
dyn->x87stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)scratch;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x87_do_push(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
dyn->x87stack+=1;
|
||||
// move all regs in cache, and find a free one
|
||||
@@ -571,6 +659,7 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst)
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -584,10 +673,13 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
++dyn->x87cache[i];
|
||||
if(s1)
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1;
|
||||
#endif
|
||||
}
|
||||
void x87_do_pop(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
dyn->x87stack-=1;
|
||||
// move all regs in cache, poping ST0
|
||||
@@ -599,12 +691,16 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst)
|
||||
dyn->x87reg[i] = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3);
|
||||
int ret = 0;
|
||||
for (int i=0; i<8 && !ret; ++i)
|
||||
if(dyn->x87cache[i] != -1)
|
||||
@@ -653,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)
|
||||
@@ -666,6 +762,8 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
dyn->x87cache[i] = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)s3;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -673,6 +771,7 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2); MAYUSE(s3);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = 0;
|
||||
for (int i=0; (i<8) && (!ret); ++i)
|
||||
@@ -681,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
|
||||
@@ -691,13 +790,17 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
|
||||
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
|
||||
}
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)s3;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st)
|
||||
@@ -711,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) {
|
||||
@@ -727,6 +830,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)st;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -736,6 +840,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
#if STEP > 1
|
||||
return dyn->x87reg[x87_get_cache(dyn, ninst, s1, s2, a)];
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -744,6 +849,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
|
||||
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -753,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
|
||||
@@ -763,12 +869,15 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
}
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
#if STEP > 1
|
||||
MAYUSE(s2);
|
||||
x87_stackcount(dyn, ninst, s1);
|
||||
int ret = -1;
|
||||
for (int i=0; (i<8) && (ret==-1); ++i)
|
||||
@@ -778,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
|
||||
@@ -792,18 +901,22 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
fpu_free_reg(dyn, dyn->x87reg[ret]);
|
||||
dyn->x87cache[ret] = -1;
|
||||
dyn->x87reg[ret] = -1;
|
||||
#else
|
||||
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
// search in cache first
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]==st) {
|
||||
// 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) {
|
||||
@@ -827,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) {
|
||||
@@ -838,21 +951,22 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
#else
|
||||
(void)dyn; (void)s1; (void)s2; (void)st;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int round_map[] = {0, 2, 1, 3}; // map x64 -> arm round flag
|
||||
|
||||
// Set rounding according to cw flags, return reg to restore flags
|
||||
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
LDRH_U12(s1, xEmu, offsetof(x64emu_t, cw));
|
||||
UBFXx(s2, s1, 10, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
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
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
MSR_fpcr(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
@@ -860,10 +974,11 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags
|
||||
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
UBFXx(s2, s1, 13, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
RBITw(s2, s1); // round is on bits 13-14 on x86,
|
||||
LSRw(s2, s2, 17); // but we want the reverse of that
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
@@ -874,45 +989,56 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
// Restore round flag
|
||||
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1);
|
||||
MSR_fpcr(s1); // put back fpscr
|
||||
}
|
||||
|
||||
// MMX helpers
|
||||
static void mmx_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
MAYUSE(dyn);
|
||||
for (int i=0; i<8; ++i)
|
||||
dyn->mmxcache[i] = -1;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a MMX reg, create the entry if needed
|
||||
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
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;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
|
||||
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// purge the MMX cache only(needs 3 scratch registers)
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void)ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -921,23 +1047,28 @@ 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;
|
||||
}
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
|
||||
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -946,14 +1077,18 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
// SSE / SSE2 helpers
|
||||
static void sse_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
(void)ninst;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<16; ++i)
|
||||
dyn->ssecache[i] = -1;
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a SSE reg, create the entry if needed
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
@@ -961,24 +1096,43 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
VLDR128_U12(ret, xEmu, offsetof(x64emu_t, xmm[a]));
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
int ret = dyn->ssecache[a] = fpu_get_reg_xmm(dyn, a);
|
||||
return ret;
|
||||
#else
|
||||
(void)dyn; (void)a;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
// 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)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<8; ++i)
|
||||
@@ -994,12 +1148,15 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge XMM0..7 Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
// purge the SSE cache only
|
||||
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
for (int i=0; i<16; ++i)
|
||||
@@ -1015,55 +1172,68 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(old!=-1) {
|
||||
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
for (int i=0; i<16; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int start = not07?8:0;
|
||||
// only SSE regs needs to be push back to xEmu
|
||||
int n=0;
|
||||
for (int i=0; i<16; i++)
|
||||
for (int i=start; i<16; i++)
|
||||
if(dyn->ssecache[i]!=-1)
|
||||
++n;
|
||||
if(!n)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tPush XMM Cache (%d)------\n", n);
|
||||
for (int i=0; i<16; ++i)
|
||||
for (int i=start; i<16; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Push XMM Cache (%d)\n", n);
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
|
||||
{
|
||||
(void) ninst; (void)s1;
|
||||
#if STEP > 1
|
||||
int start = not07?8:0;
|
||||
// only SSE regs needs to be pop back from xEmu
|
||||
int n=0;
|
||||
for (int i=0; i<16; i++)
|
||||
for (int i=start; i<16; i++)
|
||||
if(dyn->ssecache[i]!=-1)
|
||||
++n;
|
||||
if(!n)
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tPop XMM Cache (%d)------\n", n);
|
||||
for (int i=0; i<16; ++i)
|
||||
for (int i=start; i<16; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
VLDR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
|
||||
#else
|
||||
(void)dyn;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1096,6 +1266,8 @@ void fpu_reset(dynarec_arm_t* dyn, int ninst)
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
|
||||
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
|
||||
LSRw(s3, s3, 5);
|
||||
@@ -1105,4 +1277,4 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
LSRw_REG(s4, s4, s3);
|
||||
MVNw_REG(s4, s4);
|
||||
BFIw(xFlags, s4, F_PF, 1);
|
||||
}
|
||||
}
|
||||
+172
-117
@@ -47,7 +47,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 3, rex, 0, D); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
|
||||
LDRx_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -55,10 +55,20 @@
|
||||
ed = xEAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 2, rex, 0, D); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
LDRw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define GETSEDw(D) if((nextop&0xC0)==0xC0) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
SXTWx(x1, ed); \
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
|
||||
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
|
||||
#define GETEDH(hint, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
@@ -96,6 +106,25 @@
|
||||
ed = x1; \
|
||||
}
|
||||
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O);}
|
||||
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDOx(O, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
|
||||
LDRx_REG(x1, wback, O); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define GETSEDOw(O, D) if((nextop&0xC0)==0xC0) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
SXTWx(x1, ed); \
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
|
||||
LDRSW_REG(x1, wback, O); \
|
||||
wb = ed = x1; \
|
||||
}
|
||||
//FAKEELike GETED, but doesn't get anything
|
||||
#define FAKEED if(!MODREG) { \
|
||||
addr = fakeed(dyn, addr, ninst, nextop); \
|
||||
@@ -166,19 +195,24 @@
|
||||
ed = i; \
|
||||
}
|
||||
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
|
||||
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
|
||||
wback = (nextop&7); \
|
||||
wb2 = (wback>>2); \
|
||||
wback = xEAX+(wback&3); \
|
||||
UBFXx(i, wback, wb2, 8);\
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
|
||||
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
#define GETEBO(i, D) if(MODREG) { \
|
||||
if(rex.rex) { \
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wb2 = 0; \
|
||||
} else { \
|
||||
wback = (nextop&7); \
|
||||
wb2 = (wback>>2)*8; \
|
||||
wback = xRAX+(wback&3); \
|
||||
} \
|
||||
UBFXx(i, wback, wb2, 8); \
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, D); \
|
||||
ADDx_REG(wback, wback, i); \
|
||||
LDRB_U12(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
|
||||
#define GETSEB(i, D) if(MODREG) { \
|
||||
@@ -243,115 +277,123 @@
|
||||
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
|
||||
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
|
||||
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
|
||||
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
|
||||
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
|
||||
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
|
||||
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
|
||||
// Branch to MARK if cond (use j32)
|
||||
// Branch to MARK if cond (use j64)
|
||||
#define B_MARK(cond) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK unconditionnal (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK unconditionnal (use j64)
|
||||
#define B_MARK_nocond \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK if reg is 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK if reg is 0 (use j64)
|
||||
#define CBZxw_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBZxw(reg, j32)
|
||||
// Branch to MARK if reg is not 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBZxw(reg, j64)
|
||||
// Branch to MARK if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
// Branch to MARK if reg is not 0 (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Branch to MARK if reg is not 0 (use j64)
|
||||
#define CBNZw_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBNZw(reg, j32)
|
||||
// Branch to MARK2 if cond (use j32)
|
||||
j64 = GETMARK-(dyn->arm_size); \
|
||||
CBNZw(reg, j64)
|
||||
// Branch to MARK2 if cond (use j64)
|
||||
#define B_MARK2(cond) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK2 unconditionnal (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK2 unconditionnal (use j64)
|
||||
#define B_MARK2_nocond \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK2 if reg is not 0 (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK2 if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK2(reg) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to MARK2 if set
|
||||
#define TBNZ_MARK2(A, N) \
|
||||
j32 = GETMARK2-(dyn->arm_size); \
|
||||
TBNZ(A, N, j32)
|
||||
// Branch to MARK3 if cond (use j32)
|
||||
j64 = GETMARK2-(dyn->arm_size); \
|
||||
TBNZ(A, N, j64)
|
||||
// Branch to MARK3 if cond (use j64)
|
||||
#define B_MARK3(cond) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK3 unconditionnal (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARK3 unconditionnal (use j64)
|
||||
#define B_MARK3_nocond \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK3 if reg is not 0 (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
B(j64)
|
||||
// Branch to MARK3 if reg is not 0 (use j64)
|
||||
#define CBNZx_MARK3(reg) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to MARK3 if set
|
||||
#define TBNZ_MARK3(A, N) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
TBNZ(A, N, j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
TBNZ(A, N, j64)
|
||||
// Test bit N of A and branch to MARK3 if not set
|
||||
#define TBZ_MARK3(A, N) \
|
||||
j32 = GETMARK3-(dyn->arm_size); \
|
||||
TBZ(A, N, j32)
|
||||
// Branch to next instruction if cond (use j32)
|
||||
j64 = GETMARK3-(dyn->arm_size); \
|
||||
TBZ(A, N, j64)
|
||||
// Branch to next instruction if cond (use j64)
|
||||
#define B_NEXT(cond) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
Bcond(cond, j32)
|
||||
// Branch to next instruction unconditionnal (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
Bcond(cond, j64)
|
||||
// Branch to next instruction unconditionnal (use j64)
|
||||
#define B_NEXT_nocond \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
|
||||
B(j32)
|
||||
// Branch to next instruction if reg is 0 (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
|
||||
B(j64)
|
||||
// Branch to next instruction if reg is 0 (use j64)
|
||||
#define CBZw_NEXT(reg) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZw(reg, j32)
|
||||
// Branch to next instruction if reg is 0 (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZw(reg, j64)
|
||||
// Branch to next instruction if reg is 0 (use j64)
|
||||
#define CBZx_NEXT(reg) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZx(reg, j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZx(reg, j64)
|
||||
// Branch to next instruction if reg is not 0 (use j64)
|
||||
#define CBNZx_NEXT(reg) \
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBNZx(reg, j64)
|
||||
// Test bit N of A and branch to next instruction if not set
|
||||
#define TBZ_NEXT(A, N) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBZ(A, N, j32)
|
||||
// Branch to MARKSEG if cond (use j32)
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBZ(A, N, j64)
|
||||
// Test bit N of A and branch to next instruction if set
|
||||
#define TBNZ_NEXT(A, N) \
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
TBNZ(A, N, j64)
|
||||
// Branch to MARKSEG if cond (use j64)
|
||||
#define B_MARKSEG(cond) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKSEG if reg is 0 (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARKSEG if reg is 0 (use j64)
|
||||
#define CBZw_MARKSEG(reg) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBZw(reg, j32)
|
||||
// Branch to MARKSEG if reg is not 0 (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBZw(reg, j64)
|
||||
// Branch to MARKSEG if reg is not 0 (use j64)
|
||||
#define CBNZw_MARKSEG(reg) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBNZw(reg, j32)
|
||||
// Branch to MARKLOCK if cond (use j32)
|
||||
j64 = GETMARKSEG-(dyn->arm_size); \
|
||||
CBNZw(reg, j64)
|
||||
// Branch to MARKLOCK if cond (use j64)
|
||||
#define B_MARKLOCK(cond) \
|
||||
j32 = GETMARKLOCK-(dyn->arm_size); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j32)
|
||||
j64 = GETMARKLOCK-(dyn->arm_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j64)
|
||||
#define CBNZx_MARKLOCK(reg) \
|
||||
j32 = GETMARKLOCK-(dyn->arm_size); \
|
||||
CBNZx(reg, j32)
|
||||
j64 = GETMARKLOCK-(dyn->arm_size); \
|
||||
CBNZx(reg, j64)
|
||||
|
||||
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
|
||||
@@ -400,6 +442,7 @@
|
||||
|
||||
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define STP_REGS(A, B) STPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define LDP_REGS(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
|
||||
#define STORE_XEMU_REGS(A) \
|
||||
STORE_REG(RAX); \
|
||||
STORE_REG(RCX); \
|
||||
@@ -465,11 +508,16 @@
|
||||
if(A) {STPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
|
||||
else {STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}
|
||||
|
||||
#define LOAD_XEMU_CALL(A) \
|
||||
#define LOAD_XEMU_CALL(A) \
|
||||
if(A) {LDPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
|
||||
else {LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}; \
|
||||
if(A==xRIP) dyn->last_ip = 0
|
||||
|
||||
#define LOAD_XEMU_REM() \
|
||||
LDP_REGS(R10, R11); \
|
||||
LDP_REGS(R12, R13); \
|
||||
LDP_REGS(R14, R15)
|
||||
|
||||
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=1;}
|
||||
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
|
||||
#define SET_NODF() dyn->dfnone = 0
|
||||
@@ -477,11 +525,11 @@
|
||||
|
||||
#ifndef READFLAGS
|
||||
#define READFLAGS(A) \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
|
||||
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
|
||||
if(dyn->state_flags!=SF_PENDING) { \
|
||||
LDRw_U12(x3, xEmu, offsetof(x64emu_t, df)); \
|
||||
j32 = (GETMARKF)-(dyn->arm_size); \
|
||||
CBZw(x3, j32); \
|
||||
j64 = (GETMARKF)-(dyn->arm_size); \
|
||||
CBZw(x3, j64); \
|
||||
} \
|
||||
CALL_(UpdateFlags, -1, 0); \
|
||||
MARKF; \
|
||||
@@ -491,9 +539,11 @@
|
||||
#endif
|
||||
#ifndef SETFLAGS
|
||||
#define SETFLAGS(A, B) \
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)|X_PEND)))) \
|
||||
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A))); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
|
||||
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)/*|X_PEND*/)))) \
|
||||
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A)|X_PEND)); \
|
||||
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
|
||||
((B==SF_SET_PENDING && !(dyn->insts[ninst].x64.need_flags&X_PEND)?SF_SET:B))
|
||||
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
#define JUMP(A)
|
||||
@@ -595,16 +645,17 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
|
||||
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
|
||||
|
||||
#define geted STEPNAME(geted_)
|
||||
#define geted32 STEPNAME(geted32_)
|
||||
#define geted16 STEPNAME(geted16_)
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog_)
|
||||
#define jump_to_next STEPNAME(jump_to_next_)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog_)
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog_)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog_)
|
||||
#define call_c STEPNAME(call_c_)
|
||||
#define grab_segdata STEPNAME(grab_segdata_)
|
||||
#define geted STEPNAME(geted)
|
||||
#define geted32 STEPNAME(geted32)
|
||||
#define geted16 STEPNAME(geted16)
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog)
|
||||
#define jump_to_next STEPNAME(jump_to_next)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog)
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog)
|
||||
#define call_c STEPNAME(call_c)
|
||||
#define call_n STEPNAME(call_n)
|
||||
#define grab_segdata STEPNAME(grab_segdata)
|
||||
#define emit_cmp8 STEPNAME(emit_cmp8)
|
||||
#define emit_cmp16 STEPNAME(emit_cmp16)
|
||||
#define emit_cmp32 STEPNAME(emit_cmp32)
|
||||
@@ -693,6 +744,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
|
||||
#define sse_get_reg STEPNAME(sse_get_reg)
|
||||
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
|
||||
#define sse_forget_reg STEPNAME(sse_forget_reg)
|
||||
#define sse_purge07cache STEPNAME(sse_purge07cache)
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
@@ -706,13 +758,13 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#endif
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s);
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s);
|
||||
|
||||
|
||||
// generic x64 helper
|
||||
@@ -720,8 +772,9 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits);
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
|
||||
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
|
||||
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
|
||||
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
|
||||
@@ -790,8 +843,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
@@ -832,6 +885,8 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
|
||||
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
|
||||
// forget neon register for a SSE reg, create the entry if needed
|
||||
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
|
||||
// purge the XMM0..XMM7 cache (before function call)
|
||||
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
|
||||
@@ -847,12 +902,12 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
#endif
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
|
||||
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
@@ -860,7 +915,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
//uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
|
||||
@@ -978,4 +1033,4 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
, cNE, cEQ, X_SF|X_OF|X_ZF) \
|
||||
break
|
||||
|
||||
#endif //__DYNAREC_ARM64_HELPER_H__
|
||||
#endif //__DYNAREC_ARM64_HELPER_H__
|
||||
@@ -75,6 +75,10 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
while(pk==0x3E) { //Branch Taken Hint ignored
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
rex.rex = 0;
|
||||
while(pk>=0x40 && pk<=0x4f) {
|
||||
rex.rex = pk;
|
||||
@@ -96,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 && (
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct dynarec_arm_s {
|
||||
uint32_t isize; // size in byte of x64 instructions included
|
||||
void* block; // memory pointer where next instruction is emited
|
||||
uintptr_t arm_start; // start of the arm code
|
||||
int arm_size; // size of emitted arm code
|
||||
size_t arm_size; // size of emitted arm code
|
||||
int state_flags;// actual state for on-demand flags
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state)
|
||||
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
|
||||
@@ -59,4 +59,4 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
|
||||
|
||||
int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
#endif //__DYNAREC_ARM_PRIVATE_H_
|
||||
@@ -15,8 +15,9 @@
|
||||
#define SF_UNKNOWN 0
|
||||
#define SF_SET 1
|
||||
#define SF_PENDING 2
|
||||
#define SF_MAYSET 3
|
||||
#define SF_SUBSET 4
|
||||
#define SF_SET_PENDING 3
|
||||
#define SF_MAYSET 4
|
||||
#define SF_SUBSET 5
|
||||
|
||||
typedef struct instruction_x64_s {
|
||||
uintptr_t addr; //address of the instruction
|
||||
|
||||
+68
-65
@@ -225,13 +225,14 @@ const char* DumpRelType(int t)
|
||||
return buff;
|
||||
}
|
||||
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym)
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version)
|
||||
{
|
||||
static char buff[4096];
|
||||
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
|
||||
memset(buff, 0, sizeof(buff));
|
||||
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d",
|
||||
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)",
|
||||
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
|
||||
sym->st_info, sym->st_other, sym->st_shndx);
|
||||
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -246,116 +247,118 @@ const char* IdxSymName(elfheader_t *h, int sym)
|
||||
|
||||
void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP) {
|
||||
printf_log(LOG_DUMP, "ELF Dump main header\n");
|
||||
printf_log(LOG_DUMP, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_log(LOG_DUMP, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_log(LOG_DUMP, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_log(LOG_DUMP, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_log(LOG_DUMP, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_log(LOG_DUMP, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_log(LOG_DUMP, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_log(LOG_DUMP, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump ==========\n");
|
||||
if(box64_dump) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump main header\n");
|
||||
printf_dump(LOG_NEVER, " Entry point = %p\n", (void*)header->e_entry);
|
||||
printf_dump(LOG_NEVER, " Program Header table offset = %p\n", (void*)header->e_phoff);
|
||||
printf_dump(LOG_NEVER, " Section Header table offset = %p\n", (void*)header->e_shoff);
|
||||
printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags);
|
||||
printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize);
|
||||
printf_dump(LOG_NEVER, " Program Header Entry num/size = %zu(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header Entry num/size = %zu(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
|
||||
printf_dump(LOG_NEVER, " Section Header index num = %zu(%d)\n", h->SHIdx, header->e_shstrndx);
|
||||
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numPHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump PEntries ====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries (%zu)\n", h->numPHEntries);
|
||||
for (size_t i=0; i<h->numPHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " PHEntry %04zu : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
|
||||
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numSHEntries; ++i)
|
||||
printf_log(LOG_DUMP, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_log(LOG_DUMP, "ELF Dump Sections ====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections (%zu)\n", h->numSHEntries);
|
||||
for (size_t i=0; i<h->numSHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " Section %04zu : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpSymTab(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->SymTab) {
|
||||
if(box64_dump && h->SymTab) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab(%d)=\n", h->numSymTab);
|
||||
for (int i=0; i<h->numSymTab; ++i)
|
||||
printf_log(LOG_DUMP, " %s:SymTab[%d] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab(%zu)=\n", h->numSymTab);
|
||||
for (size_t i=0; i<h->numSymTab; ++i)
|
||||
printf_dump(LOG_NEVER, " %s:SymTab[%zu] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
|
||||
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
|
||||
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
|
||||
printf_log(LOG_DUMP, "ELF Dump SymTab=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicSections(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->Dynamic) {
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
printf_log(LOG_DUMP, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump Dynamic=====\n");
|
||||
if(box64_dump && h->Dynamic) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%zu)=\n", h->numDynamic);
|
||||
for (size_t i=0; i<h->numDynamic; ++i)
|
||||
printf_dump(LOG_NEVER, " Dynamic %04zu : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynSym(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynSym) {
|
||||
if(box64_dump && h->DynSym) {
|
||||
const char* name = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym(%d)=\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i)
|
||||
printf_log(LOG_DUMP, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i));
|
||||
printf_log(LOG_DUMP, "ELF Dump DynSym=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym(%zu)=\n", h->numDynSym);
|
||||
for (size_t i=0; i<h->numDynSym; ++i) {
|
||||
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
|
||||
}
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicNeeded(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(box64_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
for (size_t i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
printf_log(LOG_DUMP, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpDynamicRPath(elfheader_t *h)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->DynStrTab) {
|
||||
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
if(box64_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (size_t i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag==DT_RPATH) {
|
||||
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
|
||||
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
}
|
||||
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP) {
|
||||
if(box64_dump) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
|
||||
i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF64_R_TYPE(rel[i].r_info)),
|
||||
ELF64_R_SYM(rel[i].r_info), IdxSymName(h, ELF64_R_SYM(rel[i].r_info)));
|
||||
printf_log(LOG_DUMP, "ELF Dump Rel Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name)
|
||||
{
|
||||
if(box64_log>=LOG_DUMP && h->rela) {
|
||||
if(box64_dump && h->rela) {
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
|
||||
for (int i = 0; i<cnt; ++i)
|
||||
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname,
|
||||
printf_dump(LOG_NEVER, " %s:%s[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, name,
|
||||
i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF64_R_TYPE(rela[i].r_info)),
|
||||
ELF64_R_SYM(rela[i].r_info), IdxSymName(h, ELF64_R_SYM(rela[i].r_info)),
|
||||
rela[i].r_addend);
|
||||
printf_log(LOG_DUMP, "ELF Dump RelA Table=====\n");
|
||||
printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,24 +369,24 @@ void DumpBinary(char* p, int sz)
|
||||
unsigned char* d = (unsigned char*)p;
|
||||
int delta = ((uintptr_t)p)&0xf;
|
||||
for (int i = 0; sz; ++i) {
|
||||
printf_log(LOG_DUMP, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
printf_dump(LOG_NEVER, "%p ", (void*)(((uintptr_t)d)&~0xf));
|
||||
int n = 16 - delta;
|
||||
if (n>sz) n = sz;
|
||||
int fill = 16-sz;
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%02X ", d[j]);
|
||||
printf_dump(LOG_NEVER, "%02X ", d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, " | ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, " | ");
|
||||
for (int j = 0; j<delta; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
for (int j = 0; j<n; ++j)
|
||||
printf_log(LOG_DUMP, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
printf_dump(LOG_NEVER, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
|
||||
for (int j = 0; j<fill; ++j)
|
||||
printf_log(LOG_DUMP, " ");
|
||||
printf_log(LOG_DUMP, "\n");
|
||||
printf_dump(LOG_NEVER, " ");
|
||||
printf_dump(LOG_NEVER, "\n");
|
||||
d+=n;
|
||||
sz-=n;
|
||||
delta=0;
|
||||
|
||||
+411
-220
File diff suppressed because it is too large.
Load diff
@@ -13,23 +13,28 @@ typedef struct needed_libs_s needed_libs_t;
|
||||
struct elfheader_s {
|
||||
char* name;
|
||||
char* path; // Resolved path to file
|
||||
int numPHEntries;
|
||||
size_t numPHEntries;
|
||||
Elf64_Phdr *PHEntries;
|
||||
int numSHEntries;
|
||||
size_t numSHEntries;
|
||||
Elf64_Shdr *SHEntries;
|
||||
int SHIdx;
|
||||
int numSST;
|
||||
size_t SHIdx;
|
||||
size_t numSST;
|
||||
char* SHStrTab;
|
||||
char* StrTab;
|
||||
Elf64_Sym* SymTab;
|
||||
int numSymTab;
|
||||
size_t numSymTab;
|
||||
char* DynStr;
|
||||
Elf64_Sym* DynSym;
|
||||
int numDynSym;
|
||||
size_t numDynSym;
|
||||
Elf64_Dyn* Dynamic;
|
||||
int numDynamic;
|
||||
size_t numDynamic;
|
||||
char* DynStrTab;
|
||||
int szDynStrTab;
|
||||
size_t szDynStrTab;
|
||||
Elf64_Half* VerSym;
|
||||
Elf64_Verneed* VerNeed;
|
||||
int szVerNeed;
|
||||
Elf64_Verdef* VerDef;
|
||||
int szVerDef;
|
||||
int e_type;
|
||||
|
||||
intptr_t delta; // should be 0
|
||||
@@ -37,19 +42,19 @@ struct elfheader_s {
|
||||
uintptr_t entrypoint;
|
||||
uintptr_t initentry;
|
||||
uintptr_t initarray;
|
||||
int initarray_sz;
|
||||
size_t initarray_sz;
|
||||
uintptr_t finientry;
|
||||
uintptr_t finiarray;
|
||||
int finiarray_sz;
|
||||
size_t finiarray_sz;
|
||||
|
||||
uintptr_t rel;
|
||||
int relsz;
|
||||
size_t relsz;
|
||||
int relent;
|
||||
uintptr_t rela;
|
||||
int relasz;
|
||||
size_t relasz;
|
||||
int relaent;
|
||||
uintptr_t jmprel;
|
||||
int pltsz;
|
||||
size_t pltsz;
|
||||
int pltent;
|
||||
uint64_t pltrel;
|
||||
uintptr_t gotplt;
|
||||
@@ -60,18 +65,20 @@ struct elfheader_s {
|
||||
uintptr_t plt;
|
||||
uintptr_t plt_end;
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
size_t textsz;
|
||||
|
||||
uintptr_t paddr;
|
||||
uintptr_t vaddr;
|
||||
int align;
|
||||
size_t align;
|
||||
uint64_t memsz;
|
||||
uint64_t stacksz;
|
||||
int stackalign;
|
||||
uint32_t tlssize;
|
||||
int tlsalign;
|
||||
size_t stackalign;
|
||||
uintptr_t tlsaddr;
|
||||
uint64_t tlssize;
|
||||
uint64_t tlsfilesize;
|
||||
size_t tlsalign;
|
||||
|
||||
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
|
||||
int init_done;
|
||||
int fini_done;
|
||||
@@ -133,4 +140,4 @@ struct elfheader_s {
|
||||
|
||||
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
|
||||
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
+140
-66
@@ -43,7 +43,7 @@ int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
|
||||
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num)
|
||||
{
|
||||
int n = FindSection(s, size, SHStrTab, name);
|
||||
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
|
||||
@@ -141,7 +141,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->numSHEntries = section.sh_size;
|
||||
}
|
||||
// now read all section headers
|
||||
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
|
||||
printf_log(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries);
|
||||
h->SHEntries = (Elf64_Shdr*)calloc(h->numSHEntries, sizeof(Elf64_Shdr));
|
||||
fseeko64(f, header.e_shoff ,SEEK_SET);
|
||||
if(fread(h->SHEntries, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
|
||||
@@ -157,7 +157,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
}
|
||||
}
|
||||
|
||||
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
|
||||
printf_log(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries);
|
||||
h->PHEntries = (Elf64_Phdr*)calloc(h->numPHEntries, sizeof(Elf64_Phdr));
|
||||
fseeko64(f, header.e_phoff ,SEEK_SET);
|
||||
if(fread(h->PHEntries, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
|
||||
@@ -172,68 +172,125 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->SHIdx = h->SHEntries[0].sh_link;
|
||||
}
|
||||
if(h->SHIdx > h->numSHEntries) {
|
||||
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
|
||||
printf_log(LOG_INFO, "Incoherent Section String Table Index : %zu / %zu\n", h->SHIdx, h->numSHEntries);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
// load Section table
|
||||
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
|
||||
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx);
|
||||
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if(box64_log>=LOG_DUMP) DumpMainHeader(&header, h);
|
||||
if(box64_dump) DumpMainHeader(&header, h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
|
||||
if(box64_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
|
||||
if(box64_dump && h->SymTab) DumpSymTab(h);
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
|
||||
if(box64_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
|
||||
if(box64_dump && h->Dynamic) DumpDynamicSections(h);
|
||||
// grab DT_REL & DT_RELA stuffs
|
||||
// also grab the DT_STRTAB string table
|
||||
{
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag == DT_REL)
|
||||
h->rel = h->Dynamic[i].d_un.d_ptr;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELSZ)
|
||||
h->relsz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELENT)
|
||||
h->relent = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELA)
|
||||
h->rela = h->Dynamic[i].d_un.d_ptr;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELASZ)
|
||||
h->relasz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_RELAENT)
|
||||
h->relaent = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
|
||||
h->pltgot = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTREL)
|
||||
h->pltrel = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
|
||||
h->pltsz = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_JMPREL)
|
||||
h->jmprel = h->Dynamic[i].d_un.d_val;
|
||||
else if(h->Dynamic[i].d_tag == DT_STRTAB)
|
||||
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
|
||||
else if(h->Dynamic[i].d_tag == DT_STRSZ)
|
||||
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
|
||||
for (size_t i=0; i<h->numDynamic; ++i) {
|
||||
Elf64_Dyn d = h->Dynamic[i];
|
||||
Elf64_Word val = d.d_un.d_val;
|
||||
Elf64_Addr ptr = d.d_un.d_ptr;
|
||||
switch (d.d_tag) {
|
||||
case DT_REL:
|
||||
h->rel = ptr;
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
h->relsz = val;
|
||||
break;
|
||||
case DT_RELENT:
|
||||
h->relent = val;
|
||||
break;
|
||||
case DT_RELA:
|
||||
h->rela = ptr;
|
||||
break;
|
||||
case DT_RELASZ:
|
||||
h->relasz = val;
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
h->relaent = val;
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
h->pltgot = ptr;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
h->pltrel = val;
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
h->pltsz = val;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
h->jmprel = ptr;
|
||||
break;
|
||||
case DT_STRTAB:
|
||||
h->DynStrTab = (char*)(ptr);
|
||||
break;
|
||||
case DT_STRSZ:
|
||||
h->szDynStrTab = val;
|
||||
break;
|
||||
case DT_INIT: // Entry point
|
||||
h->initentry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
|
||||
break;
|
||||
case DT_INIT_ARRAY:
|
||||
h->initarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
|
||||
break;
|
||||
case DT_INIT_ARRAYSZ:
|
||||
h->initarray_sz = val / sizeof(Elf64_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
|
||||
break;
|
||||
case DT_FINI: // Exit hook
|
||||
h->finientry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
|
||||
break;
|
||||
case DT_FINI_ARRAY:
|
||||
h->finiarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
|
||||
break;
|
||||
case DT_FINI_ARRAYSZ:
|
||||
h->finiarray_sz = val / sizeof(Elf64_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz);
|
||||
break;
|
||||
case DT_VERNEEDNUM:
|
||||
h->szVerNeed = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
|
||||
break;
|
||||
case DT_VERNEED:
|
||||
h->VerNeed = (Elf64_Verneed*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
|
||||
break;
|
||||
case DT_VERDEFNUM:
|
||||
h->szVerDef = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
|
||||
break;
|
||||
case DT_VERDEF:
|
||||
h->VerDef = (Elf64_Verdef*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(h->rel) {
|
||||
if(h->relent != sizeof(Elf64_Rel)) {
|
||||
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%lx)\n", h->relent, sizeof(Elf64_Rel));
|
||||
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%zx)\n", h->relent, sizeof(Elf64_Rel));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
printf_log(LOG_DEBUG, "Rel Table @%p (0x%zx/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
}
|
||||
if(h->rela) {
|
||||
if(h->relaent != sizeof(Elf64_Rela)) {
|
||||
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%lx)\n", h->relaent, sizeof(Elf64_Rela));
|
||||
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%zx)\n", h->relaent, sizeof(Elf64_Rela));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
printf_log(LOG_DEBUG, "RelA Table @%p (0x%zx/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
}
|
||||
if(h->jmprel) {
|
||||
if(h->pltrel == DT_REL) {
|
||||
@@ -241,16 +298,16 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
} else if(h->pltrel == DT_RELA) {
|
||||
h->pltent = sizeof(Elf64_Rela);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%ld)\n", h->pltsz, h->pltrel);
|
||||
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%zx, type=%ld)\n", h->pltsz, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
|
||||
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%zx, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
}
|
||||
if(h->DynStrTab && h->szDynStrTab) {
|
||||
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
|
||||
@@ -275,44 +332,61 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
|
||||
}
|
||||
// look for .init entry point
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
|
||||
// grab version of symbols
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
|
||||
if(ii) {
|
||||
h->initentry = h->SHEntries[ii].sh_addr;
|
||||
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
|
||||
}
|
||||
// and .init_array
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array");
|
||||
if(ii) {
|
||||
h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
|
||||
h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %d elements\n", (void*)h->initarray, h->initarray_sz);
|
||||
}
|
||||
// look for .fini entry point
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
|
||||
if(ii) {
|
||||
h->finientry = h->SHEntries[ii].sh_addr;
|
||||
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
|
||||
}
|
||||
// and .fini_array
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array");
|
||||
if(ii) {
|
||||
h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
|
||||
h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %d elements\n", (void*)h->finiarray, h->finiarray_sz);
|
||||
h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
|
||||
}
|
||||
// grab .text for main code
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
|
||||
if(ii) {
|
||||
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
h->textsz = h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
|
||||
printf_log(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz);
|
||||
}
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
|
||||
if(box64_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version)
|
||||
{
|
||||
if(!h->VerNeed || (version<2))
|
||||
return NULL;
|
||||
/*if(version==1)
|
||||
return "*";*/
|
||||
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(aux->vna_other==version)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
|
||||
}
|
||||
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index)
|
||||
{
|
||||
if(!h->VerDef || (index<1))
|
||||
return NULL;
|
||||
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
|
||||
while(def) {
|
||||
if(def->vd_ndx==index) {
|
||||
if(def->vd_cnt<1)
|
||||
return NULL;
|
||||
/*if(def->vd_flags&VER_FLG_BASE)
|
||||
return NULL;*/
|
||||
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
|
||||
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
|
||||
}
|
||||
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#define F8 *(uint8_t*)(R_RIP++)
|
||||
#define F8S *(int8_t*)(R_RIP++)
|
||||
#define F16 *(uint16_t*)(R_RIP+=2, R_RIP-2)
|
||||
#define F16S *(int16_t*)(R_RIP+=2, R_RIP-2)
|
||||
#define F32 *(uint32_t*)(R_RIP+=4, R_RIP-4)
|
||||
#define F32S *(int32_t*)(R_RIP+=4, R_RIP-4)
|
||||
#define F32S64 (uint64_t)(int64_t)F32S
|
||||
|
||||
+17
-8
@@ -109,6 +109,7 @@ EXPORTDYN
|
||||
void SetupX64Emu(x64emu_t *emu)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
|
||||
(void)emu; // Not doing much here...
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -130,6 +131,8 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
|
||||
|
||||
void AddCleanup(x64emu_t *emu, void *p)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
@@ -141,6 +144,8 @@ void AddCleanup(x64emu_t *emu, void *p)
|
||||
|
||||
void AddCleanup1Arg(x64emu_t *emu, void *p, void* a)
|
||||
{
|
||||
(void)emu;
|
||||
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
@@ -213,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;
|
||||
@@ -322,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)
|
||||
@@ -348,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, " ");
|
||||
}
|
||||
@@ -365,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;
|
||||
@@ -460,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;
|
||||
@@ -473,7 +480,9 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
|
||||
|
||||
uint64_t ReadTSC(x64emu_t* emu)
|
||||
{
|
||||
//TODO: implement hardware counter read?
|
||||
(void)emu;
|
||||
|
||||
//TODO: implement hardware counter read? (only available in kernel space?)
|
||||
// Read the TimeStamp Counter as 64bits.
|
||||
// this is supposed to be the number of instructions executed since last reset
|
||||
// fall back to gettime...
|
||||
|
||||
@@ -30,10 +30,12 @@ typedef struct x64emu_s {
|
||||
reg64_t regs[16];
|
||||
x64flags_t eflags;
|
||||
reg64_t ip;
|
||||
uintptr_t old_ip;
|
||||
// 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;
|
||||
@@ -42,8 +44,8 @@ typedef struct x64emu_s {
|
||||
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
|
||||
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
|
||||
fpu_p_reg_t p_regs[8];
|
||||
// sse
|
||||
sse_regs_t xmm[16];
|
||||
// old ip
|
||||
uintptr_t old_ip;
|
||||
// defered flags
|
||||
int dummy1; // to align on 64bits with df
|
||||
defered_flags_t df;
|
||||
|
||||
+82
-32
@@ -92,60 +92,110 @@ void x64Int3(x64emu_t* emu)
|
||||
char *tmp;
|
||||
int post = 0;
|
||||
int perr = 0;
|
||||
uint32_t *pu32 = NULL;
|
||||
uint64_t *pu64 = NULL;
|
||||
const char *s = NULL;
|
||||
s = GetNativeName((void*)addr);
|
||||
if(addr==(uintptr_t)PltResolver) {
|
||||
snprintf(buff, 256, "%s", " ... ");
|
||||
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "open ")) {
|
||||
} else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "mkdir")==s) {
|
||||
} else if (!strcmp(s, "fopen") || !strcmp(s, "fopen64")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
|
||||
perr = 2;
|
||||
} else if (!strcmp(s, "__openat64") || !strcmp(s, "openat64") || !strcmp(s, "__openat64_2")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
|
||||
perr = 1;
|
||||
} else if (strstr(s, "mkdir")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "opendir")==s) {
|
||||
} else if (strstr(s, "opendir")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
perr = 2;
|
||||
} else if(strstr(s, "strlen")==s) {
|
||||
} else if (!strcmp(s, "read")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "write")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "access")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "lseek64") || !strcmp(s, "my_lseek64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "lseek") || !strcmp(s, "my_lseek")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "puts")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if(strstr(s, "strcmp")==s) {
|
||||
} else if (strstr(s, "strlen")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (strstr(s, "strcmp")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)R_RSI);
|
||||
} else if(!strcmp(s, "poll")) {
|
||||
struct pollfd* pfd = (struct pollfd*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
|
||||
} else if(strstr(s, "my___printf_chk")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if(!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress")) {
|
||||
} else if (strstr(s, "getenv")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if(!strcmp(s, "glGetStringi")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
} else if (!strcmp(s, "poll")) {
|
||||
struct pollfd* pfd = (struct pollfd*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
|
||||
} else if (strstr(s, "my___printf_chk") || !strcmp(s, "__printf_chk")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if (strstr(s, "my___snprintf_chk") || !strcmp(s, "__snprintf_chk")) {
|
||||
tmp = (char*)(R_R8);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, R_EDX, R_RCX, (tmp)?tmp:"(nil)", (void*)(R_R9));
|
||||
} else if (strstr(s, "my_snprintf") || !strcmp(s, "snprintf")) {
|
||||
tmp = (char*)(R_RDX);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (tmp)?tmp:"(nil)", (void*)(R_RCX));
|
||||
} else if (!strcmp(s, "getcwd")) {
|
||||
post = 2;
|
||||
} else if(!strcmp(s, "glFramebufferTexture2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI);
|
||||
} else if (!strcmp(s, "ftok")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
perr = 1;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, tmp?tmp:"nil", R_ESI);
|
||||
} else if (!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress") || !strcmp(s, "glXGetProcAddressARB")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glLabelObjectEXT")) {
|
||||
tmp = (char*)(R_RCX);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, \"%s\")", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_ECX, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glGetStringi")) {
|
||||
post = 2;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
} else if (!strcmp(s, "glFramebufferTexture2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, 0x%x, 0x%x, %u, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d);
|
||||
} else if(!strcmp(s, "glTexSubImage2D")) {
|
||||
} else if (!strcmp(s, "glTexSubImage2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
|
||||
} else if(!strcmp(s, "glCompressedTexSubImage2D")) {
|
||||
} else if (!strcmp(s, "glCompressedTexSubImage2D")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
|
||||
} else if(!strcmp(s, "glVertexAttribPointer")) {
|
||||
} else if (!strcmp(s, "glVertexAttribPointer")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%u, %d, 0x%x, %d, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, (void*)R_R9);
|
||||
} else if(!strcmp(s, "glDrawElements")) {
|
||||
} else if (!strcmp(s, "glDrawElements")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, (void*)R_RCX);
|
||||
} else if(!strcmp(s, "glUniform4fv")) {
|
||||
} else if (!strcmp(s, "glUniform4fv")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %d, %p[%g/%g/%g/%g...])", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, (void*)R_RDX, ((float*)(R_RDX))[0], ((float*)(R_RDX))[1], ((float*)(R_RDX))[2], ((float*)(R_RDX))[3]);
|
||||
} else if(!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
|
||||
} else if (!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %lu, 0x%x, 0x%x, %d, %ld)", tid, *(void**)(R_RSP), s,
|
||||
(void*)R_RDI, R_RSI, (int)(R_RDX), (int)R_RCX, (int)R_R8, R_R9);
|
||||
} else if(!strcmp(s, "sscanf")) {
|
||||
} else if (!strcmp(s, "sscanf")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if(!strcmp(s, "XCreateWindow")) {
|
||||
} else if (!strcmp(s, "XCreateWindow")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, 0x%lx, %p)", tid, *(void**)(R_RSP), s,
|
||||
(void*)R_RDI, (void*)R_RSI, (int)R_EDX, (int)R_ECX, R_R8d, R_R9d,
|
||||
@@ -160,23 +210,23 @@ void x64Int3(x64emu_t* emu)
|
||||
w(emu, addr); // some function never come back, so unlock the mutex first!
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
if(post)
|
||||
switch(post) {
|
||||
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
|
||||
switch(post) { // Only ever 2 for now...
|
||||
case 1: snprintf(buff2, 63, " [%llu sec %llu nsec]", pu64?pu64[0]:~0ull, pu64?pu64[1]:~0ull);
|
||||
break;
|
||||
case 2: snprintf(buff2, 63, "(%s)", R_RAX?((char*)R_RAX):"nil");
|
||||
break;
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu64?((char*)pu64):"nil");
|
||||
break;
|
||||
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
|
||||
break;
|
||||
case 5: {
|
||||
uint32_t* p = (uint32_t*)R_RAX;
|
||||
uint32_t* p = (uint32_t*)R_RAX; // uint64_t? (case never used)
|
||||
if(p)
|
||||
snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
snprintf(buff2, 63, " size=%ux%u, pitch=%u, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
else
|
||||
snprintf(buff2, 63, "NULL Surface");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(perr==1 && ((int)R_EAX)<0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
@@ -199,4 +249,4 @@ void x64Int3(x64emu_t* emu)
|
||||
int GetTID()
|
||||
{
|
||||
return syscall(SYS_gettid);
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -785,7 +785,7 @@ uint8_t rol8(x64emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -808,7 +808,7 @@ uint16_t rol16(x64emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -831,7 +831,7 @@ uint32_t rol32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -854,7 +854,7 @@ uint64_t rol64(x64emu_t *emu, uint64_t d, uint8_t s)
|
||||
if((cnt = s % 64) != 0) {
|
||||
d = (d << cnt) + ((d >> (64 - cnt)) & ((1L << cnt) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
|
||||
if(s == 1) {
|
||||
@@ -881,7 +881,7 @@ uint8_t ror8(x64emu_t *emu, uint8_t d, uint8_t s)
|
||||
if((cnt = s % 8) != 0) {
|
||||
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -904,7 +904,7 @@ uint16_t ror16(x64emu_t *emu, uint16_t d, uint8_t s)
|
||||
if((cnt = s % 16) != 0) {
|
||||
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -927,7 +927,7 @@ uint32_t ror32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
if((cnt = s % 32) != 0) {
|
||||
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -950,7 +950,7 @@ uint64_t ror64(x64emu_t *emu, uint64_t d, uint8_t s)
|
||||
if((cnt = s % 64) != 0) {
|
||||
d = (d << (64 - cnt)) + ((d >> (cnt)) & ((1L << (64 - cnt)) - 1L));
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
|
||||
if(s == 1) {
|
||||
@@ -1400,7 +1400,7 @@ void idiv64(x64emu_t *emu, uint64_t s)
|
||||
}
|
||||
quot = dvd/(int64_t)s;
|
||||
mod = dvd%(int64_t)s;
|
||||
if (llabs(quot) > 0x7fffffffffffffffL) {
|
||||
if ((quot > 0x7fffffffffffffffLL) || (quot < -0x7fffffffffffffffLL)) {
|
||||
INTR_RAISE_DIV0(emu);
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-1
@@ -235,21 +235,25 @@ static inline uint64_t neg64(x64emu_t *emu, uint64_t s)
|
||||
|
||||
static inline uint8_t not8(x64emu_t *emu, uint8_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint16_t not16(x64emu_t *emu, uint16_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint32_t not32(x64emu_t *emu, uint32_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
static inline uint64_t not64(x64emu_t *emu, uint64_t s)
|
||||
{
|
||||
(void)emu; // No flags affected
|
||||
return ~s;
|
||||
}
|
||||
|
||||
@@ -588,7 +592,7 @@ static inline void mul32_eax(x64emu_t *emu, uint32_t s)
|
||||
static inline void mul64_rax(x64emu_t *emu, uint64_t s)
|
||||
{
|
||||
emu->df = d_mul64;
|
||||
__int128 res = (__int128)R_RAX * s;
|
||||
unsigned __int128 res = (unsigned __int128)R_RAX * s;
|
||||
emu->res.u64 = R_RAX = (uint64_t)res;
|
||||
emu->op1.u64 = R_RDX = (uint64_t)(res >> 64);
|
||||
}
|
||||
|
||||
+164
-30
@@ -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);
|
||||
@@ -70,6 +75,8 @@ x64emurun:
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
while((opcode==0x3E)) //Branch Taken Hint ignored
|
||||
opcode = F8;
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
@@ -156,6 +163,9 @@ x64emurun:
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x36: /* SS: (ignored) */
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
@@ -234,19 +244,26 @@ x64emurun:
|
||||
GD->sq[0] = ED->sdword[0];
|
||||
else
|
||||
if(MODREG)
|
||||
GD->q[0] = ED->sdword[0];
|
||||
GD->q[0] = ED->dword[0]; // not really a sign extension
|
||||
else
|
||||
GD->sdword[0] = ED->sdword[0]; // meh?
|
||||
break;
|
||||
case 0x64: /* FS: prefix */
|
||||
if(Run64(emu, rex)) {
|
||||
if(Run64(emu, rex, _FS)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
case 0x65: /* GS: prefix */
|
||||
if(Run64(emu, rex, _GS)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0x66: /* 16bits prefix */
|
||||
if(Run66(emu, rex, rep)) {
|
||||
unimp = 1;
|
||||
@@ -274,10 +291,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, ED->q[0], tmp64u);
|
||||
else
|
||||
if((nextop&0xC0)==0xC0)
|
||||
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
else
|
||||
GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
|
||||
break;
|
||||
case 0x6A: /* Push Ib */
|
||||
tmp64s = F8S;
|
||||
@@ -293,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);
|
||||
@@ -383,7 +406,7 @@ x64emurun:
|
||||
#ifdef DYNAREC
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
|
||||
if(MODREG) { // reg / reg: no lock
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
@@ -397,12 +420,12 @@ x64emurun:
|
||||
#else
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
if(!MODREG)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
if(!MODREG)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
@@ -411,7 +434,7 @@ x64emurun:
|
||||
#ifdef DYNAREC
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
if(rex.w) {
|
||||
tmp64u = GD->q[0];
|
||||
GD->q[0] = ED->q[0];
|
||||
@@ -487,7 +510,14 @@ x64emurun:
|
||||
else
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8C: /* MOV Ed, Seg */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
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;
|
||||
GETED(0);
|
||||
@@ -495,7 +525,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
GD->q[0] = (uint32_t)(uintptr_t)ED;
|
||||
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
|
||||
break;
|
||||
|
||||
case 0x8F: /* POP Ed */
|
||||
@@ -510,7 +540,26 @@ x64emurun:
|
||||
R_ESP += sizeof(void*);
|
||||
}
|
||||
break;
|
||||
case 0x90: /* NOP */
|
||||
case 0x90: /* NOP or XCHG R8, RAX*/
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97: /* XCHG reg,EAX */
|
||||
tmp8u = _AX+(opcode&7)+(rex.b<<3);
|
||||
if(tmp8u!=_AX) {
|
||||
if(rex.w) {
|
||||
tmp64u = R_RAX;
|
||||
R_RAX = emu->regs[tmp8u].q[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
} else {
|
||||
tmp64u = R_EAX;
|
||||
R_RAX = emu->regs[tmp8u].dword[0];
|
||||
emu->regs[tmp8u].q[0] = tmp64u;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x98: /* CWDE */
|
||||
@@ -539,6 +588,7 @@ x64emurun:
|
||||
RESET_FLAGS(emu);
|
||||
break;
|
||||
case 0x9E: /* SAHF */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x01, F_CF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x04, F_PF);
|
||||
@@ -558,7 +608,7 @@ x64emurun:
|
||||
if(rex.w)
|
||||
R_RAX = *(uint64_t*)F64;
|
||||
else
|
||||
R_EAX = *(uint32_t*)F64;
|
||||
R_RAX = *(uint32_t*)F64;
|
||||
break;
|
||||
case 0xA2: /* MOV Ob,AL */
|
||||
*(uint8_t*)F64 = R_AL;
|
||||
@@ -974,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
|
||||
@@ -1020,7 +1075,26 @@ 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)&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;
|
||||
case 0xD0: /* GRP2 Eb,1 */
|
||||
case 0xD2: /* GRP2 Eb,CL */
|
||||
nextop = F8;
|
||||
@@ -1146,7 +1220,44 @@ x64emurun:
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0xE0: /* LOOPNZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX && !ACCESS_FLAG(F_ZF))
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE1: /* LOOPZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX && ACCESS_FLAG(F_ZF))
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE2: /* LOOP */
|
||||
tmp8s = F8S;
|
||||
--R_RCX; // don't update flags
|
||||
if(R_RCX)
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 0xE3: /* JECXZ */
|
||||
tmp8s = F8S;
|
||||
if(!R_RCX)
|
||||
R_RIP += tmp8s;
|
||||
STEP
|
||||
break;
|
||||
case 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);
|
||||
@@ -1164,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;
|
||||
@@ -1174,6 +1293,16 @@ 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);
|
||||
break;
|
||||
case 0xF6: /* GRP3 Eb(,Ib) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
@@ -1263,13 +1392,13 @@ x64emurun:
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
div32(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
//emu->regs[_AX].dword[1] = 0; // already put high regs to 0
|
||||
//emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
case 7: /* IDIV Ed */
|
||||
idiv32(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
//emu->regs[_AX].dword[1] = 0;
|
||||
//emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1283,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);
|
||||
@@ -1340,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...
|
||||
}
|
||||
@@ -1359,16 +1494,15 @@ 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];
|
||||
STEP
|
||||
goto fini; // exit loop to recompute CS...
|
||||
}
|
||||
break;
|
||||
|
||||
+91
-37
@@ -48,18 +48,46 @@ 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);
|
||||
break;
|
||||
|
||||
case 0x0D:
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 1: //PREFETCHW
|
||||
__builtin_prefetch((void*)ED, 1, 0);
|
||||
break;
|
||||
default: //???
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10: /* MOVUPS Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
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;
|
||||
@@ -126,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;
|
||||
@@ -288,7 +324,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
GD->dword[0] = 0;
|
||||
GD->q[0] = 0;
|
||||
for(int i=0; i<4; ++i)
|
||||
GD->dword[0] |= ((EX->ud[i]>>31)&1)<<i;
|
||||
break;
|
||||
@@ -696,19 +732,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
@@ -726,8 +762,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
tmp8u = R_CL;
|
||||
if(rex.w)
|
||||
ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u);
|
||||
else
|
||||
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else
|
||||
ED->dword[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAB: /* BTS Ed,Gd */
|
||||
@@ -735,13 +775,14 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
@@ -749,7 +790,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
@@ -768,8 +808,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
tmp8u = (opcode==0xAC)?(F8):R_CL;
|
||||
if(rex.w)
|
||||
ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u);
|
||||
else
|
||||
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
else
|
||||
ED->dword[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
|
||||
}
|
||||
break;
|
||||
case 0xAE: /* Grp Ed (SSE) */
|
||||
nextop = F8;
|
||||
@@ -818,7 +862,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
break;
|
||||
case 0xB0: /* CMPXCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
@@ -858,20 +902,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
@@ -902,8 +946,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -922,8 +964,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@@ -946,8 +986,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@@ -968,8 +1006,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CHECK_FLAGS(emu);
|
||||
GETED(1);
|
||||
tmp8u = F8;
|
||||
if(!MODREG)
|
||||
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -996,23 +1032,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
if(rex.w)
|
||||
ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6));
|
||||
else
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->q[0] ^= (1LL<<tmp8u);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
@@ -1143,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;
|
||||
@@ -1258,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);
|
||||
|
||||
+249
-34
@@ -22,20 +22,20 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run64(x64emu_t *emu, rex_t rex)
|
||||
int Run64(x64emu_t *emu, rex_t rex, int seg)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u; (void)tmp16u;
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
int rep;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
@@ -108,6 +108,32 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x10:
|
||||
switch(rep) {
|
||||
case 1: /* MOVSD Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->q[0] = EX->q[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
// EX is not a register
|
||||
GX->q[1] = 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* MOVSS Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->ud[0] = EX->ud[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
// EX is not a register (reg to reg only move 31:0)
|
||||
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 1: /* MOVSD Ex, Gx */
|
||||
@@ -155,6 +181,23 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAF: /* IMUL Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
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;
|
||||
}
|
||||
@@ -188,36 +231,23 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
|
||||
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
return Run6664(emu, rex);
|
||||
|
||||
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;
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(1, tlsdata);
|
||||
tmp8u = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
|
||||
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
|
||||
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
|
||||
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
|
||||
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
|
||||
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
|
||||
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
|
||||
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
@@ -314,8 +344,193 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0xD1: /* GRP2 Ed,1 */
|
||||
case 0xD3: /* GRP2 Ed,CL */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
tmp8u = (opcode==0xD1)?1:R_CL;
|
||||
if(rex.w) {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->q[0] = rol64(emu, ED->q[0], tmp8u); break;
|
||||
case 1: ED->q[0] = ror64(emu, ED->q[0], tmp8u); break;
|
||||
case 2: ED->q[0] = rcl64(emu, ED->q[0], tmp8u); break;
|
||||
case 3: ED->q[0] = rcr64(emu, ED->q[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: ED->q[0] = shl64(emu, ED->q[0], tmp8u); break;
|
||||
case 5: ED->q[0] = shr64(emu, ED->q[0], tmp8u); break;
|
||||
case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break;
|
||||
}
|
||||
} else {
|
||||
if(MODREG)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->q[0] = rol32(emu, ED->dword[0], tmp8u); break;
|
||||
case 1: ED->q[0] = ror32(emu, ED->dword[0], tmp8u); break;
|
||||
case 2: ED->q[0] = rcl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 3: ED->q[0] = rcr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: ED->q[0] = shl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 5: ED->q[0] = shr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 7: ED->q[0] = sar32(emu, ED->dword[0], tmp8u); break;
|
||||
}
|
||||
else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
|
||||
case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
|
||||
case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 4:
|
||||
case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
|
||||
case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
|
||||
case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 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;
|
||||
}
|
||||
}
|
||||
+47
-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 */
|
||||
@@ -246,6 +273,20 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Od */
|
||||
if(rex.w)
|
||||
R_RAX = *(uint64_t*)F64;
|
||||
else
|
||||
R_AX = *(uint16_t*)F64;
|
||||
break;
|
||||
|
||||
case 0xA3: /* MOV Od,EAX */
|
||||
if(rex.w)
|
||||
*(uint64_t*)F64 = R_RAX;
|
||||
else
|
||||
*(uint16_t*)F64 = R_AX;
|
||||
break;
|
||||
|
||||
case 0xA5: /* (REP) MOVSW */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
@@ -557,6 +598,9 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
R_RIP += tmp32s;
|
||||
break;
|
||||
|
||||
case 0xF0: /* LOCK: */
|
||||
return Run66F0(emu, rex);
|
||||
|
||||
case 0xF7: /* GRP3 Ew(,Iw) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
|
||||
+575
-17
@@ -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);
|
||||
@@ -256,16 +342,263 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = ((((int32_t)(GX->sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
|
||||
GX->uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 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);
|
||||
GETGX;
|
||||
for(int i=7; i>=0; --i)
|
||||
GX->sw[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x21: /* PMOVSXBD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=3; i>=0; --i)
|
||||
GX->sd[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x22: /* PMOVSXBQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sb[i];
|
||||
break;
|
||||
case 0x23: /* PMOVSXWD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=3; i>=0; --i)
|
||||
GX->sd[i] = EX->sw[i];
|
||||
break;
|
||||
case 0x24: /* PMOVSXWQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sw[i];
|
||||
break;
|
||||
case 0x25: /* PMOVSXDQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=1; i>=0; --i)
|
||||
GX->sq[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
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);
|
||||
GETGX;
|
||||
tmp8u = F8; // ignoring bit 3 interupt thingy
|
||||
if(tmp8u&4)
|
||||
tmp8u = (emu->mxcsr>>13)&3;
|
||||
else
|
||||
tmp8u &= 3;
|
||||
switch(tmp8u) {
|
||||
case ROUND_Nearest:
|
||||
GX->d[0] = floor(EX->d[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->d[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->d[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->d[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 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);
|
||||
@@ -282,6 +615,75 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x17: // EXTRACTPS ED, GX, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
ED->dword[0] = GX->ud[tmp8u&3];
|
||||
if(MODREG && rex.w) ED->dword[1] = 0;
|
||||
break;
|
||||
|
||||
case 0x20: // PINSRB GX, ED, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->ub[tmp8u&0xf] = ED->byte[0];
|
||||
break;
|
||||
case 0x21: // INSERTPS GX, EX, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
|
||||
GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<i))
|
||||
GX->ud[i] = 0;
|
||||
break;
|
||||
case 0x22: // PINSRD GX, ED, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->ud[tmp8u&0x3] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x40: /* DPPS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
tmpf = 0.0f;
|
||||
for(int i=0; i<4; ++i)
|
||||
if(tmp8u&(1<<(i+4)))
|
||||
tmpf += GX->f[i]*EX->f[i];
|
||||
for(int i=0; i<4; ++i)
|
||||
GX->f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
|
||||
break;
|
||||
|
||||
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp32u = F8;
|
||||
for (int i = 4; i < 8; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
for (int i = 12; i < 16; ++i)
|
||||
GX->ub[i] = subbytes[EX->ub[i]];
|
||||
GX->ud[0] = GX->ud[1];
|
||||
tmp8u = GX->ub[4];
|
||||
GX->ud[1] = GX->ud[1] >> 8;
|
||||
GX->ub[7] = tmp8u;
|
||||
GX->ud[1] ^= tmp32u;
|
||||
GX->ud[2] = GX->ud[3];
|
||||
tmp8u = GX->ub[12];
|
||||
GX->ud[3] = GX->ud[3] >> 8;
|
||||
GX->ub[15] = tmp8u;
|
||||
GX->ud[3] ^= tmp32u;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -756,13 +1158,20 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
@@ -788,18 +1197,25 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
EW->q[0] |= (1LL<<(GW->q[0]&63));
|
||||
EW->q[0] |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
EW->word[0] |= (1<<(GW->word[0]&15));
|
||||
EW->word[0] |= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
}
|
||||
@@ -855,31 +1271,157 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<(GW->q[0]&63))) {
|
||||
if(EW->q[0] & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->q[0] ^= (1LL<<(GW->q[0]&63));
|
||||
EW->q[0] ^= (1LL<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15))) {
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW->word[0]&15));
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gw,Eb */
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
GETGW;
|
||||
GW->word[0] = EB->byte[0];
|
||||
break;
|
||||
case 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;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
if(EW->word[0] & (1<<(GW->word[0]&15)))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<(GW->word[0]&15));
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->q[0] ^= (1LL<<tmp8u);
|
||||
} else {
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
}
|
||||
break;
|
||||
case 0xBC: /* BSF Ew,Gw */
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -1005,6 +1547,22 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[1] = eax1.q[1];
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* BSWAP reg16 */
|
||||
tmp8u = (opcode&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
emu->regs[tmp8u].q[0] = __builtin_bswap64(emu->regs[tmp8u].q[0]);
|
||||
} else {
|
||||
emu->regs[tmp8u].word[0] = __builtin_bswap16(emu->regs[tmp8u].word[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD1: /* PSRLW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
|
||||
@@ -27,6 +27,7 @@ int Run6664(x64emu_t *emu, rex_t rex)
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
|
||||
opcode = F8;
|
||||
@@ -39,6 +40,33 @@ int Run6664(x64emu_t *emu, rex_t rex)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0xD6: /* MOVQ Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
if(MODREG)
|
||||
EX->q[1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV Ew,Gw */
|
||||
nextop = F8;
|
||||
GETEW_OFFS(0, tlsdata);
|
||||
GETGW;
|
||||
if(rex.w)
|
||||
EW->q[0] = GW->q[0];
|
||||
else
|
||||
EW->word[0] = GW->word[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
nextop = F8;
|
||||
GETEW_OFFS(0, tlsdata);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64run.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64run_private.h"
|
||||
#include "x64primop.h"
|
||||
#include "x64trace.h"
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "bridge.h"
|
||||
#include "dynarec/arm64_lock.h"
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run66F0(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int32_t tmp32s;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped, *opgd;
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
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 */
|
||||
nextop = F8;
|
||||
GETED((opcode==0x83)?1:2);
|
||||
tmp64s = (opcode==0x83)?(F8S):(F16S);
|
||||
tmp64u = (uint64_t)tmp64s;
|
||||
#ifdef DYNAREC
|
||||
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);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
|
||||
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
|
||||
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
|
||||
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
|
||||
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
|
||||
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
|
||||
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
|
||||
case 7: cmp16(emu, ED->word[0], tmp64u); break;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+12
-5
@@ -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;
|
||||
|
||||
@@ -52,13 +53,13 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
|
||||
@@ -71,13 +72,13 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
|
||||
@@ -167,7 +168,7 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
GD->q[0] = (uint32_t)(uintptr_t)ED;
|
||||
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
|
||||
break;
|
||||
|
||||
case 0xC1: /* GRP2 Ed,Ib */
|
||||
@@ -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;
|
||||
|
||||
+13
-9
@@ -27,16 +27,17 @@
|
||||
|
||||
int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
{
|
||||
(void)rep;
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
int32_t tmp32s, tmp32s2; (void)tmp32s; (void)tmp32s2;
|
||||
uint32_t tmp32u, tmp32u2; (void)tmp32u; (void)tmp32u2;
|
||||
uint64_t tmp64u, tmp64u2; (void)tmp64u; (void)tmp64u2;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
sse_regs_t *opex, *opgx, eax1; (void)eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1; (void)opem; (void)opgm; (void)eam1;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -45,6 +46,9 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
case 0x2E: /* UCOMISS Gx, Ex */
|
||||
// same for now
|
||||
case 0x2F: /* COMISS Gx, Ex */
|
||||
if(rep) {
|
||||
return 1;
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
@@ -65,4 +69,4 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+14
-12
@@ -27,16 +27,18 @@
|
||||
|
||||
int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
{
|
||||
// Hmmmm....
|
||||
(void)rep;
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u, tmp8u2;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u, tmp16u2;
|
||||
int32_t tmp32s;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3;
|
||||
reg64_t *oped, *opgd;
|
||||
uint8_t nextop; (void)nextop;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
uint8_t tmp8u, tmp8u2; (void)tmp8u; (void)tmp8u2;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u, tmp16u2; (void)tmp16u; (void)tmp16u2;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
int64_t tmp64s; (void)tmp64s;
|
||||
uint64_t tmp64u, tmp64u2, tmp64u3; (void)tmp64u; (void)tmp64u2; (void)tmp64u3;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -47,7 +49,7 @@ int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
// REX prefix before the F0 are ignored
|
||||
// REX prefix before the 66 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
@@ -56,11 +58,11 @@ int Run6766(x64emu_t *emu, rex_t rex, int rep)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F: /* more opcdes */
|
||||
case 0x0F: /* more opcodes */
|
||||
return Run67660F(emu, rex);
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -26,22 +26,22 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
int16_t tmp16s;
|
||||
uint16_t tmp16u;
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1, *opex2;
|
||||
mmx87_regs_t *opem, *opgm;
|
||||
int8_t tmp8s; (void)tmp8s;
|
||||
uint8_t tmp8u; (void)tmp8u;
|
||||
int16_t tmp16s; (void)tmp16s;
|
||||
uint16_t tmp16u; (void)tmp16u;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
uint32_t tmp32u; (void)tmp32u;
|
||||
int64_t tmp64s; (void)tmp64s;
|
||||
uint64_t tmp64u; (void)tmp64u;
|
||||
reg64_t *oped, *opgd; (void)oped; (void)opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x6F: /* MOVDQA Gx,Ex */
|
||||
case 0x6F: /* MOVDQA Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
@@ -49,7 +49,7 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[1] = EX->q[1];
|
||||
break;
|
||||
|
||||
case 0x76: /* PCMPEQD Gx,Ex */
|
||||
case 0x76: /* PCMPEQD Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
@@ -61,4 +61,4 @@ int Run67660F(x64emu_t *emu, rex_t rex)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
|
||||
{
|
||||
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
|
||||
|
||||
// let's cheat and set all args...
|
||||
if(init) {
|
||||
PushExit(emu);
|
||||
@@ -53,9 +55,11 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
|
||||
|
||||
DynaRun(emu);
|
||||
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 1; // finished!
|
||||
if(!emu->quit) {
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 1; // finished!
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -944,7 +948,7 @@ uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
|
||||
const char* getAddrFunctionName(uintptr_t addr)
|
||||
{
|
||||
static char ret[1000];
|
||||
uint32_t sz = 0;
|
||||
uint64_t sz = 0;
|
||||
uintptr_t start = 0;
|
||||
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
|
||||
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
|
||||
@@ -959,7 +963,7 @@ const char* getAddrFunctionName(uintptr_t addr)
|
||||
|
||||
void printFunctionAddr(uintptr_t nextaddr, const char* text)
|
||||
{
|
||||
uint32_t sz = 0;
|
||||
uint64_t sz = 0;
|
||||
uintptr_t start = 0;
|
||||
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
|
||||
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
|
||||
@@ -991,12 +995,18 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
my_context->trace_dynarec = dynarec;
|
||||
}
|
||||
#else
|
||||
(void)dynarec;
|
||||
if(my_context->trace_tid != tid) {
|
||||
printf_log(LOG_NONE, "Thread %04d|\n", tid);
|
||||
my_context->trace_tid = tid;
|
||||
}
|
||||
#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) {
|
||||
@@ -1178,6 +1188,8 @@ reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t
|
||||
|
||||
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
@@ -1205,6 +1217,8 @@ reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint32_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->regs[(m&0x07)];
|
||||
@@ -1234,7 +1248,7 @@ mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->mmx87[m&0x07];
|
||||
return &emu->mmx[m&0x07];
|
||||
} else return (mmx87_regs_t*)GetECommon(emu, rex, m, delta);
|
||||
}
|
||||
|
||||
@@ -1279,8 +1293,10 @@ reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
(void)rex;
|
||||
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
return &emu->mmx87[m&7];
|
||||
return &emu->mmx[m&7];
|
||||
}
|
||||
|
||||
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
|
||||
@@ -102,12 +102,13 @@ void UpdateFlags(x64emu_t *emu);
|
||||
#define RESET_FLAGS(emu) emu->df = d_none
|
||||
|
||||
int Run0F(x64emu_t *emu, rex_t rex);
|
||||
int Run64(x64emu_t *emu, rex_t rex);
|
||||
int Run64(x64emu_t *emu, rex_t rex, int seg);
|
||||
int Run66(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run660F(x64emu_t *emu, rex_t rex);
|
||||
int Run6664(x64emu_t *emu, rex_t rex);
|
||||
int Run66D9(x64emu_t *emu, rex_t rex);
|
||||
int Run66DD(x64emu_t *emu, rex_t rex);
|
||||
int Run66F0(x64emu_t *emu, rex_t rex);
|
||||
int Run67(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run670F(x64emu_t *emu, rex_t rex, int rep);
|
||||
int Run6766(x64emu_t *emu, rex_t rex, int rep);
|
||||
@@ -123,12 +124,6 @@ int RunDF(x64emu_t *emu, rex_t rex);
|
||||
int RunF0(x64emu_t *emu, rex_t rex);
|
||||
int RunF20F(x64emu_t *emu, rex_t rex);
|
||||
int RunF30F(x64emu_t *emu, rex_t rex);
|
||||
//void Run66D9(x64emu_t *emu); // x87
|
||||
//void Run6766(x64emu_t *emu);
|
||||
//void RunGS(x64emu_t *emu);
|
||||
//void RunFS(x64emu_t *emu);
|
||||
//void RunFS66(x64emu_t *emu, uintptr_t tlsdata);
|
||||
//void RunLock66(x64emu_t *emu);
|
||||
|
||||
void x64Syscall(x64emu_t *emu);
|
||||
void x64Int3(x64emu_t* emu);
|
||||
@@ -146,4 +141,4 @@ const char* GetNativeName(void* p);
|
||||
void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec);
|
||||
#endif
|
||||
|
||||
#endif //__X86RUN_PRIVATE_H_
|
||||
#endif //__X86RUN_PRIVATE_H_
|
||||
+5
-1
@@ -185,19 +185,23 @@ 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);
|
||||
break;
|
||||
case 0xFD: /* FSCALE */
|
||||
// this could probably be done by just altering the exponant part of the float...
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
if(ST0.d!=0.0)
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
ST0.d = sin(ST0.d);
|
||||
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);
|
||||
|
||||
+5
-5
@@ -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).q)
|
||||
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;
|
||||
@@ -177,4 +177,4 @@ int RunDF(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+285
-26
@@ -30,8 +30,8 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
uint8_t tmp8u;
|
||||
int32_t tmp32s;
|
||||
uint8_t tmp8u, tmp8u2; (void)tmp8u2;
|
||||
int32_t tmp32s; (void)tmp32s;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
@@ -197,7 +197,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
} else {
|
||||
tmp64u |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp64u);
|
||||
tmp32s = arm64_lock_write_dd(ED, tmp64u);
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
@@ -281,27 +281,46 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
if(((uintptr_t)ED)&7) {
|
||||
do {
|
||||
tmp64u = ED->q[0] & ~0xffLL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_b(ED, GD->q[0]&0xff);
|
||||
if(!tmp32s)
|
||||
ED->q[0] = GD->q[0];
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
cmp64(emu, R_RAX, tmp64u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
|
||||
} else {
|
||||
R_RAX = tmp64u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
cmp32(emu, R_EAX, tmp32u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_d(ED, GD->dword[0]);
|
||||
} else {
|
||||
R_RAX = tmp32u;
|
||||
R_EAX = tmp32u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
@@ -318,6 +337,9 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
} else {
|
||||
R_EAX = ED->dword[0];
|
||||
}
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
@@ -347,7 +369,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
@@ -359,6 +381,9 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
@@ -380,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);
|
||||
@@ -388,7 +594,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
if(rex.w) {
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
tmp64u2 = add64(emu, tmp64u, GD->dword[0]);
|
||||
tmp64u2 = add64(emu, tmp64u, GD->q[0]);
|
||||
} while(arm64_lock_write_dd(ED, tmp64u2));
|
||||
GD->q[0] = tmp64u;
|
||||
} else {
|
||||
@@ -482,8 +688,8 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
ED->dword[1] = R_ECX;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
R_RAX = tmp32u;
|
||||
R_RDX = tmp32u2;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
@@ -495,6 +701,39 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
return Run66F0(emu, rex); // more opcode F0 66 and 66 F0 is the same
|
||||
|
||||
case 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;
|
||||
@@ -631,9 +870,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, inc64(emu, tmp64u)));
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
do {
|
||||
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
tmp64u = inc64(emu, tmp64u);
|
||||
} while(arm64_lock_write_b(ED, tmp64u&0xff));
|
||||
ED->q[0] = tmp64u;
|
||||
}
|
||||
else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, inc64(emu, tmp64u)));
|
||||
else {
|
||||
if((uintptr_t)ED&3) {
|
||||
//meh.
|
||||
@@ -667,9 +916,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, dec64(emu, tmp64u)));
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned
|
||||
do {
|
||||
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
|
||||
tmp64u |= arm64_lock_read_b(ED);
|
||||
tmp64u = dec64(emu, tmp64u);
|
||||
} while(arm64_lock_write_b(ED, tmp64u&0xff));
|
||||
ED->q[0] = tmp64u;
|
||||
}
|
||||
else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
} while(arm64_lock_write_dd(ED, dec64(emu, tmp64u)));
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
@@ -700,4 +959,4 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -116,6 +116,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
GD->sdword[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -211,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;
|
||||
@@ -228,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);
|
||||
|
||||
+37
-1
@@ -43,7 +43,7 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->ud[0] = EX->ud[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
if(!MODREG) {
|
||||
// EX is not a register (reg to reg only move 31:0)
|
||||
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
+269
-27
@@ -36,10 +36,16 @@
|
||||
typedef struct x64_sigaction_s x64_sigaction_t;
|
||||
typedef struct x64_stack_s x64_stack_t;
|
||||
|
||||
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);
|
||||
@@ -47,6 +53,7 @@ int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss);
|
||||
void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
|
||||
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
|
||||
int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
|
||||
void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
@@ -57,7 +64,7 @@ int fcntl(int fd, int cmd, ... /* arg */ );
|
||||
|
||||
// Syscall table for x86_64 can be found
|
||||
typedef struct scwrap_s {
|
||||
int x64s;
|
||||
uint32_t x64s; // 32 bits?
|
||||
int nats;
|
||||
int nbpars;
|
||||
} scwrap_t;
|
||||
@@ -67,30 +74,104 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 1, __NR_write, 3 }, // same
|
||||
//{ 2, __NR_open, 3 }, // flags need transformation
|
||||
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//{ 4, __NR_stat, 2 }, // Need to align struct stat
|
||||
//{ 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},
|
||||
//{ 13, __NR_rt_sigaction, 4} // wrapped to use my_ version
|
||||
{ 12, __NR_brk, 1},
|
||||
//{ 13, __NR_rt_sigaction, 4}, // wrapped to use my_ version
|
||||
{ 14, __NR_rt_sigprocmask, 4},
|
||||
{ 16, __NR_ioctl, 3},
|
||||
{ 20, __NR_writev, 3},
|
||||
#ifdef __NR_access
|
||||
{ 21, __NR_access, 2},
|
||||
#endif
|
||||
#ifdef __NR_pipe
|
||||
{ 22, __NR_pipe, 1},
|
||||
#endif
|
||||
#ifdef __NR_select
|
||||
{ 23, __NR_select, 5},
|
||||
#endif
|
||||
//{ 25, __NR_mremap, 5}, // wrapped to track protection
|
||||
{ 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
|
||||
#ifdef __NR_unlink
|
||||
{ 87, __NR_unlink, 1},
|
||||
#endif
|
||||
//{ 89, __NR_readlink, 3}, // not always existing, better use the wrapped version anyway
|
||||
{ 96, __NR_gettimeofday, 2},
|
||||
{ 97, __NR_getrlimit, 2},
|
||||
{ 101, __NR_ptrace, 4},
|
||||
{ 125, __NR_capget, 2},
|
||||
{ 126, __NR_capset, 2},
|
||||
{ 127, __NR_rt_sigpending, 2},
|
||||
//{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack
|
||||
{ 157, __NR_prctl, 5 }, // needs wrapping?
|
||||
//{ 158, __NR_arch_prctl, 2}, //need wrapping
|
||||
{ 186, __NR_gettid, 0 }, //0xBA
|
||||
{ 200, __NR_tkill, 2 },
|
||||
#ifdef __NR_time
|
||||
{ 201, __NR_time, 1},
|
||||
#endif
|
||||
{ 202, __NR_futex, 6},
|
||||
{ 203, __NR_sched_setaffinity, 3},
|
||||
{ 204, __NR_sched_getaffinity, 3},
|
||||
{ 217, __NR_getdents64, 3},
|
||||
{ 220, __NR_semtimedop, 4},
|
||||
{ 228, __NR_clock_gettime, 2},
|
||||
{ 229, __NR_clock_getres, 2},
|
||||
{ 230, __NR_clock_nanosleep, 4},
|
||||
{ 234, __NR_tgkill, 3},
|
||||
#ifdef __NR_inotify_init
|
||||
{ 253, __NR_inotify_init, 0}, //0xFD
|
||||
#endif
|
||||
{ 254, __NR_inotify_add_watch, 3},
|
||||
{ 255, __NR_inotify_rm_watch, 2},
|
||||
{ 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 {
|
||||
@@ -102,6 +183,45 @@ struct mmap_arg_struct {
|
||||
unsigned long offset;
|
||||
};
|
||||
|
||||
#ifndef __NR_getdents
|
||||
typedef struct x86_linux_dirent_s {
|
||||
unsigned long d_ino;
|
||||
unsigned long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[];
|
||||
} x86_linux_dirent_t;
|
||||
|
||||
typedef struct nat_linux_dirent64_s {
|
||||
ino64_t d_ino;
|
||||
off64_t d_off;
|
||||
unsigned short d_reclen;
|
||||
unsigned char d_type;
|
||||
char d_name[];
|
||||
} nat_linux_dirent64_t;
|
||||
|
||||
ssize_t DirentFromDirent64(void* dest, void* source, ssize_t count)
|
||||
{
|
||||
nat_linux_dirent64_t *src = (nat_linux_dirent64_t*)source;
|
||||
x86_linux_dirent_t *dst = (x86_linux_dirent_t*)dest;
|
||||
ssize_t ret = count;
|
||||
while(count>0) {
|
||||
dst->d_ino = src->d_ino;
|
||||
dst->d_reclen = src->d_reclen+1;
|
||||
strcpy(dst->d_name, src->d_name);
|
||||
dst->d_off = src->d_off?(src->d_off+1):0;
|
||||
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -2) = 0;
|
||||
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -1) = src->d_type;
|
||||
|
||||
count -= src->d_reclen;
|
||||
ret += 1;
|
||||
src = (nat_linux_dirent64_t*)(((uintptr_t)src) + src->d_reclen);
|
||||
dst = (x86_linux_dirent_t*)(((uintptr_t)dst) + dst->d_reclen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//struct x86_pt_regs {
|
||||
// long ebx;
|
||||
// long ecx;
|
||||
@@ -135,7 +255,7 @@ struct mmap_arg_struct {
|
||||
void EXPORT x64Syscall(x64emu_t *emu)
|
||||
{
|
||||
RESET_FLAGS(emu);
|
||||
uint32_t s = R_EAX;
|
||||
uint32_t s = R_EAX; // EAX? (syscalls only go up to 547 anyways)
|
||||
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p %p", (void*)R_RIP, s, s, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8, (void*)R_R9);
|
||||
// check wrapper first
|
||||
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
|
||||
@@ -145,7 +265,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
switch(syscallwrap[i].nbpars) {
|
||||
case 0: *(int64_t*)&R_RAX = syscall(sc); break;
|
||||
case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
|
||||
case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
|
||||
case 2: if(s==33) {printf_dump(LOG_DEBUG, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
|
||||
case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
|
||||
case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
|
||||
case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
|
||||
@@ -161,34 +281,64 @@ 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
|
||||
*(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
|
||||
*(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
|
||||
case 23: // sys_select
|
||||
R_EAX = (uint32_t)select(R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8);
|
||||
break;
|
||||
#endif
|
||||
case 25: // sys_mremap
|
||||
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
|
||||
break;
|
||||
#ifndef __NR_vfork
|
||||
case 56: // vfork
|
||||
{
|
||||
int64_t r = vfork();
|
||||
R_RAX = r;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
@@ -196,21 +346,63 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
R_RAX = fork();
|
||||
break;
|
||||
#endif
|
||||
case 131: // sys_sigaltstack
|
||||
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
size_t count = R_RDX;
|
||||
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
|
||||
ssize_t ret = syscall(__NR_getdents64, R_EDI, d64, count);
|
||||
ret = DirentFromDirent64((void*)R_RSI, d64, ret);
|
||||
R_RAX = (uint64_t)ret;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_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
|
||||
*(int64_t*)&R_RAX = mkdir((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
*(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
|
||||
*(int64_t*)&R_RAX = my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
case 158: // sys_arch_prctl
|
||||
*(int64_t*)&R_RAX = my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 201: // sys_time
|
||||
R_RAX = (uintptr_t)time((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
R_EAX = (int)syscall(__NR_inotify_init1, 0);
|
||||
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)
|
||||
@@ -222,8 +414,8 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
|
||||
uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
{
|
||||
uint32_t s = R_EDI;;
|
||||
printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
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);
|
||||
for (int i=0; i<cnt; i++) {
|
||||
@@ -246,35 +438,85 @@ 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 (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 (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 (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();
|
||||
#endif
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
size_t count = R_RCX;
|
||||
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
|
||||
ssize_t ret = syscall(__NR_getdents64, R_ESI, d64, count);
|
||||
ret = DirentFromDirent64((void*)R_RDX, d64, ret);
|
||||
return (uint64_t)ret;
|
||||
}
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
return (uint64_t)(int64_t)mkdir((void*)R_RSI, R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
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 (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);
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
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;
|
||||
|
||||
+59
-8
@@ -8,6 +8,7 @@
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
#include "x64emu.h"
|
||||
#include "x64emu_private.h"
|
||||
#include "x64tls.h"
|
||||
#include "elfloader.h"
|
||||
|
||||
@@ -27,6 +28,7 @@ typedef struct thread_area_s
|
||||
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once3 = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void thread_key_alloc0() {
|
||||
pthread_key_create(&my_context->segtls[0].key, NULL);
|
||||
@@ -37,6 +39,9 @@ static void thread_key_alloc1() {
|
||||
static void thread_key_alloc2() {
|
||||
pthread_key_create(&my_context->segtls[2].key, NULL);
|
||||
}
|
||||
static void thread_key_alloc3() {
|
||||
pthread_key_create(&my_context->segtls[3].key, NULL);
|
||||
}
|
||||
|
||||
uint32_t my_set_thread_area(thread_area_t* td)
|
||||
{
|
||||
@@ -123,12 +128,57 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
|
||||
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
|
||||
*/
|
||||
|
||||
ResetSegmentsCache(thread_get_emu());
|
||||
ResetSegmentsCache(emu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define POS_TLS 0x50
|
||||
int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
{
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_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:
|
||||
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;
|
||||
}
|
||||
// other are unsupported
|
||||
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define POS_TLS 0x200
|
||||
/*
|
||||
tls record should looks like:
|
||||
void* tcb 0x00
|
||||
void* dtv 0x08
|
||||
void* self 0x10
|
||||
int multiple 0x18
|
||||
int gscope 0x1c
|
||||
void* sysinfo 0x20
|
||||
uintptr_t stack_guard 0x28
|
||||
uitnptr_t pointer_guard 0x30
|
||||
uint64_t vgetcpu[2] 0x38
|
||||
uint32_t features 0x48
|
||||
int unused 0x4c
|
||||
void* private[4] 0x50
|
||||
void* private_ss 0x70
|
||||
uintptr_t ssp_base 0x78
|
||||
.... padding .... 0x200?
|
||||
*/
|
||||
|
||||
static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
{
|
||||
@@ -142,20 +192,21 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
pthread_setspecific(context->tlskey, data);
|
||||
// copy canary...
|
||||
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, sizeof(void*)); // put canary in place
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x28), context->canary, sizeof(void*)); // put canary in place
|
||||
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, sizeof(void*));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &tlsptr, sizeof(void*)); // set tcb and self same address
|
||||
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
|
||||
memcpy((void*)(tlsptr+sizeof(void*)), &dtp, sizeof(void*));
|
||||
if(dtsize) {
|
||||
for (size_t i=0; i<context->elfsize; ++i) {
|
||||
for (int i=0; i<context->elfsize; ++i) {
|
||||
// set pointer
|
||||
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16), &dtp, sizeof(void*));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8), &i, sizeof(void*)); // index
|
||||
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16) = dtp;
|
||||
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8) = i; // index
|
||||
}
|
||||
}
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, sizeof(void*)); // address of vsyscall
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x20), &context->vsyscall, sizeof(void*)); // address of vsyscall
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -203,7 +254,7 @@ void* GetSegmentBase(uint32_t desc)
|
||||
if(base==0x6)
|
||||
return GetSeg33Base();
|
||||
|
||||
if(base>6 && base<10 && my_context->segtls[base-7].present) {
|
||||
if(base>6 && base<11 && my_context->segtls[base-7].present) {
|
||||
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,19 @@
|
||||
#include "x87emu_private.h"
|
||||
//#include "x64run_private.h"
|
||||
|
||||
void fpu_do_free(x64emu_t* emu, int i)
|
||||
{
|
||||
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
|
||||
// check if all empty
|
||||
for(int j=0; j<8; ++j)
|
||||
if(emu->p_regs[j].tag != 0b11)
|
||||
return;
|
||||
emu->fpu_stack = 0;
|
||||
}
|
||||
|
||||
void reset_fpu(x64emu_t* emu)
|
||||
{
|
||||
memset(emu->mmx87, 0, sizeof(emu->mmx87));
|
||||
memset(emu->x87, 0, sizeof(emu->x87));
|
||||
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
|
||||
emu->cw = 0x37F;
|
||||
emu->sw.x16 = 0x0000;
|
||||
@@ -167,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;
|
||||
@@ -196,6 +206,21 @@ double FromLD(void* ld)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef HAVE_LD80BITS
|
||||
long double LD2localLD(void* ld)
|
||||
{
|
||||
// local implementation may not be try Quad precision, but double-double precision, so simple way to keep the 80bits precision in the conversion
|
||||
double ret;
|
||||
LD2D(ld, &ret);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
long double LD2localLD(void* ld)
|
||||
{
|
||||
return *(long double*)ld;
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_loadenv(x64emu_t* emu, char* p, int b16)
|
||||
{
|
||||
emu->cw = *(uint16_t*)p;
|
||||
@@ -269,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;
|
||||
@@ -285,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));
|
||||
}
|
||||
@@ -294,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;
|
||||
@@ -308,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));
|
||||
}
|
||||
@@ -322,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));
|
||||
}
|
||||
@@ -338,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,13 +14,9 @@ typedef struct x64emu_s x64emu_t;
|
||||
#define LN2 0.69314718055994531
|
||||
#define LG2 0.3010299956639812
|
||||
|
||||
//void Run66D9(x64emu_t *emu);
|
||||
//void Run66DD(x64emu_t *emu);
|
||||
//void RunDF(x64emu_t *emu);
|
||||
|
||||
#define ST0 emu->mmx87[emu->top]
|
||||
#define ST1 emu->mmx87[(emu->top+1)&7]
|
||||
#define ST(a) emu->mmx87[(emu->top+(a))&7]
|
||||
#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]
|
||||
@@ -54,15 +50,7 @@ static inline void fpu_do_pop(x64emu_t* emu)
|
||||
emu->top = (emu->top+1)&7;
|
||||
}
|
||||
|
||||
static inline void fpu_do_free(x64emu_t* emu, int i)
|
||||
{
|
||||
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
|
||||
// check if all empty
|
||||
for(int i=0; i<8; ++i)
|
||||
if(emu->p_regs[i].tag != 0b11)
|
||||
return;
|
||||
emu->fpu_stack = 0;
|
||||
}
|
||||
void fpu_do_free(x64emu_t* emu, int i);
|
||||
|
||||
void reset_fpu(x64emu_t* emu);
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ int init_auxval(int argc, const char **argv, const char **env);
|
||||
#endif
|
||||
|
||||
unsigned long real_getauxval(unsigned long type);
|
||||
//unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
|
||||
unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
|
||||
|
||||
#endif //__AUXVAL_H__
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include "pathcoll.h"
|
||||
#include "dictionnary.h"
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -81,9 +82,10 @@ typedef struct box64context_s {
|
||||
|
||||
char* fullpath;
|
||||
char* box64path; // path of current box64 executable
|
||||
char* box86path; // path of box86 executable (if present)
|
||||
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
uint64_t stacksz;
|
||||
size_t stackalign;
|
||||
void* stack; // alocated stack
|
||||
|
||||
elfheader_t **elfs; // elf headers and memory
|
||||
@@ -97,10 +99,12 @@ typedef struct box64context_s {
|
||||
|
||||
lib_t *maplib; // lib and symbols handling
|
||||
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
|
||||
dic_t *versym; // dictionnary of versionned symbols
|
||||
|
||||
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
|
||||
bridge_t *system; // other bridges
|
||||
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
|
||||
@@ -119,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)
|
||||
@@ -144,6 +149,7 @@ typedef struct box64context_s {
|
||||
library_t *asound;
|
||||
library_t *pulse;
|
||||
library_t *d3dadapter9;
|
||||
library_t *libglu;
|
||||
|
||||
int deferedInit;
|
||||
elfheader_t **deferedInitList;
|
||||
@@ -152,8 +158,8 @@ typedef struct box64context_s {
|
||||
|
||||
pthread_key_t tlskey; // then tls key to have actual tlsdata
|
||||
void* tlsdata; // the initial global tlsdata
|
||||
int32_t tlssize; // wanted size of tlsdata
|
||||
base_segment_t segtls[3]; // only handling 0/1/2 descriptors
|
||||
int64_t tlssize; // wanted size of tlsdata
|
||||
base_segment_t segtls[4]; // only handling 0/1/2 descriptors (3 is internal use)
|
||||
|
||||
uintptr_t *auxval_start;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+14
-11
@@ -20,11 +20,11 @@ void customFree(void* p);
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size);
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy);
|
||||
|
||||
dynablocklist_t* getDB(uintptr_t idx);
|
||||
void addJumpTableIfDefault64(void* addr, void* jmp);
|
||||
@@ -38,19 +38,22 @@ uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
#define PROT_ALLOC 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, uintptr_t size);
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void protectDBnolock(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
void protectDBnolock(uintptr_t addr, size_t size);
|
||||
void unprotectDB(uintptr_t addr, size_t size);
|
||||
void lockDB();
|
||||
void unlockDB();
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
void* find47bitBlock(size_t size);
|
||||
void* find47bitBlockNearHint(void* hint, size_t size);
|
||||
|
||||
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
|
||||
int unlockCustommemMutex();
|
||||
@@ -60,4 +63,4 @@ void relockCustommemMutex(int locks);
|
||||
void init_custommem_helper(box64context_t* ctx);
|
||||
void fini_custommem_helper(box64context_t* ctx);
|
||||
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
+13
-2
@@ -4,6 +4,7 @@
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
extern int box64_log; // log level
|
||||
extern int box64_dump; // dump elf or not
|
||||
extern int box64_dynarec_log;
|
||||
extern int box64_dynarec;
|
||||
extern int box64_pagesize;
|
||||
@@ -11,8 +12,13 @@ extern int box64_pagesize;
|
||||
extern int box64_dynarec_dump;
|
||||
extern int box64_dynarec_trace;
|
||||
extern int box64_dynarec_forced;
|
||||
extern int box64_dynarec_largest;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
#ifdef ARM64
|
||||
extern int arm64_asimd;
|
||||
extern int arm64_aes;
|
||||
extern int arm64_pmull;
|
||||
extern int arm64_crc32;
|
||||
#endif
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -23,7 +29,9 @@ 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
|
||||
extern int box64_nogtk; // disabling the use of wrapped gtk
|
||||
extern int box64_novulkan; // disabling the use of wrapped vulkan
|
||||
@@ -34,12 +42,15 @@ extern int box64_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
#define LOG_NONE 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
#define LOG_DUMP 3
|
||||
#define LOG_NEVER 3
|
||||
#define LOG_VERBOSE 3
|
||||
|
||||
extern FILE* ftrace;
|
||||
|
||||
#define printf_log(L, ...) do {if(L<=box64_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define printf_dump(L, ...) do {if(box64_dump || (L<=box64_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if(L<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#ifndef __DICTIONNARY_H_
|
||||
#define __DICTIONNARY_H_
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void dic_t;
|
||||
|
||||
dic_t *NewDictionnary();
|
||||
void FreeDictionnary(dic_t **dic);
|
||||
|
||||
const char* AddDictionnary(dic_t* dic, const char* s);
|
||||
int ExistDictionnary(dic_t* dic, const char* s);
|
||||
|
||||
#endif //__DICTIONNARY_H_
|
||||
@@ -11,7 +11,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
|
||||
void FreeDynablockList(dynablocklist_t** dynablocks);
|
||||
void FreeDynablock(dynablock_t* db);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
//return 1 if Dynareblock is empty
|
||||
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef struct elfheader_s elfheader_t;
|
||||
const char* DumpSection(Elf64_Shdr *s, char* SST);
|
||||
const char* DumpDynamic(Elf64_Dyn *s);
|
||||
const char* DumpPHEntry(Elf64_Phdr *e);
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym);
|
||||
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version);
|
||||
const char* DumpRelType(int t);
|
||||
const char* SymName(elfheader_t *h, Elf64_Sym* sym);
|
||||
const char* IdxSymName(elfheader_t *h, int sym);
|
||||
|
||||
@@ -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);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
|
||||
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);
|
||||
@@ -41,7 +41,7 @@ void* GetElfDelta(elfheader_t* h);
|
||||
uint32_t GetBaseSize(elfheader_t* h);
|
||||
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
|
||||
elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
|
||||
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
|
||||
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint64_t* sz);
|
||||
int32_t GetTLSBase(elfheader_t* h);
|
||||
uint32_t GetTLSSize(elfheader_t* h);
|
||||
void* GetTLSPointer(box64context_t* context, elfheader_t* h);
|
||||
@@ -55,5 +55,9 @@ void CreateMemorymapFile(box64context_t* context, int fd);
|
||||
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version);
|
||||
const char* GetParentSymbolVersion(elfheader_t* h, int index);
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
|
||||
#endif //__ELF_LOADER_H_
|
||||
Loaded 100 of 604 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user