mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-09 04:09:46 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5c4deb42b | ||
|
|
069193e8b7 | ||
|
|
a424e996b3 | ||
|
|
3c81248335 | ||
|
|
1e3f277a71 | ||
|
|
3adeabb06d | ||
|
|
4593111871 | ||
|
|
7440be495e | ||
|
|
fded1a0718 | ||
|
|
ebbb2821d0 | ||
|
|
643b950eef | ||
|
|
63a20f537a | ||
|
|
ae94148bee | ||
|
|
9301eb9ee0 | ||
|
|
19448e242c | ||
|
|
f26c2f0812 | ||
|
|
6573476ea2 | ||
|
|
f73430a3f8 | ||
|
|
3bf90844b1 | ||
|
|
6546ae8e67 | ||
|
|
d01bdf9186 | ||
|
|
88b6cc1907 | ||
|
|
8922b63769 | ||
|
|
30d4713b28 | ||
|
|
498a52439c | ||
|
|
88798b78fc | ||
|
|
0ce7390ac1 | ||
|
|
00f5eb5338 | ||
|
|
d9967d7ea5 | ||
|
|
d42031293d | ||
|
|
76903904d0 | ||
|
|
a42f232b1e | ||
|
|
72a505a3e8 | ||
|
|
ae221ed5bd | ||
|
|
76115b30b8 | ||
|
|
7401d46bcd | ||
|
|
ee61d9c95a | ||
|
|
6db666c565 | ||
|
|
050acaa8c6 | ||
|
|
e83232fcf6 | ||
|
|
ece7ea36d9 | ||
|
|
73d27a625f | ||
|
|
a8d4f17add | ||
|
|
af6fb49e48 | ||
|
|
c593988bc1 | ||
|
|
2d590bb1f5 | ||
|
|
aef3677970 | ||
|
|
7d11254a52 | ||
|
|
3b9feeed12 | ||
|
|
6d3ca2df80 | ||
|
|
5d69ed5f4a | ||
|
|
81d13a8e0b | ||
|
|
544a2ac034 | ||
|
|
9a2bf37ac1 | ||
|
|
550d252386 | ||
|
|
2b3bdd7e60 | ||
|
|
4f38801ba6 | ||
|
|
31b41f5b94 | ||
|
|
03ce3c6592 | ||
|
|
2a4649f6ef | ||
|
|
96c3615ea5 | ||
|
|
adfcfafdc2 | ||
|
|
0a37f1cc30 | ||
|
|
70018a774b | ||
|
|
009bb94f17 | ||
|
|
0e0f1e2037 | ||
|
|
a0a0bc8270 | ||
|
|
25c532610b | ||
|
|
fcfd90b86f | ||
|
|
738d22a68a | ||
|
|
8c63b76343 | ||
|
|
ba7a04851f | ||
|
|
e3d15db6c5 | ||
|
|
ca46df09d8 | ||
|
|
f053e02868 | ||
|
|
42cbe1b397 | ||
|
|
42fe124a0e | ||
|
|
d809b59daa | ||
|
|
e14d4042d9 | ||
|
|
371b346bf7 | ||
|
|
b038dd5c9d | ||
|
|
2681a6db0d | ||
|
|
5ff1ea1435 | ||
|
|
759f165549 | ||
|
|
cb27ac8d93 | ||
|
|
035c77ad91 | ||
|
|
b45c249ed9 | ||
|
|
b90991f039 | ||
|
|
8d49ae5c68 | ||
|
|
49047cf972 | ||
|
|
aa5485ae27 | ||
|
|
fc0d9c5f92 | ||
|
|
8309c5feeb | ||
|
|
4693cac13b | ||
|
|
79f2b8448a | ||
|
|
7e09961ee7 | ||
|
|
21aded91f0 | ||
|
|
6b4bb5e7cb | ||
|
|
c1eef81fdb | ||
|
|
b1e6fa4f2b | ||
|
|
e672641878 | ||
|
|
fef0140098 | ||
|
|
4084eade0c | ||
|
|
748552d792 | ||
|
|
ff50b0c391 | ||
|
|
23e7d5c370 | ||
|
|
676b7523b3 | ||
|
|
880616397f | ||
|
|
ace8536987 | ||
|
|
3370ae4dcf | ||
|
|
8a6a1312f2 | ||
|
|
a9d633ab2d | ||
|
|
765a9d8325 | ||
|
|
67c6a661e5 | ||
|
|
b897d55873 | ||
|
|
7b099f9c64 | ||
|
|
c172fbd883 | ||
|
|
5fb581a51f | ||
|
|
f3a08a51ef | ||
|
|
a7b9590f6f | ||
|
|
998a114172 | ||
|
|
29f65bb6be | ||
|
|
cce9293413 | ||
|
|
b91a95ee49 | ||
|
|
0eb682a95b | ||
|
|
424312c2d8 | ||
|
|
969ee91506 | ||
|
|
f56ee97676 | ||
|
|
f667ec631d | ||
|
|
7bcf1cc0ae | ||
|
|
dba4ff3cff | ||
|
|
0ff030a44c | ||
|
|
7babbcf62b | ||
|
|
fd303c6e94 | ||
|
|
a8495b00f2 | ||
|
|
ae70f168a8 | ||
|
|
b239bec2c5 | ||
|
|
d0f05fed3b | ||
|
|
717c0e1299 | ||
|
|
8760064ddb | ||
|
|
ab0059eeee | ||
|
|
19a7d2139a | ||
|
|
5319117636 | ||
|
|
c5b32180d2 | ||
|
|
62baaf99b1 | ||
|
|
c03dd5951a | ||
|
|
555f4e132f | ||
|
|
c3209a2736 | ||
|
|
0b29d724db | ||
|
|
931a8063b4 | ||
|
|
c74406c89e | ||
|
|
c44b8b1936 | ||
|
|
b1671dd98d | ||
|
|
0baf0ff24a | ||
|
|
2929d7256b | ||
|
|
8d769dd3c2 | ||
|
|
e8d6f083a3 | ||
|
|
817c3d7058 | ||
|
|
e2a7dd0f17 | ||
|
|
f781537adb | ||
|
|
c2c65f46cb | ||
|
|
0f65adfaab | ||
|
|
efafe96b08 | ||
|
|
858957f6f7 | ||
|
|
128724d147 | ||
|
|
c6c6bfcf2c | ||
|
|
4f451ff653 | ||
|
|
7822f29140 | ||
|
|
98d434a0a9 | ||
|
|
61c1f7157c | ||
|
|
5ab4028257 | ||
|
|
717769f1cc | ||
|
|
7278bc9cde | ||
|
|
7bc67cd168 | ||
|
|
bc23a90ef7 | ||
|
|
2070b53967 | ||
|
|
37a8ac3b32 | ||
|
|
3b2e75055f | ||
|
|
9f5e12992a | ||
|
|
eede8e1e8d | ||
|
|
b40c4ebcd7 | ||
|
|
53e449a96f | ||
|
|
d35217d39d | ||
|
|
883463f2d5 | ||
|
|
9abfdb3431 | ||
|
|
e942a8433b | ||
|
|
0163746709 | ||
|
|
dfbdd81d41 | ||
|
|
b474a9061b | ||
|
|
eaeef7e9e9 | ||
|
|
30091b2af6 | ||
|
|
73b51adfb3 | ||
|
|
34a82f7bfc | ||
|
|
159bbcf4a4 | ||
|
|
398a8b12c2 | ||
|
|
d45558782f | ||
|
|
1c3f4c078f | ||
|
|
48588a2556 | ||
|
|
4ae5391637 | ||
|
|
28e11dec31 | ||
|
|
b343ab69a5 | ||
|
|
697dc5fa3f | ||
|
|
fa12161c47 | ||
|
|
9f0f1efafe | ||
|
|
aa4c56e466 | ||
|
|
09e1464bc8 | ||
|
|
b689c745a0 | ||
|
|
28c2c56271 | ||
|
|
2d666965cf | ||
|
|
444d5c7580 | ||
|
|
5d694fe2f2 | ||
|
|
ccd9692875 | ||
|
|
8c553cad5d | ||
|
|
a99a68b03a | ||
|
|
acb01382df | ||
|
|
23d63686e6 | ||
|
|
c0083beec0 | ||
|
|
1d680c2039 | ||
|
|
bb273b55e2 | ||
|
|
d119ae5ed4 | ||
|
|
d78dbbe4c7 | ||
|
|
663ac80fd0 | ||
|
|
2d34788607 | ||
|
|
cbf4e37bba | ||
|
|
74b70253b2 | ||
|
|
0343ee119c | ||
|
|
f9c9868349 | ||
|
|
1395090241 | ||
|
|
dc938e8a60 | ||
|
|
7dd4f1ab72 | ||
|
|
d53c9c1e87 | ||
|
|
424a08607c | ||
|
|
0d2a060e66 | ||
|
|
9748c55dd0 | ||
|
|
130d96b31e | ||
|
|
e6e420d9a3 | ||
|
|
bde4adcdef | ||
|
|
3746ae9cf3 | ||
|
|
0c4eed79da | ||
|
|
8bbd9abd27 | ||
|
|
dfa15ad9fc | ||
|
|
00ac1fdcd1 | ||
|
|
af7bfc7de7 | ||
|
|
e3759a5cd0 | ||
|
|
c5f4820b4e | ||
|
|
a3d9da2fd4 | ||
|
|
e592d2eb6d | ||
|
|
e57aaadb1d | ||
|
|
0d2492bfde | ||
|
|
1a3483e086 | ||
|
|
171c213b32 | ||
|
|
c4dcb316ca | ||
|
|
725f612eb5 | ||
|
|
3539ed5bfe | ||
|
|
a8bd94e34f | ||
|
|
0d59028eb2 | ||
|
|
7ae39b38a0 | ||
|
|
b69f9b9536 | ||
|
|
6dbc4d44a8 | ||
|
|
397eff9712 | ||
|
|
51c23856f3 | ||
|
|
6cb6605a63 | ||
|
|
6ad164d522 | ||
|
|
19915ad238 | ||
|
|
5e8fb55955 | ||
|
|
d535bf35a8 | ||
|
|
17d73a93f1 | ||
|
|
ac2f2516a2 | ||
|
|
8994f9580c | ||
|
|
6013325637 | ||
|
|
ba19837104 | ||
|
|
509a1bf56e | ||
|
|
5b07a475e1 | ||
|
|
bb97366338 | ||
|
|
a527fdcc28 | ||
|
|
5c3a4deed8 | ||
|
|
70b9bed510 | ||
|
|
37795375b6 | ||
|
|
903f9ddb41 | ||
|
|
4b6ade050f | ||
|
|
02cfa0be7f | ||
|
|
da7a7a4d0e | ||
|
|
84a1b6976f | ||
|
|
4d1641b321 | ||
|
|
ee561da549 | ||
|
|
ba1493857f | ||
|
|
fb7a0318a0 | ||
|
|
479ade9cb7 | ||
|
|
dfe62ceac8 | ||
|
|
a36c9bfe73 | ||
|
|
a7119cae76 | ||
|
|
c33368bfb4 | ||
|
|
886999bc5b | ||
|
|
1a750182d6 | ||
|
|
03a69053a6 | ||
|
|
5788d4af1e | ||
|
|
517fe28806 | ||
|
|
b272bdb198 | ||
|
|
910d22a532 | ||
|
|
2a85ea9c61 | ||
|
|
3ee5c792d1 | ||
|
|
8e377ca074 | ||
|
|
451cfa521b | ||
|
|
6d02f7f897 | ||
|
|
3e811f869e | ||
|
|
1f17a57528 | ||
|
|
8c2ea218a5 | ||
|
|
9f01b2ec0d | ||
|
|
86c5dfd664 | ||
|
|
c31aa8a78d | ||
|
|
648d99c9e6 | ||
|
|
cfe541e3ca | ||
|
|
b6faad0354 | ||
|
|
8aee3f4185 | ||
|
|
fe44725804 | ||
|
|
870e0872c0 | ||
|
|
2874e30991 | ||
|
|
d92b46426c | ||
|
|
1c34edb857 | ||
|
|
aba3bcc81a | ||
|
|
085529217e | ||
|
|
50d8016e86 | ||
|
|
4a033b8e76 | ||
|
|
4f5ad4b3ac | ||
|
|
104d51df8c | ||
|
|
5c9ab0a27d | ||
|
|
065d91cf9b | ||
|
|
acceb3155a | ||
|
|
4130e0847c | ||
|
|
37a451a38e | ||
|
|
dd26d06e1c | ||
|
|
235784b46f | ||
|
|
66af0f810c | ||
|
|
72b60a2ab3 | ||
|
|
40e6f46013 | ||
|
|
a701ff87ec | ||
|
|
6e78bc1726 | ||
|
|
3b4181c616 | ||
|
|
2bd3fa6aa7 | ||
|
|
4d0d971212 | ||
|
|
1e451e3353 | ||
|
|
207f829066 | ||
|
|
f1fba8eb42 | ||
|
|
146287331a | ||
|
|
490dcac380 | ||
|
|
e8264eb0db | ||
|
|
3c07dd58eb | ||
|
|
fcdd8fc383 | ||
|
|
0b56f5aebd | ||
|
|
178537116b | ||
|
|
11cfae2a98 | ||
|
|
348bd64449 | ||
|
|
b36eca9792 | ||
|
|
683b77c9bd | ||
|
|
7809f23d4b | ||
|
|
37a9549298 | ||
|
|
8fa2368a63 | ||
|
|
72ca99051b | ||
|
|
905e3ae583 | ||
|
|
29be84ba47 | ||
|
|
636c350461 | ||
|
|
89e305878b | ||
|
|
45873cc2b1 | ||
|
|
a32955ffec | ||
|
|
5b45f871df |
No files matched your search
+65
-8
@@ -1,11 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
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(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(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)
|
||||
if(RK3399 OR RPI4ARM64 OR RK3326)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
@@ -47,6 +49,13 @@ if(RPI4ARM64)
|
||||
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(-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)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
@@ -129,11 +138,16 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/emu/x64run66d9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run66dd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run670f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run6766.c"
|
||||
"${BOX64_ROOT}/src/emu/x64run67660f.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund8.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rund9.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runda.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundb.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundc.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundd.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runde.c"
|
||||
"${BOX64_ROOT}/src/emu/x64rundf.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf0.c"
|
||||
"${BOX64_ROOT}/src/emu/x64runf20f.c"
|
||||
@@ -163,26 +177,57 @@ set(ELFLOADER_SRC
|
||||
set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedalut.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/wrappedfontconfig.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.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/wrappedlibogg.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/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/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/wrappedlibxi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxmu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxpm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxrandr.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxrender.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxss.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxt.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxtst.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlzma.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/wrappedpulse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
|
||||
@@ -193,8 +238,13 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.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"
|
||||
)
|
||||
|
||||
@@ -256,16 +306,17 @@ if(ARM_DYNAREC)
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_65.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_66.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_67.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c"
|
||||
"${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_db.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
|
||||
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.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"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f0.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_660f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_6664.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f20f.c"
|
||||
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f30f.c"
|
||||
)
|
||||
@@ -321,10 +372,16 @@ if(ARM_DYNAREC)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
|
||||
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")
|
||||
endif()
|
||||
else()
|
||||
target_link_options(${BOX64} PUBLIC -rdynamic)
|
||||
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
if(NOT NOLOADADDR)
|
||||
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
|
||||
|
||||
@@ -53,6 +53,16 @@ Only on builds with trace enabled.
|
||||
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
|
||||
* 1 : Dump the XMM registers.
|
||||
|
||||
#### BOX64_TRACE_EMM
|
||||
Only on builds with trace enabled.
|
||||
* 0 : The EMM (i.e. XMM/x87) register will not be logged with the general and x86 registers. (Default.)
|
||||
* 1 : Dump the EMM registers.
|
||||
|
||||
#### BOX64_TRACE_COLOR
|
||||
Only on builds with trace enabled.
|
||||
* 0 : The general registers will always be the default white color. (Default.)
|
||||
* 1 : The general registers will change color in the dumps when they changed value.
|
||||
|
||||
#### BOX64_LOAD_ADDR
|
||||
Try to load at 0xXXXXXX main binary (if binary is a PIE)
|
||||
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
|
||||
|
||||
+306
-206
@@ -3,7 +3,8 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H']
|
||||
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P']
|
||||
assert(all(c not in values[:i] for i, c in enumerate(values)))
|
||||
def splitchar(s):
|
||||
try:
|
||||
ret = [len(s), values.index(s[0])]
|
||||
@@ -38,8 +39,10 @@ def main(root, defines, files, ver):
|
||||
global values
|
||||
|
||||
# Initialize variables: gbl for all values, redirects for redirections
|
||||
gbl = {}
|
||||
redirects = {}
|
||||
# mytypedefs is a list of all "*FE*" types per filename
|
||||
gbl = {}
|
||||
redirects = {}
|
||||
mytypedefs = {}
|
||||
|
||||
# First read the files inside the headers
|
||||
for filepath in files:
|
||||
@@ -82,10 +85,21 @@ def main(root, defines, files, ver):
|
||||
# If the line is a `GO...' line (GO/GOM/GO2/...)...
|
||||
elif ln.startswith("GO"):
|
||||
# ... then look at the second parameter of the line
|
||||
funname = ln.split(",")[0].split("(")[1].strip()
|
||||
ln = ln.split(",")[1].split(")")[0].strip()
|
||||
|
||||
if len(ln) < 3:
|
||||
raise NotImplementedError("Type {0} too short ({1}:{2})".format(ln, filename, line[:-1]))
|
||||
if "E" in ln:
|
||||
if ("E" in ln[:2]) or ("E" in ln[3:]):
|
||||
raise NotImplementedError(
|
||||
"emu64_t* not as the first parameter ({0}:{1})".format(filename, line[:-1]))
|
||||
if len(ln) < 4:
|
||||
raise NotImplementedError("Type {0} too short ({1}:{2})".format(ln, filename, line[:-1]))
|
||||
|
||||
if ln[1] not in ["F"]:
|
||||
raise NotImplementedError("Bad middle letter {0} ({1}:{2})".format(ln[1], filename, line[:-1]))
|
||||
|
||||
if any(c not in values for c in ln[2:]) or (('v' in ln[2:]) and (len(ln) > 3)):
|
||||
old = ln
|
||||
# This needs more work
|
||||
@@ -93,16 +107,27 @@ def main(root, defines, files, ver):
|
||||
if any(c not in acceptables for c in ln[2:]):
|
||||
raise NotImplementedError("{0} ({1}:{2})".format(ln[2:], filename, line[:-1]))
|
||||
# Ok, this is acceptable: there is 0, 1 and/or void
|
||||
ln = (ln
|
||||
ln = ln[:2] + (ln[2:]
|
||||
.replace("v", "") # void -> nothing
|
||||
.replace("0", "p") # 0 -> pointer
|
||||
.replace("1", "i")) # 1 -> integer
|
||||
assert(len(ln) >= 3)
|
||||
redirects.setdefault(" && ".join(dependants), {})
|
||||
redirects[" && ".join(dependants)][old] = ln
|
||||
# Simply append the function name if it's not yet existing
|
||||
gbl.setdefault(" && ".join(dependants), [])
|
||||
if ln not in gbl[" && ".join(dependants)]:
|
||||
gbl[" && ".join(dependants)].append(ln)
|
||||
|
||||
if ln[2] == "E":
|
||||
# filename isn't stored with the '_private.h' part
|
||||
if len(ln) > 3:
|
||||
ln = ln[:2] + ln[3:]
|
||||
else:
|
||||
ln = ln[:2] + "v"
|
||||
mytypedefs.setdefault(filename[:-10], {})
|
||||
mytypedefs[filename[:-10]].setdefault(ln, [])
|
||||
mytypedefs[filename[:-10]][ln].append(funname)
|
||||
|
||||
gbl_vals = {}
|
||||
for k in gbl:
|
||||
@@ -182,8 +207,12 @@ def main(root, defines, files, ver):
|
||||
gbl[k].sort(key=lambda v: splitchar(v))
|
||||
values = values + ['0', '1']
|
||||
for k in redirects:
|
||||
redirects[k].sort(key=lambda v: splitchar(v[0]) + [0] + splitchar(v[1]))
|
||||
redirects[k].sort(key=lambda v: splitchar(v[0]) + [-1] + splitchar(v[1]))
|
||||
values = values[:-2]
|
||||
mytypedefs_vals = dict((fn, sorted(mytypedefs[fn].keys(), key=lambda v: splitchar(v))) for fn in mytypedefs)
|
||||
for fn in mytypedefs:
|
||||
for v in mytypedefs_vals[fn]:
|
||||
mytypedefs[fn][v].sort()
|
||||
|
||||
# Check if there was any new functions
|
||||
functions_list = ""
|
||||
@@ -203,17 +232,58 @@ def main(root, defines, files, ver):
|
||||
# Mark as OK for CMake
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
|
||||
file.write(functions_list)
|
||||
#return 0
|
||||
return 0
|
||||
except IOError:
|
||||
# The file does not exist yet, first run
|
||||
pass
|
||||
|
||||
# Detect simple wrappings
|
||||
simple_wraps = {}
|
||||
|
||||
# H could be allowed maybe?
|
||||
allowed_simply = "v"
|
||||
allowed_regs = "cCwWiuIUlLp"
|
||||
allowed_fpr = "fd"
|
||||
|
||||
# Sanity checks
|
||||
forbidden_simple = "EeDKVOSNMHP"
|
||||
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(values))
|
||||
assert(all(c not in allowed_regs for c in allowed_simply))
|
||||
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
|
||||
assert(all(c not in allowed_simply + allowed_regs + allowed_fpr for c in forbidden_simple))
|
||||
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in values))
|
||||
|
||||
# Only search on real wrappers
|
||||
for k in ["()"] + gbl_idxs:
|
||||
for v in gbl[k]:
|
||||
regs_count = 0
|
||||
fpr_count = 0
|
||||
|
||||
if v[0] in forbidden_simple:
|
||||
continue
|
||||
for c in v[2:]:
|
||||
if c in allowed_regs:
|
||||
regs_count = regs_count + 1
|
||||
elif c in allowed_fpr:
|
||||
fpr_count = fpr_count + 1
|
||||
elif c in allowed_simply:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
else:
|
||||
# No character in forbidden_simply
|
||||
if (regs_count <= 6) and (fpr_count <= 4):
|
||||
# All checks passed!
|
||||
simple_wraps.setdefault(k, []).append(v)
|
||||
simple_idxs = list(simple_wraps.keys())
|
||||
simple_idxs.sort(key=lambda v: [-1] if v == "()" else splitdef(v, defines))
|
||||
|
||||
# Now the files rebuilding part
|
||||
# File headers and guards
|
||||
files_headers = {
|
||||
"wrapper.c": """/*****************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v%s)
|
||||
*****************************************************************/
|
||||
files_header = {
|
||||
"wrapper.c": """/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v{version}) *
|
||||
*******************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@@ -229,7 +299,7 @@ extern void* my__IO_2_1_stdin_ ;
|
||||
extern void* my__IO_2_1_stdout_;
|
||||
|
||||
static void* io_convert(void* v)
|
||||
{
|
||||
{lbr}
|
||||
if(!v)
|
||||
return v;
|
||||
if(v==my__IO_2_1_stderr_)
|
||||
@@ -239,15 +309,16 @@ static void* io_convert(void* v)
|
||||
if(v==my__IO_2_1_stdout_)
|
||||
return stdout;
|
||||
return v;
|
||||
}
|
||||
{rbr}
|
||||
|
||||
#define ST0val ST0.d
|
||||
|
||||
int of_convert(int);
|
||||
|
||||
""",
|
||||
"wrapper.h": """/*****************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v%s)
|
||||
*****************************************************************/
|
||||
"wrapper.h": """/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v{version}) *
|
||||
*******************************************************************/
|
||||
#ifndef __WRAPPER_H_
|
||||
#define __WRAPPER_H_
|
||||
#include <stdint.h>
|
||||
@@ -261,7 +332,7 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
|
||||
// list of defined wrapper
|
||||
// v = void, i = int32, u = uint32, U/I= (u)int64
|
||||
// l = signed long, L = unsigned long (long is an int with the size of a pointer)
|
||||
// p = pointer, P = callback
|
||||
// p = pointer, P = void* on the stack
|
||||
// f = float, d = double, D = long double, K = fake long double
|
||||
// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct
|
||||
// 0 = constant 0, 1 = constant 1
|
||||
@@ -275,57 +346,53 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
|
||||
// M = ... automatically sending 2 args
|
||||
// H = Huge 128bits value/struct
|
||||
|
||||
""",
|
||||
"fntypes.h": """/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v{version}) *
|
||||
*******************************************************************/
|
||||
#ifndef __{filename}TYPES_H_
|
||||
#define __{filename}TYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
"""
|
||||
}
|
||||
files_guards = {"wrapper.c": """""",
|
||||
files_guard = {"wrapper.c": """""",
|
||||
"wrapper.h": """
|
||||
#endif //__WRAPPER_H_
|
||||
int isSimpleWrapper(wrapper_t fun);
|
||||
|
||||
#endif // __WRAPPER_H_
|
||||
""",
|
||||
"fntypes.h": """
|
||||
#endif // __{filename}TYPES_H_
|
||||
"""
|
||||
}
|
||||
|
||||
# Rewrite the wrapper.h file:
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
|
||||
file.write(files_headers["wrapper.h"] % ver)
|
||||
for v in gbl["()"]:
|
||||
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
for k in gbl_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in gbl[k]:
|
||||
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
file.write("#endif\n")
|
||||
file.write("\n")
|
||||
for v in redirects["()"]:
|
||||
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
for k in redirects_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in redirects[k]:
|
||||
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
file.write("#endif\n")
|
||||
file.write(files_guards["wrapper.h"])
|
||||
|
||||
# Rewrite the wrapper.c file:
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
|
||||
file.write(files_headers["wrapper.c"] % ver)
|
||||
def generate_typedefs(arr, file):
|
||||
# i and u should only be 32 bits
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H P
|
||||
types = ["x64emu_t*", "x64emu_t**", "void", "int8_t", "int16_t", "int64_t", "int64_t", "uint8_t", "uint16_t", "uint64_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*"]
|
||||
if len(values) != len(types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
|
||||
|
||||
# First part: typedefs
|
||||
for v in gbl["()"]:
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H
|
||||
types = ["x64emu_t*", "x64emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128"]
|
||||
if len(values) != len(types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
|
||||
|
||||
for v in arr:
|
||||
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
|
||||
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
|
||||
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
|
||||
file.write(files_header["wrapper.c"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# First part: typedefs
|
||||
generate_typedefs(gbl["()"], file)
|
||||
for k in gbl_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in gbl[k]:
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H
|
||||
types = ["x64emu_t*", "x64emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128"]
|
||||
if len(values) != len(types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
|
||||
|
||||
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
|
||||
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
|
||||
generate_typedefs(gbl[k], file)
|
||||
file.write("#endif\n")
|
||||
|
||||
file.write("\n")
|
||||
@@ -335,153 +402,162 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
|
||||
# Helper variables
|
||||
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
|
||||
# vreg: value is in a general register
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H
|
||||
vreg = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2]
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H P
|
||||
vreg = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0]
|
||||
# vxmm: value is in a XMM register
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H
|
||||
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M H P
|
||||
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
# vother: value is elsewere
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M, H
|
||||
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M, H P
|
||||
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
|
||||
# vstack: value is on the stack (or out of register)
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M, H
|
||||
vstack = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2]
|
||||
# E e v c w i I C W u U f d D K l L p V O S N M, H P
|
||||
vstack = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1]
|
||||
arg_s = [
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"*(int8_t*)(R_RSP + {p}), ", # c
|
||||
"*(int16_t*)(R_RSP + {p}), ", # w
|
||||
"*(int32_t*)(R_RSP + {p}), ", # i
|
||||
"*(int64_t*)(R_RSP + {p}), ", # I
|
||||
"*(uint8_t*)(R_RSP + {p}), ", # C
|
||||
"*(uint16_t*)(R_RSP + {p}), ", # W
|
||||
"*(uint32_t*)(R_RSP + {p}), ", # u
|
||||
"*(uint64_t*)(R_RSP + {p}), ", # U
|
||||
"*(float*)(R_RSP + {p}), ", # f
|
||||
"*(double*)(R_RSP + {p}), ", # d
|
||||
"*(long double*)(R_RSP + {p}), ", # D
|
||||
"FromLD((void*)(R_RSP + {p})), ", # K
|
||||
"*(intptr_t*)(R_RSP + {p}), ", # l
|
||||
"*(uintptr_t*)(R_RSP + {p}), ", # L
|
||||
"*(void**)(R_RSP + {p}), ", # p
|
||||
"", # V
|
||||
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
|
||||
"io_convert(*(void**)(R_RSP + {p})), ", # S
|
||||
"*(void**)(R_RSP + {p}), ", # N
|
||||
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
|
||||
"*(unsigned __int128)(R_RSP + {p}), " # H
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"*(int8_t*)(R_RSP + {p}), ", # c
|
||||
"*(int16_t*)(R_RSP + {p}), ", # w
|
||||
"*(int64_t*)(R_RSP + {p}), ", # i should be int32_t
|
||||
"*(int64_t*)(R_RSP + {p}), ", # I
|
||||
"*(uint8_t*)(R_RSP + {p}), ", # C
|
||||
"*(uint16_t*)(R_RSP + {p}), ", # W
|
||||
"*(uint64_t*)(R_RSP + {p}), ", # u should be uint32_t
|
||||
"*(uint64_t*)(R_RSP + {p}), ", # U
|
||||
"*(float*)(R_RSP + {p}), ", # f
|
||||
"*(double*)(R_RSP + {p}), ", # d
|
||||
"*(long double*)(R_RSP + {p}), ", # D
|
||||
"FromLD((void*)(R_RSP + {p})), ", # K
|
||||
"*(intptr_t*)(R_RSP + {p}), ", # l
|
||||
"*(uintptr_t*)(R_RSP + {p}), ", # L
|
||||
"*(void**)(R_RSP + {p}), ", # p
|
||||
"", # V
|
||||
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
|
||||
"io_convert(*(void**)(R_RSP + {p})), ", # S
|
||||
"*(void**)(R_RSP + {p}), ", # N
|
||||
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
|
||||
"*(unsigned __int128)(R_RSP + {p}), ", # H
|
||||
"*(void**)(R_RSP + {p}), ", # P
|
||||
]
|
||||
arg_r = [
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"(int8_t){p}, ", # c
|
||||
"(int16_t){p}, ", # w
|
||||
"(int32_t){p}, ", # i
|
||||
"(int64_t){p}, ", # I
|
||||
"(uint8_t){p}, ", # C
|
||||
"(uint16_t){p}, ", # W
|
||||
"(uint32_t){p}, ", # u
|
||||
"(uint64_t){p}, ", # U
|
||||
"", # f
|
||||
"", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"(intptr_t){p}, ", # l
|
||||
"(uintptr_t){p}, ", # L
|
||||
"(void*){p}, ", # p
|
||||
"", # V
|
||||
"of_convert((int32_t){p}), ", # O
|
||||
"io_convert((void*){p}), ", # S
|
||||
"(void*){p}, ", # N
|
||||
"(void*){p}, ", # M
|
||||
"#error use pp instead, ", #H
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"(int8_t){p}, ", # c
|
||||
"(int16_t){p}, ", # w
|
||||
"(int64_t){p}, ", # i should int32_t
|
||||
"(int64_t){p}, ", # I
|
||||
"(uint8_t){p}, ", # C
|
||||
"(uint16_t){p}, ", # W
|
||||
"(uint64_t){p}, ", # u should uint32_t
|
||||
"(uint64_t){p}, ", # U
|
||||
"", # f
|
||||
"", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"(intptr_t){p}, ", # l
|
||||
"(uintptr_t){p}, ", # L
|
||||
"(void*){p}, ", # p
|
||||
"", # V
|
||||
"of_convert((int32_t){p}), ", # O
|
||||
"io_convert((void*){p}), ", # S
|
||||
"(void*){p}, ", # N
|
||||
"(void*){p}, ", # M
|
||||
"\n#error Use pp instead\n", # H
|
||||
"", # P
|
||||
]
|
||||
arg_x = [
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"", # c
|
||||
"", # w
|
||||
"", # i
|
||||
"", # I
|
||||
"", # C
|
||||
"", # W
|
||||
"", # u
|
||||
"", # U
|
||||
"emu->xmm[{p}].f[0], ", # f
|
||||
"emu->xmm[{p}].d[0], ", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"", # l
|
||||
"", # L
|
||||
"", # p
|
||||
"", # V
|
||||
"", # O
|
||||
"", # S
|
||||
"", # N
|
||||
"", # M
|
||||
"", # H
|
||||
"", # E
|
||||
"", # e
|
||||
"", # v
|
||||
"", # c
|
||||
"", # w
|
||||
"", # i
|
||||
"", # I
|
||||
"", # C
|
||||
"", # W
|
||||
"", # u
|
||||
"", # U
|
||||
"emu->xmm[{p}].f[0], ", # f
|
||||
"emu->xmm[{p}].d[0], ", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"", # l
|
||||
"", # L
|
||||
"", # p
|
||||
"", # V
|
||||
"", # O
|
||||
"", # S
|
||||
"", # N
|
||||
"", # M
|
||||
"", # H
|
||||
"", # P
|
||||
]
|
||||
arg_o = [
|
||||
"emu, ", # E
|
||||
"&emu, ", # e
|
||||
"", # v
|
||||
"", # c
|
||||
"", # w
|
||||
"", # i
|
||||
"", # I
|
||||
"", # C
|
||||
"", # W
|
||||
"", # u
|
||||
"", # U
|
||||
"", # f
|
||||
"", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"", # l
|
||||
"", # L
|
||||
"", # p
|
||||
"(void*)(R_RSP + {p}), ", # V
|
||||
"", # O
|
||||
"", # S
|
||||
"", # N
|
||||
"", # M
|
||||
"", # H
|
||||
"emu, ", # E
|
||||
"&emu, ", # e
|
||||
"", # v
|
||||
"", # c
|
||||
"", # w
|
||||
"", # i
|
||||
"", # I
|
||||
"", # C
|
||||
"", # W
|
||||
"", # u
|
||||
"", # U
|
||||
"", # f
|
||||
"", # d
|
||||
"", # D
|
||||
"", # K
|
||||
"", # l
|
||||
"", # L
|
||||
"", # p
|
||||
"(void*)(R_RSP + {p}), ", # V
|
||||
"", # O
|
||||
"", # S
|
||||
"", # N
|
||||
"", # M
|
||||
"", # H
|
||||
"", # P
|
||||
]
|
||||
|
||||
vals = [
|
||||
"\n#error Invalid return type: emulator\n", # E
|
||||
"\n#error Invalid return type: &emulator\n", # e
|
||||
"fn({0});", # v
|
||||
"R_RAX=fn({0});", # c
|
||||
"R_RAX=fn({0});", # w
|
||||
"R_RAX=fn({0});", # i
|
||||
"R_RAX=(uint64_t)fn({0});", # I
|
||||
"R_RAX=(unsigned char)fn({0});", # C
|
||||
"R_RAX=(unsigned short)fn({0});", # W
|
||||
"R_RAX=(uint32_t)fn({0});", # u
|
||||
"R_RAX=fn({0});", # U
|
||||
"emu->xmm[0].f[0]=fn({0});", # f
|
||||
"emu->xmm[0].d[0]=fn({0});", # d
|
||||
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
|
||||
"R_RAX=(intptr_t)fn({0});", # l
|
||||
"R_RAX=(uintptr_t)fn({0});", # L
|
||||
"R_RAX=(uintptr_t)fn({0});", # p
|
||||
"\n#error Invalid return type: va_list\n", # V
|
||||
"\n#error Invalid return type: at_flags\n", # O
|
||||
"\n#error Invalid return type: _io_file*\n", # S
|
||||
"\n#error Invalid return type: ... with 1 arg\n", # N
|
||||
"\n#error Invalid return type: ... with 2 args\n", # M
|
||||
"\n#error Invalid return type: emulator\n", # E
|
||||
"\n#error Invalid return type: &emulator\n", # e
|
||||
"fn({0});", # v
|
||||
"R_RAX=fn({0});", # c
|
||||
"R_RAX=fn({0});", # w
|
||||
"R_RAX=(int64_t)fn({0});", # i int32_t normaly
|
||||
"R_RAX=(int64_t)fn({0});", # I
|
||||
"R_RAX=(unsigned char)fn({0});", # C
|
||||
"R_RAX=(unsigned short)fn({0});", # W
|
||||
"R_RAX=(uint64_t)fn({0});", # u uint32_t normaly
|
||||
"R_RAX=fn({0});", # U
|
||||
"emu->xmm[0].f[0]=fn({0});", # f
|
||||
"emu->xmm[0].d[0]=fn({0});", # d
|
||||
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
|
||||
"R_RAX=(intptr_t)fn({0});", # l
|
||||
"R_RAX=(uintptr_t)fn({0});", # L
|
||||
"R_RAX=(uintptr_t)fn({0});", # p
|
||||
"\n#error Invalid return type: va_list\n", # V
|
||||
"\n#error Invalid return type: at_flags\n", # O
|
||||
"\n#error Invalid return type: _io_file*\n", # S
|
||||
"\n#error Invalid return type: ... with 1 arg\n", # N
|
||||
"\n#error Invalid return type: ... with 2 args\n", # M
|
||||
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
|
||||
"\n#error Invalid return type: pointer in the stack\n", # P
|
||||
]
|
||||
# Asserts
|
||||
if len(values) != len(arg_s):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(values), lenargr=len(arg_s)))
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(values), lenargs=len(arg_s)))
|
||||
if len(values) != len(arg_r):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_r) = {lenargr}".format(lenval=len(values), lenargr=len(arg_r)))
|
||||
if len(values) != len(arg_x):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_x) = {lenargx}".format(lenval=len(values), lenargx=len(arg_x)))
|
||||
if len(values) != len(arg_o):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_o) = {lenargo}".format(lenval=len(values), lenargo=len(arg_o)))
|
||||
if len(values) != len(vals):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
|
||||
|
||||
@@ -510,27 +586,8 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
|
||||
|
||||
def function_writer(f, N, W, rettype, args):
|
||||
f.write("void {0}(x64emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
|
||||
if any(cc in 'PG' for cc in args):
|
||||
# Vulkan struct or GValue pointer, need to unwrap functions at the end
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("void* save{d}=NULL; void *arg{d} = VulkanFromx86(*(void**)(R_RSP + {d}), &save{d}); ".format(d=delta))
|
||||
if c == 'G':
|
||||
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_RSP + {d})); ".format(d=delta))
|
||||
delta = delta + deltas[values.index(c)]
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " ")
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
|
||||
if c == 'G':
|
||||
f.write("unalignGValue(*(void**)(R_RSP + {d}), &arg{d}); ".format(d=delta))
|
||||
delta = delta + deltas[values.index(c)]
|
||||
f.write("}\n")
|
||||
else:
|
||||
# Generic function
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
|
||||
# Generic function
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
|
||||
|
||||
for v in gbl["()"]:
|
||||
function_writer(file, v, v + "_t", v[0], v[2:])
|
||||
@@ -548,7 +605,50 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
|
||||
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
|
||||
file.write("#endif\n")
|
||||
|
||||
file.write(files_guards["wrapper.c"])
|
||||
# Write the isSimpleWrapper function
|
||||
file.write("\nint isSimpleWrapper(wrapper_t fun) {\n")
|
||||
for k in simple_idxs:
|
||||
if k != "()":
|
||||
file.write("#if " + k + "\n")
|
||||
for v in simple_wraps[k]:
|
||||
file.write("\tif (fun == &" + v + ") return 1;\n")
|
||||
if k != "()":
|
||||
file.write("#endif\n")
|
||||
file.write("\treturn 0;\n}\n")
|
||||
|
||||
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the wrapper.h file:
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
|
||||
file.write(files_header["wrapper.h"].format(lbr="{", rbr="}", version=ver))
|
||||
for v in gbl["()"]:
|
||||
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
for k in gbl_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in gbl[k]:
|
||||
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
file.write("#endif\n")
|
||||
file.write("\n")
|
||||
for v in redirects["()"]:
|
||||
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
for k in redirects_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in redirects[k]:
|
||||
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
|
||||
file.write("#endif\n")
|
||||
file.write(files_guard["wrapper.h"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the *types.h files:
|
||||
for fn in mytypedefs:
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", fn + "types.h"), 'w') as file:
|
||||
file.write(files_header["fntypes.h"].format(lbr="{", rbr="}", version=ver, filename=fn))
|
||||
generate_typedefs(mytypedefs_vals[fn], file)
|
||||
file.write("\n#define SUPER() ADDED_FUNCTIONS()")
|
||||
for v in mytypedefs_vals[fn]:
|
||||
for f in mytypedefs[fn][v]:
|
||||
file.write(" \\\n\tGO({0}, {1}_t)".format(f, v))
|
||||
file.write("\n")
|
||||
file.write(files_guard["fntypes.h"].format(lbr="{", rbr="}", version=ver, filename=fn))
|
||||
|
||||
# Save the string for the next iteration, writing was successful
|
||||
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
|
||||
@@ -561,6 +661,6 @@ if __name__ == '__main__':
|
||||
for i, v in enumerate(sys.argv):
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.2.0.09") != 0:
|
||||
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.3.0.10") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
+101
-17
@@ -68,6 +68,77 @@ void free_tlsdatasize(void* p)
|
||||
|
||||
void x64Syscall(x64emu_t *emu);
|
||||
|
||||
int unlockMutex()
|
||||
{
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
|
||||
GO(my_context->mutex_once, 5)
|
||||
GO(my_context->mutex_once2, 6)
|
||||
GO(my_context->mutex_trace, 7)
|
||||
#ifdef DYNAREC
|
||||
GO(my_context->mutex_dyndump, 8)
|
||||
#else
|
||||
GO(my_context->mutex_lock, 8)
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
#undef GO
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void relockMutex(int locks)
|
||||
{
|
||||
relockCustommemMutex(locks);
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_lock(&A); \
|
||||
|
||||
GO(my_context->mutex_once, 5)
|
||||
GO(my_context->mutex_once2, 6)
|
||||
GO(my_context->mutex_trace, 7)
|
||||
#ifdef DYNAREC
|
||||
GO(my_context->mutex_dyndump, 8)
|
||||
#else
|
||||
GO(my_context->mutex_lock, 8)
|
||||
#endif
|
||||
GO(my_context->mutex_tls, 9)
|
||||
GO(my_context->mutex_thread, 10)
|
||||
#undef GO
|
||||
}
|
||||
|
||||
static void init_mutexes(box64context_t* context)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
static void atfork_child_box64context(void)
|
||||
{
|
||||
// (re)init mutex if it was lock before the fork
|
||||
init_mutexes(my_context);
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
box64context_t *NewBox64Context(int argc)
|
||||
{
|
||||
@@ -96,16 +167,9 @@ box64context_t *NewBox64Context(int argc)
|
||||
context->argc = argc;
|
||||
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
|
||||
|
||||
pthread_mutex_init(&context->mutex_once, NULL);
|
||||
pthread_mutex_init(&context->mutex_once2, NULL);
|
||||
pthread_mutex_init(&context->mutex_trace, NULL);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_dyndump, NULL);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, NULL);
|
||||
pthread_mutex_init(&context->mutex_thread, NULL);
|
||||
init_mutexes(context);
|
||||
pthread_atfork(NULL, NULL, atfork_child_box64context);
|
||||
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
|
||||
|
||||
@@ -129,16 +193,16 @@ void FreeBox64Context(box64context_t** context)
|
||||
|
||||
box64context_t* ctx = *context; // local copy to do the cleanning
|
||||
|
||||
if(ctx->local_maplib)
|
||||
FreeLibrarian(&ctx->local_maplib, NULL);
|
||||
if(ctx->maplib)
|
||||
FreeLibrarian(&ctx->maplib, NULL);
|
||||
|
||||
for(int i=0; i<ctx->elfsize; ++i) {
|
||||
FreeElfHeader(&ctx->elfs[i]);
|
||||
}
|
||||
free(ctx->elfs);
|
||||
|
||||
if(ctx->maplib)
|
||||
FreeLibrarian(&ctx->maplib);
|
||||
if(ctx->local_maplib)
|
||||
FreeLibrarian(&ctx->local_maplib);
|
||||
|
||||
FreeCollection(&ctx->box64_path);
|
||||
FreeCollection(&ctx->box64_ld_lib);
|
||||
FreeCollection(&ctx->box64_emulated_libs);
|
||||
@@ -174,8 +238,6 @@ void FreeBox64Context(box64context_t** context)
|
||||
|
||||
FreeDLPrivate(&ctx->dlprivate);
|
||||
|
||||
free(ctx->stack);
|
||||
|
||||
free(ctx->fullpath);
|
||||
free(ctx->box64path);
|
||||
|
||||
@@ -266,3 +328,25 @@ void free_neededlib(needed_libs_t* needed)
|
||||
free(needed->libs);
|
||||
needed->libs = NULL;
|
||||
}
|
||||
|
||||
void add_dependedlib(needed_libs_t* depended, library_t* lib)
|
||||
{
|
||||
if(!depended)
|
||||
return;
|
||||
if(depended->size == depended->cap) {
|
||||
depended->cap += 8;
|
||||
depended->libs = (library_t**)realloc(depended->libs, depended->cap*sizeof(library_t*));
|
||||
}
|
||||
depended->libs[depended->size++] = lib;
|
||||
}
|
||||
|
||||
void free_dependedlib(needed_libs_t* depended)
|
||||
{
|
||||
if(!depended)
|
||||
return;
|
||||
depended->cap = 0;
|
||||
depended->size = 0;
|
||||
if(depended->libs)
|
||||
free(depended->libs);
|
||||
depended->libs = NULL;
|
||||
}
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 0
|
||||
#define BOX64_REVISION 6
|
||||
#define BOX64_REVISION 8
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+199
-33
@@ -21,6 +21,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include "custommem.h"
|
||||
#include "khash.h"
|
||||
#include "threads.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/arm64_lock.h"
|
||||
@@ -55,7 +56,7 @@ typedef struct blocklist_s {
|
||||
|
||||
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
|
||||
|
||||
static pthread_mutex_t mutex_blocks = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t mutex_blocks;
|
||||
static int n_blocks = 0; // number of blocks for custom malloc
|
||||
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
|
||||
|
||||
@@ -427,6 +428,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
return 0;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
#ifndef USE_MMAP
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box64_pagesize, size)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
@@ -450,14 +452,11 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
|
||||
if(pthread_mutex_trylock(&mutex_mmap)) {
|
||||
sched_yield(); // give it a chance
|
||||
if(pthread_mutex_trylock(&mutex_mmap))
|
||||
return 0; // cannot lock, baillout
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
|
||||
uintptr_t ret = FindFreeDynarecMap(db, size);
|
||||
if(!ret)
|
||||
@@ -470,7 +469,10 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
|
||||
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
{
|
||||
if(!addr || !size)
|
||||
return;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
#else
|
||||
@@ -482,6 +484,7 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_mmap);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&mutex_mmap);
|
||||
@@ -514,12 +517,21 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
int idx3 = (i>>32)&((1<<DYNAMAP_SHIFT)-1);
|
||||
int idx2 = (i>>16)&((1<<DYNAMAP_SHIFT)-1);
|
||||
int idx1 = (i )&((1<<DYNAMAP_SHIFT)-1);
|
||||
if(!dynmap123[idx3])
|
||||
dynmap123[idx3] = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
|
||||
if(!dynmap123[idx3][idx2])
|
||||
dynmap123[idx3][idx2] = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
|
||||
if(!dynmap123[idx3][idx2][idx1])
|
||||
dynmap123[idx3][idx2][idx1] = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||
if(!dynmap123[idx3]) {
|
||||
dynablocklist_t*** p = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3], p)!=p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2]) {
|
||||
dynablocklist_t** p = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], p)!=p)
|
||||
free(p);
|
||||
}
|
||||
if(!dynmap123[idx3][idx2][idx1]) {
|
||||
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], p)!=p)
|
||||
FreeDynablockList(&p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,23 +571,25 @@ void addJumpTableIfDefault64(void* addr, void* jmp)
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
box64_jmptbl3[idx3] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
box64_jmptbl3[idx3][idx2] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
box64_jmptbl3[idx3][idx2][idx1] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)
|
||||
box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)jmp;
|
||||
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, arm64_next);
|
||||
}
|
||||
void setJumpTableDefault64(void* addr)
|
||||
{
|
||||
@@ -594,6 +608,23 @@ void setJumpTableDefault64(void* addr)
|
||||
return;
|
||||
box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)arm64_next;
|
||||
}
|
||||
int isJumpTableDefault64(void* addr)
|
||||
{
|
||||
uintptr_t idx3, idx2, idx1, idx0;
|
||||
idx3 = (((uintptr_t)addr)>>48)&0xffff;
|
||||
idx2 = (((uintptr_t)addr)>>32)&0xffff;
|
||||
idx1 = (((uintptr_t)addr)>>16)&0xffff;
|
||||
idx0 = (((uintptr_t)addr) )&0xffff;
|
||||
if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
|
||||
return 1;
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
|
||||
return 1;
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
|
||||
return 1;
|
||||
if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)
|
||||
return 1;
|
||||
return (box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)?1:0;
|
||||
}
|
||||
uintptr_t getJumpTable64()
|
||||
{
|
||||
return (uintptr_t)box64_jmptbl3;
|
||||
@@ -602,27 +633,30 @@ uintptr_t getJumpTable64()
|
||||
uintptr_t getJumpTableAddress64(uintptr_t addr)
|
||||
{
|
||||
uintptr_t idx3, idx2, idx1, idx0;
|
||||
idx3 = (((uintptr_t)addr)>>48)&0xffff;
|
||||
idx2 = (((uintptr_t)addr)>>32)&0xffff;
|
||||
idx1 = (((uintptr_t)addr)>>16)&0xffff;
|
||||
idx0 = (((uintptr_t)addr) )&0xffff;
|
||||
idx3 = ((addr)>>48)&0xffff;
|
||||
idx2 = ((addr)>>32)&0xffff;
|
||||
idx1 = ((addr)>>16)&0xffff;
|
||||
idx0 = ((addr) )&0xffff;
|
||||
if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
|
||||
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault1;
|
||||
box64_jmptbl3[idx3] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
|
||||
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = box64_jmptbldefault0;
|
||||
box64_jmptbl3[idx3][idx2] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm64_next;
|
||||
box64_jmptbl3[idx3][idx2][idx1] = tbl;
|
||||
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
return (uintptr_t)&box64_jmptbl3[idx3][idx2][idx1][idx0];
|
||||
@@ -650,7 +684,7 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
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);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -674,7 +708,7 @@ void protectDBnolock(uintptr_t addr, uintptr_t size)
|
||||
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);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +742,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
uint8_t prot = kh_value(memprot, k)[ii];
|
||||
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
|
||||
if(prot&PROT_DYNAREC) {
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
}
|
||||
}
|
||||
@@ -734,8 +768,8 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
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_DYNAREC);
|
||||
kh_value(memprot, k)[ii] = prot|dyn;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -755,7 +789,27 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = prot;
|
||||
kh_value(memprot, k)[ii] = prot|PROT_ALLOC;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
|
||||
int ret;
|
||||
pthread_mutex_lock(&mutex_prot);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
|
||||
khint_t k = kh_put(memprot, memprot, key, &ret);
|
||||
if(ret) {
|
||||
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
|
||||
kh_value(memprot, k) = m;
|
||||
}
|
||||
const uintptr_t ii = i&(MEMPROT_SIZE-1);
|
||||
kh_value(memprot, k)[ii] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_prot);
|
||||
}
|
||||
@@ -775,15 +829,126 @@ uint32_t getProtection(uintptr_t addr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LOWEST (void*)0x20000
|
||||
int availableBlock(uint8_t* p, size_t n)
|
||||
{
|
||||
for (int i=0; i<n; ++i, ++p)
|
||||
if(*p)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
// slow iterative search... Would need something better one day
|
||||
const uint32_t key = 0; // upper value is 0 by request
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
#undef LOWEST
|
||||
|
||||
int unlockCustommemMutex()
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
#define GO(A, B) \
|
||||
i = checkMutex(&A); \
|
||||
if(i) { \
|
||||
pthread_mutex_unlock(&A); \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
#undef GO
|
||||
return ret;
|
||||
}
|
||||
|
||||
void relockCustommemMutex(int locks)
|
||||
{
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_lock(&A); \
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
GO(mutex_prot, 1)
|
||||
#ifdef DYNAREC
|
||||
GO(mutex_mmap, 2)
|
||||
#endif
|
||||
#undef GO
|
||||
}
|
||||
|
||||
static void init_mutexes(void)
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
pthread_mutex_init(&mutex_prot, &attr);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&mutex_mmap, &attr);
|
||||
#endif
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
static void atfork_child_custommem(void)
|
||||
{
|
||||
// (re)init mutex if it was lock before the fork
|
||||
init_mutexes();
|
||||
}
|
||||
|
||||
void init_custommem_helper(box64context_t* ctx)
|
||||
{
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
memprot = kh_init(memprot);
|
||||
pthread_mutex_init(&mutex_prot, NULL);
|
||||
init_mutexes();
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&mutex_mmap, NULL);
|
||||
#ifdef ARM64
|
||||
if(box64_dynarec)
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i) {
|
||||
@@ -796,6 +961,7 @@ void init_custommem_helper(box64context_t* ctx)
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
#endif
|
||||
pthread_atfork(NULL, NULL, atfork_child_custommem);
|
||||
}
|
||||
|
||||
void fini_custommem_helper(box64context_t *ctx)
|
||||
@@ -870,5 +1036,5 @@ void fini_custommem_helper(box64context_t *ctx)
|
||||
#endif
|
||||
free(p_blocks);
|
||||
pthread_mutex_destroy(&mutex_prot);
|
||||
//pthread_mutex_destroy(&mutex_blocks);
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
}
|
||||
+469
-23
@@ -137,6 +137,7 @@
|
||||
#define ADDx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
|
||||
#define ADDw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define ADDSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
|
||||
#define ADDw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
|
||||
#define ADDxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define ADDSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
|
||||
#define ADDxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
|
||||
@@ -306,6 +307,14 @@
|
||||
#define LDAXRxw(Rt, Rn) EMIT(MEMAX_gen(2+rex.w, 1, 31, Rn, Rt))
|
||||
#define STLXRxw(Rs, Rt, Rn) EMIT(MEMAX_gen(2+rex.w, 0, Rs, Rn, Rt))
|
||||
|
||||
#define MEMAX_pair(size, L, Rs, Rt2, Rn, Rt) (1<<31 | (size)<<30 | 0b001000<<24 | (L)<<22 | 1<<21 | (Rs)<<16 | 1<<15 | (Rt2)<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDAXPx(Rt, Rt2, Rn) EMIT(MEMAX_pair(1, 1, 31, Rt2, Rn, Rt))
|
||||
#define LDAXPw(Rt, Rt2, Rn) EMIT(MEMAX_pair(0, 1, 31, Rt2, Rn, Rt))
|
||||
#define LDAXPxw(Rt, Rt2, Rn) EMIT(MEMAX_pair(rex.w, 1, 31, Rt2, Rn, Rt))
|
||||
#define STLXPx(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(1, 0, Rs, Rt2, Rn, Rt))
|
||||
#define STLXPw(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(0, 0, Rs, Rt2, Rn, Rt))
|
||||
#define STLXPxw(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(rex.w, 0, Rs, Rt2, Rn, Rt))
|
||||
|
||||
// LOAD/STORE Exclusive
|
||||
#define MEMX_gen(size, L, Rs, Rn, Rt) ((size)<<30 | 0b001000<<24 | (L)<<22 | (Rs)<<16 | 0<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
|
||||
#define LDXRB(Rt, Rn) EMIT(MEMX_gen(0b00, 1, 31, Rn, Rt))
|
||||
@@ -319,6 +328,24 @@
|
||||
#define LDXRxw(Rt, Rn) EMIT(MEMX_gen(2+rex.w, 1, 31, Rn, Rt))
|
||||
#define STXRxw(Rs, Rt, Rn) EMIT(MEMX_gen(2+rex.w, 0, Rs, Rn, Rt))
|
||||
|
||||
// Prefetch
|
||||
#define PRFM_register(Rm, option, S, Rn, Rt) (0b11<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | 0b10<<10 | (Rn)<<5 | (Rt))
|
||||
#define PLD_L1_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00000))
|
||||
#define PLD_L2_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00010))
|
||||
#define PLD_L3_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00100))
|
||||
#define PLD_L1_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00001))
|
||||
#define PLD_L2_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00011))
|
||||
#define PLD_L3_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00101))
|
||||
|
||||
#define PRFM_imm(imm12, Rn, Rt) (0b11<<30 | 0b111<<27 | 0b01<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
#define PLD_L1_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00000))
|
||||
#define PLD_L2_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00010))
|
||||
#define PLD_L3_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00100))
|
||||
#define PLD_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00001))
|
||||
#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))
|
||||
|
||||
|
||||
// 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))
|
||||
#define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
|
||||
@@ -584,9 +611,31 @@
|
||||
#define MRS_nzvc(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
|
||||
// MSR : to System register
|
||||
#define MSR_nzvc(Rt) EMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
|
||||
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=2
|
||||
#define VMRS(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
|
||||
#define VMSR(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
|
||||
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=0
|
||||
#define MRS_fpcr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
|
||||
#define MSR_fpcr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
|
||||
// mrs x0, fpsr : 1101010100 1 1 1 011 0100 0100 001 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=1
|
||||
#define MRS_fpsr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 1, Rt))
|
||||
#define MSR_fpsr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 1, Rt))
|
||||
// NEON Saturation Bit
|
||||
#define FPSR_QC 27
|
||||
// NEON Input Denormal Cumulative
|
||||
#define FPSR_IDC 7
|
||||
// NEON IneXact Cumulative
|
||||
#define FPSR_IXC 4
|
||||
// NEON Underflow Cumulative
|
||||
#define FPSR_UFC 3
|
||||
// NEON Overflow Cumulative
|
||||
#define FPSR_OFC 2
|
||||
// NEON Divide by 0 Cumulative
|
||||
#define FPSR_DZC 1
|
||||
// NEON Invalid Operation Cumulative
|
||||
#define FPSR_IOC 0
|
||||
|
||||
// FCSEL
|
||||
#define FCSEL_scalar(type, Rm, cond, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | (cond)<<12 | 0b11<<10 | (Rn)<<5 | (Rd))
|
||||
#define FCSELS(Sd, Sn, Sm, cond) EMIT(FCSEL_scalar(0b00, Sm, cond, Sn, Sd))
|
||||
#define FCSELD(Dd, Dn, Dm, cond) EMIT(FCSEL_scalar(0b01, Dm, cond, Dn, Dd))
|
||||
|
||||
// VLDR
|
||||
#define VMEM_gen(size, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | 0b01<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
|
||||
@@ -602,6 +651,22 @@
|
||||
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
|
||||
// imm16 must be 4-aligned
|
||||
#define VSTR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
|
||||
// (imm14) must be 1-aligned
|
||||
#define VSTR16_U12(Ht, Rn, imm14) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm14>>1))&0xfff, Rn, Ht))
|
||||
|
||||
#define VMEMUR_vector(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
|
||||
// signed offset, no alignement!
|
||||
#define VLDR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VLDR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VLDR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VLDR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VLDR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
|
||||
// signed offset, no alignement!
|
||||
#define VSTR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VSTR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VSTR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
|
||||
#define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
|
||||
|
||||
#define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
|
||||
#define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
|
||||
@@ -629,6 +694,12 @@
|
||||
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Dt))
|
||||
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Dt))
|
||||
|
||||
#define VLDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | 1<<26 | (imm19)<<5 | (Rt))
|
||||
#define VLDR32_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b00, ((imm19)>>2)&0x7FFFF, Vt))
|
||||
#define VLDR64_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Vt))
|
||||
#define VLDR128_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b10, ((imm19)>>2)&0x7FFFF, Vt))
|
||||
|
||||
|
||||
#define LD1R_gen(Q, size, Rn, Rt) ((Q)<<30 | 0b0011010<<23 | 1<<22 | 0<<21 | 0b110<<13 | (size)<<10 | (Rn)<<5 | (Rt))
|
||||
#define VLDQ1R_8(Vt, Rn) EMIT(LD1R_gen(1, 0b00, Rn, Vt))
|
||||
#define VLDQ1R_16(Vt, Rn) EMIT(LD1R_gen(1, 0b01, Rn, Vt))
|
||||
@@ -664,9 +735,24 @@
|
||||
#define VSHLQ_32(Vd, Vn, shift) EMIT(SHL_vector(1, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
|
||||
#define VSHLQ_64(Vd, Vn, shift) EMIT(SHL_vector(1, 0b1000 | (((shift)>>3)&7), (shift)&7, Vn, Vd))
|
||||
#define VSHL_8(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0001, (shift)&7, Vn, Vd))
|
||||
#define VSHL_16(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0010 | ((shift)>>3)&1, (shift)&7, Vn, Vd))
|
||||
#define VSHL_16(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0010 | (((shift)>>3)&1), (shift)&7, Vn, Vd))
|
||||
#define VSHL_32(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
|
||||
|
||||
#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 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))
|
||||
|
||||
#define SHL_vector_vector(Q, U, size, Rm, R, S, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b010<<13 | (R)<<12 | (S)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SSHL_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHL_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b01, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHL_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b10, Vm, 0, 0, Vn, Vd))
|
||||
#define SSHLQ_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b00, Vm, 0, 0, Vn, Vd))
|
||||
#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 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))
|
||||
#define VSHRQ_16(Vd, Vn, shift) EMIT(SHR_vector(1, 1, 0b0010 | (((16-(shift))>>3)&1), (16-(shift))&7, Vn, Vd))
|
||||
@@ -683,7 +769,12 @@
|
||||
#define VSSHR_16(Vd, Vn, shift) EMIT(SHR_vector(0, 0, 0b0010 | (((16-(shift))>>3)&1), (16-(shift))&7, Vn, Vd))
|
||||
#define VSSHR_32(Vd, Vn, shift) EMIT(SHR_vector(0, 0, 0b0100 | (((32-(shift))>>3)&3), (32-(shift))&7, Vn, Vd))
|
||||
|
||||
#define SHR_scalar_imm(U, immh, immb, o1, o0, Rn, Rd) (0b01<<30 | (U)<<29 | 0b111110<<23 | (immh)<<19 | (immb)<<16 | (o1)<<13 | (o0)<<12 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SSHR_64(Vd, Vn, shift) EMIT(SHR_scalar_imm(0, 0b1000 | (((64-(shift))>>3)&7), (64-(shift))&7, 0, 0, Vn, Vd))
|
||||
#define USHR_64(Vd, Vn, shift) EMIT(SHR_scalar_imm(1, 0b1000 | (((64-(shift))>>3)&7), (64-(shift))&7, 0, 0, Vn, Vd))
|
||||
|
||||
#define EXT_vector(Q, Rm, imm4, Rn, Rd) ((Q)<<30 | 0b101110<<24 | (Rm)<<16 | (imm4)<<11 | (Rn)<<5 | (Rd))
|
||||
#define VEXT_8(Rd, Rn, Rm, index) EMIT(EXT_vector(0, Rm, index, Rn, Rd))
|
||||
#define VEXTQ_8(Rd, Rn, Rm, index) EMIT(EXT_vector(1, Rm, index, Rn, Rd))
|
||||
|
||||
// Shift Left and Insert (not touching lower part of dest)
|
||||
@@ -723,6 +814,22 @@
|
||||
#define VSUB_16(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define VSUB_32(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
#define NEGABS_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define NEG_8(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b00, Vn, Vd))
|
||||
#define NEG_16(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b01, Vn, Vd))
|
||||
#define NEG_32(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b10, Vn, Vd))
|
||||
#define NEGQ_8(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b00, Vn, Vd))
|
||||
#define NEGQ_16(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b01, Vn, Vd))
|
||||
#define NEGQ_32(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b10, Vn, Vd))
|
||||
#define NEGQ_64(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b11, Vn, Vd))
|
||||
#define ABS_8(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b00, Vn, Vd))
|
||||
#define ABS_16(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b01, Vn, Vd))
|
||||
#define ABS_32(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b10, Vn, Vd))
|
||||
#define ABSQ_8(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b00, Vn, Vd))
|
||||
#define ABSQ_16(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b01, Vn, Vd))
|
||||
#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))
|
||||
|
||||
// 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
|
||||
@@ -742,12 +849,21 @@
|
||||
#define FMOVS(Sd, Sn) EMIT(FMOV_register(0b00, Sn, Sd))
|
||||
#define FMOVD(Dd, Dn) EMIT(FMOV_register(0b01, Dn, Dd))
|
||||
|
||||
#define FMOV_vector_imm(Q, op, abc, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | 0b1111<<12 | 1<<10 | (defgh)<<5 | (Rd))
|
||||
#define VFMOVS_8(Vd, u8) EMIT(FMOV_vector_imm(0, 0, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
|
||||
#define VFMOVSQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 0, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
|
||||
#define VFMOVDQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 1, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
|
||||
|
||||
#define FMOV_scalar_imm(type, imm8, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (imm8)<<13 | 0b100<<10 | (Rd))
|
||||
#define FMOVS_8(Sd, u8) EMIT(FMOV_scalar_imm(0b00, u8, Sd))
|
||||
#define FMOVD_8(Dd, u8) EMIT(FMOV_scalar_imm(0b01, u8, Dd))
|
||||
|
||||
// VMOV
|
||||
#define VMOV_element(imm5, imm4, Rn, Rd) (1<<30 | 1<<29 | 0b01110000<<21 | (imm5)<<16 | (imm4)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VMOVeB(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<1) | 1, i2, Vn, Vd))
|
||||
#define VMOVeH(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<2) | 2, i2<<1, Vn, Vd))
|
||||
#define VMOVeS(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<3) | 4, i2<<2, Vn, Vd))
|
||||
#define VMOVeD(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<4) | 8, i2<<3, Vn, Vd))
|
||||
#define VMOVeB(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<1) | 1, (i2), Vn, Vd))
|
||||
#define VMOVeH(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<2) | 2, (i2)<<1, Vn, Vd))
|
||||
#define VMOVeS(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<3) | 4, (i2)<<2, Vn, Vd))
|
||||
#define VMOVeD(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<4) | 8, (i2)<<3, Vn, Vd))
|
||||
|
||||
#define VMOV_from(imm5, Rn, Rd) (1<<30 | 0<<29 | 0b01110000<<21 | (imm5)<<16 | 0b0011<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VMOVQBfrom(Vd, index, Wn) EMIT(VMOV_from(((index)<<1) | 1, Wn, Vd))
|
||||
@@ -761,6 +877,9 @@
|
||||
#define VMOVHto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<2) | 2, Vn, Wd))
|
||||
#define VMOVSto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<3) | 4, Vn, Wd))
|
||||
|
||||
#define MVN_vector(Q, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VMVNQ(Rd, Rn) EMIT(MVN_vector(1, Rn, Rd))
|
||||
|
||||
// VORR
|
||||
#define ORR_vector(Q, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | 0b10<<22 | 1<<21 | (Rm)<<16 | 0b00011<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VORRQ(Vd, Vn, Vm) EMIT(ORR_vector(1, Vm, Vn, Vd))
|
||||
@@ -802,18 +921,27 @@
|
||||
|
||||
// ADD Pair
|
||||
#define ADDP_vector(Q, size, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10111<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VADDPQ_8(Vd, Vn, Vm) EMIT(ADDP(1, 0b00, Vm, Vn, Vd))
|
||||
#define VADDPQ_16(Vd, Vn, Vm) EMIT(ADDP(1, 0b01, Vm, Vn, Vd))
|
||||
#define VADDPQ_32(Vd, Vn, Vm) EMIT(ADDP(1, 0b10, Vm, Vn, Vd))
|
||||
#define VADDPQ_64(Vd, Vn, Vm) EMIT(ADDP(1, 0b11, Vm, Vn, Vd))
|
||||
#define VADDP_8(Vd, Vn, Vm) EMIT(ADDP(0, 0b00, Vm, Vn, Vd))
|
||||
#define VADDP_16(Vd, Vn, Vm) EMIT(ADDP(0, 0b01, Vm, Vn, Vd))
|
||||
#define VADDP_32(Vd, Vn, Vm) EMIT(ADDP(0, 0b10, Vm, Vn, Vd))
|
||||
#define VADDPQ_8(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b00, Vm, Vn, Vd))
|
||||
#define VADDPQ_16(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b01, Vm, Vn, Vd))
|
||||
#define VADDPQ_32(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b10, Vm, Vn, Vd))
|
||||
#define VADDPQ_64(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b11, Vm, Vn, Vd))
|
||||
#define VADDP_8(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b00, Vm, Vn, Vd))
|
||||
#define VADDP_16(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b01, Vm, Vn, Vd))
|
||||
#define VADDP_32(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b10, Vm, Vn, Vd))
|
||||
|
||||
#define FADDP_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11010<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFADDPQS(Vd, Vn, Vm) EMIT(FADDP_vector(1, 0, Vm, Vn, Vd))
|
||||
#define VFADDPQD(Vd, Vn, Vm) EMIT(FADDP_vector(1, 1, Vm, Vn, Vd))
|
||||
|
||||
// NEG / ABS
|
||||
#define FNEGABS_scalar(type, opc, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (opc)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
#define FNEGS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b10, Sn, Sd))
|
||||
#define FNEGD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b10, Dn, Dd))
|
||||
|
||||
#define FABSS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b01, Sn, Sd))
|
||||
#define FABSD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b01, Dn, Dd))
|
||||
|
||||
|
||||
// MUL
|
||||
#define FMUL_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11011<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFMULS(Sd, Sn, Sm) EMIT(FMUL_vector(0, 0, Sm, Sn, Sd))
|
||||
@@ -1019,8 +1147,8 @@
|
||||
#define SCVTFDx(Dd, Xn) EMIT(SCVTF_scalar(1, 0b01, 0b00, 0b010, Xn, Dd))
|
||||
|
||||
#define SCVTF_vector_scalar(U, sz, Rn, Rd) (1<<30 | (U)<<29 | 0b11110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define SCVTFSS(Vd, Vn) EMIT(SCVT_vector_scalar(0, 0, Vn, Vd))
|
||||
#define SCVTFDD(Vd, Vn) EMIT(SCVT_vector_scalar(0, 1, Vn, Vd))
|
||||
#define SCVTFSS(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 0, Vn, Vd))
|
||||
#define SCVTFDD(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 1, Vn, Vd))
|
||||
|
||||
#define SCVTF_vector(Q, U, sz, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define SCVTFS(Vd, Vn) EMIT(SCVTF_vector(0, 0, 0, Vn, Vd))
|
||||
@@ -1028,6 +1156,28 @@
|
||||
#define SCVTQFS(Vd, Vn) EMIT(SCVTF_vector(1, 0, 0, Vn, Vd))
|
||||
#define SCVTQFD(Vd, Vn) EMIT(SCVTF_vector(1, 0, 1, Vn, Vd))
|
||||
|
||||
// FRINTI Floating-point Round to Integral, using current rounding mode from FPCR (vector).
|
||||
#define FRINT_vector(Q, U, o2, sz, o1, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o2)<<23 | (sz)<<22 | 0b10000<<17 | 0b1100<<13 | (o1)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define VFRINTIS(Vd,Vn) EMIT(FRINT_vector(0, 1, 1, 0, 1, Vn, Vd))
|
||||
#define VFRINTISQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 0, 1, Vn, Vd))
|
||||
#define VFRINTIDQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 1, 1, Vn, Vd))
|
||||
|
||||
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
|
||||
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
|
||||
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
|
||||
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
|
||||
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
|
||||
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
|
||||
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
|
||||
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
|
||||
#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))
|
||||
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
|
||||
#define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
|
||||
#define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
|
||||
#define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
|
||||
|
||||
// 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))
|
||||
#define VFMINS(Vd, Vn, Vm) EMIT(FMINMAX_vector(0, 0, 1, 0, Vm, Vn, Vd))
|
||||
@@ -1088,6 +1238,7 @@
|
||||
#define TBL_gen(Q, Rm, len, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (Rm)<<16 | (len)<<13 | (op)<<12 | (Rn)<<5 | (Rd))
|
||||
//Use Rm[] to pick from Rn element and store in Rd. Out-of-range element gets 0
|
||||
#define VTBLQ1_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b00, 0, Rn, Rd))
|
||||
#define VTBL1_8(Rd, Rn, Rm) EMIT(TBL_gen(0, Rm, 0b00, 0, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn, Rn+1 element and store in Rd. Out-of-range element gets 0
|
||||
#define VTBLQ2_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b01, 0, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn, Rn+1, Rn+2 element and store in Rd. Out-of-range element gets 0
|
||||
@@ -1116,6 +1267,14 @@
|
||||
#define VTRNQ2_8(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b00, Vm, 1, Vn, Vd))
|
||||
|
||||
// QXTN / QXTN2
|
||||
#define QXTN_scalar(U, size, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 0b10000<<17 | 0b10100<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
// Signed saturating extract Narrow, from D to S
|
||||
#define SQXTN_S_D(Sd, Dn) EMIT(QXTN_scalar(0, 0b10, Dn, Sd))
|
||||
// Signed saturating extract Narrow, from S to H
|
||||
#define SQXTN_H_S(Hd, Sn) EMIT(QXTN_scalar(0, 0b01, Sn, Hd))
|
||||
// Signed saturating extract Narrow, from H to B
|
||||
#define SQXTN_B_H(Bd, Hn) EMIT(QXTN_scalar(0, 0b00, Hn, Bd))
|
||||
|
||||
#define QXTN_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b10100<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
// Signed saturating extract Narrow, takes Rn element and reduce 64->32 with Signed saturation and fit lower part of Rd
|
||||
#define SQXTN_32(Rd, Rn) EMIT(QXTN_vector(0, 0, 0b10, Rn, Rd))
|
||||
@@ -1129,22 +1288,39 @@
|
||||
#define SQXTN_8(Rd, Rn) EMIT(QXTN_vector(0, 0, 0b00, Rn, Rd))
|
||||
// Signed saturating extract Narrow, takes Rn element and reduce 16->8 with Signed saturation and fit higher part of Rd
|
||||
#define SQXTN2_8(Rd, Rn) EMIT(QXTN_vector(1, 0, 0b00, Rn, Rd))
|
||||
// Unsigned saturating Extract Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit lower part of Rd
|
||||
#define UQXTN_32(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b10, Rn, Rd))
|
||||
// Unsigned saturating Extract Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit higher part of Rd
|
||||
#define UQXTN2_32(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b10, Rn, Rd))
|
||||
// Unsigned saturating extract Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit lower part of Rd
|
||||
#define UQXTN_16(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b01, Rn, Rd))
|
||||
// Unsigned saturating extract Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit higher part of Rd
|
||||
#define UQXTN2_16(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b01, Rn, Rd))
|
||||
// Unsigned saturating extract Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit lower part of Rd
|
||||
#define UQXTN_8(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b00, Rn, Rd))
|
||||
// Unsigned saturating extract Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit higher part of Rd
|
||||
#define UQXTN2_8(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b00, Rn, Rd))
|
||||
|
||||
#define QXTUN_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b10010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit lower part of Rd
|
||||
#define SQXTUN_32(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b10, Rn, Rd))
|
||||
#define SQXTUN_32(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b10, Rn, Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit higher part of Rd
|
||||
#define SQXTUN2_32(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b10, Rn, Rd))
|
||||
#define SQXTUN2_32(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b10, Rn, Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit lower part of Rd
|
||||
#define SQXTUN_16(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b01, Rn, Rd))
|
||||
#define SQXTUN_16(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b01, Rn, Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit higher part of Rd
|
||||
#define SQXTUN2_16(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b01, Rn, Rd))
|
||||
#define SQXTUN2_16(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b01, Rn, Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit lower part of Rd
|
||||
#define SQXTUN_8(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b00, Rn, Rd))
|
||||
#define SQXTUN_8(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b00, Rn, Rd))
|
||||
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit higher part of Rd
|
||||
#define SQXTUN2_8(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b00, Rn, Rd))
|
||||
#define SQXTUN2_8(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b00, Rn, Rd))
|
||||
|
||||
// Integer CMP
|
||||
// EQual
|
||||
#define CMEQ_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10001<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VCMEQ_8(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b00, Rm, Rn, Rd))
|
||||
#define VCMEQ_16(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b01, Rm, Rn, Rd))
|
||||
#define VCMEQ_32(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b10, Rm, Rn, Rd))
|
||||
#define VCMEQQ_8(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b00, Rm, Rn, Rd))
|
||||
#define VCMEQQ_16(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b01, Rm, Rn, Rd))
|
||||
#define VCMEQQ_32(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b10, Rm, Rn, Rd))
|
||||
@@ -1172,6 +1348,22 @@
|
||||
#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))
|
||||
|
||||
// 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))
|
||||
#define FCMEQQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 0, 0, 1, Rm, 0, Rn, Rd))
|
||||
#define FCMEQQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 0, 0, 0, Rm, 0, Rn, Rd))
|
||||
// Greater or Equal
|
||||
#define FCMGEQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 1, Rm, 0, Rn, Rd))
|
||||
#define FCMGEQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 0, Rm, 0, Rn, Rd))
|
||||
#define FCMGEQD_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 1, Rm, 1, Rn, Rd))
|
||||
#define FCMGEQS_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 0, Rm, 1, Rn, Rd))
|
||||
// Greater Than
|
||||
#define FCMGTQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 1, Rm, 0, Rn, Rd))
|
||||
#define FCMGTQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 0, Rm, 0, Rn, Rd))
|
||||
#define FCMGTQD_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 1, Rm, 1, Rn, Rd))
|
||||
#define FCMGTQS_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 0, Rm, 1, Rn, Rd))
|
||||
|
||||
// UMULL / SMULL
|
||||
#define MULL_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b1100<<12 |(Rn)<<5 |(Rd))
|
||||
#define VUMULL_8(Rd, Rn, Rm) EMIT(MULL_vector(0, 1, 0b00, Rm, Rn, Rd))
|
||||
@@ -1180,5 +1372,259 @@
|
||||
#define VUMULL2_8(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b00, Rm, Rn, Rd))
|
||||
#define VUMULL2_16(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b01, Rm, Rn, Rd))
|
||||
#define VUMULL2_32(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b10, Rm, Rn, Rd))
|
||||
#define VSMULL_8(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b00, Rm, Rn, Rd))
|
||||
#define VSMULL_16(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b01, Rm, Rn, Rd))
|
||||
#define VSMULL_32(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b10, Rm, Rn, Rd))
|
||||
#define VSMULL2_8(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b00, Rm, Rn, Rd))
|
||||
#define VSMULL2_16(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b01, Rm, Rn, Rd))
|
||||
#define VSMULL2_32(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b10, Rm, Rn, Rd))
|
||||
|
||||
// MUL
|
||||
#define MUL_vector(Q, size, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10011<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define VMUL_8(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b00, Vm, Vn, Vd))
|
||||
#define VMUL_16(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b01, Vm, Vn, Vd))
|
||||
#define VMUL_32(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b10, Vm, Vn, Vd))
|
||||
#define VMULQ_8(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b00, Vm, Vn, Vd))
|
||||
#define VMULQ_16(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b01, Vm, Vn, Vd))
|
||||
#define VMULQ_32(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
// (S/Q)ADD
|
||||
#define QADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00001<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SQADDQ_8(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SQADDQ_16(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQADDQ_32(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SQADDQ_64(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b11, Vm, Vn, Vd))
|
||||
#define UQADDQ_8(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UQADDQ_16(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UQADDQ_32(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b10, Vm, Vn, Vd))
|
||||
#define UQADDQ_64(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b11, Vm, Vn, Vd))
|
||||
#define SQADD_8(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SQADD_16(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQADD_32(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SQADD_64(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b11, Vm, Vn, Vd))
|
||||
#define UQADD_8(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UQADD_16(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UQADD_32(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
#define UQADD_64(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b11, Vm, Vn, Vd))
|
||||
|
||||
// Absolute Difference
|
||||
#define AD_vector(Q, U, size, Rm, ac, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b0111<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
// Signed Absolute Difference and accumulate
|
||||
#define SABAQ_8(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b00, Rm, 1, Rn, Rd))
|
||||
#define SABAQ_16(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b01, Rm, 1, Rn, Rd))
|
||||
#define SABAQ_32(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b10, Rm, 1, Rn, Rd))
|
||||
#define SABA_8(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b00, Rm, 1, Rn, Rd))
|
||||
#define SABA_16(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b01, Rm, 1, Rn, Rd))
|
||||
#define SABA_32(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b10, Rm, 1, Rn, Rd))
|
||||
// Signed Absolute Difference
|
||||
#define SABDQ_8(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define SABDQ_16(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b01, Rm, 0, Rn, Rd))
|
||||
#define SABDQ_32(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b10, Rm, 0, Rn, Rd))
|
||||
#define SABD_8(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define SABD_16(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b01, Rm, 0, Rn, Rd))
|
||||
#define SABD_32(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b10, Rm, 0, Rn, Rd))
|
||||
|
||||
#define ADL_vector(Q, U, size, Rm, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b01<<14 | (op)<<13 | 1<<12 | (Rn)<<5 | (Rd))
|
||||
#define SABAL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define SABAL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b00, Rm, 0, Rn, Rd))
|
||||
#define SABAL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b01, Rm, 0, Rn, Rd))
|
||||
#define SABAL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b01, Rm, 0, Rn, Rd))
|
||||
#define SABAL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b10, Rm, 0, Rn, Rd))
|
||||
#define SABAL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b10, Rm, 0, Rn, Rd))
|
||||
#define UABAL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b00, Rm, 0, Rn, Rd))
|
||||
#define UABAL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b00, Rm, 0, Rn, Rd))
|
||||
#define UABAL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b01, Rm, 0, Rn, Rd))
|
||||
#define UABAL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b01, Rm, 0, Rn, Rd))
|
||||
#define UABAL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b10, Rm, 0, Rn, Rd))
|
||||
#define UABAL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b10, Rm, 0, Rn, Rd))
|
||||
#define SABDL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b00, Rm, 1, Rn, Rd))
|
||||
#define SABDL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b00, Rm, 1, Rn, Rd))
|
||||
#define SABDL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b01, Rm, 1, Rn, Rd))
|
||||
#define SABDL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b01, Rm, 1, Rn, Rd))
|
||||
#define SABDL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b10, Rm, 1, Rn, Rd))
|
||||
#define SABDL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b10, Rm, 1, Rn, Rd))
|
||||
#define UABDL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b00, Rm, 1, Rn, Rd))
|
||||
#define UABDL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b00, Rm, 1, Rn, Rd))
|
||||
#define UABDL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b01, Rm, 1, Rn, Rd))
|
||||
#define UABDL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b01, Rm, 1, Rn, Rd))
|
||||
#define UABDL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b10, Rm, 1, Rn, Rd))
|
||||
#define UABDL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b10, Rm, 1, Rn, Rd))
|
||||
|
||||
// Add Pairwise
|
||||
#define ADDLP_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (op)<<14 | 0b10<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define SADDLPQ_8(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b00, 0, Rn, Rd))
|
||||
#define SADDLPQ_16(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b01, 0, Rn, Rd))
|
||||
#define SADDLPQ_32(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b10, 0, Rn, Rd))
|
||||
#define SADDLP_8(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b00, 0, Rn, Rd))
|
||||
#define SADDLP_16(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b01, 0, Rn, Rd))
|
||||
#define SADDLP_32(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b10, 0, Rn, Rd))
|
||||
#define UADDLPQ_8(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b00, 0, Rn, Rd))
|
||||
#define UADDLPQ_16(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b01, 0, Rn, Rd))
|
||||
#define UADDLPQ_32(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b10, 0, Rn, Rd))
|
||||
#define UADDLP_8(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b00, 0, Rn, Rd))
|
||||
#define UADDLP_16(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b01, 0, Rn, Rd))
|
||||
#define UADDLP_32(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b10, 0, Rn, Rd))
|
||||
|
||||
// Add accros vector
|
||||
#define ADDLV_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b11000<<17 | 0b00011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
#define SADDLVQ_8(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b00, Rn, Rd))
|
||||
#define SADDLVQ_16(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b01, Rn, Rd))
|
||||
#define SADDLVQ_32(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b10, Rn, Rd))
|
||||
#define SADDLV_8(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b00, Rn, Rd))
|
||||
#define SADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b01, Rn, Rd))
|
||||
#define SADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b10, Rn, Rd))
|
||||
#define UADDLVQ_8(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b00, Rn, Rd))
|
||||
#define UADDLVQ_16(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b01, Rn, Rd))
|
||||
#define UADDLVQ_32(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b10, Rn, Rd))
|
||||
#define UADDLV_8(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b00, Rn, Rd))
|
||||
#define UADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b01, Rn, Rd))
|
||||
#define UADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b10, Rn, Rd))
|
||||
|
||||
// MOV Immediate
|
||||
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
|
||||
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
|
||||
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
|
||||
|
||||
// SHLL and eXtend Long
|
||||
#define SHLL_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b10100<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define USHLL2_8(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0001, (imm)&0x7, Vn, Vd))
|
||||
#define USHLL_8(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0001, (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL2_8(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0001, (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL_8(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0001, (imm)&0x7, Vn, Vd))
|
||||
#define USHLL2_16(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
|
||||
#define USHLL_16(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL2_16(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL_16(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
|
||||
#define USHLL2_32(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
|
||||
#define USHLL_32(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL2_32(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
|
||||
#define SSHLL_32(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
|
||||
|
||||
#define UXTL_8(Vd, Vn) USHLL_8(Vd, Vn, 0)
|
||||
#define UXTL2_8(Vd, Vn) USHLL2_8(Vd, Vn, 0)
|
||||
#define UXTL_16(Vd, Vn) USHLL_16(Vd, Vn, 0)
|
||||
#define UXTL2_16(Vd, Vn) USHLL2_16(Vd, Vn, 0)
|
||||
#define UXTL_32(Vd, Vn) USHLL_32(Vd, Vn, 0)
|
||||
#define UXTL2_32(Vd, Vn) USHLL2_32(Vd, Vn, 0)
|
||||
|
||||
#define SXTL_8(Vd, Vn) SSHLL_8(Vd, Vn, 0)
|
||||
#define SXTL2_8(Vd, Vn) SSHLL2_8(Vd, Vn, 0)
|
||||
#define SXTL_16(Vd, Vn) SSHLL_16(Vd, Vn, 0)
|
||||
#define SXTL2_16(Vd, Vn) SSHLL2_16(Vd, Vn, 0)
|
||||
#define SXTL_32(Vd, Vn) SSHLL_32(Vd, Vn, 0)
|
||||
#define SXTL2_32(Vd, Vn) SSHLL2_32(Vd, Vn, 0)
|
||||
|
||||
// SHRN
|
||||
#define QSHRN_vector(Q, U, immh, immb, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b1001<<12 | (op)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define UQSHRN_8(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
|
||||
#define UQSHRN2_8(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN_8(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN2_8(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
|
||||
#define UQSHRN_16(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
|
||||
#define UQSHRN2_16(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN_16(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN2_16(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
|
||||
#define UQSHRN_32(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
|
||||
#define UQSHRN2_32(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN_32(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
|
||||
#define SQSHRN2_32(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
|
||||
|
||||
// UQSUB
|
||||
#define QSUB_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00101<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define UQSUB_8(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UQSUB_16(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UQSUB_32(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
#define UQSUB_64(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b11, Vm, Vn, Vd))
|
||||
#define SQSUB_8(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SQSUB_16(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQSUB_32(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SQSUB_64(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b11, Vm, Vn, Vd))
|
||||
#define UQSUBQ_8(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UQSUBQ_16(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UQSUBQ_32(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b10, Vm, Vn, Vd))
|
||||
#define UQSUBQ_64(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b11, Vm, Vn, Vd))
|
||||
#define SQSUBQ_8(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SQSUBQ_16(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQSUBQ_32(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SQSUBQ_64(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b11, Vm, Vn, Vd))
|
||||
|
||||
// MAX/MIN vector
|
||||
#define MINMAX_vector(Q, U, size, Rm, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b0110<<12 | (op)<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 0, Vn, Vd))
|
||||
#define SMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 0, Vn, Vd))
|
||||
#define SMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 0, Vn, Vd))
|
||||
#define SMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 0, Vn, Vd))
|
||||
#define UMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 0, Vn, Vd))
|
||||
#define UMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 0, Vn, Vd))
|
||||
#define UMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 0, Vn, Vd))
|
||||
#define UMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 0, Vn, Vd))
|
||||
#define SMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 1, Vn, Vd))
|
||||
#define SMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 1, Vn, Vd))
|
||||
#define SMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 1, Vn, Vd))
|
||||
#define SMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 1, Vn, Vd))
|
||||
#define UMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 1, Vn, Vd))
|
||||
#define UMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 1, Vn, Vd))
|
||||
#define UMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 1, Vn, Vd))
|
||||
#define UMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 1, Vn, Vd))
|
||||
#define SMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 0, Vn, Vd))
|
||||
#define SMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 0, Vn, Vd))
|
||||
#define SMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 0, Vn, Vd))
|
||||
#define SMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 0, Vn, Vd))
|
||||
#define UMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 0, Vn, Vd))
|
||||
#define UMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 0, Vn, Vd))
|
||||
#define UMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 0, Vn, Vd))
|
||||
#define UMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 0, Vn, Vd))
|
||||
#define SMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 1, Vn, Vd))
|
||||
#define SMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 1, Vn, Vd))
|
||||
#define SMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 1, Vn, Vd))
|
||||
#define SMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 1, Vn, Vd))
|
||||
#define UMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 1, Vn, Vd))
|
||||
#define UMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 1, Vn, Vd))
|
||||
#define UMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 1, Vn, Vd))
|
||||
#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
|
||||
|
||||
// HADD vector
|
||||
#define HADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SHADD_16(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SHADD_32(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SHADDQ_8(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SHADDQ_16(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SHADDQ_32(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b10, Vm, Vn, Vd))
|
||||
#define UHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UHADD_16(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UHADD_32(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
#define UHADDQ_8(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b00, Vm, Vn, Vd))
|
||||
#define UHADDQ_16(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b01, Vm, Vn, Vd))
|
||||
#define UHADDQ_32(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
#define RHADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00010<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SRHADD_8(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SRHADD_16(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SRHADD_32(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SRHADDQ_8(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SRHADDQ_16(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SRHADDQ_32(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b10, Vm, Vn, Vd))
|
||||
#define URHADD_8(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b00, Vm, Vn, Vd))
|
||||
#define URHADD_16(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define URHADD_32(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
#define URHADDQ_8(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b00, Vm, Vn, Vd))
|
||||
#define URHADDQ_16(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b01, Vm, Vn, Vd))
|
||||
#define URHADDQ_32(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b10, Vm, Vn, Vd))
|
||||
|
||||
// QRDMULH Signed saturating (Rounding) Doubling Multiply returning High half
|
||||
#define QDMULH_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10110<<11 | 1<<10 | (Rn)<<5 | (Rd))
|
||||
#define SQRDMULH_8(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b00, Vm, Vn, Vd))
|
||||
#define SQRDMULH_16(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b01, Vm, Vn, Vd))
|
||||
#define SQRDMULH_32(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b10, Vm, Vn, Vd))
|
||||
#define SQRDMULHQ_8(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b00, Vm, Vn, Vd))
|
||||
#define SQRDMULHQ_16(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b01, Vm, Vn, Vd))
|
||||
#define SQRDMULHQ_32(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b10, Vm, Vn, Vd))
|
||||
#define SQDMULH_8(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b00, Vm, Vn, Vd))
|
||||
#define SQDMULH_16(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b01, Vm, Vn, Vd))
|
||||
#define SQDMULH_32(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b10, Vm, Vn, Vd))
|
||||
#define SQDMULHQ_8(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b00, Vm, Vn, Vd))
|
||||
#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))
|
||||
|
||||
#endif //__ARM64_EMITTER_H__
|
||||
@@ -13,8 +13,11 @@
|
||||
.global arm64_lock_write_d
|
||||
.global arm64_lock_read_dd
|
||||
.global arm64_lock_write_dd
|
||||
.global arm64_lock_read_dq
|
||||
.global arm64_lock_write_dq
|
||||
.global arm64_lock_xchg
|
||||
.global arm64_lock_storeifnull
|
||||
.global arm64_lock_storeifref
|
||||
|
||||
|
||||
arm64_lock_read_b:
|
||||
@@ -64,24 +67,49 @@ arm64_lock_write_dd:
|
||||
stlxr w0, x1, [x2]
|
||||
ret
|
||||
|
||||
arm64_lock_read_dq:
|
||||
// address is r2, return is r0, r1
|
||||
ldaxp x4, x3, [x2]
|
||||
str x4, [x0]
|
||||
str x3, [x1]
|
||||
ret
|
||||
|
||||
arm64_lock_write_dq:
|
||||
// address is r2, value is r0, r1, return is r0
|
||||
// r0 needs to be aligned
|
||||
stlxp w3, x0, x1, [x2]
|
||||
mov w0, w3
|
||||
ret
|
||||
|
||||
|
||||
arm64_lock_xchg:
|
||||
// address is x0, value is x1, return old value in x0
|
||||
ldaxr x2, [x0]
|
||||
stlxr w3, x1, [x0]
|
||||
cmp w3, #1
|
||||
beq arm64_lock_xchg
|
||||
cbnz w3, arm64_lock_xchg
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
|
||||
ldaxr x2, [x0]
|
||||
cmp x2, #0
|
||||
bne arm64_lock_storeifnull_exit
|
||||
cbnz x2, arm64_lock_storeifnull_exit
|
||||
mov x2, x1
|
||||
stlxr w3, x2, [x0]
|
||||
cmp w3, #1
|
||||
beq arm64_lock_storeifnull
|
||||
cbnz w3, arm64_lock_storeifnull
|
||||
arm64_lock_storeifnull_exit:
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
|
||||
ldaxr x3, [x0]
|
||||
cmp x2, x3
|
||||
bne arm64_lock_storeifref_exit
|
||||
stlxr w4, x1, [x0]
|
||||
cbnz w4, arm64_lock_storeifref
|
||||
mov x0, x1
|
||||
ret
|
||||
arm64_lock_storeifref_exit:
|
||||
mov x0, x3
|
||||
ret
|
||||
@@ -17,15 +17,23 @@ extern uint32_t arm64_lock_read_d(void* addr);
|
||||
// STLXR of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_d(void* addr, uint32_t val);
|
||||
|
||||
// LDAXRD of ADDR
|
||||
// LDAXR of ADDR
|
||||
extern uint64_t arm64_lock_read_dd(void* addr);
|
||||
// STLXR of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dd(void* addr, uint64_t val);
|
||||
|
||||
// LDAXRD of ADDR
|
||||
extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
|
||||
// STLXRD of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
|
||||
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifnull(void*p, void* val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
@@ -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
|
||||
// preserve return value
|
||||
|
||||
+274
-6
@@ -180,10 +180,21 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
}
|
||||
if(isMask(opcode, "0x011000iiiiiiiiiiiiiiiiiiittttt", &a)) {
|
||||
int size = ((opcode>>30)&1)?3:2;
|
||||
int offset = signExtend(imm, 9)<<size;
|
||||
int offset = signExtend(imm, 19)<<2;
|
||||
snprintf(buff, sizeof(buff), "LDR %s, [#%+d]\t;%p", (size==2)?Wt[Rt]:Xt[Rt], offset, (void*)(addr+offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "10011000iiiiiiiiiiiiiiiiiiittttt", &a)) {
|
||||
int offset = signExtend(imm, 19)<<2;
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [#%+d]\t;%p", Xt[Rt], offset, (void*)(addr+offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "ff011100iiiiiiiiiiiiiiiiiiittttt", &a)) {
|
||||
int offset = signExtend(imm, 19)<<2;
|
||||
const char* Y[] = {"S", "D", "Q", "?"};
|
||||
snprintf(buff, sizeof(buff), "LDR %s%d, [#%+d]\t;%p", Y[sf], Rt, offset, (void*)(addr+offset));
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "1x111000011mmmmmoooS10nnnnnttttt", &a)) {
|
||||
int size = (opcode>>30)&3;
|
||||
const char* extend[] = {"?0", "?1", "UXTW", "LSL", "?4", "?5", "SXTW", "SXTX"};
|
||||
@@ -275,6 +286,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], offset);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "011110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
int offset = imm<<1;
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "LDRSH %s, [%s]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "LDRSH %s, [%s, #%d]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], offset);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "001110011xiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
int offset = imm<<1;
|
||||
if(!offset)
|
||||
@@ -699,7 +718,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
if(isMask(opcode, "f1011010100mmmmmdddd00nnnnnddddd", &a)) {
|
||||
if(isMask(opcode, "f1011010100mmmmmcccc00nnnnnddddd", &a)) {
|
||||
if(Rm!=31 && (cond&0b1110)!=0b1110 && Rn!=31 && Rn==Rm)
|
||||
snprintf(buff, sizeof(buff), "CINV %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond^1]);
|
||||
else if(Rm==31 && (cond&0b1110)!=0b1110 && Rn==31)
|
||||
@@ -840,6 +859,42 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
// VADD / VSUB
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm100001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[((sf)<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "V%s V%d.%s, V%d.%s, V%d.%s", a.U?"SUB":"ADD", Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// VMUL
|
||||
if(isMask(opcode, "0Q001110ff1mmmmm100111nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[((sf)<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "VMUL V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
// CMP
|
||||
if(isMask(opcode, "0Q101110ff1mmmmm100011nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[((sf)<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "VCMEQ V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// Shift
|
||||
if(isMask(opcode, "0QU011110hhhhrrr000001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd ="??";
|
||||
int s = 0;
|
||||
if(shift==0b0001) {Vd = Y[a.Q]; s=16-((shift)<<3 | immr);}
|
||||
else if((shift&0b1110)==0b0010) {Vd = Y[2+a.Q]; s=32-((shift)<<3 | immr);}
|
||||
else if((shift&0b1100)==0b0100) {Vd = Y[4+a.Q]; s=64-((shift)<<3 | immr);}
|
||||
else if((shift&0b1000)==0b1000) {Vd = Y[6+a.Q]; s=128-((shift)<<3 | immr);}
|
||||
snprintf(buff, sizeof(buff), "%cSHR V%d.%s, V%d.%s, #%d", a.U?'U':'S', Rd, Vd, Rn, Vd, s);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// INS
|
||||
if(isMask(opcode, "01101110000rrrrr0ssss1nnnnnddddd", &a)) {
|
||||
char s = '?';
|
||||
@@ -905,7 +960,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "VFSUB %c%d.%d%c, %c%d.%d%c, %c%d.%c%d", s, Rd, n, d, s, Rn, n, d, s, Rm, s, d);
|
||||
snprintf(buff, sizeof(buff), "VFSUB %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "00011110ff1mmmmm001110nnnnnddddd", &a)) {
|
||||
@@ -933,7 +988,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "VFDIV %c%d.%d%c, %c%d.%d%c, %c%d.%c%d", s, Rd, n, d, s, Rn, n, d, s, Rm, s, d);
|
||||
snprintf(buff, sizeof(buff), "VFDIV %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "00011110ff1mmmmm000110nnnnnddddd", &a)) {
|
||||
@@ -965,6 +1020,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "FCMP %c%d, %c%d", s, Rn, s, Rm);
|
||||
return buff;
|
||||
}
|
||||
//FMIN/FMAX
|
||||
if(isMask(opcode, "00011110ff1mmmmm01oo10nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
snprintf(buff, sizeof(buff), "F%s %c%d, %c%d, %c%d", (option==3)?"MINNM":((option==2)?"MINNMP":((!option)?"MAXNM":"MAXNMP")), s, Rd, s, Rn, s, Rm);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0Q001110of1mmmmm110001nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
int n = (sf==0)?2:1;
|
||||
n *= a.Q?2:1;
|
||||
snprintf(buff, sizeof(buff), "F%sNM%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FCVT
|
||||
if(isMask(opcode, "f0011110pp10010U000000nnnnnddddd", &a)) {
|
||||
@@ -992,6 +1060,13 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "SCVTF %c%d, %s", s, Rd, sf?Xt[Rn]:Wt[Rn]);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU011100f100001110110nnnnnddddd", &a)) {
|
||||
char s = a.Q?'V':'D';
|
||||
char d = sf?'D':'S';
|
||||
int n = (a.Q && !sf)?4:2;
|
||||
snprintf(buff, sizeof(buff), "%cCVTF %c%d.%d%c, %c%d.%d%c", a.U?'U':'S', s, Rd, n, d, s, Rn, n, d);
|
||||
return buff;
|
||||
}
|
||||
|
||||
if(isMask(opcode, "0001111000100010110000nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "FCVT D%d, S%d", Rd, Rn);
|
||||
@@ -1002,13 +1077,25 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0Q00111001100001011110nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "FCVTL%s V%d.2D, V%d.%dS", a.Q?"2":"", Rd, Rn, a.Q?4:0);
|
||||
snprintf(buff, sizeof(buff), "FCVTL%s V%d.2D, V%d.%dS", a.Q?"2":"", Rd, Rn, a.Q?4:2);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0Q10111000100001011010nnnnnddddd", &a)) {
|
||||
if(isMask(opcode, "0Q10111001100001011010nnnnnddddd", &a)) {
|
||||
snprintf(buff, sizeof(buff), "FCVTXN%s V%d.%dS, V%d.2D", a.Q?"2":"", Rd, a.Q?4:2, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "01U11110of100001101o10nnnnnddddd", &a)) {
|
||||
char s = (sf==0)?'S':((sf==1)?'D':'?');
|
||||
const char* roundings[] = {"N", "M", "P", "Z"};
|
||||
snprintf(buff, sizeof(buff), "FCVT%s%s %c%d, %c%d", roundings[option], a.U?"U":"", s, Rd, s, Rn);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "f0011110oo1cc000000000nnnnnddddd", &a)) {
|
||||
char s = (option==0)?'S':((option==1)?'D':'?');
|
||||
const char* roundings[] = {"N", "P", "M", "Z"};
|
||||
snprintf(buff, sizeof(buff), "FCVT%sS %s, %c%d", roundings[a.c], sf?Xt[Rd]:Wt[Rd], s, Rn);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// FMOV
|
||||
if(isMask(opcode, "00011110pp100000010000nnnnnddddd", &a)) {
|
||||
@@ -1031,6 +1118,187 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
return buff;
|
||||
}
|
||||
|
||||
// TBL / TBX
|
||||
if(isMask(opcode, "0Q001110000mmmmm0ffo00nnnnnddddd", &a)) {
|
||||
char X = (option)?'X':'L';
|
||||
const char* Y = (a.Q)?"16B":"8B";
|
||||
if(sf==0)
|
||||
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rm, Y);
|
||||
else if(sf==1)
|
||||
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rm, Y);
|
||||
else if(sf==2)
|
||||
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rn+2, Rm, Y);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B, V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rn+2, Rn+3, Rm, Y);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// ZIP / UZP
|
||||
if(isMask(opcode, "0Q001110ff0mmmmm0o1110nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "ZIP%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0Q001110ff0mmmmm0o0110nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "UZP%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// EXT
|
||||
if(isMask(opcode, "0Q101110000mmmmm0iiii0nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B"};
|
||||
const char* Vd = Y[a.Q];
|
||||
snprintf(buff, sizeof(buff), "EXT V%d.%s, V%d.%s, V%d.%s, #%d", Rd, Vd, Rn, Vd, Rm, Vd, imm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// Absolute Difference
|
||||
// SABA / SABD / UABA / UABD
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm0111c1nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "%cAB%c V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm01c100nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* Z[] = {"8H", "4S", "2D", "?"};
|
||||
const char* Va = Z[(sf<<1)];
|
||||
snprintf(buff, sizeof(buff), "%cAB%cL%s V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', a.Q?"2":"", Rd, Va, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
// Add pair / accros vector
|
||||
if(isMask(opcode, "0QU01110ff1000000c1010nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* Z[] = {"4H", "8H", "2S", "4S", "1D", "2D", "??", "???"};
|
||||
const char* Va = Z[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "%cAD%cLP V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', Rd, Va, Rn, Vd);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU01110ff110000001110nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* Z[] = {"H", "S", "D", "?"};
|
||||
snprintf(buff, sizeof(buff), "%cADDLV V%d.%s, V%d.%s", a.U?'U':'S', Rd, Z[sf], Rn, Vd);
|
||||
return buff;
|
||||
}
|
||||
// HADD
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm000001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "%cHADD V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm000101nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "%cRHADD V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
//SQ(R)DMULH
|
||||
if(isMask(opcode, "0QU01110ff1mmmmm101101nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
snprintf(buff, sizeof(buff), "SQ%sDMULH V%d.%s, V%d.%s, V%d.%s", a.U?"R":"", Rd, Vd, Rn, Vd, Rm, Vd);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// MOV immediate
|
||||
if(isMask(opcode, "0Q00111100000iii111001iiiiiddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B"};
|
||||
const char* Vd = Y[a.Q];
|
||||
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// LD1/ST1 single structure
|
||||
if(isMask(opcode, "0Q0011010L000000cc0Sffnnnnnttttt", &a)) {
|
||||
int scale = a.c;
|
||||
int idx = 0;
|
||||
const char* Y[] = {"B", "H", "S", "D"};
|
||||
switch(scale) {
|
||||
case 3: scale = sf; /* rep = 1; */ break;
|
||||
case 0: idx = (a.Q<<3) | (a.S<<2) | sf; break;
|
||||
case 1: idx = (a.Q<<2) | (a.S<<1) | (sf>>1); break;
|
||||
case 2: if(!(sf&1))
|
||||
idx = (a.Q<<1) | a.S;
|
||||
else {
|
||||
scale = 3;
|
||||
idx = a.Q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
snprintf(buff, sizeof(buff), "%s1 {V%d.%s}[%d], [%s]", a.L?"LD":"ST", Rt, Y[scale], idx, XtSp[Rn]);
|
||||
return buff;
|
||||
}
|
||||
// LDUR/STUR
|
||||
if(isMask(opcode, "ff111100cL0iiiiiiiii00nnnnnttttt", &a)) {
|
||||
const char* Y[] = {"B", "H", "S", "D", "Q"};
|
||||
int sz = sf;
|
||||
if(sz==0 && a.c)
|
||||
sz = 4;
|
||||
int offset = signExtend(imm, 9);
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
|
||||
return buff;
|
||||
}
|
||||
// LDR/STR vector immediate
|
||||
if(isMask(opcode, "ff111101cLiiiiiiiiiiiinnnnnttttt", &a)) {
|
||||
const char* Y[] = {"B", "H", "S", "D", "Q"};
|
||||
int sz = sf;
|
||||
if(sz==0 && a.c)
|
||||
sz = 4;
|
||||
int offset = imm<<sz;
|
||||
if(!offset)
|
||||
snprintf(buff, sizeof(buff), "%sR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "%sR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// (S/U)QXT(U)N
|
||||
if(isMask(opcode, "0Q101110ff100001001010nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* Z[] = {"8H", "4S", "2D", "?"};
|
||||
const char* Va = Z[sf];
|
||||
snprintf(buff, sizeof(buff), "SQXTUN%s V%d.%s, V%d.%s", a.Q?"2":"", Rd, Vd, Rn, Va);
|
||||
return buff;
|
||||
}
|
||||
if(isMask(opcode, "0QU01110ff100001010010nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
|
||||
const char* Vd = Y[(sf<<1) | a.Q];
|
||||
const char* Z[] = {"8H", "4S", "2D", "?"};
|
||||
const char* Va = Z[sf];
|
||||
snprintf(buff, sizeof(buff), "%cQXTN%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Vd, Rn, Va);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// (S/U)SSHL(2) / (U/S)XTL(2)
|
||||
if(isMask(opcode, "0QU011110hhhhiii101001nnnnnddddd", &a)) {
|
||||
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
|
||||
const char* Z[] = {"8H", "4S", "2D", "?"};
|
||||
int sz = 3;
|
||||
if((a.h&0b1111)==0b0001) sz=0;
|
||||
else if((a.h&0b1110)==0b0010) sz=1;
|
||||
else if((a.h&0b1100)==0b0100) sz=2;
|
||||
int sh=(((a.h)<<3)|(imm)) - (8<<sz);
|
||||
const char* Vd = Y[(sz<<1)|a.Q];
|
||||
const char* Va = Z[sz];
|
||||
if(!sh)
|
||||
snprintf(buff, sizeof(buff), "%cXTL%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd);
|
||||
else
|
||||
snprintf(buff, sizeof(buff), "%cSHLL%s V%d.%s, V%d.%s, #%d", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd, sh);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
|
||||
|
||||
+10
-10
@@ -69,7 +69,7 @@ void FreeDynablock(dynablock_t* db)
|
||||
if(db->parent->direct) {
|
||||
uintptr_t addr = (uintptr_t)db->x64_addr;
|
||||
if(addr>=startdb && addr<enddb)
|
||||
db->parent->direct[addr-startdb] = NULL;
|
||||
arm64_lock_xchg(&db->parent->direct[addr-startdb], 0); // secured write
|
||||
}
|
||||
// remove jumptable
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
@@ -247,10 +247,6 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
return NULL;
|
||||
}
|
||||
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
|
||||
// this should be useless
|
||||
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
|
||||
//*created = 0;
|
||||
//return NULL;
|
||||
return AddNewDynablock(getDBFromAddress(addr), addr, created);
|
||||
}
|
||||
dynablock_t* block = NULL;
|
||||
@@ -323,22 +319,26 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(!created)
|
||||
return block; // existing block...
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
// fill the block
|
||||
block->x64_addr = (void*)addr;
|
||||
if(!FillBlock64(block, filladdr)) {
|
||||
void* old = (void*)arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], 0);
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
void* ret = FillBlock64(block, filladdr);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
if(old!=block && old) {// put it back in place, strange things are happening here!
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], (uintptr_t)old);
|
||||
// doing nothing else, the block as not be writen
|
||||
}
|
||||
free(block);
|
||||
block = NULL;
|
||||
}
|
||||
#if 1
|
||||
#if 0
|
||||
if(box64_dynarec_dump)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
#endif
|
||||
|
||||
@@ -37,9 +37,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
{
|
||||
#ifdef HAVE_TRACE
|
||||
if(!addr) {
|
||||
x2-=8; // actual PC is 2 instructions ahead
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2);
|
||||
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2, db, db?(void*)getX64Address(db, (uintptr_t)x2):NULL);
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
}
|
||||
#endif
|
||||
dynablock_t* current = NULL;
|
||||
@@ -47,6 +46,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
|
||||
dynablock_t* block = DBGetBlock(emu, addr, 1, ¤t);
|
||||
if(!block) {
|
||||
// no block, let link table as is...
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
//tableupdate(arm64_epilog, addr, table);
|
||||
return arm64_epilog;
|
||||
}
|
||||
|
||||
+35
-16
@@ -315,8 +315,11 @@ int Table64(dynarec_arm_t *dyn, uint64_t val)
|
||||
idx = i;
|
||||
// not found, add it
|
||||
if(idx==-1) {
|
||||
if(dyn->table64size == dyn->table64cap) {
|
||||
dyn->table64cap+=4;
|
||||
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
|
||||
}
|
||||
idx = dyn->table64size++;
|
||||
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64size * sizeof(uint64_t));
|
||||
dyn->table64[idx] = val;
|
||||
}
|
||||
// calculate offset
|
||||
@@ -325,18 +328,21 @@ int Table64(dynarec_arm_t *dyn, uint64_t val)
|
||||
}
|
||||
|
||||
|
||||
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end)
|
||||
return NULL;
|
||||
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
}
|
||||
// init the helper
|
||||
dynarec_arm_t helper = {0};
|
||||
helper.start = addr;
|
||||
arm_pass0(&helper, addr);
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
block->done = 1;
|
||||
@@ -344,11 +350,12 @@ 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);
|
||||
// pass 1, addresses, x64 jump addresses, flags
|
||||
arm_pass1(&helper, addr);
|
||||
// calculate barriers
|
||||
uintptr_t start = helper.insts[0].x64.addr;
|
||||
uintptr_t end = helper.insts[helper.size].x64.addr+helper.insts[helper.size].x64.size;
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x64.jmp) {
|
||||
uintptr_t j = helper.insts[i].x64.jmp;
|
||||
@@ -398,10 +405,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
printFunctionAddr(helper.start, " => ");
|
||||
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
helper.arm_size = 0;
|
||||
int oldtable64size = helper.table64size;
|
||||
int oldarmsize = helper.arm_size;
|
||||
helper.arm_size = 0;
|
||||
helper.table64size = 0; // reset table64 (but not the cap)
|
||||
arm_pass3(&helper, addr);
|
||||
if(sz!=(helper.arm_size + helper.table64size*8)) {
|
||||
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);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
|
||||
@@ -413,10 +422,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
//TODO: Cancel block and return empty one
|
||||
}
|
||||
// add table64 if needed
|
||||
if(helper.table64size) {
|
||||
memcpy(p+helper.arm_size, helper.table64, helper.table64size*8);
|
||||
memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
|
||||
}
|
||||
// all done...
|
||||
__clear_cache(p, p+sz); // need to clear the cache before execution...
|
||||
@@ -440,11 +450,18 @@ 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;
|
||||
block->x64_size = end-start+1;
|
||||
if(box64_dynarec_largest<block->x64_size)
|
||||
box64_dynarec_largest = block->x64_size;
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// fill sons if any
|
||||
// Check if something changed, to abbort if it as
|
||||
if(block->hash != hash) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
free(helper.sons_x64);
|
||||
free(helper.sons_arm);
|
||||
FreeDynarecMap(block, (uintptr_t)p, sz);
|
||||
return NULL;
|
||||
} // fill sons if any
|
||||
dynablock_t** sons = NULL;
|
||||
int sons_size = 0;
|
||||
if(helper.sons_size) {
|
||||
@@ -458,10 +475,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
son->x64_size = end-helper.sons_x64[i];
|
||||
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;
|
||||
sons[sons_size++] = son;
|
||||
if(!son->parent)
|
||||
son->parent = block->parent;
|
||||
sons[sons_size] = son;
|
||||
++sons_size;
|
||||
}
|
||||
}
|
||||
if(sons_size) {
|
||||
|
||||
+133
-23
@@ -24,7 +24,7 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
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)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
uint8_t gd, ed;
|
||||
@@ -37,8 +37,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint64_t u64;
|
||||
uint8_t wback, wb1, wb2;
|
||||
int fixedaddress;
|
||||
rex_t rex;
|
||||
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
|
||||
|
||||
opcode = F8;
|
||||
MAYUSE(eb1);
|
||||
@@ -47,17 +45,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MAYUSE(tmp);
|
||||
MAYUSE(j32);
|
||||
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
INST_NAME("ADD Eb, Gb");
|
||||
@@ -833,7 +820,37 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETED(0);
|
||||
emit_test32(dyn, ninst, rex, ed, gd, x3, x5);
|
||||
break;
|
||||
|
||||
case 0x86:
|
||||
INST_NAME("(LOCK)XCHG Eb, Gb");
|
||||
// Do the swap
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
GETGB(x4);
|
||||
if(rex.rex) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb1 = ed;
|
||||
eb2 = 0;
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3);
|
||||
eb2 = ((ed&4)>>2);
|
||||
}
|
||||
UBFXw(x1, eb1, eb2*8, 8);
|
||||
// do the swap 14 -> ed, 1 -> gd
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
BFIx(eb1, x4, eb2*8, 8);
|
||||
} else {
|
||||
GETGB(x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
LDAXRB(x1, ed);
|
||||
// do the swap 14 -> strb(ed), 1 -> gd
|
||||
STLXRB(x3, x4, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
}
|
||||
break;
|
||||
case 0x87:
|
||||
INST_NAME("(LOCK)XCHG Ed, Gd");
|
||||
nextop = F8;
|
||||
@@ -903,7 +920,39 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8A:
|
||||
INST_NAME("MOV Gb, Eb");
|
||||
nextop = F8;
|
||||
if(rex.rex) {
|
||||
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
gb2=0;
|
||||
} else {
|
||||
gd = (nextop&0x38)>>3;
|
||||
gb1 = xRAX+(gd&3);
|
||||
gb2 = ((gd&4)>>2);
|
||||
}
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
if(wb2) {
|
||||
UBFXw(x4, wback, wb2*8, 8);
|
||||
ed = x4;
|
||||
} else {
|
||||
ed = wback;
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
|
||||
LDRB_U12(x4, wback, fixedaddress);
|
||||
ed = x4;
|
||||
}
|
||||
BFIx(gb1, ed, gb2*8, 8);
|
||||
break;
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, Ed");
|
||||
nextop=F8;
|
||||
@@ -926,7 +975,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
|
||||
MOVxw_REG(gd, ed);
|
||||
} else if(ed>=xRAX && !rex.w) {
|
||||
}
|
||||
else if(!rex.w) {
|
||||
MOVw_REG(gd, gd); //truncate the higher 32bits as asked
|
||||
}
|
||||
}
|
||||
@@ -966,7 +1016,46 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
|
||||
case 0x9E:
|
||||
INST_NAME("SAHF");
|
||||
SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF, SF_SUBSET);
|
||||
MOV32w(x2, 0b11010101);
|
||||
BICw_REG(xFlags, xFlags, x2);
|
||||
UBFXx(x1, xRAX, 8, 8);
|
||||
ANDw_REG(x1, x1, x2);
|
||||
ORRw_REG(xFlags, xFlags, x1);
|
||||
SET_DFNONE(x1);
|
||||
break;
|
||||
case 0x9F:
|
||||
INST_NAME("LAHF");
|
||||
READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
|
||||
BFIx(xRAX, xFlags, 8, 8);
|
||||
break;
|
||||
case 0xA0:
|
||||
INST_NAME("MOV AL,Ob");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
LDRB_U12(x2, x1, 0);
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
break;
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX,Od");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
LDRxw_U12(xRAX, x1, 0);
|
||||
break;
|
||||
case 0xA2:
|
||||
INST_NAME("MOV Ob,AL");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRB_U12(xRAX, x1, 0);
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od,EAX");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRxw_U12(xRAX, x1, 0);
|
||||
break;
|
||||
case 0xA4:
|
||||
if(rep) {
|
||||
INST_NAME("REP MOVSB");
|
||||
@@ -1453,9 +1542,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
TABLE64(x3, addr); // expected return address
|
||||
CMPSx_REG(xRIP, x3);
|
||||
B_MARK(cNE);
|
||||
LDRw_U12(x1, xEmu, offsetof(x64emu_t, quit));
|
||||
CMPSw_U12(x1, 1);
|
||||
B_NEXT(cNE);
|
||||
LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit));
|
||||
CBZw_NEXT(w1);
|
||||
MARK;
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
}
|
||||
@@ -1766,7 +1854,26 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0xD8:
|
||||
addr = dynarec64_D8(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
case 0xD9:
|
||||
addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xDB:
|
||||
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xDD:
|
||||
addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xDF:
|
||||
addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("CALL Id");
|
||||
i32 = F32S;
|
||||
@@ -2061,7 +2168,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x64.set_flags, 1) {
|
||||
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
|
||||
|
||||
+726
-21
@@ -39,25 +39,27 @@
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR128_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
a = mmx_get_reg(dyn, ninst, x1, gd)
|
||||
#define GETEM(a, D) \
|
||||
if(MODREG) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, (nextop&7)); \
|
||||
|
||||
#define GETEM(a, D) \
|
||||
if(MODREG) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, (nextop&7));\
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0); \
|
||||
a = fpu_get_scratch_double(dyn); \
|
||||
VLD1_64(a, ed); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
#define PUTEM(a) \
|
||||
if(!MODREG) { \
|
||||
VST1_64(a, ed); \
|
||||
|
||||
#define PUTEM(a) \
|
||||
if(!MODREG) { \
|
||||
VSTR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -68,9 +70,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0;
|
||||
int d0, d1;
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
MAYUSE(s0);
|
||||
@@ -79,6 +82,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MAYUSE(v0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(wb2);
|
||||
@@ -91,7 +95,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
CALL(arm_ud, -1);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("MOVUPS Gx,Ex");
|
||||
@@ -188,6 +196,37 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VST1_64(v0, 1, ed);
|
||||
}
|
||||
break;
|
||||
case 0x18:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
INST_NAME("NOP (multibyte)");
|
||||
} else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("PREFETCHh Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PLD_L1_STREAM_U12(ed, fixedaddress);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("PREFETCHh Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PLD_L1_KEEP_U12(ed, fixedaddress);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("PREFETCHh Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PLD_L2_KEEP_U12(ed, fixedaddress);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("PREFETCHh Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
|
||||
PLD_L3_KEEP_U12(ed, fixedaddress);
|
||||
break;
|
||||
default:
|
||||
INST_NAME("NOP (multibyte)");
|
||||
FAKEED;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
INST_NAME("NOP (multibyte)");
|
||||
@@ -243,6 +282,55 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
INST_NAME("RDTSC");
|
||||
CALL(ReadTSC, xRAX); // will return the u64 in xEAX
|
||||
LSRx(xRDX, xRAX, 32);
|
||||
MOVw_REG(xRAX, xRAX); // wipe upper part
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
//SSE3
|
||||
nextop=F8;
|
||||
switch(nextop) {
|
||||
case 0x00:
|
||||
INST_NAME("PSHUFB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
MOVI_8(d0, 0b10001111);
|
||||
VAND(d0, d0, q1); // mask the index
|
||||
VTBL1_8(q0, q0, d0);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
INST_NAME("PMADDUBSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
UXTL_8(v0, q0); // this is unsigned, so 0 extended
|
||||
SXTL_8(v1, q1); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
SADDLPQ_16(v1, v0);
|
||||
SQXTN_16(q0, v1);
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("PMULHRSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
SQRDMULH_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
GETFLAGS; \
|
||||
@@ -261,6 +349,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GOCOND(0x40, "CMOV", "Gd, Ed");
|
||||
#undef GO
|
||||
|
||||
case 0x51:
|
||||
INST_NAME("SQRTPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX_empty(v0);
|
||||
VFSQRTQS(v0, q0);
|
||||
break;
|
||||
|
||||
case 0x54:
|
||||
INST_NAME("ANDPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -285,9 +381,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x57:
|
||||
INST_NAME("XORPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VEORQ(v0, v0, q0);
|
||||
GETG;
|
||||
if(MODREG && ((nextop&7)+(rex.b<<3)==gd)) {
|
||||
// special case for XORPS Gx, Gx
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VEORQ(q0, q0, q0);
|
||||
} else {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(q1, 0);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
INST_NAME("ADDPS Gx, Ex");
|
||||
@@ -324,6 +427,325 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETGX(v0);
|
||||
VFSUBQS(v0, v0, q0);
|
||||
break;
|
||||
case 0x5D:
|
||||
INST_NAME("MINPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
VFMINQS(v0, v0, v1);
|
||||
break;
|
||||
case 0x5E:
|
||||
INST_NAME("DIVPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFDIVQS(v0, v0, q0);
|
||||
break;
|
||||
case 0x5F:
|
||||
INST_NAME("MAXPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
VFMAXQS(v0, v0, v1);
|
||||
break;
|
||||
case 0x60:
|
||||
INST_NAME("PUNPCKLBW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
VZIP1_8(d0, d0, d1);
|
||||
break;
|
||||
case 0x61:
|
||||
INST_NAME("PUNPCKLWD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
VZIP1_16(d0, d0, d1);
|
||||
break;
|
||||
case 0x62:
|
||||
INST_NAME("PUNPCKLDQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
VZIP1_32(d0, d0, d1);
|
||||
break;
|
||||
case 0x63:
|
||||
INST_NAME("PACKSSWB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 0, d0, 0);
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
SQXTN_8(d0, q0);
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
INST_NAME("PACKUSWB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
|
||||
VMOVeD(q0, 1, v1, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VLD1_64(q0, 1, ed);
|
||||
}
|
||||
SQXTUN_8(v0, q0);
|
||||
break;
|
||||
case 0x68:
|
||||
INST_NAME("PUNPCKHBW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
VZIP2_8(q0, q0, q1);
|
||||
break;
|
||||
case 0x69:
|
||||
INST_NAME("PUNPCKHWD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
VZIP2_16(q0, q0, q1);
|
||||
break;
|
||||
case 0x6A:
|
||||
INST_NAME("PUNPCKHDQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
VZIP2_32(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x6E:
|
||||
INST_NAME("MOVD Gm, Ed");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x3, gd);
|
||||
if(MODREG) {
|
||||
ed = xRAX + (nextop&7) + (rex.b<<3);
|
||||
if(rex.w) {
|
||||
FMOVDx(v0, ed);
|
||||
} else {
|
||||
FMOVSw(v0, ed);
|
||||
}
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
if(rex.w) {
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
} else {
|
||||
VLDR32_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x6F:
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7); // no rex.b on MMX
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVeD(v0, 0, v1, 0);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x70:
|
||||
INST_NAME("PSHUFW Gm,Em,Ib");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if(MODREG) {
|
||||
u8 = F8;
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if(u8==0x4E) {
|
||||
if(v0==v1) {
|
||||
VEXT_8(v0, v0, v0, 4); // Swap Up/Lower 32bits parts
|
||||
} else {
|
||||
VMOVeS(v0, 0, v1, 1);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
}
|
||||
} else if(u8==0x00) {
|
||||
// dumplicate lower 16bits to all spot
|
||||
if(v0!=v1) {
|
||||
VMOVeH(v0, 0, v1, 0);
|
||||
}
|
||||
VMOVeH(v0, 1, v1, 0);
|
||||
VMOVeS(v0, 1, v1, 0);
|
||||
} else if(v0!=v1) {
|
||||
VMOVeH(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeH(v0, 1, v1, (u8>>(1*2))&3);
|
||||
VMOVeH(v0, 2, v1, (u8>>(2*2))&3);
|
||||
VMOVeH(v0, 3, v1, (u8>>(3*2))&3);
|
||||
} else {
|
||||
uint64_t swp[4] = {
|
||||
(0)|(1<<8),
|
||||
(2)|(3<<8),
|
||||
(4)|(5<<8),
|
||||
(6)|(7<<8)
|
||||
};
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
tmp64u = swp[(u8>>(0*2))&3] | (swp[(u8>>(1*2))&3]<<16);
|
||||
tmp64u |= (swp[(u8>>(2*2))&3]<<32) | (swp[(u8>>(3*2))&3]<<48);
|
||||
MOV64x(x2, tmp64u);
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(v0, v1, d0);
|
||||
}
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
if (u8) {
|
||||
i32 = -1;
|
||||
for (int i=0; i<4; ++i) {
|
||||
int32_t idx = (u8>>(i*2))&3;
|
||||
if(idx!=i32) {
|
||||
ADDx_U12(x2, ed, idx*2);
|
||||
i32 = idx;
|
||||
}
|
||||
VLD1_16(v0, i, x2);
|
||||
}
|
||||
} else {
|
||||
VLD1R_16(v0, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x71:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLW Em, Ib");
|
||||
GETEM(q0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>15) {
|
||||
VEOR(q0, q0, q0);
|
||||
} else if(u8) {
|
||||
VSHR_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("PSRAW Ex, Ib");
|
||||
GETEM(q0, 1);
|
||||
u8 = F8;
|
||||
if(u8>15) u8=15;
|
||||
if(u8) {
|
||||
VSSHR_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLW Ex, Ib");
|
||||
GETEM(q0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>15) {
|
||||
VEOR(q0, q0, q0);
|
||||
} else {
|
||||
VSHL_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*ok = 0;
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x73:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLQ Em, Ib");
|
||||
GETEM(q0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>63) {
|
||||
VEOR(q0, q0, q0);
|
||||
} else if(u8) {
|
||||
USHR_64(q0, q0, u8);
|
||||
}
|
||||
PUTEM(q0);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLQ Em, Ib");
|
||||
GETEM(q0, 1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
if (u8>63) {
|
||||
VEOR(q0, q0, q0);
|
||||
} else {
|
||||
SHL_64(q0, q0, u8);
|
||||
}
|
||||
PUTEM(q0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0x74:
|
||||
INST_NAME("PCMPEQB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
VCMEQ_8(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0x77:
|
||||
INST_NAME("EMMS");
|
||||
// empty MMX, FPU now usable
|
||||
mmx_purgecache(dyn, ninst, x1);
|
||||
/*emu->top = 0;
|
||||
emu->fpu_stack = 0;*/ //TODO: Check if something is needed here?
|
||||
break;
|
||||
|
||||
case 0x7E:
|
||||
INST_NAME("MOVD Ed, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX + (nextop&7) + (rex.b<<3);
|
||||
if(rex.w) {
|
||||
VMOVQDto(ed, v0, 0);
|
||||
} else {
|
||||
VMOVSto(ed, v0, 0);
|
||||
MOVxw_REG(ed, ed);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
|
||||
if(rex.w) {
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
} else {
|
||||
VSTR32_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x7F:
|
||||
INST_NAME("MOVQ Em, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOV(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
@@ -628,7 +1050,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
u8 = F8;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
|
||||
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);
|
||||
@@ -649,7 +1071,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
|
||||
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);
|
||||
@@ -673,7 +1095,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
|
||||
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);
|
||||
@@ -697,7 +1119,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
|
||||
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);
|
||||
@@ -814,6 +1236,66 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPS 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: FCMEQQS(v0, v0, v1); break; // Equal
|
||||
case 1: FCMGTQS(v0, v1, v0); break; // Less than
|
||||
case 2: FCMGEQS(v0, v1, v0); break; // Less or equal
|
||||
case 3: FCMEQQS(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQS(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
VMVNQ(v0, v0);
|
||||
break; // NaN (NaN is not equal to himself)
|
||||
case 4: FCMEQQS(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
case 5: FCMGTQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
|
||||
case 6: FCMGEQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
|
||||
case 7: FCMEQQS(v0, v0, v0);
|
||||
if(v0!=v1) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMEQQS(q0, v1, v1);
|
||||
VANDQ(v0, v0, q0);
|
||||
}
|
||||
break; // not NaN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gm,Ed,Ib");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
u8 = (F8)&3;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
VMOVQHfrom(v0, u8, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = (F8)&3;
|
||||
VLD1_16(v0, u8, wback);
|
||||
}
|
||||
break;
|
||||
case 0xC5:
|
||||
INST_NAME("PEXTRW Gd,Em,Ib");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
GETEM(v0, 1);
|
||||
u8 = (F8)&3;
|
||||
VMOVHto(gd, v0, u8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = (F8)&3;
|
||||
LDRH_U12(gd, wback, u8*2);
|
||||
}
|
||||
break;
|
||||
case 0xC6:
|
||||
INST_NAME("SHUFPS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
@@ -854,6 +1336,229 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
REVxw(gd, gd);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
INST_NAME("PMULLW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
VMUL_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
UQSUB_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xD9:
|
||||
INST_NAME("PSUBUSW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
UQSUB_16(q0, q0, q1);
|
||||
break;
|
||||
case 0xDA:
|
||||
INST_NAME("PMINUB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
UMIN_8(d0, d0, d1);
|
||||
break;
|
||||
case 0xDB:
|
||||
INST_NAME("PAND Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VAND(v0, v0, v1);
|
||||
break;
|
||||
case 0xDC:
|
||||
INST_NAME("PADDUSB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
UQADD_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xDD:
|
||||
INST_NAME("PADDUSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
UQADD_16(q0, q0, q1);
|
||||
break;
|
||||
case 0xDE:
|
||||
INST_NAME("PMAXUB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
UMAX_8(d0, d0, d1);
|
||||
break;
|
||||
case 0xDF:
|
||||
INST_NAME("PANDN Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VBIC(v0, v1, v0);
|
||||
break;
|
||||
case 0xE0:
|
||||
INST_NAME("PAVGB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
URHADD_8(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xE3:
|
||||
INST_NAME("PAVGW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
URHADD_16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xE5:
|
||||
INST_NAME("PMULHW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VSMULL_16(q0, v0, v1);
|
||||
SQSHRN_16(v0, q0, 16);
|
||||
break;
|
||||
|
||||
case 0xE7:
|
||||
INST_NAME("MOVNTQ Em, Gm"); // Non Temporal par not handled for now
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xE8:
|
||||
INST_NAME("PSUBSB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(q0, 0);
|
||||
SQSUB_8(v0, v0, q0);
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("PSUBSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(q0, 0);
|
||||
SQSUB_16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEB:
|
||||
INST_NAME("POR Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VORR(v0, v0, v1);
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("PADDSB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
SQADD_8(d0, d0, d1);
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("PADDSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
SQADD_16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gm,Em");
|
||||
nextop = F8;
|
||||
gd = ((nextop&0x38)>>3);
|
||||
if(MODREG && ((nextop&7))==gd) {
|
||||
// special case for PXOR Gx, Gx
|
||||
q0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VEOR(q0, q0, q0);
|
||||
} else {
|
||||
q0 = mmx_get_reg(dyn, ninst, x1, gd);
|
||||
GETEM(q1, 0);
|
||||
VEOR(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF2:
|
||||
INST_NAME("PSLLD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(v0, 0, d1, 0);
|
||||
VMOVeD(v0, 1, d1, 0);
|
||||
SQXTN_32(v0, v0); // 2*q1 in 32bits now
|
||||
SSHL_32(d0, d0, v0);
|
||||
break;
|
||||
|
||||
case 0xF6:
|
||||
INST_NAME("PSADBW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VEOR(d1, d1, d1); // is it necessary?
|
||||
UABDL_8(d0, q0, q1);
|
||||
UADDLVQ_16(d1, d0);
|
||||
VMOVeD(q0, 0, d1, 0);
|
||||
break;
|
||||
|
||||
case 0xF8:
|
||||
INST_NAME("PSUBB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VSUB_8(v0, v0, v1);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("PSUBW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VSUB_16(v0, v0, v1);
|
||||
break;
|
||||
case 0xFA:
|
||||
INST_NAME("PSUBD Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VSUB_32(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xFC:
|
||||
INST_NAME("PADDB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VADD_8(v0, v0, v1);
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("PADDW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VADD_16(v0, v0, v1);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("PADDD Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1, 0);
|
||||
VADD_32(v0, v0, v1);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -27,12 +27,15 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t u8;
|
||||
int32_t j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t gd, ed, eb1, eb2;
|
||||
uint8_t wback;
|
||||
int64_t i64;
|
||||
int fixedaddress;
|
||||
MAYUSE(j32);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
@@ -47,6 +50,16 @@ 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);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
@@ -162,6 +175,29 @@ 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);
|
||||
nextop=F8;
|
||||
if(MODREG) { // reg <= u8
|
||||
u8 = F8;
|
||||
if(!rex.rex) {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
} else {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0;
|
||||
}
|
||||
MOV32w(x3, u8);
|
||||
BFIx(eb1, x3, eb2*8, 8);
|
||||
} else { // mem <= u8
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
STRB_REG(x3, ed, x4);
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
INST_NAME("MOV FS:Ed, Id");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
|
||||
@@ -51,6 +51,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch(opcode) {
|
||||
case 0x01:
|
||||
INST_NAME("ADD Ew, Gw");
|
||||
@@ -286,6 +289,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x69:
|
||||
INST_NAME("IMUL Gw,Ew,Iw");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
@@ -325,7 +336,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_add16(dyn, ninst, ed, x5, x2, x4);
|
||||
@@ -334,7 +345,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_or16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -344,7 +355,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_adc16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -354,7 +365,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -363,7 +374,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_and16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -372,7 +383,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_sub16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -381,7 +392,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
emit_xor16(dyn, ninst, x1, x5, x2, x4);
|
||||
@@ -390,7 +401,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
GETEW(x1, (opcode==81)?2:1);
|
||||
GETEW(x1, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(i16) {
|
||||
MOV32w(x2, i16);
|
||||
@@ -480,6 +491,29 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
break;
|
||||
|
||||
case 0xAB:
|
||||
if(rep) {
|
||||
INST_NAME("REP STOSW");
|
||||
CBZx_NEXT(xRCX);
|
||||
TBNZ_MARK2(xFlags, F_DF);
|
||||
MARK; // Part with DF==0
|
||||
STRH_S9_postindex(xRAX, xRDI, 2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK(xRCX);
|
||||
B_NEXT_nocond;
|
||||
MARK2; // Part with DF==1
|
||||
STRH_S9_postindex(xRAX, xRDI, -2);
|
||||
SUBx_U12(xRCX, xRCX, 1);
|
||||
CBNZx_MARK2(xRCX);
|
||||
// done
|
||||
} else {
|
||||
INST_NAME("STOSW");
|
||||
GETDIR(x3, 2);
|
||||
STRH_U12(xRAX, xRDI, 0);
|
||||
ADDx_REG(xRDI, xRDI, x3);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB8:
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
|
||||
@@ -50,24 +50,52 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
uint8_t eb1, eb2;
|
||||
uint64_t tmp64u;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j32);
|
||||
#if 0//STEP == 3
|
||||
#if 0//STEP > 1
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("MOVUPD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("MOVUPD 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));
|
||||
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 0x12:
|
||||
INST_NAME("MOVLPD Gx, Eq");
|
||||
nextop = F8;
|
||||
@@ -119,6 +147,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VLD1_64(v0, 1, ed);
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
INST_NAME("MOVHPD Gx, Eq");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VLD1_64(v0, 1, ed);
|
||||
break;
|
||||
case 0x17:
|
||||
INST_NAME("MOVHPD Eq, Gx");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
// access register instead of memory is bad opcode!
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
VST1_64(v0, 1, ed);
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
INST_NAME("NOP (multibyte)");
|
||||
@@ -168,6 +220,76 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
|
||||
case 0x38: // SSSE3 opcodes
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0x00:
|
||||
INST_NAME("PSHUFB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
MOVIQ_8(d0, 0b10001111);
|
||||
VANDQ(d0, d0, q1); // mask the index
|
||||
VTBLQ1_8(q0, q0, d0);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
INST_NAME("PMADDUBSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
UXTL_8(v0, q0); // this is unsigned, so 0 extended
|
||||
SXTL_8(v1, q1); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
SADDLPQ_16(v1, v0);
|
||||
UXTL2_8(v0, q0); // this is unsigned
|
||||
SQXTN_16(q0, v1); // SQXTN reset the vector so need to grab the high part first
|
||||
SXTL2_8(v1, q1); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
SADDLPQ_16(v0, v0);
|
||||
SQXTN2_16(q0, v0);
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("PMULHRSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
SQRDMULHQ_16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3A: // these are some more SSSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0F:
|
||||
INST_NAME("PALIGNR Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 1);
|
||||
u8 = F8;
|
||||
if(u8>31) {
|
||||
VEORQ(q0, q0, q0);
|
||||
} else if(u8>15) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VEORQ(d0, d0, d0);
|
||||
VEXTQ_8(q0, q0, d0, u8-16);
|
||||
} else {
|
||||
VEXTQ_8(q0, q1, q0, u8);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
GETFLAGS; \
|
||||
@@ -214,7 +336,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0);
|
||||
VEORQ(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x58:
|
||||
INST_NAME("ADDPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFADDQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x59:
|
||||
INST_NAME("MULPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFMULQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x5A:
|
||||
INST_NAME("CVTPD2PS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -247,7 +382,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VFCVTNSQS(v0, v1);
|
||||
#endif
|
||||
break;
|
||||
case 0x5C:
|
||||
INST_NAME("SUBPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFSUBQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x5D:
|
||||
INST_NAME("MINPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFMINQD(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x5F:
|
||||
INST_NAME("MAXPD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0, 0);
|
||||
GETGX(v0);
|
||||
VFMAXQD(v0, v0, q0);
|
||||
break;
|
||||
case 0x60:
|
||||
INST_NAME("PUNPCKLBW Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -269,7 +425,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
VZIP1Q_32(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x63:
|
||||
INST_NAME("PACKSSWB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
SQXTN_8(q0, q0);
|
||||
if(q0==q1) {
|
||||
VMOVeD(q0, 1, q0, 0);
|
||||
} else {
|
||||
SQXTN2_8(q0, q1);
|
||||
}
|
||||
break;
|
||||
case 0x64:
|
||||
INST_NAME("PCMPGTB Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -291,7 +458,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(v1, 0);
|
||||
VCMGTQ_32(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
INST_NAME("PACKUSWB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
SQXTUN_8(v0, v0);
|
||||
if(v0==v1) {
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else {
|
||||
SQXTUN2_8(v0, v1);
|
||||
}
|
||||
break;
|
||||
case 0x68:
|
||||
INST_NAME("PUNPCKHBW Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -337,7 +515,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VLD1_64(v0, 1, ed);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6D:
|
||||
INST_NAME("PUNPCKHQDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
VMOVeD(v0, 0, v0, 1);
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
VMOVeD(v0, 1, v1, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
ADDSx_U12(x1, ed, 8);
|
||||
VLD1_64(v0, 1, x1);
|
||||
}
|
||||
break;
|
||||
case 0x6E:
|
||||
INST_NAME("MOVD Gx, Ed");
|
||||
nextop = F8;
|
||||
@@ -369,41 +560,47 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETG;
|
||||
i32 = -1;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if(MODREG) {
|
||||
u8 = F8;
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if(u8==0x4E) {
|
||||
if(v0==v1) {
|
||||
VSWP(v0, v0+1);
|
||||
VEXTQ_8(v0, v0, v0, 8); // Swap Up/Lower 64bits parts
|
||||
} else {
|
||||
VMOVeD(v0, 0, v1, 1);
|
||||
VMOVeD(v0, 1, v1, 0);
|
||||
}
|
||||
} else if(u8==0x00) {
|
||||
// dumplicate 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(v0!=v1) {
|
||||
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
|
||||
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
|
||||
VMOVeS(v0, 2, v1, (u8>>(2*2))&3);
|
||||
VMOVeS(v0, 3, v1, (u8>>(3*2))&3);
|
||||
} else {
|
||||
uint32_t swp[4] = {
|
||||
uint64_t swp[4] = {
|
||||
(0)|(1<<8)|(2<<16)|(3<<24),
|
||||
(4)|(5<<8)|(6<<16)|(7<<24),
|
||||
(8)|(9<<8)|(10<<16)|(11<<24),
|
||||
(12)|(13<<8)|(14<<16)|(15<<24)
|
||||
};
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
if(v0==v1) {
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else
|
||||
q1 = v1;
|
||||
MOV32w(x2, swp[(u8>>(0*2))&3]);
|
||||
MOV32w(x3, swp[(u8>>(1*2))&3]);
|
||||
VMOVQSfrom(d0, 0, x2);
|
||||
VMOVQSfrom(d0, 1, x3);
|
||||
MOV32w(x2, swp[(u8>>(2*2))&3]);
|
||||
MOV32w(x3, swp[(u8>>(3*2))&3]);
|
||||
VMOVQSfrom(d0, 2, x2);
|
||||
VMOVQSfrom(d0, 3, x3);
|
||||
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);
|
||||
VTBLQ1_8(v0, v1, d0);
|
||||
}
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = F8;
|
||||
if (u8) {
|
||||
@@ -591,6 +788,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
INST_NAME("PCMPEQB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
VCMEQQ_8(v0, v0, q0);
|
||||
break;
|
||||
case 0x75:
|
||||
INST_NAME("PCMPEQW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
VCMEQQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0x76:
|
||||
INST_NAME("PCMPEQD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
VCMEQQ_32(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x7E:
|
||||
INST_NAME("MOVD Ed,Gx");
|
||||
nextop = F8;
|
||||
@@ -792,6 +1011,55 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
BFIx(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gx,Ed,Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
if(MODREG) {
|
||||
u8 = (F8)&7;
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
VMOVQHfrom(v0, u8, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = (F8)&7;
|
||||
VLD1_16(v0, u8, wback);
|
||||
}
|
||||
break;
|
||||
case 0xC5:
|
||||
INST_NAME("PEXTRW Gd,Ex,Ib");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
GETEX(v0, 1);
|
||||
u8 = (F8)&7;
|
||||
VMOVHto(gd, v0, u8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
|
||||
u8 = (F8)&7;
|
||||
LDRH_U12(gd, wback, u8*2);
|
||||
}
|
||||
break;
|
||||
case 0xC6:
|
||||
INST_NAME("SHUFPD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
if(v0==v1 && u8==0) {
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
} else {
|
||||
if(v0==v1)
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
else
|
||||
q0 = v0;
|
||||
VMOVeD(q0, 0, v0, (u8&1));
|
||||
VMOVeD(q0, 1, v1, ((u8>>1)&1));
|
||||
if(v0==v1) {
|
||||
VMOVQ(v0, q0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0xD4:
|
||||
INST_NAME("PADDQ Gx,Ex");
|
||||
@@ -800,7 +1068,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
VADDQ_64(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xD5:
|
||||
INST_NAME("PMULLW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
VMULQ_16(q0, q0, q1);
|
||||
break;
|
||||
case 0xD6:
|
||||
INST_NAME("MOVQ Ex, Gx");
|
||||
nextop = F8;
|
||||
@@ -815,6 +1089,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
UQSUBQ_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xD9:
|
||||
INST_NAME("PSUBUSW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
UQSUBQ_16(q0, q0, q1);
|
||||
break;
|
||||
case 0xDA:
|
||||
INST_NAME("PMINUB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1,0);
|
||||
UMINQ_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xDB:
|
||||
INST_NAME("PAND Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -822,7 +1117,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
VANDQ(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xDC:
|
||||
INST_NAME("PADDUSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
UQADDQ_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xDD:
|
||||
INST_NAME("PADDUSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
UQADDQ_16(q0, q0, q1);
|
||||
break;
|
||||
case 0xDE:
|
||||
INST_NAME("PMAXUB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
UMAXQ_8(q0, q0, q1);
|
||||
break;
|
||||
case 0xDF:
|
||||
INST_NAME("PANDN Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -831,6 +1146,114 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBICQ(v0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("PAVGB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
URHADDQ_8(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xE1:
|
||||
INST_NAME("PSRAW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(v0, 0, q1, 0);
|
||||
VMOVeD(v0, 1, q1, 0);
|
||||
SQXTN_32(v0, v0); // 2*q1 in 32bits now
|
||||
NEG_32(v0, v0); // because we want SHR and not SHL
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SQXTN_16(v0, v0); // 4*q1 in 32bits now
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SSHLQ_16(q0, q0, v0);
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("PSRAD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(v0, 0, q1, 0);
|
||||
VMOVeD(v0, 1, q1, 0);
|
||||
SQXTN_32(v0, v0); // 2*q1 in 32bits now
|
||||
NEG_32(v0, v0); // because we want SHR and not SHL
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SSHLQ_32(q0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
INST_NAME("PMULHUW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VUMULL_16(q0, v0, v1);
|
||||
VUMULL2_16(q1, v0, v1);
|
||||
UQSHRN_16(v0, q0, 16);
|
||||
UQSHRN2_16(v0, q1, 16);
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("PMULHW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VSMULL_16(q0, v0, v1);
|
||||
VSMULL2_16(q1, v0, v1);
|
||||
SQSHRN_16(v0, q0, 16);
|
||||
SQSHRN2_16(v0, q1, 16);
|
||||
break;
|
||||
case 0xE6:
|
||||
INST_NAME("CVTPD2DQ 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
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("PSUBSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SQSUBQ_8(v0, v0, q0);
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("PSUBSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SQSUBQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEA:
|
||||
INST_NAME("PMINSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SMINQ_16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("POR Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -838,6 +1261,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q0, 0);
|
||||
VORRQ(v0, v0, q0);
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("PADDSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SQADDQ_8(v0, v0, q0);
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("PADDSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0, 0);
|
||||
SQADDQ_16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gx,Ex");
|
||||
@@ -854,6 +1291,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF2:
|
||||
INST_NAME("PSLLD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(v0, 0, q1, 0);
|
||||
VMOVeD(v0, 1, q1, 0);
|
||||
SQXTN_32(v0, v0); // 2*q1 in 32bits now
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
SSHLQ_32(q0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xF4:
|
||||
INST_NAME("PMULUDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -869,6 +1319,32 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VUZP1Q_32(q1, v1, v1);
|
||||
VUMULL_32(v0, q0, q1);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("PMADDWD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VSMULL_16(q0, v0, v1);
|
||||
VSMULL2_16(q1, v0, v1);
|
||||
VADDPQ_32(v0, q0, q1);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("PSADBW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VEOR(d1, d1, d1); // is it necessary?
|
||||
UABDL_8(d0, q0, q1);
|
||||
UADDLVQ_16(d1, d0);
|
||||
VMOVeD(q0, 0, d1, 0);
|
||||
UABDL2_8(d0, q0, q1);
|
||||
UADDLVQ_16(d1, d0);
|
||||
VMOVeD(q0, 1, d1, 0);
|
||||
break;
|
||||
|
||||
case 0xF8:
|
||||
INST_NAME("PSUBB Gx,Ex");
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#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 "dynarec_arm64_helper.h"
|
||||
#include "dynarec_arm64_functions.h"
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
|
||||
// REX prefix before the 66 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
/*if(rex.w && opcode!=0x0f) { // rex.w cancels "66", but not for 66 0f type of prefix
|
||||
MESSAGE(LOG_DUMP, "Here!\n");
|
||||
return dynarec64_64(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
|
||||
}*/
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ed");
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
if(rex.w) {
|
||||
MOVx_REG(gd, ed);
|
||||
} else {
|
||||
if(ed!=gd) {
|
||||
BFIx(gd, ed, 0, 16);
|
||||
}
|
||||
}
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(rex.w) {
|
||||
LDRx_REG(gd, ed, x4);
|
||||
} else {
|
||||
LDRH_REG(x1, ed, x4);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
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)
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int8_t i8;
|
||||
int32_t i32, j32;
|
||||
MAYUSE(j32);
|
||||
@@ -40,6 +43,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x8D:
|
||||
INST_NAME("LEA Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if(MODREG) { // reg <= reg? that's an invalid operation
|
||||
DEFAULT;
|
||||
} else { // mem <= reg
|
||||
// should a geted32 be created, to use 32bits regs instead of 64bits?
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=gd) {
|
||||
MOVw_REG(gd, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
#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_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
MAYUSE(s0);
|
||||
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 ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = 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 ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = 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");
|
||||
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("FSUB ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FSUBR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FDIV ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
INST_NAME("FDIVR ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FADD ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FADDD(v1, v1, s0);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FMUL ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FMULD(v1, v1, s0);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FCOM ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FCMPD(v1, s0);
|
||||
FCOM(x1, x2, x3);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FCOMP ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FCMPD(v1, s0);
|
||||
FCOM(x1, x2, x3);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FSUB ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FSUBD(v1, v1, s0);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FSUBR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FSUBD(v1, s0, v1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FDIV ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FDIVD(v1, v1, s0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FDIVR ST0, float[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(s0, s0);
|
||||
FDIVD(v1, s0, v1);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
#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_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback, wb1;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int i1, i2, i3;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FLD STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
v2 = x87_do_push(dyn, ninst);
|
||||
FMOVD(v2, v1);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FXCH STx");
|
||||
// swap the cache value, not the double value itself :p
|
||||
i1 = x87_get_cache(dyn, ninst, x1, x2, nextop&7);
|
||||
i2 = x87_get_cache(dyn, ninst, x1, x2, 0);
|
||||
i3 = dyn->x87cache[i1];
|
||||
dyn->x87cache[i1] = dyn->x87cache[i2];
|
||||
dyn->x87cache[i2] = i3;
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
INST_NAME("FNOP");
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FCHS");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
FNEGD(v1, v1);
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("FABS");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
FABSD(v1, v1);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
INST_NAME("FTST");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
FCMPD_0(v1);
|
||||
FCOM(x1, x2, x3); // same flags...
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("FXAM");
|
||||
x87_refresh(dyn, ninst, x1, x2, 0);
|
||||
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
|
||||
break;
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("FLD1");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, 1.0);
|
||||
break;
|
||||
case 0xE9:
|
||||
INST_NAME("FLDL2T");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, L2T);
|
||||
break;
|
||||
case 0xEA:
|
||||
INST_NAME("FLDL2E");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, L2E);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("FLDPI");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, PI);
|
||||
break;
|
||||
case 0xEC:
|
||||
INST_NAME("FLDLG2");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, LG2);
|
||||
break;
|
||||
case 0xED:
|
||||
INST_NAME("FLDLN2");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, LN2);
|
||||
break;
|
||||
case 0xEE:
|
||||
INST_NAME("FLDZ");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, 0.0);
|
||||
break;
|
||||
|
||||
case 0xFA:
|
||||
INST_NAME("FSQRT");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
FSQRTD(v1, v1);
|
||||
break;
|
||||
|
||||
case 0xFC:
|
||||
INST_NAME("FRNDINT");
|
||||
// use C helper for now, nothing staightforward is available
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_frndint, -1);
|
||||
/*
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
VCMP_F64_0(v1);
|
||||
VMRS_APSR();
|
||||
B_NEXT(cVS); // Unordered, skip
|
||||
B_NEXT(cEQ); // Zero, skip
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x3);
|
||||
VCVT_S32_F64(x1, v1); // limit to 32bits....
|
||||
VCVT_F64_S32(v1, x1);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
*/
|
||||
break;
|
||||
case 0xF0:
|
||||
INST_NAME("F2XM1");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_f2xm1, -1);
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("FYL2X");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2x, -1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("FTAN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_ftan, -1);
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
FTABLE64(v1, 1.0);
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("FPATAN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fpatan, -1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("FXTRACT");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fxtract, -1);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem1, -1);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("FDECSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
SUBw_U12(x2, x2, 1);
|
||||
ANDw_mask(x2, x2, 0, 2); //mask=7
|
||||
STRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
break;
|
||||
case 0xF7:
|
||||
INST_NAME("FINCSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
ADDw_U12(x2, x2, 1);
|
||||
ANDw_mask(x2, x2, 0, 2); //mask=7
|
||||
STRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem, -1);
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("FYL2XP1");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fyl2xp1, -1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xFB:
|
||||
INST_NAME("FSINCOS");
|
||||
x87_do_push_empty(dyn, ninst, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fsincos, -1);
|
||||
break;
|
||||
case 0xFD:
|
||||
INST_NAME("FSCALE");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fscale, -1);
|
||||
break;
|
||||
case 0xFE:
|
||||
INST_NAME("FSIN");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fsin, -1);
|
||||
break;
|
||||
case 0xFF:
|
||||
INST_NAME("FCOS");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
CALL(arm_fcos, -1);
|
||||
break;
|
||||
|
||||
|
||||
case 0xD1:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
case 0xEF:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
FCVT_D_S(v1, s0);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FCVT_S_D(s0, v1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VSTR32_U12(s0, ed, fixedaddress);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FSTP float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FCVT_S_D(s0, v1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VSTR32_U12(s0, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FLDENV Ed");
|
||||
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) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
MOV32w(x2, 0);
|
||||
CALL(fpu_loadenv, -1);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLDCW Ew");
|
||||
GETEW(x1, 0);
|
||||
STRH_U12(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
|
||||
UBFXw(x1, x1, 10, 2); // extract round
|
||||
STRw_U12(x1, xEmu, offsetof(x64emu_t, round));
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
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) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
MOV32w(x2, 0);
|
||||
CALL(fpu_savenv, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTCW Ew");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
ed = x1;
|
||||
wb1 = 1;
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
|
||||
EWBACK;
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
#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_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
uint8_t u8;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int j32;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FCMOVNB ST0, STx");
|
||||
READFLAGS(X_CF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
TSTw_mask(xFlags, 0, 0); //mask=1<<F_CF
|
||||
FCSELD(v1, v2, v1, cEQ); // F_CF==0
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
INST_NAME("FCMOVNE ST0, STx");
|
||||
READFLAGS(X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
TSTw_mask(xFlags, 0b011010, 0); //mask=1<<F_ZF
|
||||
FCSELD(v1, v2, v1, cEQ); // F_ZF==0
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCMOVNBE ST0, STx");
|
||||
READFLAGS(X_CF|X_ZF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
MOV32w(x1, (1<<F_CF)|(1<<F_ZF));
|
||||
TSTw_REG(xFlags, x1);
|
||||
FCSELD(v1, v2, v1, cEQ); // F_CF==0 & F_ZF==0
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FCMOVNU ST0, STx");
|
||||
READFLAGS(X_PF);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
TSTw_mask(xFlags, 0b011110, 0); //mask=1<<F_PF
|
||||
FCSELD(v1, v2, v1, cEQ); // F_PF==0
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("FDISI8087_NOP"); // so.. NOP?
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("FNCLEX");
|
||||
LDRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
|
||||
MOV32w(x1, 0);
|
||||
BFIw(x2, x1, 0, 8); // IE .. PE, SF, ES
|
||||
BFIw(x2, x1, 15, 1); // B
|
||||
STRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
|
||||
break;
|
||||
case 0xE3:
|
||||
INST_NAME("FNINIT");
|
||||
x87_purgecache(dyn, ninst, x1, x2, x3);
|
||||
CALL(reset_fpu, -1);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMI ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
SXTL_32(v1, s0);
|
||||
SCVTFDD(v1, v1);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT32ZD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_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);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT32XD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_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);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT32XD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_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);
|
||||
MOV32w(x5, 0x80000000);
|
||||
STRw_U12(x5, wback, fixedaddress);
|
||||
#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);
|
||||
}
|
||||
CALL(arm_fld, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
x87_forget(dyn, ninst, x1, x3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
CALL(arm_fstp, -1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
#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_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREE STx");
|
||||
break; // not handling Tag...
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FST ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FMOVD(v2, v1);
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("FSTP ST0, ST0");
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
INST_NAME("FSTP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FMOVD(v2, v1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
INST_NAME("FUCOM 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);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMP 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 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FLD double");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VLDR64_U12(v1, ed, fixedaddress);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP i64, ST0");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FRINT64ZD(s0, v1);
|
||||
FCVTZSxD(x2, s0);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FST double");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v1, ed, fixedaddress);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FSTP double");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VSTR64_U12(v1, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
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);}
|
||||
CALL(arm_frstor, -1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
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);}
|
||||
CALL(arm_fsave, -1);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
|
||||
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
|
||||
BFIw(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
|
||||
STRH_U12(x3, ed, fixedaddress); // store whole sw flags
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
#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_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t ed, wback, u8;
|
||||
int fixedaddress;
|
||||
int v1, v2;
|
||||
int j32;
|
||||
int s0;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREEP STx");
|
||||
// not handling Tag...
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FNSTSW AX");
|
||||
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
|
||||
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
|
||||
BFIw(x1, x2, 11, 3); // inject top
|
||||
BFIw(xRAX, x1, 0, 16);
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
INST_NAME("FUCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
INST_NAME("FCOMIP ST0, STx");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
FCMPD(v1, v2);
|
||||
FCOMI(x1, x2);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
LDRSHw_U12(x1, wback, fixedaddress);
|
||||
SCVTFDw(v1, x1);
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
// this version needs ARM v8.5, //TODO: add detection of this extensio to use it
|
||||
FRINT32ZD(s0, v1);
|
||||
// no saturation instruction on Arm, so using NEON
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
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);
|
||||
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);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("FIST Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT32XD(s0, v1);
|
||||
// no saturation instruction on Arm, so using NEON
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
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);
|
||||
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);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("FISTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT32XD(s0, v1);
|
||||
// no saturation instruction on Arm, so using NEON
|
||||
VFCVTZSd(s0, s0);
|
||||
SQXTN_S_D(s0, s0);
|
||||
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);
|
||||
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);
|
||||
MOV32w(x5, 0x8000);
|
||||
STRH_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 4:
|
||||
INST_NAME("FBLD ST0, tbytes");
|
||||
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);}
|
||||
CALL(fpu_fbld, -1);
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FILD ST0, i64");
|
||||
v1 = x87_do_push(dyn, ninst);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
LDRx_U12(x1, wback, fixedaddress);
|
||||
SCVTFDx(v1, x1);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FBSTP tbytes, ST0");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
if(ed!=x1) {MOVx_REG(x1, ed);}
|
||||
CALL(fpu_fbst, -1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
FRINT64XD(s0, v1);
|
||||
VFCVTZSd(s0, s0);
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
#else
|
||||
MSR_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MRS_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);
|
||||
MOV64x(x5, 0x8000000000000000LL);
|
||||
STRx_U12(x5, wback, fixedaddress);
|
||||
#endif
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -1257,7 +1257,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
MSR_nzvc(s3); // load CC into ARM CF
|
||||
ADCw_REG(s1, s1, s2);
|
||||
IFX(X_PEND) {
|
||||
STRw_REG(s1, xEmu, offsetof(x64emu_t, res));
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORRw_REG(s3, s4, s2); // s3 = op1 | op2
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// 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)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
|
||||
@@ -38,7 +38,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
BICxw(s4, s2, s1); // s4 = ~op1 & op2
|
||||
}
|
||||
SUBSxw_REG(s5, s1, s2); // res = s1 - s2
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRxw_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_AF) {
|
||||
@@ -76,7 +76,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
|
||||
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
MOV64xw(s4, 0);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRxw_U12(s4, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -113,7 +113,7 @@ 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
|
||||
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s3, d_cmp16);
|
||||
@@ -121,7 +121,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -162,7 +162,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
|
||||
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
MOV32w(s3, 0);
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -192,7 +192,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
// 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)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s4, d_cmp8);
|
||||
@@ -204,7 +204,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
} else {
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -242,7 +242,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
|
||||
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
MOV32w(s4, 0);
|
||||
STRB_U12(s4, xEmu, offsetof(x64emu_t, op2));
|
||||
@@ -273,7 +273,7 @@ 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
|
||||
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, rex.w?d_tst64:d_tst32);
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
@@ -283,7 +283,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
ANDSxw_REG(s3, s1, s2); // res = s1 & s2
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -310,7 +310,7 @@ 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
|
||||
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst16);
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
@@ -322,7 +322,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
BFCw(xFlags, F_CF, 1);
|
||||
}
|
||||
ANDSw_REG(s5, s1, s2); // res = s1 & s2
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
@@ -342,7 +342,7 @@ 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
|
||||
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
SET_DF(s3, d_tst8);
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
@@ -354,7 +354,7 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
BFCw(xFlags, F_CF, 1);
|
||||
}
|
||||
ANDSw_REG(s5, s1, s2); // res = s1 & s2
|
||||
IFX(X_PEND) {
|
||||
IFX_PENDOR0 {
|
||||
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
|
||||
@@ -120,8 +120,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// Aligned version
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
ed = x1;
|
||||
CMPSxw_REG(xRAX, ed);
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRxw(x4, gd, wback);
|
||||
@@ -132,18 +131,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MARK3;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x3, wback); // dummy read, to arm the write...
|
||||
ed = x1;
|
||||
CMPSxw_REG(xRAX, ed);
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARK3(x4);
|
||||
STRxw_U12(gd, wback, 0);
|
||||
B_MARK_nocond;
|
||||
MARK;
|
||||
// Common part (and fallback for EAX != Ed)
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
|
||||
MOVxw_REG(xRAX, ed);
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
|
||||
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -185,11 +182,52 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXPxw(x2, x3, wback);
|
||||
CMPSxw_REG(xRAX, x2);
|
||||
B_MARK(cNE); // EAX != Ed[0]
|
||||
CMPSxw_REG(xRDX, x3);
|
||||
B_MARK(cNE); // EDX != Ed[1]
|
||||
STLXPxw(x4, xRBX, xRCX, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
MOV32w(x1, 1);
|
||||
B_MARK3_nocond;
|
||||
MARK;
|
||||
MOVxw_REG(xRAX, x2);
|
||||
MOVxw_REG(xRDX, x3);
|
||||
MOV32w(x1, 0);
|
||||
MARK3;
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
INST_NAME("LOCK SUB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_sub32(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_sub32(dyn, ninst, rex, x1, gd, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
@@ -371,6 +409,33 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
INST_NAME("LOCK XCHG Ed, Gd");
|
||||
nextop = F8;
|
||||
if(MODREG) {
|
||||
GETGD;
|
||||
GETED(0);
|
||||
MOVxw_REG(x1, gd);
|
||||
MOVxw_REG(gd, ed);
|
||||
MOVxw_REG(ed, x1);
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
|
||||
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, ed);
|
||||
STLXRxw(x3, gd, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, ed, 0);
|
||||
STRxw_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -37,12 +37,17 @@
|
||||
#define GETGX(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETGX_empty(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint8_t u8;
|
||||
uint64_t u64;
|
||||
int v0, v1;
|
||||
int q0;
|
||||
int d0, d1;
|
||||
@@ -89,6 +94,21 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
INST_NAME("MOVDDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
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);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
VMOVeD(v0, 1, v0, 0);
|
||||
break;
|
||||
|
||||
case 0x2A:
|
||||
INST_NAME("CVTSI2SD Gx, Ed");
|
||||
@@ -188,7 +208,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x5D:
|
||||
INST_NAME("MINSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(v1, 0);
|
||||
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
@@ -208,7 +228,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x5F:
|
||||
INST_NAME("MAXSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(v1, 0);
|
||||
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
@@ -217,6 +237,26 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeD(v0, 0, d0, 0); // to not erase uper part
|
||||
break;
|
||||
|
||||
case 0x70:
|
||||
INST_NAME("PSHUFLW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETEX(v1, 1);
|
||||
GETGX(v0);
|
||||
|
||||
u8 = F8;
|
||||
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
|
||||
u64 = 0;
|
||||
for (int i=0; i<4; ++i) {
|
||||
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
|
||||
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
|
||||
}
|
||||
MOV64x(x2, u64);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
break;
|
||||
|
||||
case 0x7C:
|
||||
INST_NAME("HADDPS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -231,6 +271,46 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VFADDPQS(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 1);
|
||||
u8 = F8;
|
||||
if((u8&7)==6){
|
||||
FCMPD(v1, v0);
|
||||
} else {
|
||||
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 3: CSETMx(x2, cVS); break; // NaN
|
||||
case 4: CSETMx(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
|
||||
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 7: CSETMx(x2, cVC); break; // not NaN
|
||||
}
|
||||
VMOVQDfrom(v0, 0, x2);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("LDDQU Gx,Ex");
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t nextop, u8;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint64_t u64;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int fixedaddress;
|
||||
int j32;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
@@ -57,6 +59,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);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -136,7 +139,31 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(d0, 0);
|
||||
FCVTZSxwS(gd, d0);
|
||||
break;
|
||||
|
||||
case 0x2D:
|
||||
INST_NAME("CVTSS2SI Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEX(q0, 0);
|
||||
#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
|
||||
FCVTNSxwS(gd, q0); // 0: Nearest (even)
|
||||
B_NEXT_nocond;
|
||||
FCVTMSxwS(gd, q0); // 1: Toward -inf
|
||||
B_NEXT_nocond;
|
||||
FCVTPSxwS(gd, q0); // 2: Toward +inf
|
||||
B_NEXT_nocond;
|
||||
FCVTZSxwS(gd, q0); // 3: Toward 0
|
||||
#else
|
||||
FCVTNSxwS(gd, q0);
|
||||
#endif
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -146,6 +173,22 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FSQRTS(d1, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1, 0);
|
||||
d0 = 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);
|
||||
VMOVeS(v0, 0, d0, 0);
|
||||
break;
|
||||
|
||||
case 0x58:
|
||||
INST_NAME("ADDSS Gx, Ex");
|
||||
@@ -174,6 +217,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FCVT_D_S(d0, v1);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
break;
|
||||
case 0x5B:
|
||||
INST_NAME("CVTPS2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(d0, 0);
|
||||
GETGX_empty(v0);
|
||||
VFCVTZSQS(v0, d0);
|
||||
break;
|
||||
|
||||
case 0x5C:
|
||||
INST_NAME("SUBSS Gx, Ex");
|
||||
@@ -227,6 +277,25 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x70:
|
||||
INST_NAME("PSHUFHW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETEX(v1, 1);
|
||||
GETGX(v0);
|
||||
|
||||
u8 = F8;
|
||||
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
|
||||
u64 = 0;
|
||||
for (int i=0; i<4; ++i) {
|
||||
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+8)<<(i*16+0);
|
||||
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+9)<<(i*16+8);
|
||||
}
|
||||
MOV64x(x2, u64);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VMOVQDfrom(d0, 0, x2);
|
||||
VTBL1_8(d0, v1, d0);
|
||||
VMOVeD(v0, 1, d0, 0);
|
||||
break;
|
||||
|
||||
case 0x7E:
|
||||
INST_NAME("MOVQ Gx, Ex");
|
||||
@@ -257,6 +326,22 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xBC:
|
||||
INST_NAME("TZCNT Gd, Ed");
|
||||
SETFLAGS(X_CF|X_ZF, SF_SET);
|
||||
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
|
||||
CLZxw(gd, x1); // x2 gets leading 0 == TZCNT
|
||||
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");
|
||||
nextop = F8;
|
||||
@@ -282,6 +367,30 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQSfrom(v0, 0, x2);
|
||||
break;
|
||||
|
||||
case 0xD6:
|
||||
INST_NAME("MOVQ2DQ Gx, Em");
|
||||
nextop = F8;
|
||||
GETGX_empty(v0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
|
||||
VEORQ(v0, v0, v0); // usefull?
|
||||
VMOV(v0, v1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE6:
|
||||
INST_NAME("CVTDQ2PD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(v1, 0);
|
||||
GETGX_empty(v0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
SXTL_32(v0, v1);
|
||||
SCVTQFD(v0, v0); // there is only I64 -> Double vector conversion, not from i32
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -140,6 +140,125 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x2;
|
||||
*fixaddress = 0;
|
||||
if(hint>0) ret = hint;
|
||||
if(hint>0 && hint<xRAX) scratch = hint;
|
||||
int absmin = 0;
|
||||
if(s) absmin=-absmax;
|
||||
MAYUSE(scratch);
|
||||
if(!(nextop&0xC0)) {
|
||||
if((nextop&7)==4) {
|
||||
uint8_t sib = F8;
|
||||
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
if((sib&0x7)==5) {
|
||||
uint32_t tmp = F32;
|
||||
if (sib_reg!=4) {
|
||||
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
|
||||
MOV32w(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);
|
||||
}
|
||||
} else {
|
||||
if (sib_reg!=4) {
|
||||
ADDw_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
ret = xRAX+(sib&0x7)+(rex.b<<3);
|
||||
}
|
||||
}
|
||||
} else if((nextop&7)==5) {
|
||||
uint32_t tmp = F32;
|
||||
MOV32w(ret, tmp);
|
||||
GETIP(addr+delta);
|
||||
ADDw_REG(ret, ret, xRIP);
|
||||
} else {
|
||||
ret = xRAX+(nextop&7)+(rex.b<<3);
|
||||
if(ret==hint) {
|
||||
MOVw_REG(hint, ret); //to clear upper part
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int64_t i64;
|
||||
uint8_t sib = 0;
|
||||
int sib_reg = 0;
|
||||
if((nextop&7)==4) {
|
||||
sib = F8;
|
||||
sib_reg = ((sib>>3)&7)+(rex.x<<3);
|
||||
}
|
||||
if(nextop&0x80)
|
||||
i64 = F32S;
|
||||
else
|
||||
i64 = F8S;
|
||||
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask))) {
|
||||
*fixaddress = i64;
|
||||
if((nextop&7)==4) {
|
||||
if (sib_reg!=4) {
|
||||
ADDw_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
ret = xRAX+(sib&0x07)+(rex.b<<3);
|
||||
}
|
||||
} else {
|
||||
ret = xRAX+(nextop&0x07)+(rex.b<<3);
|
||||
}
|
||||
} else {
|
||||
int64_t sub = (i64<0)?1:0;
|
||||
if(sub) i64 = -i64;
|
||||
if(i64<0x1000) {
|
||||
if((nextop&7)==4) {
|
||||
if (sib_reg!=4) {
|
||||
ADDw_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
scratch = xRAX+(sib&0x07)+(rex.b<<3);
|
||||
}
|
||||
} else
|
||||
scratch = xRAX+(nextop&0x07)+(rex.b<<3);
|
||||
if(sub) {
|
||||
SUBw_U12(ret, scratch, i64);
|
||||
} else {
|
||||
ADDw_U12(ret, scratch, i64);
|
||||
}
|
||||
} else {
|
||||
MOV32w(scratch, i64);
|
||||
if((nextop&7)==4) {
|
||||
if (sib_reg!=4) {
|
||||
if(sub) {
|
||||
SUBw_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
|
||||
} else {
|
||||
ADDw_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
|
||||
}
|
||||
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
|
||||
} else {
|
||||
PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
|
||||
if(sub) {
|
||||
SUBw_REG(ret, tmp, scratch);
|
||||
} else {
|
||||
ADDw_REG(ret, tmp, scratch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
|
||||
if(sub) {
|
||||
SUBw_REG(ret, tmp, scratch);
|
||||
} else {
|
||||
ADDw_REG(ret, tmp, scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ed = ret;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@@ -263,7 +382,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
#ifdef HAVE_TRACE
|
||||
//MOVx(x2, 15); no access to PC reg
|
||||
#endif
|
||||
BR(x3);
|
||||
BLR(x3); // save LR...
|
||||
}
|
||||
|
||||
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
@@ -281,7 +400,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
MOVx_REG(x1, xRIP);
|
||||
BR(x2);
|
||||
BLR(x2); // save LR
|
||||
}
|
||||
|
||||
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
@@ -305,7 +424,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
MOVx_REG(x1, xRIP);
|
||||
BR(x2);
|
||||
BLR(x2); // save LR
|
||||
}
|
||||
|
||||
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
@@ -415,22 +534,22 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
|
||||
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
|
||||
int a = dyn->x87stack;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADDx_U12(scratch, scratch, a);
|
||||
ADDw_U12(scratch, scratch, a);
|
||||
} else {
|
||||
SUBx_U12(scratch, scratch, -a);
|
||||
SUBw_U12(scratch, scratch, -a);
|
||||
}
|
||||
STRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
STRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
if(a>0) {
|
||||
SUBx_U12(scratch, scratch, a);
|
||||
SUBw_U12(scratch, scratch, a);
|
||||
} else {
|
||||
ADDx_U12(scratch, scratch, -a);
|
||||
ADDw_U12(scratch, scratch, -a);
|
||||
}
|
||||
ADDx_U12(scratch, scratch, 7);
|
||||
STRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
ANDw_mask(scratch, scratch, 0, 2); //mask=7
|
||||
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
|
||||
// reset x87stack
|
||||
dyn->x87stack = 0;
|
||||
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
|
||||
@@ -483,7 +602,7 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
int ret = 0;
|
||||
@@ -498,15 +617,15 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
// reset x87stack
|
||||
dyn->x87stack = 0;
|
||||
// Add x87stack to emu fpu_stack
|
||||
LDRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
if(a>0) {
|
||||
ADDx_U12(s2, s2, a);
|
||||
ADDw_U12(s2, s2, a);
|
||||
} else {
|
||||
SUBx_U12(s2, s2, -a);
|
||||
SUBw_U12(s2, s2, -a);
|
||||
}
|
||||
STRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
|
||||
// Sub x87stack to top, with and 7
|
||||
LDRx_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
// update tags (and top at the same time)
|
||||
if(a>0) {
|
||||
// new tag to fulls
|
||||
@@ -514,7 +633,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
ADDx_U12(s1, xEmu, offsetof(x64emu_t, p_regs));
|
||||
for (int i=0; i<a; ++i) {
|
||||
SUBw_U12(s2, s2, 1);
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + st)&7
|
||||
STRw_REG_LSL2(s3, s1, s2);
|
||||
}
|
||||
} else {
|
||||
@@ -524,7 +643,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
for (int i=0; i<-a; ++i) {
|
||||
STRw_REG_LSL2(s3, s1, s2);
|
||||
ADDw_U12(s2, s2, 1);
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + st)&7
|
||||
}
|
||||
}
|
||||
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
|
||||
@@ -540,7 +659,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1) {
|
||||
ADDw_U12(s3, s2, dyn->x87cache[i]);
|
||||
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + st)&7
|
||||
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + st)&7
|
||||
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
|
||||
fpu_free_reg(dyn, dyn->x87reg[i]);
|
||||
dyn->x87reg[i] = -1;
|
||||
@@ -569,8 +688,8 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->x87cache[i]!=-1) {
|
||||
ADDw_U12(s3, s2, dyn->x87cache[i]);
|
||||
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + i)&7
|
||||
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s3);
|
||||
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
|
||||
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -601,7 +720,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
} else {
|
||||
ADDw_U12(s2, s2, a);
|
||||
}
|
||||
ANDw_mask(s2, s2, 0b011111, 1);
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7
|
||||
}
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
@@ -640,7 +759,7 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
// Update
|
||||
if(st) {
|
||||
ADDw_U12(s2, s2, st);
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
|
||||
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);
|
||||
@@ -665,9 +784,9 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
// Update
|
||||
if(st) {
|
||||
ADDw_U12(s2, s2, st);
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
}
|
||||
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
VSTR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
|
||||
// and forget that cache
|
||||
fpu_free_reg(dyn, dyn->x87reg[ret]);
|
||||
@@ -692,7 +811,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
} else {
|
||||
ADDw_U12(s2, s2, a);
|
||||
}
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
|
||||
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s2);
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
// ok
|
||||
@@ -716,7 +835,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
} else {
|
||||
ADDw_U12(s2, s2, a);
|
||||
}
|
||||
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
|
||||
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);
|
||||
#endif
|
||||
@@ -731,10 +850,10 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
UBFXx(s2, s1, 10, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
VMRS(s1); // get fpscr
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
VMSR(s1); // put new fpscr
|
||||
MSR_fpcr(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
|
||||
@@ -745,17 +864,17 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
UBFXx(s2, s1, 13, 2); // extract round...
|
||||
MOV64x(s1, (uintptr_t)round_map);
|
||||
LDRw_REG_LSL2(s2, s1, s2);
|
||||
VMRS(s1); // get fpscr
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
MOVx_REG(s3, s1);
|
||||
BFIx(s1, s2, 22, 2); // inject new round
|
||||
VMSR(s1); // put new fpscr
|
||||
MSR_fpcr(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
|
||||
// Restore round flag
|
||||
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
VMSR(s1); // put back fpscr
|
||||
MSR_fpcr(s1); // put back fpscr
|
||||
}
|
||||
|
||||
// MMX helpers
|
||||
@@ -792,7 +911,7 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
#endif
|
||||
}
|
||||
// purge the MMX cache only(needs 3 scratch registers)
|
||||
static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
int old = -1;
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
gb1 = xRAX+(gd&3); \
|
||||
} \
|
||||
gd = i; \
|
||||
UBFXx(gd, gb1, gb2, 8);
|
||||
UBFXx(gd, gb1, gb2*8, 8);
|
||||
//GETSGB signe extend GB, will use i for gd
|
||||
#define GETSGB(i) if(rex.rex) { \
|
||||
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
@@ -264,6 +264,10 @@
|
||||
#define B_MARK_nocond \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
B(j32)
|
||||
// Branch to MARK if reg is 0 (use j32)
|
||||
#define CBZxw_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
CBZxw(reg, j32)
|
||||
// Branch to MARK if reg is not 0 (use j32)
|
||||
#define CBNZx_MARK(reg) \
|
||||
j32 = GETMARK-(dyn->arm_size); \
|
||||
@@ -324,6 +328,10 @@
|
||||
#define CBZx_NEXT(reg) \
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
|
||||
CBZx(reg, j32)
|
||||
// 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)
|
||||
#define B_MARKSEG(cond) \
|
||||
j32 = GETMARKSEG-(dyn->arm_size); \
|
||||
@@ -346,6 +354,7 @@
|
||||
CBNZx(reg, j32)
|
||||
|
||||
#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))
|
||||
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
|
||||
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
|
||||
@@ -353,8 +362,8 @@
|
||||
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOM(s1, s2, s3) \
|
||||
LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw)); /*offset is 8bits right?*/\
|
||||
MOV32w(s1, 0b01000111); \
|
||||
BICw_REG_LSL(s3, s3, s1, 8); \
|
||||
MOV32w(s1, 0b0100011100000000); \
|
||||
BICw_REG(s3, s3, s1); \
|
||||
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
|
||||
MOV32w(s2, 0b01000101); /* unordered */ \
|
||||
CSELw(s1, s2, s1, cVS); \
|
||||
@@ -390,6 +399,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 STORE_XEMU_REGS(A) \
|
||||
STORE_REG(RAX); \
|
||||
STORE_REG(RCX); \
|
||||
@@ -445,7 +455,13 @@
|
||||
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
|
||||
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
|
||||
|
||||
// Need to also store current value of some register, as they may be used by functions like setjump
|
||||
// so RBX, RSP, RBP, R12..R15 (other are scratch or parameters), R10-R11 not usefull, but why not
|
||||
// RBX, RSP and RBP are already saved in call function
|
||||
#define STORE_XEMU_CALL(A) \
|
||||
STP_REGS(R10, R11); \
|
||||
STP_REGS(R12, R13); \
|
||||
STP_REGS(R14, R15); \
|
||||
if(A) {STPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
|
||||
else {STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}
|
||||
|
||||
@@ -503,6 +519,9 @@
|
||||
#ifndef TABLE64
|
||||
#define TABLE64(A, V)
|
||||
#endif
|
||||
#ifndef FTABLE64
|
||||
#define FTABLE64(A, V)
|
||||
#endif
|
||||
|
||||
#if STEP < 2
|
||||
#define GETIP(A)
|
||||
@@ -518,14 +537,20 @@
|
||||
} \
|
||||
} else { \
|
||||
dyn->last_ip = (A); \
|
||||
TABLE64(xRIP, dyn->last_ip); \
|
||||
if(dyn->last_ip<0xffffffff) { \
|
||||
MOV64x(xRIP, dyn->last_ip); \
|
||||
} else \
|
||||
TABLE64(xRIP, dyn->last_ip); \
|
||||
}
|
||||
#define GETIP_(A) \
|
||||
if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \
|
||||
uint64_t _delta_ip = (A)-dyn->last_ip; \
|
||||
if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\
|
||||
} else { \
|
||||
TABLE64(xRIP, (A)); \
|
||||
if((A)<0xffffffff) { \
|
||||
MOV64x(xRIP, (A)); \
|
||||
} else \
|
||||
TABLE64(xRIP, (A)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -566,10 +591,12 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define dynarec64_DF STEPNAME(dynarec64_DF)
|
||||
#define dynarec64_F0 STEPNAME(dynarec64_F0)
|
||||
#define dynarec64_660F STEPNAME(dynarec64_660F)
|
||||
#define dynarec64_6664 STEPNAME(dynarec64_6664)
|
||||
#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_)
|
||||
@@ -672,6 +699,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
#define fpu_reset STEPNAME(fpu_reset)
|
||||
#define fpu_purgecache STEPNAME(fpu_purgecache)
|
||||
#define mmx_purgecache STEPNAME(mmx_purgecache)
|
||||
#define x87_purgecache STEPNAME(x87_purgecache)
|
||||
#ifdef HAVE_TRACE
|
||||
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
|
||||
#endif
|
||||
@@ -679,6 +708,9 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -808,28 +840,33 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
void fpu_reset(dynarec_arm_t* dyn, int ninst);
|
||||
// purge the FPU cache (needs 3 scratch registers)
|
||||
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// purge MMX cache
|
||||
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// purge x87 cache
|
||||
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);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
|
||||
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_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);
|
||||
//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);
|
||||
//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_D8(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_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_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_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_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
|
||||
|
||||
@@ -25,22 +25,25 @@
|
||||
#error No STEP defined
|
||||
#endif
|
||||
|
||||
void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
{
|
||||
int ok = 1;
|
||||
int ninst = 0;
|
||||
uintptr_t ip = addr;
|
||||
uintptr_t init_addr = addr;
|
||||
rex_t rex;
|
||||
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
|
||||
int need_epilog = 1;
|
||||
dyn->sons_size = 0;
|
||||
// Clean up (because there are multiple passes)
|
||||
dyn->state_flags = 0;
|
||||
dyn->dfnone = 0;
|
||||
dyn->last_ip = ip; // RIP is always set at start of block!
|
||||
MAYUSE(init_addr);
|
||||
fpu_reset(dyn, ninst);
|
||||
// ok, go now
|
||||
INIT;
|
||||
while(ok) {
|
||||
if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);}
|
||||
ip = addr;
|
||||
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
|
||||
dyn->last_ip = 0;
|
||||
@@ -65,7 +68,21 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
addr = dynarec64_00(dyn, addr, ip, ninst, &ok, &need_epilog);
|
||||
rep = 0;
|
||||
uint8_t pk = PK(0);
|
||||
while((pk==0xF2) || (pk==0xF3)) {
|
||||
rep = pk-0xF1;
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
rex.rex = 0;
|
||||
while(pk>=0x40 && pk<=0x4f) {
|
||||
rex.rex = pk;
|
||||
++addr;
|
||||
pk = PK(0);
|
||||
}
|
||||
|
||||
addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
|
||||
|
||||
INST_EPILOG;
|
||||
|
||||
@@ -94,6 +111,20 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if(ok && !isJumpTableDefault64((void*)addr))
|
||||
#else
|
||||
if(ok && dyn->insts && (ninst==dyn->size))
|
||||
#endif
|
||||
{
|
||||
#if STEP == 3
|
||||
dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
|
||||
#endif
|
||||
BARRIER(2);
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
jump_to_next(dyn, addr, 0, ninst);
|
||||
ok=0; need_epilog=0;
|
||||
}
|
||||
}
|
||||
if(need_epilog) {
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
@@ -101,4 +132,5 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
FINI;
|
||||
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
|
||||
return addr;
|
||||
}
|
||||
@@ -7,4 +7,5 @@
|
||||
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
|
||||
#define INST_NAME(name)
|
||||
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
|
||||
#define TABLE64(A, V) if((V)>0xffffffffLL) {Table64(dyn, (V)); EMIT(0);} else {MOV64x(A, V);}
|
||||
#define TABLE64(A, V) {Table64(dyn, (V)); EMIT(0);}
|
||||
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q); EMIT(0);}
|
||||
@@ -32,4 +32,5 @@
|
||||
++dyn->sons_size; \
|
||||
}
|
||||
|
||||
#define TABLE64(A, V) if((V)>0xffffffffLL) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} else {MOV64x(A, V);}
|
||||
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
|
||||
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q); MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);}
|
||||
@@ -42,6 +42,7 @@ typedef struct dynarec_arm_s {
|
||||
int dfnone; // if defered flags is already set to df_none
|
||||
uint64_t *table64; // table of 64bits value
|
||||
int table64size;// size of table (will be appended at end of executable code)
|
||||
int table64cap;
|
||||
uintptr_t tablestart;
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
int next_sz;
|
||||
|
||||
@@ -351,7 +351,7 @@ void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name)
|
||||
const char* elfname = ElfName(h);
|
||||
printf_log(LOG_DUMP, "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=%ld\n", elfname,
|
||||
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname,
|
||||
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);
|
||||
|
||||
+58
-28
@@ -106,7 +106,7 @@ int CalcLoadAddr(elfheader_t* head)
|
||||
}
|
||||
|
||||
head->stacksz = 1024*1024; //1M stack size default?
|
||||
head->stackalign = 4; // default align for stack
|
||||
head->stackalign = 16; // default align for stack
|
||||
for (int i=0; i<head->numPHEntries; ++i) {
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
uintptr_t phend = head->PHEntries[i].p_vaddr - head->vaddr + head->PHEntries[i].p_memsz;
|
||||
@@ -147,7 +147,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
|
||||
{
|
||||
uintptr_t offs = 0;
|
||||
if(mainbin && head->vaddr==0) {
|
||||
char* load_addr = getenv("BOX86_LOAD_ADDR");
|
||||
char* load_addr = getenv("BOX64_LOAD_ADDR");
|
||||
if(load_addr)
|
||||
if(sscanf(load_addr, "0x%lx", &offs)!=1)
|
||||
offs = 0;
|
||||
@@ -355,7 +355,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
|
||||
if(!h)
|
||||
return 0;
|
||||
Elf64_Rela * rel = (Elf64_Rela *)(h->rela + h->delta);
|
||||
if(!h->rel)
|
||||
if(!h->rela)
|
||||
return 0;
|
||||
int cnt = h->relasz / h->relaent;
|
||||
for (int i=0; i<cnt; ++i) {
|
||||
@@ -364,7 +364,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
|
||||
const char* symname = SymName(h, sym);
|
||||
if(!strcmp(symname, name) && t==R_X86_64_COPY) {
|
||||
*offs = sym->st_value + h->delta;
|
||||
*p = (uint64_t*)(rel[i].r_offset + h->delta);
|
||||
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -552,14 +552,17 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
uintptr_t globoffs, globend;
|
||||
uint64_t* globp;
|
||||
uintptr_t tmp = 0;
|
||||
intptr_t delta;
|
||||
switch(ELF64_R_TYPE(rela[i].r_info)) {
|
||||
case R_X86_64_NONE:
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
// should be "S + A - P" with S=symbol offset, A=addend and P=place of the storage unit, write a word32
|
||||
// can be ignored
|
||||
break;
|
||||
case R_X86_64_RELATIVE:
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
|
||||
*p += head->delta;
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend));
|
||||
*p = head->delta+ rela[i].r_addend;
|
||||
break;
|
||||
case R_X86_64_COPY:
|
||||
if(!strcmp(symname, "stdin") || !strcmp(symname, "stdout") || !strcmp(symname, "stderr")) {
|
||||
@@ -577,7 +580,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
if(offs) {
|
||||
// add r_addend to p?
|
||||
printf_log(LOG_DUMP, "Apply R_X86_64_COPY @%p with sym=%s, @%p size=%ld\n", p, symname, (void*)offs, sym->st_size);
|
||||
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
|
||||
if(p!=(void*)(offs+rela[i].r_addend))
|
||||
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
}
|
||||
@@ -587,8 +591,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
// set global offs / size for the symbol
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
|
||||
*p = globoffs + rela[i].r_addend;
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n",
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
|
||||
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
|
||||
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
|
||||
*p = globoffs/* + rela[i].r_addend*/; //no addend?
|
||||
AddWeakSymbol(GetGlobalData(maplib), symname, offs, end-offs+1);
|
||||
} else {
|
||||
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
|
||||
@@ -601,7 +608,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
|
||||
*p = offs + rela[i].r_addend;
|
||||
*p = offs/* + rela[i].r_addend*/; // not addend it seems
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -623,14 +630,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
// return -1;
|
||||
} else {
|
||||
if(p) {
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n",
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
|
||||
*p = offs + rela[i].r_addend;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend);
|
||||
printf_log(LOG_DUMP, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n",
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend);
|
||||
*p += head->delta;
|
||||
}
|
||||
break;
|
||||
@@ -639,8 +648,29 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
// return -1;
|
||||
} else {
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s addend=0x%lx (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend+*(uint64_t*)p));
|
||||
*p += offs+rela[i].r_addend;
|
||||
printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s addend=0x%lx (%p -> %p)\n",
|
||||
(bind==STB_LOCAL)?"Local":"Global", p, symname, rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
|
||||
*p /*+*/= offs+rela[i].r_addend;
|
||||
}
|
||||
break;
|
||||
case R_X86_64_TPOFF64:
|
||||
// Negated offset in static TLS block
|
||||
{
|
||||
if(h_tls)
|
||||
offs = sym->st_value;
|
||||
else {
|
||||
if(local_maplib)
|
||||
h_tls = GetGlobalSymbolElf(local_maplib, symname);
|
||||
if(!h_tls)
|
||||
h_tls = GetGlobalSymbolElf(maplib, symname);
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int64_t*)p;
|
||||
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%ld -> %ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
|
||||
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_X86_64_DTPMOD64:
|
||||
@@ -755,7 +785,7 @@ Elf64_Sym* GetFunction(elfheader_t* h, const char* name)
|
||||
// TODO: create a hash on named to avoid this loop
|
||||
for (int i=0; i<h->numSymTab; ++i) {
|
||||
int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
|
||||
if(/*h->SymTab[i].st_info == 18*/type==STT_FUNC) { // TODO: this "18" is probably defined somewhere
|
||||
if(type==STT_FUNC) {
|
||||
const char * symname = h->StrTab+h->SymTab[i].st_name;
|
||||
if(strcmp(symname, name)==0) {
|
||||
return h->SymTab+i;
|
||||
@@ -890,7 +920,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
|
||||
uname(1) man page description of the -i option). For more details of this token
|
||||
expansion, see “System Specific Shared Objects”
|
||||
*/
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, 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, box64context_t *box64, x64emu_t* emu)
|
||||
{
|
||||
DumpDynamicRPath(h);
|
||||
// update RPATH first
|
||||
@@ -927,9 +957,9 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
|
||||
free(origin);
|
||||
}
|
||||
if(strchr(rpath, '$')) {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
|
||||
printf_log(LOG_INFO, "BOX64: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
|
||||
} else {
|
||||
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
|
||||
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX64_LD_LIBRARY_PATH\n", rpath);
|
||||
PrependList(&box64->box64_ld_lib, rpath, 1);
|
||||
}
|
||||
if(rpath!=rpathref)
|
||||
@@ -943,8 +973,8 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH Handling
|
||||
if(AddNeededLib(maplib, neededlibs, local, needed, box64, emu)) {
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, needed, box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed);
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
@@ -1026,7 +1056,7 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
|
||||
h->fini_done = 1;
|
||||
// first check fini array
|
||||
Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
|
||||
for (int i=0; i<h->finiarray_sz; ++i) {
|
||||
for (int i=h->finiarray_sz-1; i>=0; --i) {
|
||||
printf_log(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
|
||||
}
|
||||
@@ -1094,7 +1124,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
const char* ret = NULL;
|
||||
uintptr_t s = 0;
|
||||
uint32_t size = 0;
|
||||
if(!h)
|
||||
if(!h || h->fini_done)
|
||||
return ret;
|
||||
|
||||
for (int i=0; i<h->numSymTab && distance!=0; ++i) {
|
||||
@@ -1132,7 +1162,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* GetDTatOffset(box64context_t* context, int index, int offset)
|
||||
void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset)
|
||||
{
|
||||
return (void*)((char*)GetTLSPointer(context, context->elfs[index])+offset);
|
||||
}
|
||||
@@ -1187,7 +1217,7 @@ typedef struct my_dl_phdr_info_s {
|
||||
void* dlpi_addr;
|
||||
const char* dlpi_name;
|
||||
Elf64_Phdr* dlpi_phdr;
|
||||
int dlpi_phnum;
|
||||
Elf64_Half dlpi_phnum;
|
||||
} my_dl_phdr_info_t;
|
||||
|
||||
static int dl_iterate_phdr_callback(x64emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
|
||||
@@ -1232,7 +1262,7 @@ static void* find_dl_iterate_phdr_Fct(void* fct)
|
||||
#undef SUPER
|
||||
|
||||
EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) {
|
||||
printf_log(LOG_INFO, "Warning: call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
|
||||
printf_log(LOG_DEBUG, "Call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
|
||||
box64context_t *context = GetEmuContext(emu);
|
||||
const char* empty = "";
|
||||
int ret = 0;
|
||||
@@ -1261,17 +1291,17 @@ void ResetSpecialCaseMainElf(elfheader_t* h)
|
||||
if(strcmp(symname, "_IO_2_1_stderr_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stderr, sym->st_size);
|
||||
my__IO_2_1_stderr_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stderr_ to %p\n", my__IO_2_1_stderr_);
|
||||
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stderr_ to %p\n", my__IO_2_1_stderr_);
|
||||
} else
|
||||
if(strcmp(symname, "_IO_2_1_stdin_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stdin, sym->st_size);
|
||||
my__IO_2_1_stdin_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stdin_ to %p\n", my__IO_2_1_stdin_);
|
||||
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stdin_ to %p\n", my__IO_2_1_stdin_);
|
||||
} else
|
||||
if(strcmp(symname, "_IO_2_1_stdout_")==0 && ((void*)sym->st_value+h->delta)) {
|
||||
memcpy((void*)sym->st_value+h->delta, stdout, sym->st_size);
|
||||
my__IO_2_1_stdout_ = (void*)sym->st_value+h->delta;
|
||||
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
|
||||
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +71,13 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_CLASS]!=ELFCLASS64) {
|
||||
if(strstr(name, ".so")) {
|
||||
// less naging on libs...
|
||||
printf_log(LOG_DEBUG, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_CLASS]==ELFCLASS32) {
|
||||
printf_log(LOG_INFO, "This is a 32bits ELF! box64 can only run 64bits ELF!\n");
|
||||
printf_log(LOG_INFO, "This is a 32bits ELF! box64 can only run 64bits ELF (%s)!\n", name);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,16 @@
|
||||
#define GETED_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
|
||||
#define GETGD opgd=GetGd(emu, rex, nextop)
|
||||
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
|
||||
#define GETEB32(D) oped=GetEb32O(emu, rex, nextop, D, 0)
|
||||
#define GETEB_OFFS(D, O) oped=GetEbO(emu, rex, nextop, D, O)
|
||||
#define GETGB opgd=GetGb(emu, rex, nextop)
|
||||
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
|
||||
#define GETEW32(D) oped=GetEw32O(emu, rex, nextop, D, 0)
|
||||
#define GETEW_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
|
||||
#define GETGW opgd=GetGw(emu, rex, nextop)
|
||||
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
|
||||
#define GETEX32(D) opex=GetEx32O(emu, rex, nextop, D, 0)
|
||||
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
|
||||
#define GETGX opgx=GetGx(emu, rex, nextop)
|
||||
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
|
||||
#define GETGM opgm=GetGm(emu, rex, nextop)
|
||||
|
||||
+50
-17
@@ -5,6 +5,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
@@ -16,6 +17,9 @@
|
||||
#include "x64run_private.h"
|
||||
#include "callback.h"
|
||||
#include "bridge.h"
|
||||
#ifdef HAVE_TRACE
|
||||
#include "x64trace.h"
|
||||
#endif
|
||||
#ifdef DYNAREC
|
||||
#include "custommem.h"
|
||||
#endif
|
||||
@@ -107,6 +111,7 @@ void SetupX64Emu(x64emu_t *emu)
|
||||
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
void SetTraceEmu(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
if(my_context->zydis) {
|
||||
@@ -121,6 +126,7 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
|
||||
trace_start = start;
|
||||
trace_end = end;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AddCleanup(x64emu_t *emu, void *p)
|
||||
{
|
||||
@@ -173,7 +179,8 @@ void CallAllCleanup(x64emu_t *emu)
|
||||
|
||||
static void internalFreeX64(x64emu_t* emu)
|
||||
{
|
||||
free(emu->stack2free);
|
||||
if(emu && emu->stack2free)
|
||||
munmap(emu->stack2free, emu->size_stack);
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -311,6 +318,10 @@ uint64_t GetRSP(x64emu_t *emu)
|
||||
{
|
||||
return R_RSP;
|
||||
}
|
||||
uint64_t GetRBP(x64emu_t *emu)
|
||||
{
|
||||
return R_RBP;
|
||||
}
|
||||
void SetFS(x64emu_t *emu, uint16_t v)
|
||||
{
|
||||
emu->segs[_FS] = v;
|
||||
@@ -329,12 +340,13 @@ void ResetFlags(x64emu_t *emu)
|
||||
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
{
|
||||
static char buff[1000];
|
||||
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
|
||||
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
|
||||
" R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
|
||||
char tmp[160];
|
||||
buff[0] = '\0';
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_emm) {
|
||||
// do emm reg is needed
|
||||
// do emm reg if needed
|
||||
for(int i=0; i<8; ++i) {
|
||||
sprintf(tmp, "mm%d:%016lx", i, emu->mmx87[i].q);
|
||||
strcat(buff, tmp);
|
||||
@@ -342,13 +354,14 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
}
|
||||
}
|
||||
if(trace_xmm) {
|
||||
// do xmm reg is needed
|
||||
// do xmm reg if needed
|
||||
for(int i=0; i<8; ++i) {
|
||||
sprintf(tmp, "%d:%016lx%016lx", i, emu->xmm[i].q[1], emu->xmm[i].q[0]);
|
||||
strcat(buff, tmp);
|
||||
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// start with FPU regs...
|
||||
if(emu->fpu_stack) {
|
||||
for (int i=0; i<emu->fpu_stack; i++) {
|
||||
@@ -362,19 +375,28 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
|
||||
strcat(buff, "\n");
|
||||
}
|
||||
for (int i=_AX; i<=_R15; ++i) {
|
||||
#ifdef HAVE_TRACE
|
||||
if (trace_regsdiff && (emu->regs[i].q[0] != emu->oldregs[i].q[0])) {
|
||||
sprintf(tmp, "\e[1;35m%s=%016lx\e[m ", regname[i], emu->regs[i].q[0]);
|
||||
emu->oldregs[i].q[0] = emu->regs[i].q[0];
|
||||
} else {
|
||||
sprintf(tmp, "%s=%016lx ", regname[i], emu->regs[i].q[0]);
|
||||
}
|
||||
#else
|
||||
sprintf(tmp, "%s=%016lx ", regname[i], emu->regs[i].q[0]);
|
||||
#endif
|
||||
strcat(buff, tmp);
|
||||
|
||||
if (i%5==4) {
|
||||
if(i==4) {
|
||||
if(emu->df) {
|
||||
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "?"
|
||||
sprintf(tmp, "flags=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
|
||||
sprintf(tmp, "flags=%s%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(D), FLAG_CHAR(S), FLAG_CHAR(Z), FLAG_CHAR(A), FLAG_CHAR(P), FLAG_CHAR(C));
|
||||
strcat(buff, tmp);
|
||||
#undef FLAG_CHAR
|
||||
} else {
|
||||
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "-"
|
||||
sprintf(tmp, "FLAGS=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
|
||||
sprintf(tmp, "FLAGS=%s%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(D), FLAG_CHAR(S), FLAG_CHAR(Z), FLAG_CHAR(A), FLAG_CHAR(P), FLAG_CHAR(C));
|
||||
strcat(buff, tmp);
|
||||
#undef FLAG_CHAR
|
||||
}
|
||||
@@ -393,8 +415,19 @@ void StopEmu(x64emu_t* emu, const char* reason)
|
||||
emu->quit = 1;
|
||||
printf_log(LOG_NONE, "%s", reason);
|
||||
// dump stuff...
|
||||
printf_log(LOG_NONE, "CPU Regs=%s\n", DumpCPURegs(emu, R_RIP));
|
||||
// TODO: stack, memory/instruction around EIP, etc..
|
||||
printf_log(LOG_NONE, "==== CPU Registers ====\n%s\n", DumpCPURegs(emu, R_RIP));
|
||||
printf_log(LOG_NONE, "======== Stack ========\nStack is from %lX to %lX\n", R_RBP, R_RSP);
|
||||
if (R_RBP == R_RSP) {
|
||||
printf_log(LOG_NONE, "RBP = RSP: leaf function detected; next 128 bytes should be either data or random.\n");
|
||||
} else {
|
||||
// TODO: display stack if operation should be allowed (to avoid crashes)
|
||||
/* for (uint64_t *sp = R_RBP; sp >= R_RSP; --sp) {
|
||||
} */
|
||||
}
|
||||
printf_log(LOG_NONE, "Old IP: %tX\n", emu->old_ip);
|
||||
#ifdef HAVE_TRACE
|
||||
printf_log(LOG_NONE, "%s\n", DecodeX64Trace(my_context->dec, emu->old_ip));
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnimpOpcode(x64emu_t* emu)
|
||||
@@ -442,16 +475,16 @@ uint64_t ReadTSC(x64emu_t* emu)
|
||||
{
|
||||
//TODO: implement hardware counter read?
|
||||
// Read the TimeStamp Counter as 64bits.
|
||||
// this is supposed to be the number of instrunctions executed since last reset
|
||||
// fall back to gettime...
|
||||
// this is supposed to be the number of instructions executed since last reset
|
||||
// fall back to gettime...
|
||||
#ifndef NOGETCLOCK
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -460,4 +493,4 @@ void ResetSegmentsCache(x64emu_t *emu)
|
||||
if(!emu)
|
||||
return;
|
||||
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ typedef struct x64emu_s {
|
||||
multiuint_t res;
|
||||
uint32_t *x64emu_parity_tab; // helper
|
||||
#ifdef HAVE_TRACE
|
||||
reg64_t oldregs[16];
|
||||
uintptr_t prev2_ip;
|
||||
#endif
|
||||
// segments
|
||||
@@ -91,4 +92,4 @@ typedef struct x64emu_s {
|
||||
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
|
||||
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
|
||||
|
||||
#endif //__X86EMU_PRIVATE_H_
|
||||
#endif //__X86EMU_PRIVATE_H_
|
||||
+47
-1
@@ -10,6 +10,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
@@ -100,12 +101,57 @@ void x64Int3(x64emu_t* emu)
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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")) {
|
||||
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);
|
||||
post = 2;
|
||||
} 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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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")) {
|
||||
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,
|
||||
(uint32_t)*(uint64_t*)(R_RSP+8), (int)*(uint64_t*)(R_RSP+16),
|
||||
(uint32_t)*(uint64_t*)(R_RSP+24), (void*)*(uint64_t*)(R_RSP+32),
|
||||
(unsigned long)*(uint64_t*)(R_RSP+40), (void*)*(uint64_t*)(R_RSP+48));
|
||||
} else {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
|
||||
}
|
||||
@@ -143,7 +189,7 @@ void x64Int3(x64emu_t* emu)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(my_context->signals[SIGTRAP])
|
||||
if(0 && my_context->signals[SIGTRAP])
|
||||
raise(SIGTRAP);
|
||||
else
|
||||
printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_RIP);
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
// This has been heavily modified to fit box86 purpose...
|
||||
// This has been heavily modified to fit box64 purpose...
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -353,8 +353,6 @@ static inline uint16_t shr16(x64emu_t *emu, uint16_t d, uint8_t s)
|
||||
|
||||
static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
{
|
||||
RESET_FLAGS(emu); // TODO: Defered this one?
|
||||
|
||||
emu->df = d_shr32;
|
||||
emu->op1.u32 = d;
|
||||
|
||||
@@ -367,8 +365,6 @@ static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
|
||||
|
||||
static inline uint64_t shr64(x64emu_t *emu, uint64_t d, uint8_t s)
|
||||
{
|
||||
RESET_FLAGS(emu); // TODO: Defered this one?
|
||||
|
||||
emu->df = d_shr64;
|
||||
emu->op1.u64 = d;
|
||||
|
||||
|
||||
+62
-12
@@ -48,7 +48,7 @@ int Run(x64emu_t *emu, int step)
|
||||
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, emu->context->stack);
|
||||
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, (void*)R_RSP);
|
||||
|
||||
x64emurun:
|
||||
|
||||
@@ -256,7 +256,7 @@ x64emurun:
|
||||
goto fini;
|
||||
break;
|
||||
case 0x67: /* reduce EASize prefix */
|
||||
if(Run67(emu, rex)) {
|
||||
if(Run67(emu, rex, rep)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ x64emurun:
|
||||
tmp32s = F8S;
|
||||
}
|
||||
if(rex.w) {
|
||||
tmp64u = (uint64_t)tmp32s;
|
||||
tmp64u = (uint64_t)(int64_t)tmp32s;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;
|
||||
case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break;
|
||||
@@ -538,7 +538,37 @@ x64emurun:
|
||||
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
|
||||
RESET_FLAGS(emu);
|
||||
break;
|
||||
|
||||
case 0x9E: /* SAHF */
|
||||
tmp8u = emu->regs[_AX].byte[1];
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x01, F_CF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x04, F_PF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x10, F_AF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x40, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(tmp8u&0x80, F_SF);
|
||||
RESET_FLAGS(emu);
|
||||
break;
|
||||
case 0x9F: /* LAHF */
|
||||
CHECK_FLAGS(emu);
|
||||
R_AH = (uint8_t)emu->eflags.x64;
|
||||
break;
|
||||
case 0xA0: /* MOV AL,Ob */
|
||||
R_AL = *(uint8_t*)F64;
|
||||
break;
|
||||
case 0xA1: /* MOV EAX,Od */
|
||||
if(rex.w)
|
||||
R_RAX = *(uint64_t*)F64;
|
||||
else
|
||||
R_EAX = *(uint32_t*)F64;
|
||||
break;
|
||||
case 0xA2: /* MOV Ob,AL */
|
||||
*(uint8_t*)F64 = R_AL;
|
||||
break;
|
||||
case 0xA3: /* MOV Od,EAX */
|
||||
if(rex.w)
|
||||
*(uint64_t*)F64 = R_RAX;
|
||||
else
|
||||
*(uint32_t*)F64 = R_EAX;
|
||||
break;
|
||||
case 0xA4: /* MOVSB */
|
||||
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
|
||||
tmp64u = (rep)?R_RCX:1L;
|
||||
@@ -889,7 +919,6 @@ x64emurun:
|
||||
else
|
||||
emu->regs[(opcode&7)+(rex.b<<3)].q[0] = F32;
|
||||
break;
|
||||
|
||||
case 0xC0: /* GRP2 Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB(1);
|
||||
@@ -1085,7 +1114,14 @@ x64emurun:
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0xDC: /* x87 opcodes */
|
||||
if(RunDC(emu, rex)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
case 0xDD: /* x87 opcodes */
|
||||
if(RunDD(emu, rex)) {
|
||||
unimp = 1;
|
||||
@@ -1094,7 +1130,14 @@ x64emurun:
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
|
||||
case 0xDE: /* x87 opcodes */
|
||||
if(RunDE(emu, rex)) {
|
||||
unimp = 1;
|
||||
goto fini;
|
||||
}
|
||||
if(emu->quit)
|
||||
goto fini;
|
||||
break;
|
||||
case 0xDF: /* x87 opcodes */
|
||||
if(RunDF(emu, rex)) {
|
||||
unimp = 1;
|
||||
@@ -1231,7 +1274,6 @@ x64emurun:
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF8: /* CLC */
|
||||
CHECK_FLAGS(emu);
|
||||
CLEAR_FLAG(F_CF);
|
||||
@@ -1274,14 +1316,22 @@ x64emurun:
|
||||
case 0: /* INC Ed */
|
||||
if(rex.w)
|
||||
ED->q[0] = inc64(emu, ED->q[0]);
|
||||
else
|
||||
ED->q[0] = inc32(emu, ED->dword[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
|
||||
ED->q[0] = dec32(emu, ED->dword[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]);
|
||||
|
||||
+255
-26
@@ -22,6 +22,7 @@
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
#ifdef DYNAREC
|
||||
#include "custommem.h"
|
||||
#include "../dynarec/arm64_lock.h"
|
||||
#endif
|
||||
|
||||
@@ -38,7 +39,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem, *opgm;
|
||||
mmx87_regs_t *opem, *opgm, eam1;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
@@ -104,6 +105,22 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[1];
|
||||
break;
|
||||
case 0x18: /* PREFETCHh Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
if(MODREG) {
|
||||
} else
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //PREFETCHnta
|
||||
case 1: //PREFETCH1
|
||||
case 2: //PREFETCH2
|
||||
case 3: //PREFETCH3
|
||||
__builtin_prefetch((void*)ED, 0, 0); // ignoring wich level of cache
|
||||
break;
|
||||
default: //NOP
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
@@ -188,6 +205,75 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
|
||||
break;
|
||||
|
||||
case 0x31: /* RDTSC */
|
||||
tmp64u = ReadTSC(emu);
|
||||
R_RDX = tmp64u>>32;
|
||||
R_RAX = tmp64u&0xFFFFFFFF;
|
||||
break;
|
||||
|
||||
case 0x38: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x00: /* PSHUFB */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
eam1 = *GM;
|
||||
for (int i=0; i<8; ++i) {
|
||||
if(EM->ub[i]&128)
|
||||
GM->ub[i] = 0;
|
||||
else
|
||||
GM->ub[i] = eam1.ub[EM->ub[i]&7];
|
||||
}
|
||||
break;
|
||||
case 0x04: /* PMADDUBSW Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = (int32_t)(GM->ub[i*2+0])*EM->sb[i*2+0] + (int32_t)(GM->ub[i*2+1])*EM->sb[i*2+1];
|
||||
GM->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
|
||||
}
|
||||
break;
|
||||
case 0x0B: /* PMULHRSW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = ((((int32_t)(GM->sw[i])*(int32_t)(EM->sw[i]))>>14) + 1)>>1;
|
||||
GM->uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1C: /* PABSB Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<8; ++i) {
|
||||
GM->sb[i] = abs(EM->sb[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1D: /* PABSW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
GM->sw[i] = abs(EM->sw[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1E: /* PABSD Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<2; ++i) {
|
||||
GM->sd[i] = abs(EM->sd[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
GOCOND(0x40
|
||||
, nextop = F8;
|
||||
@@ -443,13 +529,103 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GM->sw[2+i] = (EM->sd[i]<-32768)?-32768:((EM->sd[i]>32767)?32767:EM->sd[i]);
|
||||
break;
|
||||
|
||||
case 0x6E: /* MOVD Gm, Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGM;
|
||||
if(rex.w)
|
||||
GM->q = ED->q[0];
|
||||
else
|
||||
GM->q = ED->dword[0]; // zero extended
|
||||
break;
|
||||
case 0x6F: /* MOVQ Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
GM->q = EM->q;
|
||||
break;
|
||||
|
||||
case 0x70: /* PSHUFW Gm, Em, Ib */
|
||||
nextop = F8;
|
||||
GETEM(1);
|
||||
GETGM;
|
||||
tmp8u = F8;
|
||||
if(EM==GM) {eam1 = *GM; EM = &eam1;} // copy is needed
|
||||
for(int i=0; i<4; ++i)
|
||||
GM->uw[i] = EM->uw[(tmp8u>>(i*2))&3];
|
||||
break;
|
||||
case 0x71: /* GRP */
|
||||
nextop = F8;
|
||||
GETEM(1);
|
||||
tmp8u = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 2: /* PSRLW Em, Ib */
|
||||
if(tmp8u>15)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
for (int i=0; i<4; ++i) EM->uw[i] >>= tmp8u;
|
||||
break;
|
||||
case 4: /* PSRAW Em, Ib */
|
||||
if(tmp8u>15) tmp8u = 15;
|
||||
for (int i=0; i<4; ++i) EM->sw[i] >>= tmp8u;
|
||||
break;
|
||||
case 6: /* PSLLW Em, Ib */
|
||||
if(tmp8u>15)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
for (int i=0; i<4; ++i) EM->uw[i] <<= tmp8u;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x72: /* GRP */
|
||||
nextop = F8;
|
||||
GETEM(1);
|
||||
switch((nextop>>3)&7) {
|
||||
case 2: /* PSRLD Em, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>31)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
for (int i=0; i<2; ++i) EM->ud[i] >>= tmp8u;
|
||||
break;
|
||||
case 4: /* PSRAD Em, Ib */
|
||||
tmp8u = F8;
|
||||
for (int i=0; i<2; ++i) EM->sd[i] >>= tmp8u;
|
||||
break;
|
||||
case 6: /* PSLLD Em, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>31)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
for (int i=0; i<2; ++i) EM->ud[i] <<= tmp8u;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x73: /* GRP */
|
||||
nextop = F8;
|
||||
GETEM(1);
|
||||
switch((nextop>>3)&7) {
|
||||
case 2: /* PSRLQ Em, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>63)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
{EM->q >>= tmp8u;}
|
||||
break;
|
||||
case 6: /* PSLLQ Em, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>63)
|
||||
{EM->q = 0;}
|
||||
else
|
||||
{EM->q <<= tmp8u;}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x74: /* PCMPEQB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
@@ -486,8 +662,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GETGM;
|
||||
if(rex.w)
|
||||
ED->q[0] = GM->q;
|
||||
else
|
||||
ED->q[0] = GM->ud[0];
|
||||
else {
|
||||
if(MODREG)
|
||||
ED->q[0] = GM->ud[0];
|
||||
else
|
||||
ED->dword[0] = GM->ud[0];
|
||||
}
|
||||
break;
|
||||
case 0x7F: /* MOVQ Em, Gm */
|
||||
nextop = F8;
|
||||
@@ -622,6 +802,11 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
case 3: /* STMXCSR Md */
|
||||
ED->dword[0] = emu->mxcsr;
|
||||
break;
|
||||
case 7: /* CLFLUSH Ed */
|
||||
#ifdef DYNAREC
|
||||
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -659,13 +844,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
} else {
|
||||
cmp32(emu, R_EAX, ED->dword[0]);
|
||||
R_RAX = ED->dword[0]; // to erase upper part of RAX
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
if(MODREG)
|
||||
ED->q[0] = GD->dword[0];
|
||||
else
|
||||
ED->dword[0] = GD->dword[0];
|
||||
} else {
|
||||
R_RAX = ED->dword[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -960,6 +1144,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4: /* PINSRW Gm,Ew,Ib */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGM;
|
||||
tmp8u = F8;
|
||||
GM->uw[tmp8u&3] = ED->word[0]; // only low 16bits
|
||||
break;
|
||||
case 0xC5: /* PEXTRW Gw,Em,Ib */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGD;
|
||||
tmp8u = F8;
|
||||
GD->q[0] = EM->uw[tmp8u&3]; // 16bits extract, 0 extended
|
||||
break;
|
||||
case 0xC6: /* SHUFPS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -1078,7 +1276,13 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GM->uw[i] = (tmp32s < 0) ? 0 : tmp32s;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDA: /* PMINUB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<8; ++i)
|
||||
GM->ub[i] = (GM->ub[i]<EM->ub[i])?GM->ub[i]:EM->ub[i];
|
||||
break;
|
||||
case 0xDB: /* PAND Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
@@ -1103,14 +1307,26 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GM->uw[i] = (tmp32u>65535) ? 65535 : tmp32u;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDE: /* PMAXUB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for (int i=0; i<8; ++i)
|
||||
GM->ub[i] = (GM->ub[i]>EM->ub[i])?GM->ub[i]:EM->ub[i];
|
||||
break;
|
||||
case 0xDF: /* PANDN Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
GM->q = (~GM->q) & EM->q;
|
||||
break;
|
||||
|
||||
case 0xE0: /* PAVGB Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<8; ++i)
|
||||
GM->ub[i] = ((uint32_t)GM->ub[i]+EM->ub[i]+1)>>1;
|
||||
break;
|
||||
case 0xE1: /* PSRAW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
@@ -1135,22 +1351,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GM->sd[i] >>= tmp8u;
|
||||
}
|
||||
break;
|
||||
case 0xE3: /* PSRAQ Gm, Em */
|
||||
case 0xE3: /* PAVGW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
if(EM->q>63)
|
||||
tmp8u = 64;
|
||||
else
|
||||
tmp8u = EM->ub[0];
|
||||
GM->sq >>= tmp8u;
|
||||
for(int i=0; i<4; ++i)
|
||||
GM->uw[i] = ((uint32_t)GM->uw[i]+EM->uw[i]+1)>>1;
|
||||
break;
|
||||
case 0xE4: /* PMULHUW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<4; ++i) {
|
||||
tmp32u = (int32_t)GM->uw[i] * EM->uw[i];
|
||||
tmp32u = (uint32_t)GM->uw[i] * (uint32_t)EM->uw[i];
|
||||
GM->uw[i] = (tmp32u>>16)&0xffff;
|
||||
}
|
||||
break;
|
||||
@@ -1159,17 +1372,24 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<4; ++i) {
|
||||
tmp32s = (int32_t)GM->sw[i] * EM->sw[i];
|
||||
GM->uw[i] = (tmp32s>>16)&0xffff;
|
||||
tmp32s = (int32_t)GM->sw[i] * (int32_t)EM->sw[i];
|
||||
GM->sw[i] = (tmp32s>>16)&0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE7: /* MOVNTQ Em,Gm */
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0)
|
||||
return 1;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
EM->q = GM->q;
|
||||
break;
|
||||
case 0xE8: /* PSUBSB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)GM->sb[i] - EM->sb[i];
|
||||
tmp32s = (int32_t)GM->sb[i] - (int32_t)EM->sb[i];
|
||||
GM->sb[i] = (tmp32s>127)?127:((tmp32s<-128)?-128:tmp32s);
|
||||
}
|
||||
break;
|
||||
@@ -1257,27 +1477,36 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GM->sd[i] = tmp32s + tmp32s2;
|
||||
}
|
||||
break;
|
||||
case 0xF6: /* PSADBW Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
tmp32u = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tmp32u += (GM->ub[i]>EM->ub[i])?(GM->ub[i] - EM->ub[i]):(EM->ub[i] - GM->ub[i]);
|
||||
GM->q = tmp32u;
|
||||
break;
|
||||
|
||||
case 0xF8: /* PSUBB Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<8; ++i)
|
||||
GM->sb[i] -= EM->sb[i];
|
||||
GM->ub[i] -= EM->ub[i];
|
||||
break;
|
||||
case 0xF9: /* PSUBW Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<4; ++i)
|
||||
GM->sw[i] -= EM->sw[i];
|
||||
GM->uw[i] -= EM->uw[i];
|
||||
break;
|
||||
case 0xFA: /* PSUBD Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<2; ++i)
|
||||
GM->sd[i] -= EM->sd[i];
|
||||
GM->ud[i] -= EM->ud[i];
|
||||
break;
|
||||
|
||||
case 0xFC: /* PADDB Gm, Em */
|
||||
@@ -1285,21 +1514,21 @@ int Run0F(x64emu_t *emu, rex_t rex)
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<8; ++i)
|
||||
GM->sb[i] += EM->sb[i];
|
||||
GM->ub[i] += EM->ub[i];
|
||||
break;
|
||||
case 0xFD: /* PADDW Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<4; ++i)
|
||||
GM->sw[i] += EM->sw[i];
|
||||
GM->uw[i] += EM->uw[i];
|
||||
break;
|
||||
case 0xFE: /* PADDD Gm,Em */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
for(int i=0; i<2; ++i)
|
||||
GM->sd[i] += EM->sd[i];
|
||||
GM->ud[i] += EM->ud[i];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+171
-3
@@ -33,6 +33,8 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
int rep;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
|
||||
opcode = F8;
|
||||
@@ -42,19 +44,180 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
rep = 0;
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GETEB_OFFS(0, tlsdata); \
|
||||
GETGB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GETED_OFFS(0, tlsdata); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
|
||||
else { \
|
||||
if(MODREG) \
|
||||
ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
|
||||
else \
|
||||
ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
|
||||
} \
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GETEB_OFFS(0, tlsdata); \
|
||||
GETGB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GETED_OFFS(0, tlsdata); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
|
||||
else \
|
||||
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
|
||||
break; \
|
||||
case B+4: \
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
break; \
|
||||
case B+5: \
|
||||
if(rex.w) \
|
||||
R_RAX = OP##64(emu, R_RAX, F32S64); \
|
||||
else \
|
||||
R_RAX = OP##32(emu, R_EAX, F32); \
|
||||
break;
|
||||
|
||||
case 0x33: /* XOR Gd,Ed */
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or) /* OR 0x08 -> 0x0D */
|
||||
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
|
||||
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
|
||||
GO(0x20, and) /* AND 0x20 -> 0x25 */
|
||||
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x11:
|
||||
switch(rep) {
|
||||
case 1: /* MOVSD Ex, Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
break;
|
||||
case 2: /* MOVSS FS:Ex, Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->ud[0] = GX->ud[0];
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x29: /* MOVAPS Ex,Gx */
|
||||
switch(rep) {
|
||||
case 0:
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
EX->q[1] = GX->q[1];
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x59:
|
||||
switch(rep) {
|
||||
case 2: /* MULSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->f[0] *= EX->f[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGB;
|
||||
cmp8(emu, EB->byte[0], GB);
|
||||
break;
|
||||
case 0x39:
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = xor64(emu, GD->q[0], ED->q[0]);
|
||||
cmp64(emu, ED->q[0], GD->q[0]);
|
||||
else
|
||||
GD->q[0] = xor32(emu, GD->dword[0], ED->dword[0]);
|
||||
cmp32(emu, ED->dword[0], GD->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x3B:
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
cmp64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
cmp32(emu, GD->dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
|
||||
case 0x66:
|
||||
opcode = F8;
|
||||
|
||||
while(opcode>=0x40 && opcode<=0x4F) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
switch(opcode) {
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0xD6: /* MOVQ Ex,Gx */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
if(MODREG)
|
||||
EX->q[1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0x81: /* GRP Ed,Id */
|
||||
case 0x83: /* GRP Ed,Ib */
|
||||
nextop = F8;
|
||||
@@ -134,6 +297,11 @@ int Run64(x64emu_t *emu, rex_t rex)
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0xC6: /* MOV Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(1, tlsdata);
|
||||
EB->byte[0] = F8;
|
||||
break;
|
||||
case 0xC7: /* MOV Ed,Id */
|
||||
nextop = F8;
|
||||
GETED_OFFS(4, tlsdata);
|
||||
|
||||
+31
-1
@@ -33,6 +33,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
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;
|
||||
@@ -209,7 +210,30 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
EW->word[0] = GW->word[0];
|
||||
if(rex.w)
|
||||
EW->q[0] = GW->q[0];
|
||||
else
|
||||
EW->word[0] = GW->word[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gw,Ew */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
if(rex.w)
|
||||
GW->q[0] = EW->q[0];
|
||||
else
|
||||
GW->word[0] = EW->word[0];
|
||||
break;
|
||||
|
||||
case 0x8D: /* LEA Gw,M */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = (uint64_t)ED;
|
||||
else
|
||||
GD->word[0] = (uint16_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
case 0x90: /* NOP */
|
||||
@@ -527,6 +551,12 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
|
||||
case 0xDD: /* x87 opcdes */
|
||||
return Run66DD(emu, rex);
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, R_RIP);
|
||||
R_RIP += tmp32s;
|
||||
break;
|
||||
|
||||
case 0xF7: /* GRP3 Ew(,Iw) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
|
||||
+164
-1
@@ -78,6 +78,18 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[0] = GX->q[1];
|
||||
GX->q[1] = EX->q[1];
|
||||
break;
|
||||
case 0x16: /* MOVHPD Gx, Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGX;
|
||||
GX->q[1] = ED->q[0];
|
||||
break;
|
||||
case 0x17: /* MOVHPD Ed, Gx */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGX;
|
||||
ED->q[0] = GX->q[1];
|
||||
break;
|
||||
|
||||
case 0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
@@ -155,6 +167,126 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
|
||||
break;
|
||||
|
||||
case 0x38: // SSSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x00: /* PSHUFB */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
eax1 = *GX;
|
||||
for (int i=0; i<16; ++i) {
|
||||
if(EX->ub[i]&128)
|
||||
GX->ub[i] = 0;
|
||||
else
|
||||
GX->ub[i] = eax1.ub[EX->ub[i]&15];
|
||||
}
|
||||
break;
|
||||
case 0x01: /* PHADDW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sw[i] = GX->sw[i*2+0]+GX->sw[i*2+1];
|
||||
if(GX == EX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
|
||||
}
|
||||
break;
|
||||
case 0x02: /* PHADDD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->sd[0] += GX->sd[1];
|
||||
GX->sd[1] = GX->sd[2] + GX->sd[3];
|
||||
if(GX == EX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
GX->sd[2] = EX->sd[0] + EX->sd[1];
|
||||
GX->sd[3] = EX->sd[2] + EX->sd[3];
|
||||
}
|
||||
break;
|
||||
case 0x03: /* PHADDSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = GX->sw[i*2+0]+GX->sw[i*2+1];
|
||||
GX->sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
if(GX == EX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
|
||||
GX->sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x04: /* PMADDUBSW Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)(GX->ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX->ub[i*2+1])*EX->sb[i*2+1];
|
||||
GX->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
|
||||
}
|
||||
break;
|
||||
case 0x05: /* PHSUBW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sw[i] = GX->sw[i*2+0] - GX->sw[i*2+1];
|
||||
if(GX == EX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0B: /* PMULHRSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
tmp32s = ((((int32_t)(GX->sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
|
||||
GX->uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3A: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0F: // PALIGNR GX, EX, u8
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
if(tmp8u>31)
|
||||
{GX->q[0] = GX->q[1] = 0;}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<16; ++i, ++tmp8u)
|
||||
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX->ub[tmp8u-16]):EX->ub[tmp8u];
|
||||
GX->q[0] = eax1.q[0];
|
||||
GX->q[1] = eax1.q[1];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
GOCOND(0x40
|
||||
, nextop = F8;
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -848,6 +980,20 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC4: /* PINSRW Gx,Ew,Ib */
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->uw[tmp8u&7] = ED->word[0]; // only low 16bits
|
||||
break;
|
||||
case 0xC5: /* PEXTRW Gw,Ex,Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
GETGD;
|
||||
tmp8u = F8;
|
||||
GD->dword[0] = EX->uw[tmp8u&7]; // 16bits extract, 0 extended
|
||||
break;
|
||||
case 0xC6: /* SHUFPD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -1020,7 +1166,24 @@ int Run660F(x64emu_t *emu, rex_t rex)
|
||||
for (int i=0; i<8; ++i)
|
||||
GX->uw[i] = ((uint32_t)GX->uw[i] + EX->uw[i] + 1)>>1;
|
||||
break;
|
||||
|
||||
case 0xE4: /* PMULHUW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32u = (uint32_t)GX->uw[i] * EX->uw[i];
|
||||
GX->uw[i] = (tmp32u>>16)&0xffff;
|
||||
}
|
||||
break;
|
||||
case 0xE5: /* PMULHW Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)GX->sw[i] * EX->sw[i];
|
||||
GX->uw[i] = (tmp32s>>16)&0xffff;
|
||||
}
|
||||
break;
|
||||
case 0xE6: /* CVTTPD2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
|
||||
+234
-2
@@ -22,23 +22,143 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run67(x64emu_t *emu, rex_t rex)
|
||||
int Run67(x64emu_t *emu, rex_t rex, int rep)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
// REX prefix before the F0 are ignored
|
||||
while(opcode==0x67)
|
||||
opcode = F8;
|
||||
|
||||
// REX prefix before the 67 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
|
||||
else { \
|
||||
if(MODREG) \
|
||||
ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
|
||||
else \
|
||||
ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
|
||||
} \
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GETEB32(0); \
|
||||
GETGB; \
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GETED32(0); \
|
||||
GETGD; \
|
||||
if(rex.w) \
|
||||
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
|
||||
else \
|
||||
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
|
||||
break; \
|
||||
case B+4: \
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
break; \
|
||||
case B+5: \
|
||||
if(rex.w) \
|
||||
R_RAX = OP##64(emu, R_RAX, F32S64); \
|
||||
else \
|
||||
R_RAX = OP##32(emu, R_EAX, F32); \
|
||||
break;
|
||||
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or) /* OR 0x08 -> 0x0D */
|
||||
case 0x0F:
|
||||
return Run670F(emu, rex, rep);
|
||||
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
|
||||
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
|
||||
GO(0x20, and) /* AND 0x20 -> 0x25 */
|
||||
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x66:
|
||||
return Run6766(emu, rex, rep);
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
GETEB32(1);
|
||||
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 0x88: /* MOV Eb,Gb */
|
||||
nextop = F8;
|
||||
GETEB32(0);
|
||||
GETGB;
|
||||
EB->byte[0] = GB;
|
||||
break;
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
nextop = F8;
|
||||
GETED32(0);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
ED->q[0] = GD->q[0];
|
||||
} else {
|
||||
//if ED is a reg, than the opcode works like movzx
|
||||
if(MODREG)
|
||||
ED->q[0] = GD->dword[0];
|
||||
else
|
||||
ED->dword[0] = GD->dword[0];
|
||||
}
|
||||
break;
|
||||
case 0x8A: /* MOV Gb,Eb */
|
||||
nextop = F8;
|
||||
GETEB32(0);
|
||||
GETGB;
|
||||
GB = EB->byte[0];
|
||||
break;
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED32(0);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = ED->q[0];
|
||||
else
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8D: /* LEA Gd,M */
|
||||
nextop = F8;
|
||||
@@ -50,6 +170,47 @@ int Run67(x64emu_t *emu, rex_t rex)
|
||||
GD->q[0] = (uint32_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
case 0xC1: /* GRP2 Ed,Ib */
|
||||
nextop = F8;
|
||||
GETED32(1);
|
||||
tmp8u = F8/* & 0x1f*/; // masking done in each functions
|
||||
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 0xE0: /* LOOPNZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
@@ -76,6 +237,77 @@ int Run67(x64emu_t *emu, rex_t rex)
|
||||
R_RIP += tmp8s;
|
||||
break;
|
||||
|
||||
case 0xF7: /* GRP3 Ed(,Id) */
|
||||
nextop = F8;
|
||||
tmp8u = (nextop>>3)&7;
|
||||
GETED32((tmp8u<2)?4:0);
|
||||
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;
|
||||
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;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#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"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm64_lock.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run670F(x64emu_t *emu, rex_t rex, int 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;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x2E: /* UCOMISS Gx, Ex */
|
||||
// same for now
|
||||
case 0x2F: /* COMISS Gx, Ex */
|
||||
RESET_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
if(isnan(GX->f[0]) || isnan(EX->f[0])) {
|
||||
SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF);
|
||||
} else if(isgreater(GX->f[0], EX->f[0])) {
|
||||
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
|
||||
} else if(isless(GX->f[0], EX->f[0])) {
|
||||
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); SET_FLAG(F_CF);
|
||||
} else {
|
||||
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
|
||||
}
|
||||
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#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"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm64_lock.h"
|
||||
#endif
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
int Run6766(x64emu_t *emu, rex_t rex, int 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;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
|
||||
opcode = F8;
|
||||
|
||||
while((opcode==0xF2) || (opcode==0xF3)) {
|
||||
rep = opcode-0xF1;
|
||||
opcode = F8;
|
||||
}
|
||||
// REX prefix before the F0 are ignored
|
||||
rex.rex = 0;
|
||||
while(opcode>=0x40 && opcode<=0x4f) {
|
||||
rex.rex = opcode;
|
||||
opcode = F8;
|
||||
}
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0F: /* more opcdes */
|
||||
return Run67660F(emu, rex);
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#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 "modrm.h"
|
||||
|
||||
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;
|
||||
|
||||
opcode = F8;
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x6F: /* MOVDQA Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
GX->q[0] = EX->q[0];
|
||||
GX->q[1] = EX->q[1];
|
||||
break;
|
||||
|
||||
case 0x76: /* PCMPEQD Gx,Ex */
|
||||
nextop = F8;
|
||||
GETEX32(0);
|
||||
GETGX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+44
-11
@@ -30,8 +30,6 @@
|
||||
|
||||
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))
|
||||
{
|
||||
//TODO: register rtld_fini
|
||||
//TODO: register fini
|
||||
// let's cheat and set all args...
|
||||
if(init) {
|
||||
PushExit(emu);
|
||||
@@ -44,14 +42,20 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
|
||||
// call main and finish
|
||||
Push64(emu, GetRBP(emu)); // set frame pointer
|
||||
SetRBP(emu, GetRSP(emu)); // save RSP
|
||||
SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP
|
||||
PushExit(emu);
|
||||
SetRDX(emu, (uint64_t)my_context->envv);
|
||||
SetRSI(emu, (uint64_t)my_context->argv);
|
||||
SetRDI(emu, (uint64_t)my_context->argc);
|
||||
R_RIP=(uint64_t)main;
|
||||
#ifdef DYNAREC
|
||||
|
||||
DynaRun(emu);
|
||||
#endif
|
||||
|
||||
SetRSP(emu, GetRBP(emu)); // restore RSP
|
||||
SetRBP(emu, Pop64(emu)); // restore RBP
|
||||
emu->quit = 1; // finished!
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -921,7 +925,7 @@ void UpdateFlags(x64emu_t *emu)
|
||||
case d_rcr32:
|
||||
case d_rcr64:
|
||||
case d_unknown:
|
||||
printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
|
||||
printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
|
||||
break;
|
||||
}
|
||||
RESET_FLAGS(emu);
|
||||
@@ -1003,10 +1007,10 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
} else {
|
||||
printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip));
|
||||
uint8_t peek = PK(0);
|
||||
if(peek==0xC3 || peek==0xC2) {
|
||||
if(peek==0xC3 || peek==0xC2 || (peek==0xF3 && PK(1)==0xC3)) {
|
||||
printf_log(LOG_NONE, " => %p", *(void**)(R_RSP));
|
||||
printFunctionAddr(*(uintptr_t*)(R_RSP), "=> ");
|
||||
} else if(peek==0x55) {
|
||||
} else if(peek==0x55 || peek==0x53) {
|
||||
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
|
||||
printFunctionAddr(ip, "here: ");
|
||||
} else if(peek==0xE8) { // Call
|
||||
@@ -1065,7 +1069,7 @@ reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr
|
||||
base += Fetch32s(emu);
|
||||
return (reg64_t*)(base+R_RIP+delta);
|
||||
}
|
||||
return (reg64_t*)(emu->regs[m+(rex.b<<3)].q[0]);
|
||||
return (reg64_t*)(base + emu->regs[m+(rex.b<<3)].q[0]);
|
||||
} else {
|
||||
if((m&7)==4) {
|
||||
uint8_t sib = Fetch8(emu);
|
||||
@@ -1091,7 +1095,7 @@ reg64_t* GetECommon32O(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintp
|
||||
base += Fetch32s(emu);
|
||||
return (reg64_t*)(base+R_RIP+delta);
|
||||
}
|
||||
return (reg64_t*)(uintptr_t)(emu->regs[m+(rex.b<<3)].dword[0]);
|
||||
return (reg64_t*)(uintptr_t)(base + emu->regs[m+(rex.b<<3)].dword[0]);
|
||||
} else {
|
||||
if((m&7)==4) {
|
||||
uint8_t sib = Fetch8(emu);
|
||||
@@ -1157,6 +1161,19 @@ reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t
|
||||
} else return GetECommon32O(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Eb
|
||||
if(m>=0xC0) {
|
||||
if(rex.rex) {
|
||||
return &emu->regs[(m&0x07)+(rex.b<<3)];
|
||||
} else {
|
||||
int lowhigh = (m&4)>>2;
|
||||
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
|
||||
}
|
||||
} else return GetECommon32O(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
#define GetEw GetEd
|
||||
|
||||
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
@@ -1229,6 +1246,22 @@ sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
|
||||
} else return (sse_regs_t*)GetECommon(emu, rex, m, delta);
|
||||
}
|
||||
|
||||
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->xmm[(m&0x07)+(rex.b<<3)];
|
||||
} else return (sse_regs_t*)GetECommonO(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
|
||||
{
|
||||
uint8_t m = v&0xC7; // filter Ed
|
||||
if(m>=0xC0) {
|
||||
return &emu->xmm[(m&0x07)+(rex.b<<3)];
|
||||
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
|
||||
}
|
||||
|
||||
|
||||
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
@@ -1238,9 +1271,9 @@ reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
|
||||
{
|
||||
uint8_t m = (v&0x38)>>3;
|
||||
if(rex.rex) {
|
||||
if(rex.rex)
|
||||
return &emu->regs[(m&7)+(rex.r<<3)];
|
||||
} else
|
||||
else
|
||||
return (reg64_t*)&emu->regs[m&3].byte[m>>2];
|
||||
}
|
||||
|
||||
|
||||
@@ -81,11 +81,15 @@ reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t of
|
||||
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
|
||||
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
#define GetEw GetEd
|
||||
#define GetEw32O GetEd32O
|
||||
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);
|
||||
mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
|
||||
sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
|
||||
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
|
||||
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
#define GetGw GetGd
|
||||
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
|
||||
@@ -104,12 +108,17 @@ 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 Run67(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);
|
||||
int Run67660F(x64emu_t *emu, rex_t rex);
|
||||
int RunD8(x64emu_t *emu, rex_t rex);
|
||||
int RunD9(x64emu_t *emu, rex_t rex);
|
||||
int RunDA(x64emu_t *emu, rex_t rex);
|
||||
int RunDB(x64emu_t *emu, rex_t rex);
|
||||
int RunDC(x64emu_t *emu, rex_t rex);
|
||||
int RunDD(x64emu_t *emu, rex_t rex);
|
||||
int RunDE(x64emu_t *emu, rex_t rex);
|
||||
int RunDF(x64emu_t *emu, rex_t rex);
|
||||
int RunF0(x64emu_t *emu, rex_t rex);
|
||||
int RunF20F(x64emu_t *emu, rex_t rex);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#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 "modrm.h"
|
||||
|
||||
int RunDC(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7: /* FADD */
|
||||
ST(nextop&7).d += ST0.d;
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* FMUL */
|
||||
ST(nextop&7).d *= ST0.d;
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7: /* FCOM */
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF: /* FCOMP */
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7: /* FSUBR */
|
||||
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF: /* FSUB */
|
||||
ST(nextop&7).d -= ST0.d;
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7: /* FDIVR */
|
||||
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF: /* FDIV */
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
break;
|
||||
default:
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, double */
|
||||
ST0.d += *(double*)ED;
|
||||
break;
|
||||
case 1: /* FMUL ST0, double */
|
||||
ST0.d *= *(double*)ED;
|
||||
break;
|
||||
case 2: /* FCOM ST0, double */
|
||||
fpu_fcom(emu, *(double*)ED);
|
||||
break;
|
||||
case 3: /* FCOMP ST0, double */
|
||||
fpu_fcom(emu, *(double*)ED);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FSUB ST0, double */
|
||||
ST0.d -= *(double*)ED;
|
||||
break;
|
||||
case 5: /* FSUBR ST0, double */
|
||||
ST0.d = *(double*)ED - ST0.d;
|
||||
break;
|
||||
case 6: /* FDIV ST0, double */
|
||||
ST0.d /= *(double*)ED;
|
||||
break;
|
||||
case 7: /* FDIVR ST0, double */
|
||||
ST0.d = *(double*)ED / ST0.d;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
#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 "modrm.h"
|
||||
|
||||
int RunDE(x64emu_t *emu, rex_t rex)
|
||||
{
|
||||
uint8_t nextop;
|
||||
reg64_t *oped;
|
||||
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0: /* FADDP STx, ST0 */
|
||||
case 0xC1: /* FADDP ST1, ST0 */
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
ST(nextop&7).d += ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xC8: /* FMULP STx, ST0 */
|
||||
case 0xC9: /* FMULP ST1, ST0 */
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
ST(nextop&7).d *= ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7: /* FCOMP */
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xD9: /* FCOMPP */
|
||||
fpu_fcom(emu, ST1.d);
|
||||
fpu_do_pop(emu);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
/*ST(1).d = ST0.d - ST(1).d;
|
||||
fpu_do_pop(emu);
|
||||
break;*/
|
||||
case 0xE0: /* FSUBRP STx, ST0 */
|
||||
case 0xE1: /* FSUBRP ST1, ST0 */
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE8: /* FSUBP STx, ST0 */
|
||||
case 0xE9: /* FSUBP ST1, ST0 */
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
ST(nextop&7).d -= ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF0: /* FDIVRP STx, ST0 */
|
||||
case 0xF1: /* FDIVRP ST1, ST0 */
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF8: /* FDIVP STx, ST0 */
|
||||
case 0xF9: /* FDIVP ST1, ST0 */
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xD8:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d += EW->sword[0];
|
||||
break;
|
||||
case 1: /* FIMUL ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d *= EW->sword[0];
|
||||
break;
|
||||
case 4: /* FISUB ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d -= EW->sword[0];
|
||||
break;
|
||||
case 5: /* FISUBR ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d = (double)EW->sword[0] - ST0.d;
|
||||
break;
|
||||
case 6: /* FIDIV ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d /= EW->sword[0];
|
||||
break;
|
||||
case 7: /* FIDIVR ST0, Ew int */
|
||||
GETEW(0);
|
||||
ST0.d = (double)EW->sword[0] / ST0.d;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+356
-5
@@ -168,6 +168,113 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
opcode = F8;
|
||||
switch (opcode) {
|
||||
|
||||
case 0xAB: /* BTS Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
tmp8u&=63;
|
||||
if(MODREG) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
ED->q[0] |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
} else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
if(tmp64u & (1LL<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
} else {
|
||||
tmp64u |= (1LL<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = arm64_lock_write_d(ED, tmp64u);
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else {
|
||||
tmp8u&=31;
|
||||
if(MODREG) {
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else {
|
||||
ED->dword[0] |= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
ED->dword[1] = 0;
|
||||
} else
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
} else {
|
||||
tmp32u |= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xB0: /* CMPXCHG Eb,Gb */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETGB;
|
||||
GETEB(0);
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp8u = arm64_lock_read_b(EB);
|
||||
cmp8(emu, R_AL, tmp8u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm64_lock_write_b(EB, GB);
|
||||
} else {
|
||||
R_AL = tmp8u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp8(emu, R_AL, EB->byte[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EB->byte[0] = GB;
|
||||
} else {
|
||||
R_AL = EB->byte[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xB1: /* CMPXCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -216,6 +323,63 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xB3: /* BTR Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=rex.w?63:31;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
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 {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
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) {
|
||||
if(ED->q[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->q[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xC1: /* XADD Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -228,10 +392,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
} while(arm64_lock_write_dd(ED, tmp64u2));
|
||||
GD->q[0] = tmp64u;
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
|
||||
} while(arm64_lock_write_d(ED, tmp32u2));
|
||||
if(((uintptr_t)ED)&3) {
|
||||
do {
|
||||
tmp32u = ED->dword[0] & ~0xff;
|
||||
tmp32u |= arm64_lock_read_b(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
|
||||
} while(arm64_lock_write_b(ED, tmp32u2&0xff));
|
||||
ED->dword[0] = tmp32u2;
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
|
||||
} while(arm64_lock_write_d(ED, tmp32u2));
|
||||
}
|
||||
GD->q[0] = tmp32u;
|
||||
if(MODREG)
|
||||
ED->dword[1] = 0;
|
||||
@@ -254,6 +427,69 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xC7: /* CMPXCHG8B Gq */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
#ifdef DYNAREC
|
||||
if(rex.w)
|
||||
do {
|
||||
arm64_lock_read_dq(&tmp64u, &tmp64u2, ED);
|
||||
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
tmp32s = arm64_lock_write_dq(R_RBX, R_RCX, ED);
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_RAX = tmp64u;
|
||||
R_RDX = tmp64u2;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
else
|
||||
do {
|
||||
tmp64u = arm64_lock_read_dd(ED);
|
||||
if((R_EAX == (tmp64u&0xffffffff)) && (R_EDX == ((tmp64u>>32)&0xffffffff))) {
|
||||
SET_FLAG(F_ZF);
|
||||
tmp32s = arm64_lock_write_dd(ED, R_EBX|(((uint64_t)R_ECX)<<32));
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_RAX = tmp64u&0xffffffff;
|
||||
R_RDX = (tmp64u>>32)&0xffffffff;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
tmp64u = ED->q[0];
|
||||
tmp64u2= ED->q[1];
|
||||
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
ED->q[0] = R_RBX;
|
||||
ED->q[1] = R_RCX;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_RAX = tmp64u;
|
||||
R_RDX = tmp64u2;
|
||||
}
|
||||
} else {
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u2= ED->dword[1];
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
ED->dword[0] = R_EBX;
|
||||
ED->dword[1] = R_ECX;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -344,7 +580,122 @@ int RunF0(x64emu_t *emu, rex_t rex)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
if(rex.w) {
|
||||
tmp64u = GD->q[0];
|
||||
GD->q[0] = ED->q[0];
|
||||
ED->q[0] = tmp64u;
|
||||
} else {
|
||||
tmp32u = GD->dword[0];
|
||||
GD->q[0] = ED->dword[0];
|
||||
ED->q[0] = tmp32u;
|
||||
}
|
||||
} else {
|
||||
if(rex.w) {
|
||||
GD->q[0] = arm64_lock_xchg(ED, GD->q[0]);
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
} while(arm64_lock_write_d(ED, GD->dword[0]));
|
||||
GD->q[0] = tmp32u;
|
||||
}
|
||||
}
|
||||
#else
|
||||
GETED(0);
|
||||
GETGD;
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(rex.w) {
|
||||
tmp64u = GD->q[0];
|
||||
GD->q[0] = ED->q[0];
|
||||
ED->q[0] = tmp64u;
|
||||
} else {
|
||||
tmp32u = GD->dword[0];
|
||||
GD->q[0] = ED->dword[0];
|
||||
if(MODREG)
|
||||
ED->q[0] = tmp32u;
|
||||
else
|
||||
ED->dword[0] = tmp32u;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
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)));
|
||||
else {
|
||||
if((uintptr_t)ED&3) {
|
||||
//meh.
|
||||
do {
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u &=~0xff;
|
||||
tmp32u |= arm64_lock_read_b(ED);
|
||||
tmp32u = inc32(emu, tmp32u);
|
||||
} while(arm64_lock_write_b(ED, tmp32u&0xff));
|
||||
ED->dword[0] = tmp32u;
|
||||
} else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
} while(arm64_lock_write_d(ED, inc32(emu, tmp32u)));
|
||||
}
|
||||
if(MODREG) ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
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]);
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
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)));
|
||||
else {
|
||||
do {
|
||||
tmp32u = arm64_lock_read_d(ED);
|
||||
} while(arm64_lock_write_d(ED, dec32(emu, tmp32u)));
|
||||
if(MODREG) ED->dword[1] = 0;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
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]);
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
+14
-1
@@ -53,6 +53,12 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
GETGX;
|
||||
EX->q[0] = GX->q[0];
|
||||
break;
|
||||
case 0x12: /* MOVDDUP Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->q[1] = GX->q[0] = EX->q[0];
|
||||
break;
|
||||
|
||||
case 0x2A: /* CVTSI2SD Gx, Ed */
|
||||
nextop = F8;
|
||||
@@ -254,7 +260,14 @@ int RunF20F(x64emu_t *emu, rex_t rex)
|
||||
GX->q[1] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0xF0: /* LDDQU Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
memcpy(GX, EX, 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+44
-1
@@ -28,6 +28,8 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
uint8_t nextop;
|
||||
int8_t tmp8s;
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem;
|
||||
@@ -236,6 +238,42 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
memcpy(EX, GX, 16); // unaligned...
|
||||
break;
|
||||
|
||||
case 0xBC: /* TZCNT Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
tmp64u = ED->q[0];
|
||||
if(tmp64u) {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
tmp8u = 0;
|
||||
while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;
|
||||
GD->q[0] = tmp8u;
|
||||
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
SET_FLAG(F_CF);
|
||||
GD->q[0] = 64;
|
||||
}
|
||||
} else {
|
||||
tmp32u = ED->dword[0];
|
||||
if(tmp32u) {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
tmp8u = 0;
|
||||
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
|
||||
GD->dword[0] = tmp8u;
|
||||
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
|
||||
CLEAR_FLAG(F_CF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
SET_FLAG(F_CF);
|
||||
GD->dword[0] = 32;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC2: /* CMPSS Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GETEX(1);
|
||||
@@ -271,8 +309,13 @@ int RunF30F(x64emu_t *emu, rex_t rex)
|
||||
GX->d[0] = EX->sd[0];
|
||||
break;
|
||||
|
||||
case 0x1E: /* NOP (multi-byte), endbr64 */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+87
-12
@@ -34,18 +34,19 @@
|
||||
#include "x64tls.h"
|
||||
|
||||
typedef struct x64_sigaction_s x64_sigaction_t;
|
||||
typedef struct x64_stack_s x64_stack_t;
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
//int my_sigaction(x64emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
|
||||
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);
|
||||
//int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[]);
|
||||
//void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
|
||||
//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_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);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
@@ -62,13 +63,34 @@ typedef struct scwrap_s {
|
||||
} scwrap_t;
|
||||
|
||||
scwrap_t syscallwrap[] = {
|
||||
//{ 0, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//{ 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
|
||||
|
||||
//{ 0, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
|
||||
//{ 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
|
||||
//{ 9, __NR_mmap, 6}, // wrapped to track mmap
|
||||
//{ 10, __NR_mprotect, 3}, // same
|
||||
//{ 11, __NR_munmap, 2}, // same
|
||||
{ 5, __NR_fstat, 2},
|
||||
{ 186, __NR_gettid, 0 },
|
||||
//{ 13, __NR_rt_sigaction, 4} // wrapped to use my_ version
|
||||
#ifdef __NR_pipe
|
||||
{ 22, __NR_pipe, 1},
|
||||
#endif
|
||||
#ifdef __NR_fork
|
||||
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
|
||||
#endif
|
||||
//{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack
|
||||
{ 157, __NR_prctl, 5 }, // needs wrapping?
|
||||
{ 186, __NR_gettid, 0 }, //0xBA
|
||||
{ 202, __NR_futex, 6},
|
||||
{ 217, __NR_getdents64, 3},
|
||||
#ifdef __NR_inotify_init
|
||||
{ 253, __NR_inotify_init, 0}, //0xFD
|
||||
#endif
|
||||
{ 254, __NR_inotify_add_watch, 3},
|
||||
{ 255, __NR_inotify_rm_watch, 2},
|
||||
{ 294, __NR_inotify_init1, 1},
|
||||
{ 298, __NR_perf_event_open, 5},
|
||||
{ 318, __NR_getrandom, 3},
|
||||
};
|
||||
|
||||
struct mmap_arg_struct {
|
||||
@@ -152,6 +174,36 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
case 3: // sys_close
|
||||
R_EAX = (uint32_t)close((int)R_EDI);
|
||||
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);
|
||||
break;
|
||||
case 11: // sys_munmap
|
||||
R_EAX = (uint32_t)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*/);
|
||||
break;
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
R_EAX = (uint32_t)pipe((void*)R_RDI);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
R_RAX = fork();
|
||||
break;
|
||||
#endif
|
||||
case 131: // sys_sigaltstack
|
||||
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
break;
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
R_EAX = (int)syscall(__NR_inotify_init1, 0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
@@ -164,10 +216,11 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
#define stack(n) (R_RSP+8+n)
|
||||
#define i32(n) *(int32_t*)stack(n)
|
||||
#define u32(n) *(uint32_t*)stack(n)
|
||||
#define i64(n) *(int64_t*)stack(n)
|
||||
#define u64(n) *(uint64_t*)stack(n)
|
||||
#define p(n) *(void**)stack(n)
|
||||
|
||||
uint32_t EXPORT my_syscall(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);
|
||||
@@ -200,6 +253,28 @@ uint32_t EXPORT my_syscall(x64emu_t *emu)
|
||||
return my_open(emu, (char*)R_RSI, of_convert(R_EDX), R_ECX);
|
||||
case 3: // sys_close
|
||||
return (uint32_t)close(R_ESI);
|
||||
case 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);
|
||||
case 11: // sys_munmap
|
||||
return (uint32_t)my_munmap(emu, (void*)R_RSI, R_RDX);
|
||||
case 13: // sys_rt_sigaction
|
||||
return (uint32_t)my_sigaction(emu, (int)R_ESI, (const x64_sigaction_t *)R_RDX, (x64_sigaction_t *)R_RCX/*, (size_t)R_R8*/);
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
return (uint32_t)pipe((void*)R_RSI);
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
return fork();
|
||||
#endif
|
||||
case 131: // sys_sigaltstack
|
||||
return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
return (int)syscall(__NR_inotify_init1, 0);
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
|
||||
@@ -31,7 +31,6 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#define JMPTABL_SHIFT 16
|
||||
|
||||
typedef void* (*procaddess_t)(const char* name);
|
||||
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
|
||||
|
||||
#define MAX_SIGNAL 64
|
||||
|
||||
@@ -50,6 +49,8 @@ typedef struct needed_libs_s {
|
||||
|
||||
void add_neededlib(needed_libs_t* needed, library_t* lib);
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
void add_dependedlib(needed_libs_t* depended, library_t* lib);
|
||||
void free_dependedlib(needed_libs_t* depended);
|
||||
|
||||
typedef struct base_segment_s {
|
||||
uintptr_t base;
|
||||
@@ -70,7 +71,7 @@ typedef struct box64context_s {
|
||||
uint32_t sel_serial; // will be increment each time selectors changes
|
||||
|
||||
zydis_t *zydis; // dlopen the zydis dissasembler
|
||||
void* box64lib; // dlopen on box86 itself
|
||||
void* box64lib; // dlopen on box64 itself
|
||||
|
||||
int argc;
|
||||
char** argv;
|
||||
@@ -79,7 +80,7 @@ typedef struct box64context_s {
|
||||
char** envv;
|
||||
|
||||
char* fullpath;
|
||||
char* box64path; // path of current box86 executable
|
||||
char* box64path; // path of current box64 executable
|
||||
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
@@ -106,9 +107,6 @@ typedef struct box64context_s {
|
||||
procaddess_t glxprocaddress;
|
||||
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
|
||||
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
|
||||
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
|
||||
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
|
||||
vkprocaddess_t vkprocaddress;
|
||||
|
||||
pthread_mutex_t mutex_once;
|
||||
pthread_mutex_t mutex_once2;
|
||||
@@ -198,4 +196,9 @@ int AddTLSPartition(box64context_t* context, int tlssize);
|
||||
void thread_set_emu(x64emu_t* emu);
|
||||
x64emu_t* thread_get_emu();
|
||||
|
||||
#endif //__BOX64CONTEXT_H_
|
||||
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
|
||||
int unlockMutex();
|
||||
// relock the muxtex that were unlocked
|
||||
void relockMutex(int locks);
|
||||
|
||||
#endif //__BOX64CONTEXT_H_
|
||||
+12
-1
@@ -29,13 +29,18 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
dynablocklist_t* getDB(uintptr_t idx);
|
||||
void addJumpTableIfDefault64(void* addr, void* jmp);
|
||||
void setJumpTableDefault64(void* addr);
|
||||
int isJumpTableDefault64(void* addr);
|
||||
uintptr_t getJumpTable64();
|
||||
uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC 0x80
|
||||
#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);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
@@ -44,7 +49,13 @@ void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||
void lockDB();
|
||||
void unlockDB();
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
|
||||
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
|
||||
int unlockCustommemMutex();
|
||||
// relock the muxtex that were unlocked
|
||||
void relockCustommemMutex(int locks);
|
||||
|
||||
void init_custommem_helper(box64context_t* ctx);
|
||||
void fini_custommem_helper(box64context_t* ctx);
|
||||
|
||||
+8
-5
@@ -14,16 +14,19 @@ extern int box64_dynarec_forced;
|
||||
extern int box64_dynarec_largest;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
extern int trace_xmm; // include XMM reg in trace?
|
||||
extern int trace_emm; // include EMM reg in trace?
|
||||
extern int dlsym_error; // log dlsym error
|
||||
#ifdef HAVE_TRACE
|
||||
extern int trace_xmm; // include XMM reg in trace?
|
||||
extern int trace_emm; // include EMM reg in trace?
|
||||
extern int trace_regsdiff; // colorize standard registers on changes
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
#endif
|
||||
extern int allow_missing_libs;
|
||||
extern int box64_steam;
|
||||
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
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
|
||||
extern uint32_t default_gs;
|
||||
extern int jit_gdb; // launch gdb when a segfault is trapped
|
||||
|
||||
@@ -30,7 +30,7 @@ void CalcStack(elfheader_t* h, uint32_t* stacksz, int* 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, int local, box64context_t *box86, x64emu_t* emu);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, 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);
|
||||
@@ -45,7 +45,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
int32_t GetTLSBase(elfheader_t* h);
|
||||
uint32_t GetTLSSize(elfheader_t* h);
|
||||
void* GetTLSPointer(box64context_t* context, elfheader_t* h);
|
||||
void* GetDTatOffset(box64context_t* context, int index, int offset);
|
||||
void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset);
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr);
|
||||
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
|
||||
@@ -56,4 +56,4 @@ void CreateMemorymapFile(box64context_t* context, int fd);
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
|
||||
#endif //__ELF_LOADER_H_
|
||||
#endif //__ELF_LOADER_H_
|
||||
@@ -16,7 +16,7 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
|
||||
// 1: if file is an x86 elf, 0: if not (or not found)
|
||||
int FileIsX64ELF(const char* filename);
|
||||
|
||||
#if defined(RPI) || defined(RK3399)
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
void sanitize_mojosetup_gtk_background();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef struct kh_mapoffsets_s kh_mapoffsets_t;
|
||||
typedef char* cstr_t;
|
||||
|
||||
lib_t *NewLibrarian(box64context_t* context, int ownlibs);
|
||||
void FreeLibrarian(lib_t **maplib);
|
||||
void FreeLibrarian(lib_t **maplib, x64emu_t* emu);
|
||||
dlprivate_t *NewDLPrivate();
|
||||
void FreeDLPrivate(dlprivate_t **lib);
|
||||
|
||||
@@ -24,7 +24,7 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box86, x64emu_t* emu); // 0=success, 1=error
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name);
|
||||
library_t* GetLibInternal(const char* name);
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name);
|
||||
@@ -48,4 +48,4 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
|
||||
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
|
||||
const char* GetNameOffset(lib_t *maplib, void* offs);
|
||||
|
||||
#endif //__LIBRARIAN_H_
|
||||
#endif //__LIBRARIAN_H_
|
||||
@@ -9,12 +9,12 @@ typedef struct box64context_s box64context_t;
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
|
||||
library_t *NewLibrary(const char* path, box64context_t* box86);
|
||||
library_t *NewLibrary(const char* path, box64context_t* box64);
|
||||
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
|
||||
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
|
||||
int ReloadLibrary(library_t* lib, x64emu_t* emu);
|
||||
void InactiveLibrary(library_t* lib);
|
||||
void Free1Library(library_t **lib);
|
||||
void Free1Library(library_t **lib, x64emu_t* emu);
|
||||
|
||||
char* GetNameLib(library_t *lib);
|
||||
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
|
||||
@@ -33,4 +33,4 @@ lib_t* GetMaplib(library_t* lib);
|
||||
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. native)
|
||||
void* GetHandle(library_t* lib); // NULL if not native
|
||||
|
||||
#endif //__LIBRARY_H_
|
||||
#endif //__LIBRARY_H_
|
||||
@@ -89,6 +89,25 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
|
||||
void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
|
||||
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
|
||||
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
|
||||
|
||||
struct x64_stat64 { /* x86_64 arm64 */
|
||||
uint64_t st_dev; /* 0 */ /* 0 */
|
||||
uint64_t st_ino; /* 8 */ /* 8 */
|
||||
uint64_t st_nlink; /* 16 */ /* 20 */
|
||||
uint32_t st_mode; /* 24 */ /* 16 */
|
||||
uint32_t st_uid; /* 28 */ /* 24 */
|
||||
uint32_t st_gid; /* 32 */ /* 28 */
|
||||
int __pad0; /* 36 */ /* --- */
|
||||
uint64_t st_rdev; /* 40 */ /* 32 */
|
||||
int64_t st_size; /* 48 */ /* 48 */
|
||||
int64_t st_blksize; /* 56 */ /* 56 */
|
||||
uint64_t st_blocks; /* 64 */ /* 64 */
|
||||
struct timespec st_atim; /* 72 */ /* 72 */
|
||||
struct timespec st_mtim; /* 88 */ /* 88 */
|
||||
struct timespec st_ctim; /* 104 */ /* 104 */
|
||||
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
|
||||
} __attribute__((packed)); /* 144 */ /* 128 */
|
||||
|
||||
void UnalignStat64(const void* source, void* dest);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PATHCOLL_H_
|
||||
#define __PATHCOLL_H_
|
||||
|
||||
// utility to handle path collection (like BOX86_PATH or BOX86_LD_LIBRARY_PATH)
|
||||
// utility to handle path collection (like BOX64_PATH or BOX64_LD_LIBRARY_PATH)
|
||||
|
||||
// paths can be resized with realloc, so don't take address as invariant
|
||||
typedef struct path_collection_s
|
||||
|
||||
@@ -285,6 +285,9 @@ typedef union {
|
||||
#define R_ESI emu->regs[_SI].dword[0]
|
||||
#define R_ESP emu->regs[_SP].dword[0]
|
||||
#define R_EBP emu->regs[_BP].dword[0]
|
||||
#define R_R8d emu->regs[_R8].dword[0]
|
||||
#define R_R9d emu->regs[_R9].dword[0]
|
||||
#define R_R10d emu->regs[_R10].dword[0]
|
||||
#define R_AX emu->regs[_AX].word[0]
|
||||
#define R_BX emu->regs[_BX].word[0]
|
||||
#define R_CX emu->regs[_CX].word[0]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __SDL2RWOPS_H__
|
||||
#define __SDL2RWOPS_H__
|
||||
|
||||
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL1 SDL_RWops
|
||||
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL2 SDL_RWops
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
|
||||
typedef SDL2_RWops_t* (*sdl2_allocrw)();
|
||||
@@ -20,12 +20,12 @@ typedef struct SDL2RWSave_s {
|
||||
|
||||
// each function will be added to dictionary, and each native functions will be wrapped so they run in emulated world
|
||||
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops);
|
||||
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put Native RW function, wrapping emulated (callback style) ones if needed
|
||||
void RWNativeEnd2(SDL2_RWops_t* ops); // put back emulated function back in place
|
||||
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put native RW functions, wrapping the emulated (callback style) ones if needed
|
||||
void RWNativeEnd2(SDL2_RWops_t* ops); // put emulated function back in place
|
||||
|
||||
int64_t RWNativeSeek2(SDL2_RWops_t *ops, int64_t offset, int32_t whence);
|
||||
uint32_t RWNativeRead2(SDL2_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum);
|
||||
int32_t RWNativeWrite2(SDL2_RWops_t *ops, const void *ptr, int32_t size, int32_t num);
|
||||
int32_t RWNativeClose2(SDL2_RWops_t* ops);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -20,4 +20,7 @@ void fini_pthread_helper(box64context_t* context);
|
||||
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
|
||||
void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet);
|
||||
|
||||
//check if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
|
||||
int checkMutex(void* m);
|
||||
|
||||
#endif //_THREADS_H_
|
||||
@@ -37,6 +37,7 @@ void SetRIP(x64emu_t *emu, uint64_t v);
|
||||
void SetFS(x64emu_t *emu, uint16_t v);
|
||||
uint16_t GetFS(x64emu_t *emu);
|
||||
uint64_t GetRSP(x64emu_t *emu);
|
||||
uint64_t GetRBP(x64emu_t *emu);
|
||||
void ResetFlags(x64emu_t *emu);
|
||||
void ResetSegmentsCache(x64emu_t *emu);
|
||||
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip);
|
||||
|
||||
+88
-42
@@ -34,17 +34,58 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
|
||||
|
||||
return maplib;
|
||||
}
|
||||
void FreeLibrarian(lib_t **maplib)
|
||||
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed) {
|
||||
if (freed[idx]) return; // Already freed
|
||||
|
||||
freed[idx] = 1; // Avoid infinite loops
|
||||
library_t *lib = maplib->libraries[idx];
|
||||
printf_log(LOG_DEBUG, "Free %s\n", lib->name);
|
||||
for (int i = lib->depended.size - 1; i >= 0; --i) {
|
||||
int j;
|
||||
for (j = 0; j < maplib->libsz; ++j) {
|
||||
if (lib->depended.libs[i] == maplib->libraries[j]) break;
|
||||
}
|
||||
if (j == maplib->libsz) {
|
||||
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
|
||||
continue;
|
||||
}
|
||||
if (freed[j] == 1) {
|
||||
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->depended.libs[i]->name);
|
||||
continue;
|
||||
}
|
||||
freeLibraryRecurse(maplib, emu, j, freed);
|
||||
if (freed[idx] != 1) {
|
||||
printf_log(LOG_DEBUG, "Library cleared (cyclic dependancy break)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
library_t *oldptr = maplib->libraries[idx];
|
||||
Free1Library(&maplib->libraries[idx], emu);
|
||||
maplib->libraries[idx] = oldptr; // Temporarily save the old address
|
||||
freed[idx] = 2;
|
||||
}
|
||||
void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
|
||||
{
|
||||
// should that be in reverse order?
|
||||
if(!maplib || !*maplib)
|
||||
return;
|
||||
|
||||
if((*maplib)->ownlibs) {
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
|
||||
for (int i=0; i<(*maplib)->libsz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
|
||||
Free1Library(&(*maplib)->libraries[i].lib);
|
||||
char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
|
||||
if (!freed) {
|
||||
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
} else {
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
freeLibraryRecurse(*maplib, emu, i, freed);
|
||||
}
|
||||
for (int i=0; i<(*maplib)->libsz; ++i) {
|
||||
(*maplib)->libraries[i] = NULL;
|
||||
}
|
||||
free(freed);
|
||||
}
|
||||
}
|
||||
free((*maplib)->libraries);
|
||||
@@ -103,9 +144,9 @@ kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
|
||||
library_t* getLib(lib_t* maplib, const char* path)
|
||||
{
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
onelib_t *onelib = &maplib->libraries[i];
|
||||
if(IsSameLib(onelib->lib, path)) {
|
||||
return onelib->lib;
|
||||
library_t *lib = maplib->libraries[i];
|
||||
if(IsSameLib(lib, path)) {
|
||||
return lib;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -116,7 +157,7 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib)
|
||||
if(!maplib)
|
||||
return 0;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(maplib->libraries[i].lib==lib)
|
||||
if(maplib->libraries[i]==lib)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -125,10 +166,9 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
|
||||
{
|
||||
if (maplib->libsz == maplib->libcap) {
|
||||
maplib->libcap += 8;
|
||||
maplib->libraries = (onelib_t*)realloc(maplib->libraries, maplib->libcap*sizeof(onelib_t));
|
||||
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
|
||||
}
|
||||
maplib->libraries[maplib->libsz].lib = lib;
|
||||
maplib->libraries[maplib->libsz].name = GetNameLib(lib);
|
||||
maplib->libraries[maplib->libsz] = lib;
|
||||
++maplib->libsz;
|
||||
}
|
||||
|
||||
@@ -137,7 +177,7 @@ void MapLibAddMapLib(lib_t* dest, lib_t* src)
|
||||
if(!src)
|
||||
return;
|
||||
for(int i=0; i<src->libsz; ++i) {
|
||||
library_t* lib = src->libraries[i].lib;
|
||||
library_t* lib = src->libraries[i];
|
||||
if(!lib) continue;
|
||||
if(lib->maplib && src!=lib->maplib) { //TODO: find why is src!=lib->maplib needed
|
||||
MapLibAddMapLib(dest, lib->maplib);
|
||||
@@ -154,24 +194,23 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib)
|
||||
if(!maplib || !lib)
|
||||
return;
|
||||
int idx = 0;
|
||||
while(idx<maplib->libsz && maplib->libraries[idx].lib!=lib) ++idx;
|
||||
while(idx<maplib->libsz && maplib->libraries[idx]!=lib) ++idx;
|
||||
if(idx==maplib->libsz) //not found
|
||||
return;
|
||||
--maplib->libsz;
|
||||
if(idx!=(maplib->libsz))
|
||||
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(onelib_t)*(maplib->libsz-idx));
|
||||
maplib->libraries[maplib->libsz].lib = NULL;
|
||||
maplib->libraries[maplib->libsz].name = NULL;
|
||||
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx));
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box64, x64emu_t* emu)
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
|
||||
// first check if lib is already loaded
|
||||
library_t *lib = getLib(my_context->maplib, path);
|
||||
if(lib) {
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
|
||||
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -201,6 +240,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
|
||||
MapLibRemoveLib(my_context->local_maplib, lib);
|
||||
}
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
|
||||
return 0;
|
||||
}
|
||||
// load a new one
|
||||
@@ -211,6 +251,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
|
||||
}
|
||||
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
|
||||
|
||||
// add lib now
|
||||
if(local) {
|
||||
@@ -237,17 +278,17 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// lets load dependancies before adding symbols and launch init sequence
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, 0, box64, emu)) {
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// some special case, where dependancies may not be correct
|
||||
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
|
||||
AddNeededLib(maplib, &lib->needed, 0, "libGL.so.1", box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libGL.so.1", box64, emu);
|
||||
}
|
||||
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
|
||||
AddNeededLib(maplib, &lib->needed, 0, "libSDL-1.2.so.0", box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, 0, "libdl.so.2", box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libSDL-1.2.so.0", box64, emu);
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, "libdl.so.2", box64, emu);
|
||||
}
|
||||
// add symbols
|
||||
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
|
||||
@@ -302,8 +343,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i].lib)==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]!=self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
@@ -318,8 +359,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
@@ -341,14 +382,14 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
|
||||
return 1;
|
||||
// search in global symbols
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// library from newer to older, weak only now
|
||||
for(int i=maplib->libsz-1; i>=0; --i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) // only weak symbol haven't been found yet
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) // only weak symbol haven't been found yet
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
@@ -402,10 +443,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
|
||||
return maplib->context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i].lib);
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
return NULL;
|
||||
}
|
||||
return maplib->context->elfs[idx];
|
||||
@@ -421,7 +462,7 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
@@ -433,8 +474,8 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
|
||||
uintptr_t start=0;
|
||||
uintptr_t end=0;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i].lib)==-1)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
|
||||
if(GetElfIndex(maplib->libraries[i])==-1)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end))
|
||||
if(start || end)
|
||||
return 1;
|
||||
// nope, not found
|
||||
@@ -452,8 +493,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
|
||||
return 0;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(self)
|
||||
@@ -471,8 +512,8 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin
|
||||
return 1;
|
||||
} else {
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
}
|
||||
@@ -488,8 +529,8 @@ int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
return 1;
|
||||
} else {
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
}
|
||||
@@ -567,7 +608,12 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
|
||||
*base = GetBaseAddress(h);
|
||||
return ret;
|
||||
}
|
||||
// TODO: then search in the other libs...
|
||||
// TODO: find if cyclic references exists (should also fix MapLibAddMapLib)
|
||||
/* for (int i = 0; i < maplib->libsz; ++i) {
|
||||
// if (maplib == maplib->libraries[i]->maplib) continue;
|
||||
const char *nameInLib = FindSymbolName(maplib->libraries[i]->maplib, p, start, sz, libname, base);
|
||||
if (nameInLib) return nameInLib;
|
||||
} */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,6 @@ typedef struct onesymbol_s {
|
||||
// need to track origin?
|
||||
} onesymbol_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
library_t *lib;
|
||||
} onelib_t;
|
||||
|
||||
typedef char* cstr_t;
|
||||
|
||||
KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t)
|
||||
@@ -31,7 +26,7 @@ typedef struct lib_s {
|
||||
khash_t(mapsymbols) *localsymbols;
|
||||
khash_t(mapoffsets) *mapoffsets;
|
||||
khash_t(mapsymbols) *globaldata;
|
||||
onelib_t *libraries;
|
||||
library_t **libraries;
|
||||
int libsz;
|
||||
int libcap;
|
||||
int ownlibs;
|
||||
|
||||
+17
-9
@@ -151,7 +151,7 @@ static void initNativeLib(library_t *lib, box64context_t* context) {
|
||||
lib->type = 0;
|
||||
// Call librarian to load all dependant elf
|
||||
for(int i=0; i<lib->priv.w.needed; ++i) {
|
||||
if(AddNeededLib(context->maplib, &lib->needed, 0, lib->priv.w.neededlibs[i], context, NULL)) { // probably all native, not emulated, so that's fine
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, lib->priv.w.neededlibs[i], context, thread_get_emu())) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[i]);
|
||||
return;
|
||||
}
|
||||
@@ -246,13 +246,13 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
if(box64_nopulse) {
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
Free1Library(&lib);
|
||||
Free1Library(&lib, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(box64_novulkan) {
|
||||
if(strstr(lib->name, "libvulkan.so")==lib->name) {
|
||||
Free1Library(&lib);
|
||||
Free1Library(&lib, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +270,7 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
// nothing loaded, so error...
|
||||
if(lib->type==-1)
|
||||
{
|
||||
Free1Library(&lib);
|
||||
Free1Library(&lib, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -303,6 +303,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
return 1;
|
||||
}
|
||||
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_func) {
|
||||
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end)) {
|
||||
SetTraceEmu(trace_start, trace_end);
|
||||
@@ -316,6 +317,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
|
||||
trace_func = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RunElfInit(elf_header, emu);
|
||||
}
|
||||
if(box64_dynarec && strcmp(lib->name, "libfmod.so")==0) {
|
||||
@@ -375,10 +377,18 @@ void InactiveLibrary(library_t* lib)
|
||||
lib->active = 0;
|
||||
}
|
||||
|
||||
void Free1Library(library_t **lib)
|
||||
void Free1Library(library_t **lib, x64emu_t* emu)
|
||||
{
|
||||
if(!(*lib)) return;
|
||||
|
||||
if((*lib)->type==1 && emu) {
|
||||
elfheader_t *elf_header = (*lib)->context->elfs[(*lib)->priv.n.elf_index];
|
||||
RunElfFini(elf_header, emu);
|
||||
}
|
||||
|
||||
if((*lib)->maplib)
|
||||
FreeLibrarian(&(*lib)->maplib, emu);
|
||||
|
||||
if((*lib)->type!=-1 && (*lib)->fini) {
|
||||
(*lib)->fini(*lib);
|
||||
}
|
||||
@@ -410,9 +420,7 @@ void Free1Library(library_t **lib)
|
||||
if((*lib)->symbol2map)
|
||||
kh_destroy(symbol2map, (*lib)->symbol2map);
|
||||
free_neededlib(&(*lib)->needed);
|
||||
|
||||
if((*lib)->maplib)
|
||||
FreeLibrarian(&(*lib)->maplib);
|
||||
free_neededlib(&(*lib)->depended);
|
||||
|
||||
free(*lib);
|
||||
*lib = NULL;
|
||||
@@ -697,4 +705,4 @@ lib_t* GetMaplib(library_t* lib)
|
||||
if(!lib)
|
||||
return NULL;
|
||||
return lib->maplib;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ typedef struct wlib_s {
|
||||
void* lib; // dlopen result
|
||||
void* priv; // actual private
|
||||
void* p2; // second private
|
||||
void* box64lib; // ref to the dlopen on box86 itself from context
|
||||
void* box64lib; // ref to the dlopen on box64 itself from context
|
||||
char* altprefix; // if function names are mangled..
|
||||
int needed;
|
||||
char** neededlibs;
|
||||
@@ -73,8 +73,9 @@ typedef struct library_s {
|
||||
kh_datamap_t *datamap;
|
||||
kh_datamap_t *wdatamap;
|
||||
kh_datamap_t *mydatamap;
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
needed_libs_t needed;
|
||||
needed_libs_t depended; // used to free library
|
||||
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
|
||||
} library_t;
|
||||
|
||||
@@ -98,4 +99,4 @@ typedef struct map_onedata_s {
|
||||
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size); // Add bridges to functions
|
||||
|
||||
#endif //__LIBRARY_PRIVATE_H_
|
||||
#endif //__LIBRARY_PRIVATE_H_
|
||||
+38
-36
@@ -18,6 +18,7 @@ GO("libSDL2.so", sdl2)
|
||||
GO("libsdl2-2.0.so.0", sdl2)
|
||||
GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
|
||||
GO("libSDL2_image-2.0.so.0", sdl2image)
|
||||
GO("libSDL2_net-2.0.so.0", sdl2net)
|
||||
GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
|
||||
GO("libSDL-1.2.so.0", sdl1)
|
||||
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
|
||||
@@ -25,24 +26,24 @@ GO("libSDL_image-1.2.so.0", sdl1image)
|
||||
GO("libSDL_ttf-2.0.so.0", sdl1ttf)
|
||||
GO("libsmpeg-0.4.so.0", smpeg)
|
||||
GO("libsmpeg2-2.0.so.0", smpeg2)
|
||||
//GO("libvorbisfile.so.3", vorbisfile)
|
||||
//GO("libvorbis.so.0", libvorbis)
|
||||
//GO("libogg.so.0", libogg)
|
||||
GO("libvorbisfile.so.3", vorbisfile)
|
||||
GO("libvorbis.so.0", libvorbis)
|
||||
GO("libogg.so.0", libogg)
|
||||
//GO("libpng12.so.0", png12)
|
||||
//GO("libpng16.so.16", png16)
|
||||
GO("libXxf86vm.so.1", libxxf86vm)
|
||||
GO("libXinerama.so.1", xinerama)
|
||||
GO("libXrandr.so.2", libxrandr)
|
||||
GO("libXext.so.6", libxext)
|
||||
//GO("libXfixes.so.3", libxfixes)
|
||||
//GO("libXcursor.so.1", libxcursor)
|
||||
GO("libXfixes.so.3", libxfixes)
|
||||
GO("libXcursor.so.1", libxcursor)
|
||||
GO("libXrender.so.1", libxrender)
|
||||
GO("libXi.so.6", libxi)
|
||||
//GO("libXss.so.1", libxss)
|
||||
//GO("libXpm.so.4", libxpm)
|
||||
GO("libXss.so.1", libxss)
|
||||
GO("libXpm.so.4", libxpm)
|
||||
GO("libXau.so.6", libxau)
|
||||
GO("libXdmcp.so.6", libxdmcp)
|
||||
//GO("libX11-xcb.so.1", libx11xcb)
|
||||
GO("libX11-xcb.so.1", libx11xcb)
|
||||
GO("libxcb.so.1", libxcb)
|
||||
//GO("libxcb-xfixes.so.0", libxcbxfixes)
|
||||
//GO("libxcb-shape.so.0", libxcbshape)
|
||||
@@ -54,11 +55,11 @@ GO("libxcb.so.1", libxcb)
|
||||
//GO("libxcb-dri2.so.0", libxcbdri2)
|
||||
//GO("libxcb-dri3.so.0", libxcbdri3)
|
||||
//GO("libxcb-present.so.0", libxcbpresent)
|
||||
//GO("libXtst.so.6", libxtst)
|
||||
//GO("libXt.so.6", libxt)
|
||||
//GO("libXcomposite.so.1", libxcomposite)
|
||||
//GO("libXdamage.so.1", libxdamage)
|
||||
//GO("libXmu.so.6", libxmu)
|
||||
GO("libXtst.so.6", libxtst)
|
||||
GO("libXt.so.6", libxt)
|
||||
GO("libXcomposite.so.1", libxcomposite)
|
||||
GO("libXdamage.so.1", libxdamage)
|
||||
GO("libXmu.so.6", libxmu)
|
||||
GO("libz.so.1", libz)
|
||||
GO("libopenal.so.1", openal)
|
||||
GO("libopenal.so.0", openal)
|
||||
@@ -69,19 +70,19 @@ GO("libalure.so.1", alure)
|
||||
//GO("libjpeg.so.8", libjpeg)
|
||||
//GO("libjpeg.so.62", libjpeg62)
|
||||
//GO("libturbojpeg.so.0", turbojpeg)
|
||||
//GO("libcurl.so.4", curl)
|
||||
//GO("libcurl-gnutls.so.4", curl)
|
||||
//GO("libudev.so.0", udev0)
|
||||
//GO("libudev.so.1", udev1)
|
||||
//GO("libdbus-1.so.3", dbus)
|
||||
GO("libcurl.so.4", curl)
|
||||
GO("libcurl-gnutls.so.4", curl)
|
||||
GO("libudev.so.0", udev0)
|
||||
GO("libudev.so.1", udev1)
|
||||
GO("libdbus-1.so.3", dbus)
|
||||
//GO("libiconv.so.2", iconv)
|
||||
//GO("libdrm.so.2", libdrm)
|
||||
//GO("libcrypto.so.1", crypto)
|
||||
//GO("libssl.so.1", libssl)
|
||||
GO("libcrypto.so.1", crypto)
|
||||
GO("libssl.so.1", libssl)
|
||||
//GO("libcrypt.so.1", libcrypt)
|
||||
//GO("libutil.so.1", util)
|
||||
//GO("libuuid.so.1", libuuid)
|
||||
//GO("libresolv.so.2", libresolv)
|
||||
GO("libutil.so.1", util)
|
||||
GO("libuuid.so.1", libuuid)
|
||||
GO("libresolv.so.2", libresolv)
|
||||
GO("libpulse-simple.so.0", pulsesimple)
|
||||
GO("libpulse.so.0", pulse)
|
||||
//GO("libsndfile.so.1", libsndfile)
|
||||
@@ -103,19 +104,20 @@ GO("libpulse.so.0", pulse)
|
||||
//GO("libgudev-1.0.so.0", gudev1)
|
||||
//GO("libappindicator.so.1", appindicator)
|
||||
//GO("libatk-1.0.so.0", atk)
|
||||
//GO("libpangoft2-1.0.so", pangoft2)
|
||||
//GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
//GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
//GO("libcairo.so.2", cairo)
|
||||
//GO("libpango-1.0.so.0", pango)
|
||||
GO("libpangoft2-1.0.so", pangoft2)
|
||||
GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
GO("libcairo.so.2", cairo)
|
||||
GO("libpango-1.0.so.0", pango)
|
||||
//GO("libnm.so.0", libnm)
|
||||
//GO("libnm-glib.so.4", libnm)
|
||||
//GO("libnm-util.so.2", libnm)
|
||||
//GO("libfontconfig.so.1", fontconfig)
|
||||
//GO("libfreetype.so.6", freetype)
|
||||
//GO("libbz2.so.1", bz2)
|
||||
//GO("libSM.so.6", libsm)
|
||||
//GO("libICE.so.6", libice)
|
||||
GO("libfontconfig.so.1", fontconfig)
|
||||
GO("libfreetype.so.6", freetype)
|
||||
GO("libbz2.so.1", bz2)
|
||||
GO("liblzma.so.5", lzma)
|
||||
GO("libSM.so.6", libsm)
|
||||
GO("libICE.so.6", libice)
|
||||
//GO("libusb-1.0.so.0", libusb1)
|
||||
//GO("libncursesw.so.5", libncursesw)
|
||||
//GO("libformw.so.5", libformw)
|
||||
@@ -125,8 +127,8 @@ GO("libpulse.so.0", pulse)
|
||||
//GO("libtinfo.so.6", libtinfo6)
|
||||
//GO("libtcmalloc_minimal.so.4", tcmallocminimal)
|
||||
//GO("libmpg123.so.0", mpg123)
|
||||
//GO("libgnutls.so.30", gnutls)
|
||||
//GO("libcups.so.2", libcups)
|
||||
GO("libgnutls.so.30", gnutls)
|
||||
GO("libcups.so.2", libcups)
|
||||
//GO("d3dadapter9.so.1", d3dadapter9)
|
||||
//GO("libvulkan.so.1", vulkan)
|
||||
//GO("libvulkan.so", vulkan)
|
||||
@@ -143,4 +145,4 @@ GO("libpulse.so.0", pulse)
|
||||
|
||||
GO("ld-linux-x86-64.so.2", ldlinux)
|
||||
|
||||
//GO("crashhandler.so", crashhandler)
|
||||
GO("crashhandler.so", crashhandler)
|
||||
+224
-131
@@ -100,7 +100,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
++p;
|
||||
break;
|
||||
case 14: //%LG long double
|
||||
if((((uintptr_t)(st+1))&0xf)!=0)
|
||||
if((((uintptr_t)st)&0xf)!=0)
|
||||
st++;
|
||||
#ifdef HAVE_LD80BITS
|
||||
if((((uintptr_t)mystack)&0xf)!=0)
|
||||
@@ -136,7 +136,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
// whattt?
|
||||
// whaaaat?
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
@@ -230,11 +230,232 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
// whattt?
|
||||
// whaaaat?
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos)
|
||||
{
|
||||
// loop...
|
||||
const wchar_t* p = (const wchar_t*)fmt;
|
||||
int state = 0;
|
||||
#ifndef HAVE_LD80BITS
|
||||
double d;
|
||||
long double ld;
|
||||
#endif
|
||||
int x = 0;
|
||||
while(*p)
|
||||
{
|
||||
switch(state) {
|
||||
case 0:
|
||||
switch(*p) {
|
||||
case '%': state = 1; ++p; break;
|
||||
default:
|
||||
++p;
|
||||
}
|
||||
break;
|
||||
case 1: // normal
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'F':
|
||||
case 'f': state += 10; break; // float
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': state += 20; break; // int
|
||||
case 'h': ++p; break; // ignored...
|
||||
case '\'':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case '+':
|
||||
case '-': ++p; break; // formating, ignored
|
||||
case 'm': state = 0; ++p; break; // no argument
|
||||
case 'n':
|
||||
case 'p':
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
}
|
||||
break;
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
if(xmm) {
|
||||
*mystack = emu->xmm[x++].q[0];
|
||||
--xmm;
|
||||
mystack++;
|
||||
} else {
|
||||
*mystack = *st;
|
||||
st++; mystack++;
|
||||
}
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
case 14: //%LG long double
|
||||
if((((uintptr_t)st)&0xf)!=0)
|
||||
st++;
|
||||
#ifdef HAVE_LD80BITS
|
||||
if((((uintptr_t)mystack)&0xf)!=0)
|
||||
mystack++;
|
||||
memcpy(mystack, st, 16);
|
||||
st+=2; mystack+=2;
|
||||
#else
|
||||
// there is 128bits long double on ARM64, but they need 128bit alignment
|
||||
if((((uintptr_t)mystack)&0xf)!=0)
|
||||
mystack++;
|
||||
LD2D((void*)st, &d);
|
||||
ld = d ;
|
||||
memcpy(mystack, &ld, 16);
|
||||
st+=2; mystack+=2;
|
||||
#endif
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
case 20: // fallback
|
||||
case 21:
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
// whaaaattt?
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos)
|
||||
{
|
||||
|
||||
if(!fmt)
|
||||
return;
|
||||
// loop...
|
||||
const wchar_t* p = (const wchar_t*)fmt;
|
||||
int state = 0;
|
||||
while(*p)
|
||||
{
|
||||
switch(state) {
|
||||
case 0:
|
||||
switch(*p) {
|
||||
case '%': state = 1; ++p; break;
|
||||
default:
|
||||
++p;
|
||||
}
|
||||
break;
|
||||
case 1: // normal
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'F':
|
||||
case 'f': state += 10; break; // float
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': state += 20; break; // int
|
||||
case 'h': ++p; break; // ignored...
|
||||
case '\'':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case '+':
|
||||
case '-': ++p; break; // formating, ignored
|
||||
case 'm': state = 0; ++p; break; // no argument
|
||||
case 'n':
|
||||
case 'p':
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
}
|
||||
break;
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 14: //%LG long double
|
||||
case 20: // fallback
|
||||
case 21:
|
||||
case 22:
|
||||
case 23: // 64bits int
|
||||
case 24: // normal int / pointer
|
||||
case 30:
|
||||
if(pos<6)
|
||||
*mystack = emu->regs[regs_abi[pos++]].q[0];
|
||||
else {
|
||||
*mystack = *st;
|
||||
++st;
|
||||
}
|
||||
++mystack;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
// whaaaat?
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
|
||||
{
|
||||
@@ -418,140 +639,12 @@ void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
|
||||
} while (*p && (inblocks || state));
|
||||
}
|
||||
|
||||
void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
|
||||
{
|
||||
// loop...
|
||||
const wchar_t* p = (const wchar_t*)fmt;
|
||||
int state = 0;
|
||||
double d;
|
||||
while(*p)
|
||||
{
|
||||
switch(state) {
|
||||
case 0:
|
||||
switch(*p) {
|
||||
case '%': state = 1; ++p; break;
|
||||
default:
|
||||
++p;
|
||||
}
|
||||
break;
|
||||
case 1: // normal
|
||||
case 2: // l
|
||||
case 3: // ll
|
||||
case 4: // L
|
||||
switch(*p) {
|
||||
case '%': state = 0; ++p; break; //%% = back to 0
|
||||
case 'l': ++state; if (state>3) state=3; ++p; break;
|
||||
case 'L': state = 4; ++p; break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'F':
|
||||
case 'f': state += 10; break; // float
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': state += 20; break; // int
|
||||
case 'h': ++p; break; // ignored...
|
||||
case '\'':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case '+':
|
||||
case '-': ++p; break; // formating, ignored
|
||||
case 'm': state = 0; ++p; break; // no argument
|
||||
case 'n':
|
||||
case 'p':
|
||||
case 'S':
|
||||
case 's': state = 30; break; // pointers
|
||||
case '$': ++p; break; // should issue a warning, it's not handled...
|
||||
case '*': *(mystack++) = *(st++); ++p; break; //fetch an int in the stack
|
||||
case ' ': state=0; ++p; break;
|
||||
default:
|
||||
state=20; // other stuff, put an int...
|
||||
}
|
||||
break;
|
||||
case 11: //double
|
||||
case 12: //%lg, still double
|
||||
case 13: //%llg, still double
|
||||
case 23: // 64bits int
|
||||
if((((uint32_t)mystack)&0x7)!=0)
|
||||
mystack++;
|
||||
*(uint64_t*)mystack = *(uint64_t*)st;
|
||||
st+=2; mystack+=2;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
case 14: //%LG long double
|
||||
#ifdef HAVE_LD80BITS
|
||||
if((((uint32_t)mystack)&0x7)!=0)
|
||||
mystack++;
|
||||
memcpy(mystack, st, 10);
|
||||
st+=3; mystack+=3;
|
||||
#else
|
||||
// there is no long double on ARM, so tranform that in a regular double
|
||||
LD2D((void*)st, &d);
|
||||
if((((uint32_t)mystack)&0x7)!=0)
|
||||
mystack++;
|
||||
*(uint64_t*)mystack = *(uint64_t*)&d;
|
||||
st+=3; mystack+=2;
|
||||
#endif
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
case 20: // fallback
|
||||
case 21:
|
||||
case 22:
|
||||
case 24: // normal int / pointer
|
||||
case 30:
|
||||
*mystack = *st;
|
||||
++mystack;
|
||||
++st;
|
||||
state = 0;
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
// whattt?
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef st_atime
|
||||
#undef st_mtime
|
||||
#undef st_ctime
|
||||
|
||||
struct x64_stat64 { /* x86_64 arm64 */
|
||||
uint64_t st_dev; /* 0 */ /* 0 */
|
||||
uint64_t st_ino; /* 8 */ /* 8 */
|
||||
uint64_t st_nlink; /* 16 */ /* 20 */
|
||||
uint32_t st_mode; /* 24 */ /* 16 */
|
||||
uint32_t st_uid; /* 28 */ /* 24 */
|
||||
uint32_t st_gid; /* 32 */ /* 28 */
|
||||
int __pad0; /* 36 */ /* --- */
|
||||
uint64_t st_rdev; /* 40 */ /* 32 */
|
||||
int64_t st_size; /* 48 */ /* 48 */
|
||||
int64_t st_blksize; /* 56 */ /* 56 */
|
||||
uint64_t st_blocks; /* 64 */ /* 64 */
|
||||
struct timespec st_atim; /* 72 */ /* 72 */
|
||||
struct timespec st_mtim; /* 88 */ /* 88 */
|
||||
struct timespec st_ctim; /* 104 */ /* 104 */
|
||||
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
|
||||
} __attribute__((packed)); /* 144 */ /* 128 */
|
||||
|
||||
void UnalignStat64(const void* source, void* dest)
|
||||
{
|
||||
struct x64_stat64 *x64st = (struct x64_stat64*)dest;
|
||||
|
||||
+128
-67
@@ -119,7 +119,7 @@ struct x64_fpstate
|
||||
|
||||
typedef struct x64_fpstate *x64_fpregset_t;
|
||||
|
||||
typedef struct
|
||||
typedef struct x64_stack_s
|
||||
{
|
||||
void *ss_sp;
|
||||
int ss_flags;
|
||||
@@ -257,12 +257,6 @@ static void sigstack_destroy(void* p)
|
||||
free(ss);
|
||||
}
|
||||
|
||||
static void free_signal_emu(void* p)
|
||||
{
|
||||
if(p)
|
||||
FreeX64Emu((x64emu_t**)&p);
|
||||
}
|
||||
|
||||
static pthread_key_t sigstack_key;
|
||||
static pthread_once_t sigstack_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
@@ -270,38 +264,22 @@ static void sigstack_key_alloc() {
|
||||
pthread_key_create(&sigstack_key, sigstack_destroy);
|
||||
}
|
||||
|
||||
static pthread_key_t sigemu_key;
|
||||
static pthread_once_t sigemu_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void sigemu_key_alloc() {
|
||||
pthread_key_create(&sigemu_key, free_signal_emu);
|
||||
}
|
||||
|
||||
static x64emu_t* get_signal_emu()
|
||||
{
|
||||
x64emu_t *emu = (x64emu_t*)pthread_getspecific(sigemu_key);
|
||||
if(!emu) {
|
||||
const int stsize = 8*1024; // small stack for signal handler
|
||||
void* stack = calloc(1, stsize);
|
||||
emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stsize, 1);
|
||||
emu->type = EMUTYPE_SIGNAL;
|
||||
pthread_setspecific(sigemu_key, emu);
|
||||
}
|
||||
return emu;
|
||||
}
|
||||
|
||||
|
||||
uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
|
||||
{
|
||||
if(fnc==0 || fnc==1) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
|
||||
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
uintptr_t old_start = trace_start, old_end = trace_end;
|
||||
// trace_start = 0; trace_end = 1; // disabling trace, globably for now...
|
||||
#if 0
|
||||
trace_start = 0; trace_end = 1; // disabling trace, globably for now...
|
||||
#endif
|
||||
#endif
|
||||
|
||||
x64emu_t *emu = get_signal_emu();
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
|
||||
x64emu_t *emu = thread_get_emu();
|
||||
|
||||
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
|
||||
|
||||
/*SetFS(emu, default_fs);*/
|
||||
for (int i=0; i<6; ++i)
|
||||
@@ -334,7 +312,9 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
|
||||
|
||||
uint64_t ret = R_RAX;
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
trace_start = old_start; trace_end = old_end;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -345,13 +325,12 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
x64emu_t *sigemu = get_signal_emu();
|
||||
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
|
||||
if(!ss) {
|
||||
if(!new_ss) {
|
||||
oss->ss_flags = SS_DISABLE;
|
||||
oss->ss_sp = sigemu->init_stack;
|
||||
oss->ss_size = sigemu->size_stack;
|
||||
oss->ss_sp = emu->init_stack;
|
||||
oss->ss_size = emu->size_stack;
|
||||
} else {
|
||||
oss->ss_flags = new_ss->ss_flags;
|
||||
oss->ss_sp = new_ss->ss_sp;
|
||||
@@ -370,15 +349,14 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
|
||||
free(new_ss);
|
||||
pthread_setspecific(sigstack_key, NULL);
|
||||
|
||||
sigemu->regs[_SP].dword[0] = ((uintptr_t)sigemu->init_stack + sigemu->size_stack) & ~7;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(oss) {
|
||||
if(!new_ss) {
|
||||
oss->ss_flags = SS_DISABLE;
|
||||
oss->ss_sp = sigemu->init_stack;
|
||||
oss->ss_size = sigemu->size_stack;
|
||||
oss->ss_sp = emu->init_stack;
|
||||
oss->ss_size = emu->size_stack;
|
||||
} else {
|
||||
oss->ss_flags = new_ss->ss_flags;
|
||||
oss->ss_sp = new_ss->ss_sp;
|
||||
@@ -392,8 +370,6 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
|
||||
|
||||
pthread_setspecific(sigstack_key, new_ss);
|
||||
|
||||
sigemu->regs[_SP].dword[0] = ((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -402,11 +378,31 @@ void my_sighandler(int32_t sig)
|
||||
{
|
||||
pthread_mutex_unlock(&my_context->mutex_trace); // just in case
|
||||
printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
|
||||
// save values
|
||||
x64emu_t *emu = thread_get_emu();
|
||||
uintptr_t restorer = my_context->restorer[sig];
|
||||
uintptr_t old_regs[16] = {0};
|
||||
uintptr_t old_ip = emu->ip.q[0];
|
||||
uint64_t old_flags = emu->eflags.x64;
|
||||
for(int i=0; i<16; ++i)
|
||||
old_regs[i] = emu->regs[i].q[0];
|
||||
|
||||
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
|
||||
if(new_ss) {
|
||||
// no alternate stack, so signal RSP needs to match thread RSP!
|
||||
R_RSP = (uintptr_t)(new_ss->ss_sp+new_ss->ss_size-32);
|
||||
}
|
||||
|
||||
int exits = 0;
|
||||
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
|
||||
// restore regs
|
||||
emu->ip.q[0] = old_ip;
|
||||
emu->eflags.x64 = old_flags;
|
||||
for(int i=0; i<16; ++i)
|
||||
emu->regs[i].q[0] = old_regs[i];
|
||||
if(exits)
|
||||
exit(ret);
|
||||
// what about the restored regs?
|
||||
if(restorer)
|
||||
RunFunctionHandler(&exits, restorer, 0);
|
||||
}
|
||||
@@ -438,8 +434,8 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
|
||||
|
||||
void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
|
||||
{
|
||||
// need to create some x64_ucontext????
|
||||
pthread_mutex_unlock(&my_context->mutex_trace); // just in case
|
||||
int Locks = unlockMutex();
|
||||
|
||||
printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig]));
|
||||
|
||||
uintptr_t restorer = my_context->restorer[sig];
|
||||
@@ -455,12 +451,11 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
}
|
||||
#endif
|
||||
// stack tracking
|
||||
x64emu_t *sigemu = get_signal_emu();
|
||||
x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL;
|
||||
int used_stack = 0;
|
||||
if(new_ss) {
|
||||
if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
|
||||
frame = (uintptr_t*)sigemu->regs[_SP].q[0];
|
||||
frame = (uintptr_t*)emu->regs[_SP].q[0];
|
||||
} else {
|
||||
frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
|
||||
used_stack = 1;
|
||||
@@ -523,11 +518,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
//((unsigned int *)(&sigcontext.xstate.fpstate.padding))[8*4+12] = 0x46505853; // not yet, when XSAVE / XRSTR will be ready
|
||||
// get signal mask
|
||||
|
||||
if(!new_ss) {
|
||||
sigcontext->uc_stack.ss_sp = sigemu->init_stack;
|
||||
sigcontext->uc_stack.ss_size = sigemu->size_stack;
|
||||
sigcontext->uc_stack.ss_flags = SS_DISABLE;
|
||||
} else {
|
||||
if(new_ss) {
|
||||
sigcontext->uc_stack.ss_sp = new_ss->ss_sp;
|
||||
sigcontext->uc_stack.ss_size = new_ss->ss_size;
|
||||
sigcontext->uc_stack.ss_flags = new_ss->ss_flags;
|
||||
@@ -570,7 +561,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
} else {
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
|
||||
//X64_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box86 anyway
|
||||
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box64 anyway
|
||||
}
|
||||
if(info->si_code == SEGV_ACCERR && old_code)
|
||||
*old_code = -1;
|
||||
@@ -580,20 +571,40 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6;
|
||||
// call the signal handler
|
||||
x64_ucontext_t sigcontext_copy = *sigcontext;
|
||||
|
||||
// save old value from emu
|
||||
#define GO(A) uint64_t old_##A = R_##A
|
||||
GO(RAX);
|
||||
GO(RDI);
|
||||
GO(RSI);
|
||||
GO(RDX);
|
||||
GO(RCX);
|
||||
GO(R8);
|
||||
GO(R9);
|
||||
GO(RBP);
|
||||
#undef GO
|
||||
// set stack pointer
|
||||
sigemu->regs[_SP].dword[0] = (uintptr_t)frame;
|
||||
|
||||
// set segments
|
||||
memcpy(sigemu->segs, emu->segs, sizeof(sigemu->segs));
|
||||
R_RSP = (uintptr_t)frame;
|
||||
// set frame pointer
|
||||
R_RBP = sigcontext->uc_mcontext.gregs[X64_RBP];
|
||||
|
||||
int exits = 0;
|
||||
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
|
||||
// restore old value from emu
|
||||
#define GO(A) R_##A = old_##A
|
||||
GO(RAX);
|
||||
GO(RDI);
|
||||
GO(RSI);
|
||||
GO(RDX);
|
||||
GO(RCX);
|
||||
GO(R8);
|
||||
GO(R9);
|
||||
GO(RBP);
|
||||
#undef GO
|
||||
|
||||
if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) {
|
||||
emu_jmpbuf_t* ejb = GetJmpBuf();
|
||||
if(ejb->jmpbuf_ok) {
|
||||
#define GO(R) if(sigcontext->uc_mcontext.gregs[X64_R##R]!=sigcontext_copy.uc_mcontext.gregs[X64_R##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
|
||||
#define GO(R) ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
|
||||
GO(AX);
|
||||
GO(CX);
|
||||
GO(DX);
|
||||
@@ -603,7 +614,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
GO(SP);
|
||||
GO(BX);
|
||||
#undef GO
|
||||
#define GO(R) if(sigcontext->uc_mcontext.gregs[X64_##R]!=sigcontext_copy.uc_mcontext.gregs[X64_##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_##R]
|
||||
#define GO(R) ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
|
||||
GO(R8);
|
||||
GO(R9);
|
||||
GO(R10);
|
||||
@@ -613,10 +624,10 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
GO(R14);
|
||||
GO(R15);
|
||||
#undef GO
|
||||
if(sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP]) ejb->emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
|
||||
ejb->emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
|
||||
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
|
||||
// flags
|
||||
if(sigcontext->uc_mcontext.gregs[X64_EFL]!=sigcontext_copy.uc_mcontext.gregs[X64_EFL]) ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
|
||||
ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
|
||||
// get segments
|
||||
uint16_t seg;
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
|
||||
@@ -632,17 +643,54 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
|
||||
*old_code = -1; // re-init the value to allow another segfault at the same place
|
||||
if(used_stack) // release stack
|
||||
new_ss->ss_flags = 0;
|
||||
relockMutex(Locks);
|
||||
longjmp(ejb->jmpbuf, 1);
|
||||
}
|
||||
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":"");
|
||||
}
|
||||
// restore regs...
|
||||
#define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
|
||||
GO(AX);
|
||||
GO(CX);
|
||||
GO(DX);
|
||||
GO(DI);
|
||||
GO(SI);
|
||||
GO(BP);
|
||||
GO(SP);
|
||||
GO(BX);
|
||||
#undef GO
|
||||
#define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
|
||||
GO(R8);
|
||||
GO(R9);
|
||||
GO(R10);
|
||||
GO(R11);
|
||||
GO(R12);
|
||||
GO(R13);
|
||||
GO(R14);
|
||||
GO(R15);
|
||||
#undef GO
|
||||
emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
|
||||
emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
|
||||
uint16_t seg;
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
|
||||
#define GO(S) emu->segs[_##S]=seg; emu->segs_serial[_##S] = 0;
|
||||
GO(CS);
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
|
||||
GO(GS);
|
||||
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
|
||||
GO(FS);
|
||||
#undef GO
|
||||
|
||||
printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer);
|
||||
if(exits)
|
||||
if(exits) {
|
||||
relockMutex(Locks);
|
||||
exit(ret);
|
||||
}
|
||||
if(restorer)
|
||||
RunFunctionHandler(&exits, restorer, 0);
|
||||
RunFunctionHandler(&exits, 0, restorer, 0);
|
||||
if(used_stack) // release stack
|
||||
new_ss->ss_flags = 0;
|
||||
relockMutex(Locks);
|
||||
}
|
||||
|
||||
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
@@ -662,8 +710,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
void * pc = NULL; // unknow arch...
|
||||
#warning Unhandled architecture
|
||||
#endif
|
||||
#ifdef DYNAREC
|
||||
int Locks = unlockMutex();
|
||||
uint32_t prot = getProtection((uintptr_t)addr);
|
||||
#ifdef DYNAREC
|
||||
dynablock_t* db = NULL;
|
||||
int db_searched = 0;
|
||||
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
|
||||
@@ -698,12 +747,17 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc);
|
||||
ejb->emu->eflags.x64 = p->uc_mcontext.regs[26];
|
||||
dynarec_log(LOG_DEBUG, "Auto-SMC detected, getting out of current Dynablock!\n");
|
||||
relockMutex(Locks);
|
||||
longjmp(ejb->jmpbuf, 2);
|
||||
}
|
||||
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
|
||||
}
|
||||
// done
|
||||
if(prot&PROT_WRITE) return; // if there is no write permission, don't return and continue to program signal handling
|
||||
if(prot&PROT_WRITE) {
|
||||
// if there is no write permission, don't return and continue to program signal handling
|
||||
relockMutex(Locks);
|
||||
return;
|
||||
}
|
||||
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
db_searched = 1;
|
||||
@@ -713,6 +767,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
if(addr && pc && db) {
|
||||
// probably a glitch due to intensive multitask...
|
||||
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
|
||||
relockMutex(Locks);
|
||||
return; // try again
|
||||
}
|
||||
}
|
||||
@@ -727,6 +782,10 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr);
|
||||
exit(-1);
|
||||
} else {
|
||||
if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) {
|
||||
relockMutex(Locks);
|
||||
return; // that's probably just a multi-task glitch, like seen in terraria
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!db_searched)
|
||||
db = FindDynablockFromNativeAddress(pc);
|
||||
@@ -779,8 +838,10 @@ exit(-1);
|
||||
uint32_t hash = 0;
|
||||
if(db)
|
||||
hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
|
||||
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code,
|
||||
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
|
||||
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp,
|
||||
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_RBP,
|
||||
addr, info->si_code,
|
||||
prot, db, db?db->block:0, db?(db->block+db->size):0,
|
||||
db?db->x64_addr:0, db?(db->x64_addr+db->x64_size):0,
|
||||
getAddrFunctionName((uintptr_t)(db?db->x64_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
|
||||
@@ -794,6 +855,7 @@ exit(-1);
|
||||
else
|
||||
printf_log(log_minimum, "\n");
|
||||
}
|
||||
relockMutex(Locks);
|
||||
if(my_context->signals[sig] && my_context->signals[sig]!=1) {
|
||||
if(my_context->is_sigaction[sig])
|
||||
my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
|
||||
@@ -1168,7 +1230,6 @@ void init_signal_helper(box64context_t* context)
|
||||
sigaction(SIGILL, &action, NULL);
|
||||
|
||||
pthread_once(&sigstack_key_once, sigstack_key_alloc);
|
||||
pthread_once(&sigemu_key_once, sigemu_key_alloc);
|
||||
}
|
||||
|
||||
void fini_signal_helper()
|
||||
|
||||
+407
-120
@@ -7,6 +7,7 @@
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64context.h"
|
||||
@@ -199,7 +200,7 @@ x64emu_t* thread_get_emu()
|
||||
stacksize = stack_size;
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
void* stack = calloc(1, stacksize);
|
||||
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
x64emu_t *emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stacksize, 1);
|
||||
SetupX64Emu(emu);
|
||||
thread_set_emu(emu);
|
||||
@@ -227,6 +228,9 @@ static void* pthread_routine(void* p)
|
||||
et->emu->type = EMUTYPE_MAIN;
|
||||
// setup callstack and run...
|
||||
x64emu_t* emu = et->emu;
|
||||
Push64(emu, 0); // PUSH BP
|
||||
R_RBP = R_RSP; // MOV BP, SP
|
||||
R_RSP -= 56; // Gard zone
|
||||
PushExit(emu);
|
||||
R_RIP = et->fnc;
|
||||
R_RDI = (uintptr_t)et->arg;
|
||||
@@ -236,16 +240,61 @@ static void* pthread_routine(void* p)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef NOALIGN
|
||||
pthread_attr_t* getAlignedAttr(pthread_attr_t* m) {
|
||||
return m;
|
||||
}
|
||||
void freeAlignedAttr(void* attr) {
|
||||
}
|
||||
#else
|
||||
typedef struct aligned_attr_s {
|
||||
uint64_t sign;
|
||||
pthread_attr_t *at;
|
||||
} aligned_attr_t;
|
||||
#define SIGN_ATTR *(uint64_t*)"BOX64ATT"
|
||||
|
||||
pthread_attr_t* getAlignedAttrWithInit(pthread_attr_t* attr, int init)
|
||||
{
|
||||
if(!attr)
|
||||
return attr;
|
||||
aligned_attr_t* at = (aligned_attr_t*)attr;
|
||||
if(init && at->sign==SIGN_ATTR)
|
||||
return at->at;
|
||||
pthread_attr_t* ret = (pthread_attr_t*)calloc(1, sizeof(pthread_attr_t));
|
||||
at->sign = SIGN_ATTR;
|
||||
at->at = ret;
|
||||
if(init)
|
||||
pthread_attr_init(ret); // init?
|
||||
return ret;
|
||||
}
|
||||
pthread_attr_t* getAlignedAttr(pthread_attr_t* attr)
|
||||
{
|
||||
return getAlignedAttrWithInit(attr, 1);
|
||||
}
|
||||
void freeAlignedAttr(void* attr)
|
||||
{
|
||||
if(!attr)
|
||||
return;
|
||||
aligned_attr_t* at = (aligned_attr_t*)attr;
|
||||
if(at->sign==SIGN_ATTR) {
|
||||
free(at->at);
|
||||
at->sign = 0LL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT int my_pthread_attr_destroy(x64emu_t* emu, void* attr)
|
||||
{
|
||||
if(emu->context->stacksizes)
|
||||
FreeStackSize(emu->context->stacksizes, (uintptr_t)attr);
|
||||
return pthread_attr_destroy(attr);
|
||||
int ret = pthread_attr_destroy(getAlignedAttr(attr));
|
||||
freeAlignedAttr(attr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT int my_pthread_attr_getstack(x64emu_t* emu, void* attr, void** stackaddr, size_t* stacksize)
|
||||
{
|
||||
int ret = pthread_attr_getstack(attr, stackaddr, stacksize);
|
||||
int ret = pthread_attr_getstack(getAlignedAttr(attr), stackaddr, stacksize);
|
||||
if (ret==0)
|
||||
GetStackSize(emu, (uintptr_t)attr, stackaddr, stacksize);
|
||||
return ret;
|
||||
@@ -259,7 +308,7 @@ EXPORT int my_pthread_attr_setstack(x64emu_t* emu, void* attr, void* stackaddr,
|
||||
AddStackSize(emu->context->stacksizes, (uintptr_t)attr, stackaddr, stacksize);
|
||||
//Don't call actual setstack...
|
||||
//return pthread_attr_setstack(attr, stackaddr, stacksize);
|
||||
return pthread_attr_setstacksize(attr, stacksize);
|
||||
return pthread_attr_setstacksize(getAlignedAttr(attr), stacksize);
|
||||
}
|
||||
|
||||
EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacksize)
|
||||
@@ -267,9 +316,87 @@ EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacks
|
||||
//aarch64 have an PTHREAD_STACK_MIN of 131072 instead of 16384 on x86_64!
|
||||
if(stacksize<PTHREAD_STACK_MIN)
|
||||
stacksize = PTHREAD_STACK_MIN;
|
||||
return pthread_attr_setstacksize(attr, stacksize);
|
||||
return pthread_attr_setstacksize(getAlignedAttr(attr), stacksize);
|
||||
}
|
||||
|
||||
#ifndef NOALIGN
|
||||
EXPORT int my_pthread_attr_getdetachstate(x64emu_t* emu, pthread_attr_t* attr, int *state)
|
||||
{
|
||||
return pthread_attr_getdetachstate(getAlignedAttr(attr), state);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
|
||||
{
|
||||
return pthread_attr_getguardsize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getinheritsched(x64emu_t* emu, pthread_attr_t* attr, int* sched)
|
||||
{
|
||||
return pthread_attr_getinheritsched(getAlignedAttr(attr), sched);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
|
||||
{
|
||||
return pthread_attr_getschedparam(getAlignedAttr(attr), param);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int* policy)
|
||||
{
|
||||
return pthread_attr_getschedpolicy(getAlignedAttr(attr), policy);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getscope(x64emu_t* emu, pthread_attr_t* attr, int* scope)
|
||||
{
|
||||
return pthread_attr_getscope(getAlignedAttr(attr), scope);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
|
||||
{
|
||||
size_t size;
|
||||
return pthread_attr_getstack(getAlignedAttr(attr), addr, &size);
|
||||
//return pthread_attr_getstackaddr(getAlignedAttr(attr), addr);
|
||||
}
|
||||
EXPORT int my_pthread_attr_getstacksize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
|
||||
{
|
||||
void* addr;
|
||||
return pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
|
||||
//return pthread_attr_getstacksize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr)
|
||||
{
|
||||
return pthread_attr_init(getAlignedAttrWithInit(attr, 0));
|
||||
}
|
||||
EXPORT int my_pthread_attr_setaffinity_np(x64emu_t* emu, pthread_attr_t* attr, size_t cpusize, void* cpuset)
|
||||
{
|
||||
return pthread_attr_setaffinity_np(getAlignedAttr(attr), cpusize, cpuset);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setdetachstate(x64emu_t* emu, pthread_attr_t* attr, int state)
|
||||
{
|
||||
return pthread_attr_setdetachstate(getAlignedAttr(attr), state);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t size)
|
||||
{
|
||||
return pthread_attr_setguardsize(getAlignedAttr(attr), size);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setinheritsched(x64emu_t* emu, pthread_attr_t* attr, int sched)
|
||||
{
|
||||
return pthread_attr_setinheritsched(getAlignedAttr(attr), sched);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
|
||||
{
|
||||
return pthread_attr_setschedparam(getAlignedAttr(attr), param);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int policy)
|
||||
{
|
||||
return pthread_attr_setschedpolicy(getAlignedAttr(attr), policy);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setscope(x64emu_t* emu, pthread_attr_t* attr, int scope)
|
||||
{
|
||||
return pthread_attr_setscope(getAlignedAttr(attr), scope);
|
||||
}
|
||||
EXPORT int my_pthread_attr_setstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
|
||||
{
|
||||
size_t size = 2*1024*1024;
|
||||
my_pthread_attr_getstacksize(emu, attr, &size);
|
||||
return pthread_attr_setstack(getAlignedAttr(attr), addr, size);
|
||||
//return pthread_attr_setstackaddr(getAlignedAttr(attr), addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_routine, void* arg)
|
||||
{
|
||||
int stacksize = 2*1024*1024; //default stack size is 2Mo
|
||||
@@ -280,7 +407,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
|
||||
|
||||
if(attr) {
|
||||
size_t stsize;
|
||||
if(pthread_attr_getstacksize(attr, &stsize)==0)
|
||||
if(pthread_attr_getstacksize(getAlignedAttr(attr), &stsize)==0)
|
||||
stacksize = stsize;
|
||||
}
|
||||
if(GetStackSize(emu, (uintptr_t)attr, &attr_stack, &attr_stacksize))
|
||||
@@ -289,14 +416,14 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
|
||||
stacksize = attr_stacksize;
|
||||
own = 0;
|
||||
} else {
|
||||
stack = malloc(stacksize);
|
||||
stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
own = 1;
|
||||
}
|
||||
|
||||
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
|
||||
x64emu_t *emuthread = NewX64Emu(my_context, (uintptr_t)start_routine, (uintptr_t)stack, stacksize, own);
|
||||
SetupX64Emu(emuthread);
|
||||
SetFS(emuthread, GetFS(emu));
|
||||
//SetFS(emuthread, GetFS(emu));
|
||||
et->emu = emuthread;
|
||||
et->fnc = (uintptr_t)start_routine;
|
||||
et->arg = arg;
|
||||
@@ -308,14 +435,14 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
|
||||
}
|
||||
#endif
|
||||
// create thread
|
||||
return pthread_create((pthread_t*)t, (const pthread_attr_t *)attr,
|
||||
return pthread_create((pthread_t*)t, getAlignedAttr(attr),
|
||||
pthread_routine, et);
|
||||
}
|
||||
|
||||
void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet)
|
||||
{
|
||||
int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo
|
||||
void* stack = malloc(stacksize);
|
||||
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
|
||||
x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
|
||||
SetupX64Emu(emuthread);
|
||||
@@ -342,13 +469,13 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
|
||||
{
|
||||
// get a stack local copy of the args, as may be live in some register depending the architecture (like ARM)
|
||||
if(cancel_deep<0) {
|
||||
printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
|
||||
printf_log(LOG_NONE/*LOG_INFO*/, "BOX64: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
|
||||
cancel_deep = 0;
|
||||
}
|
||||
if(cancel_deep!=CANCEL_MAX-1)
|
||||
++cancel_deep;
|
||||
else
|
||||
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, calling __pthread_register_cancel(...) too many time\n");}
|
||||
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX64: Warning, calling __pthread_register_cancel(...) too many time\n");}
|
||||
|
||||
cancel_emu[cancel_deep] = (x64emu_t*)E;
|
||||
|
||||
@@ -359,7 +486,7 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
|
||||
int i = cancel_deep--;
|
||||
x64emu_t* emu = cancel_emu[i];
|
||||
my_longjmp(emu, cancel_buff[i]->__cancel_jmp_buf, 1);
|
||||
DynaRun(emu); // resume execution
|
||||
DynaRun(emu); // resume execution // TODO: Use ejb instead?
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -494,101 +621,19 @@ EXPORT int my_pthread_key_create(x64emu_t* emu, void* key, void* dtor)
|
||||
}
|
||||
EXPORT int my___pthread_key_create(x64emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
|
||||
|
||||
// phtread_cond_init with null attr seems to only write 1 (NULL) dword on x86, while it's 48 bytes on ARM.
|
||||
// Not sure why as sizeof(pthread_cond_init) is 48 on both platform... But Neverwinter Night init seems to rely on that
|
||||
// What about cond that are statically initialized?
|
||||
// Note, this is is a versionned function (the pthread_cond_*), and this seems to correspond to an old behaviour
|
||||
|
||||
KHASH_MAP_INIT_INT(mapcond, pthread_cond_t*);
|
||||
|
||||
// should all access to that map be behind a mutex?
|
||||
kh_mapcond_t *mapcond = NULL;
|
||||
|
||||
static pthread_cond_t* add_cond(void* cond)
|
||||
{
|
||||
pthread_mutex_lock(&my_context->mutex_thread);
|
||||
khint_t k;
|
||||
int ret;
|
||||
pthread_cond_t *c;
|
||||
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &ret);
|
||||
if(!ret)
|
||||
c = kh_value(mapcond, k); // already there... reinit an existing one?
|
||||
else
|
||||
c = kh_value(mapcond, k) = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
|
||||
*(void**)cond = cond;
|
||||
pthread_mutex_unlock(&my_context->mutex_thread);
|
||||
return c;
|
||||
}
|
||||
static pthread_cond_t* get_cond(void* cond)
|
||||
{
|
||||
pthread_cond_t* ret;
|
||||
int r;
|
||||
pthread_mutex_lock(&my_context->mutex_thread);
|
||||
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
|
||||
if(k==kh_end(mapcond)) {
|
||||
khint_t k = kh_get(mapcond, mapcond, (uintptr_t)cond);
|
||||
if(k==kh_end(mapcond)) {
|
||||
printf_log(LOG_DEBUG, "BOX86: Note: phtread_cond not found, create a new empty one\n");
|
||||
ret = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
|
||||
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &r);
|
||||
kh_value(mapcond, k) = ret;
|
||||
*(void**)cond = cond;
|
||||
pthread_cond_init(ret, NULL);
|
||||
} else
|
||||
ret = kh_value(mapcond, k);
|
||||
} else
|
||||
ret = kh_value(mapcond, k);
|
||||
pthread_mutex_unlock(&my_context->mutex_thread);
|
||||
return ret;
|
||||
}
|
||||
static void del_cond(void* cond)
|
||||
{
|
||||
if(!mapcond)
|
||||
return;
|
||||
pthread_mutex_lock(&my_context->mutex_thread);
|
||||
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
|
||||
if(k!=kh_end(mapcond)) {
|
||||
free(kh_value(mapcond, k));
|
||||
kh_del(mapcond, mapcond, k);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_thread);
|
||||
}
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
|
||||
|
||||
EXPORT int my_pthread_cond_broadcast(x64emu_t* emu, void* cond)
|
||||
|
||||
EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, pthread_cond_t* cond, void* mutex, void* abstime)
|
||||
{
|
||||
pthread_cond_t * c = get_cond(cond);
|
||||
return pthread_cond_broadcast(c);
|
||||
return pthread_cond_timedwait(cond, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
|
||||
}
|
||||
EXPORT int my_pthread_cond_destroy(x64emu_t* emu, void* cond)
|
||||
EXPORT int my_pthread_cond_wait(x64emu_t* emu, pthread_cond_t* cond, void* mutex)
|
||||
{
|
||||
pthread_cond_t * c = get_cond(cond);
|
||||
int ret = pthread_cond_destroy(c);
|
||||
if(c!=cond) del_cond(cond);
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_cond_init(x64emu_t* emu, void* cond, void* attr)
|
||||
{
|
||||
pthread_cond_t *c = add_cond(cond);
|
||||
return pthread_cond_init(c, (const pthread_condattr_t*)attr);
|
||||
}
|
||||
EXPORT int my_pthread_cond_signal(x64emu_t* emu, void* cond)
|
||||
{
|
||||
pthread_cond_t * c = get_cond(cond);
|
||||
return pthread_cond_signal(c);
|
||||
}
|
||||
EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, void* cond, void* mutex, void* abstime)
|
||||
{
|
||||
pthread_cond_t * c = get_cond(cond);
|
||||
return pthread_cond_timedwait(c, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
|
||||
}
|
||||
EXPORT int my_pthread_cond_wait(x64emu_t* emu, void* cond, void* mutex)
|
||||
{
|
||||
pthread_cond_t * c = get_cond(cond);
|
||||
return pthread_cond_wait(c, getAlignedMutex((pthread_mutex_t*)mutex));
|
||||
return pthread_cond_wait(cond, getAlignedMutex((pthread_mutex_t*)mutex));
|
||||
}
|
||||
|
||||
//EXPORT int my_pthread_attr_setscope(x64emu_t* emu, void* attr, int scope)
|
||||
//EXPORT int my_pthread_attr_setscope(x64emu_t* emu, void* at*tr, int scope)
|
||||
//{
|
||||
// if(scope!=PTHREAD_SCOPE_SYSTEM) printf_log(LOG_INFO, "Warning, scope of call to pthread_attr_setscope(...) changed from %d to PTHREAD_SCOPE_SYSTEM\n", scope);
|
||||
// return pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
|
||||
@@ -655,35 +700,69 @@ EXPORT int my_pthread_kill(x64emu_t* emu, void* thread, int sig)
|
||||
return pthread_kill((pthread_t)thread, sig);
|
||||
}
|
||||
|
||||
EXPORT void my_pthread_exit(x64emu_t* emu, void* retval)
|
||||
{
|
||||
emu->quit = 1; // to be safe
|
||||
pthread_exit(retval);
|
||||
}
|
||||
//EXPORT void my_pthread_exit(x64emu_t* emu, void* retval)
|
||||
//{
|
||||
// pthread_exit(retval);
|
||||
//}
|
||||
|
||||
#ifdef NOALIGN
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m) {
|
||||
return m;
|
||||
}
|
||||
#else
|
||||
//#define TRACK_MUTEX
|
||||
// mutex alignment
|
||||
#ifdef TRACK_MUTEX
|
||||
KHASH_MAP_INIT_INT(mutex, pthread_mutex_t*)
|
||||
|
||||
static kh_mutex_t* unaligned_mutex = NULL;
|
||||
#endif
|
||||
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
|
||||
typedef struct aligned_mutex_s {
|
||||
uint64_t dummy;
|
||||
pthread_mutex_t *m;
|
||||
uint64_t sign;
|
||||
} aligned_mutex_t;
|
||||
#define SIGNMTX *(uint64_t*)"BOX64MTX"
|
||||
|
||||
pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
|
||||
{
|
||||
if(!m)
|
||||
return NULL;
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
if(init && (am->sign==SIGNMTX))
|
||||
return am->m;
|
||||
#ifdef TRACK_MUTEX
|
||||
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
|
||||
if(k!=kh_end(unaligned_mutex))
|
||||
return kh_value(unaligned_mutex, k);
|
||||
int r;
|
||||
k = kh_put(mutex, unaligned_mutex, (uintptr_t)m, &r);
|
||||
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
|
||||
memcpy(ret, m, sizeof(pthread_mutex_t));
|
||||
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
|
||||
#else
|
||||
pthread_mutex_t* ret = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
|
||||
#endif
|
||||
if(init) {
|
||||
int kind = ((int*)m)[4]; // extract kind from original mutex
|
||||
((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind; // inject in new one (i.e. "init" it)
|
||||
}
|
||||
am->sign = SIGNMTX;
|
||||
am->m = ret;
|
||||
return ret;
|
||||
}
|
||||
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
|
||||
{
|
||||
return getAlignedMutexWithInit(m, 1);
|
||||
}
|
||||
|
||||
EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
|
||||
{
|
||||
aligned_mutex_t* am = (aligned_mutex_t*)m;
|
||||
#ifdef TRACK_MUTEX
|
||||
if(am->sign==SIGNMTX) {
|
||||
am->sign = 0;
|
||||
am->m = NULL;
|
||||
}
|
||||
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
|
||||
if(k!=kh_end(unaligned_mutex)) {
|
||||
pthread_mutex_t *n = kh_value(unaligned_mutex, k);
|
||||
@@ -693,14 +772,101 @@ EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
|
||||
return ret;
|
||||
}
|
||||
return pthread_mutex_destroy(m);
|
||||
#else
|
||||
if(am->sign!=SIGNMTX) {
|
||||
return 1; //???
|
||||
}
|
||||
int ret = pthread_mutex_destroy(am->m);
|
||||
free(am->m);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
typedef union my_mutexattr_s {
|
||||
int x86;
|
||||
pthread_mutexattr_t nat;
|
||||
} my_mutexattr_t;
|
||||
// mutexattr
|
||||
EXPORT int my_pthread_mutexattr_destroy(x64emu_t* emu, my_mutexattr_t *attr)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_destroy(&mattr.nat);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my___pthread_mutexattr_destroy(x64emu_t* emu, my_mutexattr_t *attr) __attribute__((alias("my_pthread_mutexattr_destroy")));
|
||||
EXPORT int my_pthread_mutexattr_getkind_np(x64emu_t* emu, my_mutexattr_t *attr, void* p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
//int ret = pthread_mutexattr_getkind_np(&mattr.nat, p);
|
||||
int ret = pthread_mutexattr_gettype(&mattr.nat, p);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_gettype(x64emu_t* emu, my_mutexattr_t *attr, void* p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_gettype(&mattr.nat, p);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_init(x64emu_t* emu, my_mutexattr_t *attr)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_init(&mattr.nat);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my___pthread_mutexattr_init(x64emu_t* emu, my_mutexattr_t *attr) __attribute__((alias("my_pthread_mutexattr_init")));
|
||||
EXPORT int my_pthread_mutexattr_setkind_np(x64emu_t* emu, my_mutexattr_t *attr, int k)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
//int ret = pthread_mutexattr_setkind_np(&mattr.nat, k);
|
||||
int ret = pthread_mutexattr_settype(&mattr.nat, k);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_setprotocol(x64emu_t* emu, my_mutexattr_t *attr, int p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_setprotocol(&mattr.nat, p);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_setpshared(x64emu_t* emu, my_mutexattr_t *attr, int p)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_setpshared(&mattr.nat, p);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_mutexattr_settype(x64emu_t* emu, my_mutexattr_t *attr, int t)
|
||||
{
|
||||
my_mutexattr_t mattr = {0};
|
||||
mattr.x86 = attr->x86;
|
||||
int ret = pthread_mutexattr_settype(&mattr.nat, t);
|
||||
attr->x86 = mattr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my___pthread_mutexattr_settype(x64emu_t* emu, my_mutexattr_t *attr, int t) __attribute__((alias("my_pthread_mutexattr_settype")));
|
||||
|
||||
// mutex
|
||||
int my___pthread_mutex_destroy(pthread_mutex_t *m) __attribute__((alias("my_pthread_mutex_destroy")));
|
||||
|
||||
EXPORT int my_pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *att)
|
||||
EXPORT int my_pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att)
|
||||
{
|
||||
return pthread_mutex_init(getAlignedMutex(m), att);
|
||||
my_mutexattr_t mattr = {0};
|
||||
if(att)
|
||||
mattr.x86 = att->x86;
|
||||
return pthread_mutex_init(getAlignedMutexWithInit(m, 0), att?(&mattr.nat):NULL);
|
||||
}
|
||||
EXPORT int my___pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *att) __attribute__((alias("my_pthread_mutex_init")));
|
||||
EXPORT int my___pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att) __attribute__((alias("my_pthread_mutex_init")));
|
||||
|
||||
EXPORT int my_pthread_mutex_lock(pthread_mutex_t *m)
|
||||
{
|
||||
@@ -725,6 +891,118 @@ EXPORT int my_pthread_mutex_unlock(pthread_mutex_t *m)
|
||||
return pthread_mutex_unlock(getAlignedMutex(m));
|
||||
}
|
||||
|
||||
typedef union my_condattr_s {
|
||||
int x86;
|
||||
pthread_condattr_t nat;
|
||||
} my_condattr_t;
|
||||
// condattr
|
||||
EXPORT int my_pthread_condattr_destroy(x64emu_t* emu, my_condattr_t* c)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_destroy(&cond.nat);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_condattr_getclock(x64emu_t* emu, my_condattr_t* c, void* cl)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_getclock(&cond.nat, cl);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_condattr_getpshared(x64emu_t* emu, my_condattr_t* c, void* p)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_getpshared(&cond.nat, p);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_condattr_init(x64emu_t* emu, my_condattr_t* c)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_init(&cond.nat);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_condattr_setclock(x64emu_t* emu, my_condattr_t* c, int cl)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_setclock(&cond.nat, cl);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_condattr_setpshared(x64emu_t* emu, my_condattr_t* c, int p)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_condattr_setpshared(&cond.nat, p);
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_cond_init(x64emu_t* emu, pthread_cond_t *pc, my_condattr_t* c)
|
||||
{
|
||||
my_condattr_t cond = {0};
|
||||
if(c)
|
||||
cond.x86 = c->x86;
|
||||
int ret = pthread_cond_init(pc, c?(&cond.nat):NULL);
|
||||
if(c)
|
||||
c->x86 = cond.x86;
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef union my_barrierattr_s {
|
||||
int x86;
|
||||
pthread_barrierattr_t nat;
|
||||
} my_barrierattr_t;
|
||||
// barrierattr
|
||||
EXPORT int my_pthread_barrierattr_destroy(x64emu_t* emu, my_barrierattr_t* b)
|
||||
{
|
||||
my_barrierattr_t battr = {0};
|
||||
battr.x86 = b->x86;
|
||||
int ret = pthread_barrierattr_destroy(&battr.nat);
|
||||
b->x86 = battr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_barrierattr_getpshared(x64emu_t* emu, my_barrierattr_t* b, void* p)
|
||||
{
|
||||
my_barrierattr_t battr = {0};
|
||||
battr.x86 = b->x86;
|
||||
int ret = pthread_barrierattr_getpshared(&battr.nat, p);
|
||||
b->x86 = battr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_barrierattr_init(x64emu_t* emu, my_barrierattr_t* b)
|
||||
{
|
||||
my_barrierattr_t battr = {0};
|
||||
battr.x86 = b->x86;
|
||||
int ret = pthread_barrierattr_init(&battr.nat);
|
||||
b->x86 = battr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_barrierattr_setpshared(x64emu_t* emu, my_barrierattr_t* b, int p)
|
||||
{
|
||||
my_barrierattr_t battr = {0};
|
||||
battr.x86 = b->x86;
|
||||
int ret = pthread_barrierattr_setpshared(&battr.nat, p);
|
||||
b->x86 = battr.x86;
|
||||
return ret;
|
||||
}
|
||||
EXPORT int my_pthread_barrier_init(x64emu_t* emu, pthread_barrier_t* bar, my_barrierattr_t* b, uint32_t count)
|
||||
{
|
||||
my_barrierattr_t battr = {0};
|
||||
if(b)
|
||||
battr.x86 = b->x86;
|
||||
int ret = pthread_barrier_init(bar, b?(&battr.nat):NULL, count);
|
||||
if(b)
|
||||
b->x86 = battr.x86;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void emujmpbuf_destroy(void* p)
|
||||
@@ -752,10 +1030,11 @@ emu_jmpbuf_t* GetJmpBuf()
|
||||
void init_pthread_helper()
|
||||
{
|
||||
InitCancelThread();
|
||||
mapcond = kh_init(mapcond);
|
||||
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
|
||||
#ifndef NOALIGN
|
||||
#ifdef TRACK_MUTEX
|
||||
unaligned_mutex = kh_init(mutex);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -763,20 +1042,15 @@ void fini_pthread_helper(box64context_t* context)
|
||||
{
|
||||
FreeCancelThread(context);
|
||||
CleanStackSize(context);
|
||||
pthread_cond_t *cond;
|
||||
kh_foreach_value(mapcond, cond,
|
||||
pthread_cond_destroy(cond);
|
||||
free(cond);
|
||||
);
|
||||
kh_destroy(mapcond, mapcond);
|
||||
mapcond = NULL;
|
||||
#ifndef NOALIGN
|
||||
#ifdef TRACK_MUTEX
|
||||
pthread_mutex_t *m;
|
||||
kh_foreach_value(unaligned_mutex, m,
|
||||
pthread_mutex_destroy(m);
|
||||
free(m);
|
||||
);
|
||||
kh_destroy(mutex, unaligned_mutex);
|
||||
#endif
|
||||
#endif
|
||||
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
|
||||
if(ejb) {
|
||||
@@ -789,3 +1063,16 @@ void fini_pthread_helper(box64context_t* context)
|
||||
pthread_setspecific(thread_key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int checkMutex(void* m)
|
||||
{
|
||||
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
|
||||
int ret = pthread_mutex_trylock(mutex);
|
||||
if(ret==0) {
|
||||
pthread_mutex_unlock(mutex);
|
||||
return 0;
|
||||
}
|
||||
if(ret==EDEADLK)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
+79
-21
@@ -40,10 +40,13 @@ uintptr_t box64_nodynarec_end = 0;
|
||||
int box64_dynarec = 0;
|
||||
#endif
|
||||
int dlsym_error = 0;
|
||||
#ifdef HAVE_TRACE
|
||||
int trace_xmm = 0;
|
||||
int trace_emm = 0;
|
||||
#ifdef HAVE_TRACE
|
||||
int trace_regsdiff = 0;
|
||||
uint64_t start_cnt = 0;
|
||||
uintptr_t trace_start = 0, trace_end = 0;
|
||||
char* trace_func = NULL;
|
||||
#ifdef DYNAREC
|
||||
int box64_dynarec_trace = 0;
|
||||
#endif
|
||||
@@ -58,8 +61,6 @@ int box64_nopulse = 0;
|
||||
int box64_nogtk = 0;
|
||||
int box64_novulkan = 0;
|
||||
char* libGL = NULL;
|
||||
uintptr_t trace_start = 0, trace_end = 0;
|
||||
char* trace_func = NULL;
|
||||
uintptr_t fmod_smc_start = 0;
|
||||
uintptr_t fmod_smc_end = 0;
|
||||
uint32_t default_gs = 0;
|
||||
@@ -207,6 +208,13 @@ void LoadLogEnv()
|
||||
trace_emm = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_TRACE_COLOR");
|
||||
if(p) {
|
||||
if(strlen(p)==1) {
|
||||
if(p[0]>='0' && p[1]<='0'+1)
|
||||
trace_regsdiff = p[0]-'0';
|
||||
}
|
||||
}
|
||||
p = getenv("BOX64_TRACE_START");
|
||||
if(p) {
|
||||
char* p2;
|
||||
@@ -432,6 +440,7 @@ void PrintHelp() {
|
||||
printf(" use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before init of Libs and main program\n\t (function name will probably not work then)\n");
|
||||
printf(" BOX64_TRACE_EMM with 1 to enable dump of MMX registers along with regular registers\n");
|
||||
printf(" BOX64_TRACE_XMM with 1 to enable dump of SSE registers along with regular registers\n");
|
||||
printf(" BOX64_TRACE_COLOR with 1 to enable detection of changed general register values\n");
|
||||
printf(" BOX64_TRACE_START with N to enable trace after N instructions\n");
|
||||
#ifdef DYNAREC
|
||||
printf(" BOX64_DYNAREC_TRACE with 0/1 to disable or enable Trace on generated code too\n");
|
||||
@@ -456,7 +465,7 @@ EXPORTDYN
|
||||
void LoadEnvVars(box64context_t *context)
|
||||
{
|
||||
// check BOX64_LD_LIBRARY_PATH and load it
|
||||
LoadEnvPath(&context->box64_ld_lib, ".:lib:lib64:x86_64", "BOX64_LD_LIBRARY_PATH");
|
||||
LoadEnvPath(&context->box64_ld_lib, ".:lib:lib64:x86_64:bin64:libs64", "BOX64_LD_LIBRARY_PATH");
|
||||
if(FileExist("/lib/x86_64-linux-gnu", 0))
|
||||
AddPath("/lib/x86_64-linux-gnu", &context->box64_ld_lib, 1);
|
||||
if(FileExist("/usr/lib/x86_64-linux-gnu", 0))
|
||||
@@ -589,6 +598,56 @@ void endBox64()
|
||||
if(!my_context)
|
||||
return;
|
||||
|
||||
x64emu_t* emu = thread_get_emu();
|
||||
// atexit first
|
||||
printf_log(LOG_DEBUG, "Calling atexit registered functions (exiting box64)\n");
|
||||
CallAllCleanup(emu);
|
||||
// then call all the fini
|
||||
printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n");
|
||||
RunElfFini(my_context->elfs[0], emu);
|
||||
#ifdef DYNAREC
|
||||
// disable dynarec now
|
||||
box64_dynarec = 0;
|
||||
#endif
|
||||
FreeLibrarian(&my_context->local_maplib, emu); // unload all libs
|
||||
FreeLibrarian(&my_context->maplib, emu); // unload all libs
|
||||
// waiting for all thread except this one to finish
|
||||
int this_thread = GetTID();
|
||||
int pid = getpid();
|
||||
int running = 1;
|
||||
int attempt = 0;
|
||||
printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box64context\n");
|
||||
while(running) {
|
||||
DIR *proc_dir;
|
||||
char dirname[100];
|
||||
snprintf(dirname, sizeof dirname, "/proc/self/task");
|
||||
proc_dir = opendir(dirname);
|
||||
running = 0;
|
||||
if (proc_dir)
|
||||
{
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(proc_dir)) != NULL && !running)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
int tid = atoi(entry->d_name);
|
||||
// tid != pthread_t, so no pthread functions are available here
|
||||
if(tid!=this_thread) {
|
||||
if(attempt>4000) {
|
||||
printf_log(LOG_INFO, "Stop waiting for remaining thread %04d\n", tid);
|
||||
// enough wait, kill all thread!
|
||||
syscall(__NR_tgkill, pid, tid, SIGABRT);
|
||||
} else {
|
||||
running = 1;
|
||||
++attempt;
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(proc_dir);
|
||||
}
|
||||
}
|
||||
// all done, free context
|
||||
FreeBox64Context(&my_context);
|
||||
if(libGL) {
|
||||
@@ -746,23 +805,16 @@ int main(int argc, const char **argv, const char **env) {
|
||||
AddPath("libudev.so.0", &my_context->box64_emulated_libs, 0);
|
||||
box64_steam = 1;
|
||||
}
|
||||
// special case for steam-runtime-check-requirements to fake 64bits suport
|
||||
/*// special case for steam-runtime-check-requirements to fake 64bits suport
|
||||
if(strstr(prgname, "steam-runtime-check-requirements")==prgname) {
|
||||
printf_log(LOG_INFO, "steam-runtime-check-requirements detected, faking All is good!\n");
|
||||
exit(0); // exiting, not testing anything
|
||||
}
|
||||
}*/
|
||||
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
|
||||
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
|
||||
free(my_context->argv[0]);
|
||||
my_context->argv[0] = strdup("./UnrealLinux.bin");
|
||||
}
|
||||
#ifdef RPI
|
||||
// special case for TokiTori 2+, that check if texture max size is > = 8192
|
||||
if(strstr(prgname, "TokiTori2.bin.x86")==prgname) {
|
||||
printf_log(LOG_INFO, "TokiTori 2+ detected, runtime patch to fix GPU non-power-of-two faillure\n");
|
||||
box64_tokitori2 = 1;
|
||||
}
|
||||
#endif
|
||||
// special case for zoom
|
||||
if(strstr(prgname, "zoom")==prgname) {
|
||||
printf_log(LOG_INFO, "Zoom detected, trying to use system libturbojpeg if possible\n");
|
||||
@@ -907,6 +959,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
SetRSI(emu, my_context->argc);
|
||||
SetRDX(emu, (uint64_t)my_context->argv);
|
||||
SetRCX(emu, (uint64_t)my_context->envv);
|
||||
SetRBP(emu, 0); // Frame pointer so to "No more frame pointer"
|
||||
|
||||
// child fork to handle traces
|
||||
pthread_atfork(NULL, NULL, my_child_fork);
|
||||
@@ -932,7 +985,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
// pre-load lib if needed
|
||||
if(ld_preload.size) {
|
||||
for (int i=0; i<ld_preload.size; ++i) {
|
||||
if(AddNeededLib(NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
|
||||
if(AddNeededLib(NULL, NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
|
||||
if(!strstr(ld_preload.paths[i], "vgpreload_"))
|
||||
printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]);
|
||||
}
|
||||
@@ -940,7 +993,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
}
|
||||
FreeCollection(&ld_preload);
|
||||
// Call librarian to load all dependant elf
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, 0, my_context, emu)) {
|
||||
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, my_context, emu)) {
|
||||
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
|
||||
FreeBox64Context(&my_context);
|
||||
return -1;
|
||||
@@ -962,7 +1015,7 @@ int main(int argc, const char **argv, const char **env) {
|
||||
setupTrace(my_context);
|
||||
// get entrypoint
|
||||
my_context->ep = GetEntryPoint(my_context->maplib, elf_header);
|
||||
#if defined(RPI) || defined(RK3399)
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
// before launching emulation, let's check if this is a mojosetup from GOG
|
||||
if (((strstr(prog, "bin/linux/x86/mojosetup") && getenv("MOJOSETUP_BASE")) || strstr(prog, ".mojosetup/mojosetup"))
|
||||
&& getenv("GTK2_RC_FILES")) {
|
||||
@@ -974,17 +1027,22 @@ int main(int argc, const char **argv, const char **env) {
|
||||
|
||||
// emulate!
|
||||
printf_log(LOG_DEBUG, "Start x64emu on Main\n");
|
||||
SetRSI(emu, my_context->argc);
|
||||
SetRDX(emu, (uint64_t)my_context->argv);
|
||||
SetRCX(emu, (uint64_t)my_context->envv);
|
||||
// Stack is ready, with stacked: NULL env NULL argv argc
|
||||
SetRIP(emu, my_context->ep);
|
||||
PushExit(emu);
|
||||
*(uint64_t*)GetRSP(emu) = my_context->argc;
|
||||
ResetFlags(emu);
|
||||
PushExit(emu); // push to pop it just after
|
||||
SetRDX(emu, Pop64(emu)); // RDX is exit function
|
||||
Run(emu, 0);
|
||||
// Get EAX
|
||||
int ret = GetEAX(emu);
|
||||
printf_log(LOG_DEBUG, "Emulation finished, EAX=%d\n", ret);
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
if(trace_func) {
|
||||
free(trace_func);
|
||||
trace_func = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
+52
-23
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "box64stack.h"
|
||||
#include "box64context.h"
|
||||
@@ -15,15 +16,17 @@ EXPORTDYN
|
||||
int CalcStackSize(box64context_t *context)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Calc stack size, based on %d elf(s)\n", context->elfsize);
|
||||
context->stacksz = 8*1024*1024; context->stackalign=4;
|
||||
context->stacksz = 8*1024*1024; context->stackalign=16;
|
||||
for (int i=0; i<context->elfsize; ++i)
|
||||
CalcStack(context->elfs[i], &context->stacksz, &context->stackalign);
|
||||
|
||||
if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) {
|
||||
// if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) {
|
||||
context->stack = mmap(NULL, context->stacksz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
if (context->stack==(void*)-1) {
|
||||
printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%x/0x%x) for stack\n", context->stacksz, context->stackalign);
|
||||
return 1;
|
||||
}
|
||||
memset(context->stack, 0, context->stacksz);
|
||||
//memset(context->stack, 0, context->stacksz);
|
||||
printf_log(LOG_DEBUG, "Stack is @%p size=0x%x align=0x%x\n", context->stack, context->stacksz, context->stackalign);
|
||||
|
||||
return 0;
|
||||
@@ -118,29 +121,55 @@ void SetupInitialStack(x64emu_t *emu)
|
||||
R_RSP=tmp;
|
||||
|
||||
// push the AuxVector themselves
|
||||
Push(emu, 0); Push(emu, 0); //AT_NULL(0)=0
|
||||
Push(emu, p_x86_64); Push(emu, 15); //AT_PLATFORM(15)=p_x86_64*
|
||||
Push(emu, 0); Push(emu, 66); //AT_HWCAP2(26)=0
|
||||
/* Actual sample:
|
||||
3 0x400040
|
||||
4 0x38
|
||||
5 0xb
|
||||
6 0x1000
|
||||
7 0x7f7addca6000
|
||||
8 (nil)
|
||||
9 0x401040
|
||||
11 0x3e8
|
||||
12 0x3e8
|
||||
13 0x3e8
|
||||
14 0x3e8
|
||||
16 0xbfebfbff
|
||||
15 0x7ffd5074c4c9
|
||||
17 0x64
|
||||
23 (nil)
|
||||
25 0x7ffd5074c4b9
|
||||
26 (nil)
|
||||
31 0x7ffd5074efea
|
||||
33 0x7ffd507e6000
|
||||
*/
|
||||
Push(emu, 0); Push(emu, 0); //AT_NULL(0)=0
|
||||
//Push(emu, ); Push(emu, 3); //AT_PHDR(3)=address of the PH of the executable
|
||||
//Push(emu, ); Push(emu, 4); //AT_PHENT(4)=size of PH entry
|
||||
//Push(emu, ); Push(emu, 5); //AT_PHNUM(5)=number of elf headers
|
||||
Push(emu, box64_pagesize); Push(emu, 6); //AT_PAGESZ(6)
|
||||
//Push(emu, real_getauxval(7)); Push(emu, 7); //AT_BASE(7)=ld-2.27.so start (in memory)
|
||||
Push(emu, 0); Push(emu, 8); //AT_FLAGS(8)=0
|
||||
Push(emu, R_RIP); Push(emu, 9); //AT_ENTRY(9)=entrypoint
|
||||
Push(emu, real_getauxval(11)); Push(emu, 11); //AT_UID(11)
|
||||
Push(emu, real_getauxval(12)); Push(emu, 12); //AT_EUID(12)
|
||||
Push(emu, real_getauxval(13)); Push(emu, 13); //AT_GID(13)
|
||||
Push(emu, real_getauxval(14)); Push(emu, 14); //AT_EGID(14)
|
||||
Push(emu, p_x86_64); Push(emu, 15); //AT_PLATFORM(15)=&"x86_64"
|
||||
// Push HWCAP:
|
||||
// FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4
|
||||
// MSR: 1<<5 : PAE: 1<<6 : MCE: 1<<7 ; CX8: 1<<8 : APIC:1<<9
|
||||
// SEP: 1<<11: MTRR:1<<12: PGE: 1<<13: MCA: 1<<14; CMOV:1<<15; FCMOV: 1<<16
|
||||
// MMX: 1<<23:OSFXR:1<<24: XMM: 1<<25:XMM2: 1<<26;AMD3D:1<<31
|
||||
// FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4 ; MSR: 1<<5 ; PAE: 1<<6 ; MCE: 1<<7
|
||||
// CX8: 1<<8 ; APIC:1<<9 ; SEP: 1<<11; MTRR:1<<12; PGE: 1<<13; MCA: 1<<14; CMOV:1<<15
|
||||
// FCMOV:1<<16; ; MMX: 1<<23
|
||||
// OSFXR:1<<24; XMM: 1<<25;XMM2: 1<<26; AMD3D:1<<31
|
||||
Push(emu, (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<8) | (1<<15) | (1<<16) | (1<<23) | (1<<25) | (1<<26));
|
||||
Push(emu, 16); //AT_HWCAP(16)=...
|
||||
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
|
||||
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
|
||||
Push(emu, real_getauxval(23)); Push(emu, 23); //AT_SECURE(23)=0
|
||||
Push(emu, real_getauxval(14)); Push(emu, 14); //AT_EGID(14)
|
||||
Push(emu, real_getauxval(13)); Push(emu, 13); //AT_GID(13)
|
||||
Push(emu, real_getauxval(12)); Push(emu, 12); //AT_EUID(12)
|
||||
Push(emu, real_getauxval(11)); Push(emu, 11); //AT_UID(11)
|
||||
Push(emu, box64_pagesize); Push(emu, 6); //AT_PAGESZ(6)
|
||||
Push(emu, R_RIP); Push(emu, 9); //AT_ENTRY(9)=entrypoint
|
||||
Push(emu, 0/*emu->context->vsyscall*/); Push(emu, 32); //AT_SYSINFO(32)=vsyscall
|
||||
Push(emu, 16); //AT_HWCAP(16)=...
|
||||
//Push(emu, sysconf(_SC_CLK_TCK)); Push(emu, 17); //AT_CLKTCK(17)=times() frequency
|
||||
Push(emu, real_getauxval(23)); Push(emu, 23); //AT_SECURE(23)
|
||||
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
|
||||
Push(emu, 0); Push(emu, 26); //AT_HWCAP2(26)=0
|
||||
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
|
||||
//Push(emu, ); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
|
||||
if(!emu->context->auxval_start) // store auxval start if needed
|
||||
emu->context->auxval_start = (uintptr_t*)R_RSP;
|
||||
// TODO: continue
|
||||
|
||||
// push nil / envs / nil / args / argc
|
||||
Push(emu, 0);
|
||||
@@ -150,4 +179,4 @@ void SetupInitialStack(x64emu_t *emu)
|
||||
for (int i=emu->context->argc-1; i>=0; --i)
|
||||
Push(emu, p_argv[i]);
|
||||
Push(emu, emu->context->argc);
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -91,14 +91,15 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
b = b->next;
|
||||
bridge->last = b;
|
||||
}
|
||||
sz = b->sz;
|
||||
#ifdef DYNAREC
|
||||
sz = b->sz;
|
||||
pthread_mutex_unlock(&bridge->mutex);
|
||||
if(box64_dynarec) {
|
||||
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
|
||||
if(prot)
|
||||
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
|
||||
else // only add DB if there is no protection
|
||||
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
|
||||
}
|
||||
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
|
||||
pthread_mutex_lock(&bridge->mutex);
|
||||
@@ -116,7 +117,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
|
||||
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
|
||||
pthread_mutex_unlock(&bridge->mutex);
|
||||
#ifdef DYNAREC
|
||||
if(box64_dynarec && prot)
|
||||
if(box64_dynarec)
|
||||
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
|
||||
#endif
|
||||
#ifdef HAVE_TRACE
|
||||
|
||||
@@ -77,7 +77,7 @@ int FileIsX64ELF(const char* filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(RPI) || defined(RK3399)
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
void sanitize_mojosetup_gtk_background()
|
||||
{
|
||||
// get GTK2_RC_FILES folder
|
||||
|
||||
@@ -36,8 +36,8 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
|
||||
R_ECX = 0x6C65746E;
|
||||
break;
|
||||
case 0x1:
|
||||
R_EAX = 0x00000601; // familly and all
|
||||
R_EBX = 0; // Brand indexe, CLFlush, Max APIC ID, Local APIC ID
|
||||
R_EAX = 0x00000601; // family and all
|
||||
R_EBX = 0; // Brand index, CLFlush, Max APIC ID, Local APIC ID
|
||||
R_EDX = 1 // fpu
|
||||
| 1<<4 // rdtsc
|
||||
| 1<<8 // cmpxchg8
|
||||
@@ -108,10 +108,10 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
|
||||
R_EDX = 0;
|
||||
break;
|
||||
case 0x7: // extended bits...
|
||||
/*if(R_ECX==0) R_EAX = 0;
|
||||
else*/ R_EAX = R_ECX = R_EBX = R_EDX = 0;
|
||||
if(R_ECX==1) R_EAX = 0; // Bit 5 is avx512_bf16
|
||||
else R_EAX = R_ECX = R_EBX = R_EDX = 0; // TODO
|
||||
break;
|
||||
case 0xB: // Extended Topology Enumaretion Leaf
|
||||
case 0xB: // Extended Topology Enumeration Leaf
|
||||
//TODO!
|
||||
R_EAX = 0;
|
||||
break;
|
||||
@@ -138,7 +138,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
|
||||
R_EAX = 0; // reserved
|
||||
R_EBX = 0; // reserved
|
||||
R_ECX = (1<<5) | (1<<8); // LZCNT | PREFETCHW
|
||||
R_EDX = 0;
|
||||
R_EDX = 1; // x87 FPU
|
||||
break;
|
||||
case 0x80000002: // Brand part 1 (P4 signature)
|
||||
R_EAX = 0x20202020;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#() vFu
|
||||
#() vFf
|
||||
#() vFd
|
||||
#() vFl
|
||||
#() vFp
|
||||
#() vFS
|
||||
#() cFv
|
||||
@@ -12,7 +13,6 @@
|
||||
#() cFf
|
||||
#() cFp
|
||||
#() wFp
|
||||
#() iFE
|
||||
#() iFv
|
||||
#() iFi
|
||||
#() iFu
|
||||
@@ -20,6 +20,7 @@
|
||||
#() iFd
|
||||
#() iFL
|
||||
#() iFp
|
||||
#() iFO
|
||||
#() iFS
|
||||
#() IFf
|
||||
#() IFd
|
||||
@@ -37,22 +38,30 @@
|
||||
#() fFi
|
||||
#() fFf
|
||||
#() fFp
|
||||
#() dFv
|
||||
#() dFi
|
||||
#() dFu
|
||||
#() dFd
|
||||
#() dFp
|
||||
#() lFE
|
||||
#() lFv
|
||||
#() lFi
|
||||
#() lFl
|
||||
#() lFp
|
||||
#() LFE
|
||||
#() LFv
|
||||
#() LFL
|
||||
#() LFp
|
||||
#() pFE
|
||||
#() pFv
|
||||
#() pFi
|
||||
#() pFW
|
||||
#() pFu
|
||||
#() pFd
|
||||
#() pFl
|
||||
#() pFL
|
||||
#() pFp
|
||||
#() pFV
|
||||
#() HFi
|
||||
#() HFp
|
||||
#() vFEp
|
||||
@@ -62,6 +71,7 @@
|
||||
#() vFid
|
||||
#() vFip
|
||||
#() vFWW
|
||||
#() vFWp
|
||||
#() vFui
|
||||
#() vFuu
|
||||
#() vFuf
|
||||
@@ -71,9 +81,12 @@
|
||||
#() vFff
|
||||
#() vFfp
|
||||
#() vFdd
|
||||
#() vFLp
|
||||
#() vFpi
|
||||
#() vFpu
|
||||
#() vFpf
|
||||
#() vFpd
|
||||
#() vFpl
|
||||
#() vFpL
|
||||
#() vFpp
|
||||
#() vFpS
|
||||
@@ -81,13 +94,15 @@
|
||||
#() cFpp
|
||||
#() iFEp
|
||||
#() iFii
|
||||
#() iFiI
|
||||
#() iFiu
|
||||
#() iFiU
|
||||
#() iFil
|
||||
#() iFip
|
||||
#() iFIi
|
||||
#() iFui
|
||||
#() iFuu
|
||||
#() iFup
|
||||
#() iFUU
|
||||
#() iFli
|
||||
#() iFLL
|
||||
#() iFLp
|
||||
@@ -96,6 +111,7 @@
|
||||
#() iFpI
|
||||
#() iFpC
|
||||
#() iFpu
|
||||
#() iFpU
|
||||
#() iFpf
|
||||
#() iFpd
|
||||
#() iFpl
|
||||
@@ -104,6 +120,7 @@
|
||||
#() iFpO
|
||||
#() iFSi
|
||||
#() IFEp
|
||||
#() IFpi
|
||||
#() IFpu
|
||||
#() CFui
|
||||
#() CFpi
|
||||
@@ -117,8 +134,10 @@
|
||||
#() uFpi
|
||||
#() uFpu
|
||||
#() uFpU
|
||||
#() uFpL
|
||||
#() uFpp
|
||||
#() UFEp
|
||||
#() UFii
|
||||
#() UFUp
|
||||
#() UFpp
|
||||
#() fFif
|
||||
@@ -130,16 +149,23 @@
|
||||
#() dFdi
|
||||
#() dFdd
|
||||
#() dFdp
|
||||
#() dFLL
|
||||
#() dFpi
|
||||
#() dFpp
|
||||
#() lFll
|
||||
#() lFpi
|
||||
#() lFpp
|
||||
#() LFpi
|
||||
#() LFpL
|
||||
#() LFpp
|
||||
#() pFEp
|
||||
#() pFii
|
||||
#() pFiu
|
||||
#() pFip
|
||||
#() pFui
|
||||
#() pFuu
|
||||
#() pFup
|
||||
#() pFdd
|
||||
#() pFlp
|
||||
#() pFLL
|
||||
#() pFpi
|
||||
@@ -150,6 +176,7 @@
|
||||
#() pFpp
|
||||
#() pFpV
|
||||
#() pFSi
|
||||
#() HFll
|
||||
#() HFpi
|
||||
#() vFEpi
|
||||
#() vFEpu
|
||||
@@ -178,7 +205,9 @@
|
||||
#() vFuup
|
||||
#() vFuff
|
||||
#() vFudd
|
||||
#() vFull
|
||||
#() vFupi
|
||||
#() vFupu
|
||||
#() vFfff
|
||||
#() vFfpp
|
||||
#() vFddd
|
||||
@@ -193,13 +222,19 @@
|
||||
#() vFpuI
|
||||
#() vFpuu
|
||||
#() vFpup
|
||||
#() vFpdd
|
||||
#() vFpll
|
||||
#() vFpLi
|
||||
#() vFpLL
|
||||
#() vFppi
|
||||
#() vFppu
|
||||
#() vFppL
|
||||
#() vFppp
|
||||
#() iFEiw
|
||||
#() iFEip
|
||||
#() iFEWW
|
||||
#() iFEup
|
||||
#() iFEUU
|
||||
#() iFEpi
|
||||
#() iFEpL
|
||||
#() iFEpp
|
||||
@@ -211,14 +246,18 @@
|
||||
#() iFiip
|
||||
#() iFiiO
|
||||
#() iFiuu
|
||||
#() iFiLi
|
||||
#() iFiLN
|
||||
#() iFipu
|
||||
#() iFipL
|
||||
#() iFipp
|
||||
#() iFuuu
|
||||
#() iFuup
|
||||
#() iFuff
|
||||
#() iFuLL
|
||||
#() iFfff
|
||||
#() iFLip
|
||||
#() iFLLp
|
||||
#() iFLpp
|
||||
#() iFpii
|
||||
#() iFpiu
|
||||
@@ -230,18 +269,26 @@
|
||||
#() iFpuU
|
||||
#() iFpuL
|
||||
#() iFpup
|
||||
#() iFpUi
|
||||
#() iFpUU
|
||||
#() iFpfu
|
||||
#() iFpff
|
||||
#() iFpdd
|
||||
#() iFpli
|
||||
#() iFpll
|
||||
#() iFplp
|
||||
#() iFpLi
|
||||
#() iFpLL
|
||||
#() iFpLp
|
||||
#() iFppi
|
||||
#() iFppI
|
||||
#() iFppC
|
||||
#() iFppW
|
||||
#() iFppu
|
||||
#() iFppd
|
||||
#() iFppl
|
||||
#() iFppL
|
||||
#() iFppp
|
||||
#() iFppV
|
||||
#() iFSpL
|
||||
#() IFiIi
|
||||
#() IFpIi
|
||||
@@ -257,45 +304,61 @@
|
||||
#() uFuup
|
||||
#() uFupu
|
||||
#() uFupp
|
||||
#() uFpiu
|
||||
#() uFpip
|
||||
#() uFpLp
|
||||
#() uFppi
|
||||
#() uFppu
|
||||
#() uFppp
|
||||
#() UFppi
|
||||
#() fFuii
|
||||
#() fFfff
|
||||
#() fFffp
|
||||
#() fFppL
|
||||
#() dFddd
|
||||
#() dFddp
|
||||
#() dFppi
|
||||
#() dFppp
|
||||
#() lFipi
|
||||
#() lFipL
|
||||
#() lFlll
|
||||
#() lFlpi
|
||||
#() lFppi
|
||||
#() lFppL
|
||||
#() lFSpl
|
||||
#() LFipL
|
||||
#() LFLLi
|
||||
#() LFLLI
|
||||
#() LFLpu
|
||||
#() LFLpL
|
||||
#() LFpii
|
||||
#() LFpup
|
||||
#() LFpLi
|
||||
#() LFpLp
|
||||
#() LFppi
|
||||
#() LFppL
|
||||
#() LFSpL
|
||||
#() pFEip
|
||||
#() pFEpi
|
||||
#() pFEpp
|
||||
#() pFiii
|
||||
#() pFiip
|
||||
#() pFipi
|
||||
#() pFipL
|
||||
#() pFipp
|
||||
#() pFIpi
|
||||
#() pFWWW
|
||||
#() pFuii
|
||||
#() pFupi
|
||||
#() pFupL
|
||||
#() pFUpi
|
||||
#() pFddd
|
||||
#() pFpii
|
||||
#() pFpiu
|
||||
#() pFpil
|
||||
#() pFpiL
|
||||
#() pFpip
|
||||
#() pFpCC
|
||||
#() pFpCu
|
||||
#() pFpui
|
||||
#() pFpuu
|
||||
#() pFpuL
|
||||
@@ -308,11 +371,13 @@
|
||||
#() pFppi
|
||||
#() pFppu
|
||||
#() pFppf
|
||||
#() pFppl
|
||||
#() pFppL
|
||||
#() pFppp
|
||||
#() pFpOM
|
||||
#() pFSpl
|
||||
#() vFEipV
|
||||
#() vFEpii
|
||||
#() vFEpip
|
||||
#() vFEpup
|
||||
#() vFEppp
|
||||
@@ -326,6 +391,7 @@
|
||||
#() vFiddd
|
||||
#() vFipii
|
||||
#() vFipup
|
||||
#() vFippi
|
||||
#() vFippp
|
||||
#() vFuiii
|
||||
#() vFuiip
|
||||
@@ -356,14 +422,22 @@
|
||||
#() vFdddd
|
||||
#() vFpiii
|
||||
#() vFpiip
|
||||
#() vFpiuL
|
||||
#() vFpiup
|
||||
#() vFpipp
|
||||
#() vFpuuu
|
||||
#() vFpudd
|
||||
#() vFpupp
|
||||
#() vFpdii
|
||||
#() vFpddd
|
||||
#() vFpLLL
|
||||
#() vFppii
|
||||
#() vFppid
|
||||
#() vFppip
|
||||
#() vFppui
|
||||
#() vFppuu
|
||||
#() vFppup
|
||||
#() vFppdd
|
||||
#() vFpppi
|
||||
#() vFpppu
|
||||
#() vFpppp
|
||||
@@ -373,7 +447,9 @@
|
||||
#() iFEipp
|
||||
#() iFEipV
|
||||
#() iFEupp
|
||||
#() iFEpii
|
||||
#() iFEpip
|
||||
#() iFEpLi
|
||||
#() iFEppi
|
||||
#() iFEppL
|
||||
#() iFEppp
|
||||
@@ -381,75 +457,113 @@
|
||||
#() iFEpOu
|
||||
#() iFiiii
|
||||
#() iFiiiu
|
||||
#() iFiiip
|
||||
#() iFiiiN
|
||||
#() iFiipp
|
||||
#() iFiuii
|
||||
#() iFilli
|
||||
#() iFipii
|
||||
#() iFipui
|
||||
#() iFipLp
|
||||
#() iFippi
|
||||
#() iFippu
|
||||
#() iFippL
|
||||
#() iFippp
|
||||
#() iFuipp
|
||||
#() iFuuff
|
||||
#() iFuppi
|
||||
#() iFuppp
|
||||
#() iFpiii
|
||||
#() iFpiiu
|
||||
#() iFpiid
|
||||
#() iFpiiL
|
||||
#() iFpiip
|
||||
#() iFpiuL
|
||||
#() iFpiup
|
||||
#() iFpipi
|
||||
#() iFpipC
|
||||
#() iFpipp
|
||||
#() iFpCCC
|
||||
#() iFpWWu
|
||||
#() iFpuiL
|
||||
#() iFpuip
|
||||
#() iFpuui
|
||||
#() iFpuuu
|
||||
#() iFpuup
|
||||
#() iFpuLL
|
||||
#() iFpuLp
|
||||
#() iFpupu
|
||||
#() iFpupV
|
||||
#() iFplip
|
||||
#() iFpLpi
|
||||
#() iFpLpL
|
||||
#() iFpLpp
|
||||
#() iFppii
|
||||
#() iFppiu
|
||||
#() iFppiL
|
||||
#() iFppip
|
||||
#() iFppCC
|
||||
#() iFppuw
|
||||
#() iFppui
|
||||
#() iFppuu
|
||||
#() iFppup
|
||||
#() iFppll
|
||||
#() iFpplp
|
||||
#() iFppLi
|
||||
#() iFppLL
|
||||
#() iFppLp
|
||||
#() iFpppi
|
||||
#() iFpppu
|
||||
#() iFpppL
|
||||
#() iFpppp
|
||||
#() IFEpIi
|
||||
#() IFppip
|
||||
#() IFSIii
|
||||
#() uFEpup
|
||||
#() uFifff
|
||||
#() uFuuuu
|
||||
#() uFpipu
|
||||
#() uFpipp
|
||||
#() uFpCCC
|
||||
#() uFpuip
|
||||
#() uFpuuu
|
||||
#() uFppiu
|
||||
#() uFpppi
|
||||
#() UFpipp
|
||||
#() dFppiL
|
||||
#() lFEpip
|
||||
#() lFEppL
|
||||
#() lFiipL
|
||||
#() lFipiI
|
||||
#() lFipLi
|
||||
#() lFipLI
|
||||
#() lFipLl
|
||||
#() lFpili
|
||||
#() lFpilp
|
||||
#() lFppii
|
||||
#() LFpuuu
|
||||
#() LFpLLp
|
||||
#() LFpLpp
|
||||
#() LFppii
|
||||
#() LFppip
|
||||
#() LFppLL
|
||||
#() LFppLp
|
||||
#() LFpppp
|
||||
#() pFEipp
|
||||
#() pFEupp
|
||||
#() pFEpii
|
||||
#() pFEpip
|
||||
#() pFEppi
|
||||
#() pFEppL
|
||||
#() pFEppp
|
||||
#() pFiiiu
|
||||
#() pFiiup
|
||||
#() pFippL
|
||||
#() pFuiii
|
||||
#() pFulli
|
||||
#() pFdddd
|
||||
#() pFpiii
|
||||
#() pFpiip
|
||||
#() pFpiuu
|
||||
#() pFpiLL
|
||||
#() pFpipi
|
||||
#() pFpipp
|
||||
@@ -462,6 +576,7 @@
|
||||
#() pFpuup
|
||||
#() pFpupi
|
||||
#() pFplpp
|
||||
#() pFpLip
|
||||
#() pFppii
|
||||
#() pFppiL
|
||||
#() pFppip
|
||||
@@ -474,6 +589,7 @@
|
||||
#() pFpppL
|
||||
#() pFpppp
|
||||
#() pFSppi
|
||||
#() vFEiipV
|
||||
#() vFEpuup
|
||||
#() vFEpLLp
|
||||
#() vFEpppp
|
||||
@@ -494,6 +610,7 @@
|
||||
#() vFuiiiu
|
||||
#() vFuiiip
|
||||
#() vFuiiup
|
||||
#() vFuiifi
|
||||
#() vFuiIII
|
||||
#() vFuiuii
|
||||
#() vFuiuiu
|
||||
@@ -530,51 +647,81 @@
|
||||
#() vFfffff
|
||||
#() vFddddp
|
||||
#() vFpiiii
|
||||
#() vFpiipp
|
||||
#() vFpipii
|
||||
#() vFpuipp
|
||||
#() vFpuddd
|
||||
#() vFpddii
|
||||
#() vFpdddd
|
||||
#() vFpliil
|
||||
#() vFppiii
|
||||
#() vFppiip
|
||||
#() vFppiup
|
||||
#() vFppipp
|
||||
#() vFppWui
|
||||
#() vFpppii
|
||||
#() vFppppi
|
||||
#() vFppppp
|
||||
#() iFEippp
|
||||
#() iFEpiii
|
||||
#() iFEpipi
|
||||
#() iFEpipp
|
||||
#() iFEpipV
|
||||
#() iFEpLpp
|
||||
#() iFEpLpV
|
||||
#() iFEppii
|
||||
#() iFEppip
|
||||
#() iFEppiV
|
||||
#() iFEpplp
|
||||
#() iFEpppp
|
||||
#() iFEpppV
|
||||
#() iFiiipu
|
||||
#() iFiiipp
|
||||
#() iFiiupp
|
||||
#() iFiLLLL
|
||||
#() iFipiii
|
||||
#() iFipuip
|
||||
#() iFippLp
|
||||
#() iFipppi
|
||||
#() iFipppp
|
||||
#() iFuppLp
|
||||
#() iFpiiii
|
||||
#() iFpiiiu
|
||||
#() iFpiiiL
|
||||
#() iFpiiip
|
||||
#() iFpiiuu
|
||||
#() iFpiipi
|
||||
#() iFpiipp
|
||||
#() iFpipii
|
||||
#() iFpipiL
|
||||
#() iFpippi
|
||||
#() iFpippp
|
||||
#() iFpCCCC
|
||||
#() iFpuuip
|
||||
#() iFpuuui
|
||||
#() iFpuuup
|
||||
#() iFpuuLL
|
||||
#() iFpuupp
|
||||
#() iFplluu
|
||||
#() iFpLlpp
|
||||
#() iFppiip
|
||||
#() iFppiup
|
||||
#() iFppiLi
|
||||
#() iFppipi
|
||||
#() iFppipp
|
||||
#() iFppupi
|
||||
#() iFppupp
|
||||
#() iFppllp
|
||||
#() iFppLpi
|
||||
#() iFppLpL
|
||||
#() iFppLpp
|
||||
#() iFpppii
|
||||
#() iFpppiL
|
||||
#() iFpppip
|
||||
#() iFpppLi
|
||||
#() iFpppLp
|
||||
#() iFppppi
|
||||
#() iFppppL
|
||||
#() iFppppp
|
||||
#() IFppIII
|
||||
#() uFEppuu
|
||||
@@ -583,10 +730,15 @@
|
||||
#() uFpCCCC
|
||||
#() uFpuuuu
|
||||
#() uFppiip
|
||||
#() uFppipp
|
||||
#() uFpplip
|
||||
#() uFppppp
|
||||
#() lFipLLi
|
||||
#() LFLpppp
|
||||
#() LFpLLLp
|
||||
#() LFpLppL
|
||||
#() LFpLppp
|
||||
#() LFppLLp
|
||||
#() LFppppp
|
||||
#() pFEpiii
|
||||
#() pFEpipL
|
||||
@@ -595,18 +747,24 @@
|
||||
#() pFEppii
|
||||
#() pFEppip
|
||||
#() pFEpppp
|
||||
#() pFipipL
|
||||
#() pFuiiiu
|
||||
#() pFuiipp
|
||||
#() pFpiiii
|
||||
#() pFpiiuu
|
||||
#() pFpiipi
|
||||
#() pFpiipp
|
||||
#() pFpiuuu
|
||||
#() pFpippp
|
||||
#() pFpCuup
|
||||
#() pFpCpup
|
||||
#() pFpCppp
|
||||
#() pFpuiii
|
||||
#() pFpuiip
|
||||
#() pFpuWWW
|
||||
#() pFpuuWW
|
||||
#() pFpuuup
|
||||
#() pFpdddd
|
||||
#() pFppiii
|
||||
#() pFppipi
|
||||
#() pFppipp
|
||||
#() pFppuuu
|
||||
@@ -618,6 +776,7 @@
|
||||
#() pFppppi
|
||||
#() pFppppp
|
||||
#() vFEiiipp
|
||||
#() vFEpuipp
|
||||
#() vFEpLLpp
|
||||
#() vFiiiiii
|
||||
#() vFiiiuil
|
||||
@@ -661,51 +820,92 @@
|
||||
#() vFuppppp
|
||||
#() vFffffff
|
||||
#() vFdddddd
|
||||
#() vFpiiiii
|
||||
#() vFpiiuuu
|
||||
#() vFpiippp
|
||||
#() vFpipipV
|
||||
#() vFpipppi
|
||||
#() vFpudddd
|
||||
#() vFpdddii
|
||||
#() vFpddddd
|
||||
#() vFppiiii
|
||||
#() vFppiiip
|
||||
#() vFppiipi
|
||||
#() vFppilpp
|
||||
#() vFppippi
|
||||
#() vFppupii
|
||||
#() vFpplppi
|
||||
#() vFpplppp
|
||||
#() vFppLppi
|
||||
#() vFppLppp
|
||||
#() vFpppiii
|
||||
#() vFppppii
|
||||
#() vFpppppi
|
||||
#() vFpppppp
|
||||
#() cFppLppi
|
||||
#() iFEiippi
|
||||
#() iFElpppp
|
||||
#() iFEpiipp
|
||||
#() iFEpilpV
|
||||
#() iFEpippi
|
||||
#() iFEpuppp
|
||||
#() iFEppiLi
|
||||
#() iFEppppp
|
||||
#() iFiiiiii
|
||||
#() iFiiiiip
|
||||
#() iFiuiipi
|
||||
#() iFuppipp
|
||||
#() iFipupup
|
||||
#() iFipuppp
|
||||
#() iFuppppp
|
||||
#() iFLppipp
|
||||
#() iFpiiiii
|
||||
#() iFpiiipp
|
||||
#() iFpiippp
|
||||
#() iFpiuuup
|
||||
#() iFpiuupp
|
||||
#() iFpippip
|
||||
#() iFpipppp
|
||||
#() iFpupuui
|
||||
#() iFppiiuu
|
||||
#() iFppiipi
|
||||
#() iFppipii
|
||||
#() iFppipiL
|
||||
#() iFppIppp
|
||||
#() iFppuiii
|
||||
#() iFppuiiL
|
||||
#() iFppuIII
|
||||
#() iFppuupp
|
||||
#() iFppupip
|
||||
#() iFpplppi
|
||||
#() iFppLupp
|
||||
#() iFpppiuu
|
||||
#() iFpppipi
|
||||
#() iFpppipp
|
||||
#() iFpppuii
|
||||
#() iFpppupu
|
||||
#() iFppppii
|
||||
#() iFppppip
|
||||
#() iFppppup
|
||||
#() iFpppppi
|
||||
#() iFpppppL
|
||||
#() iFpppppp
|
||||
#() uFpippup
|
||||
#() uFpppppp
|
||||
#() UFpippup
|
||||
#() lFipLipu
|
||||
#() lFipLipp
|
||||
#() LFpipipi
|
||||
#() LFSpLiip
|
||||
#() pFEpippp
|
||||
#() pFEpuipp
|
||||
#() pFEpuupp
|
||||
#() pFEpuppp
|
||||
#() pFEpLLiN
|
||||
#() pFEppLLp
|
||||
#() pFEpppLp
|
||||
#() pFEppppp
|
||||
#() pFiCiiCi
|
||||
#() pFdddddd
|
||||
#() pFpiiiiu
|
||||
#() pFpippip
|
||||
#() pFpCuuCC
|
||||
@@ -713,6 +913,7 @@
|
||||
#() pFpCuuup
|
||||
#() pFpuuuuu
|
||||
#() pFppiiii
|
||||
#() pFpppppu
|
||||
#() pFpppppp
|
||||
#() pFSpiiii
|
||||
#() vFiiiiiip
|
||||
@@ -750,10 +951,20 @@
|
||||
#() vFuuddiip
|
||||
#() vFuffffff
|
||||
#() vFudddddd
|
||||
#() vFpiiiipp
|
||||
#() vFpiiliip
|
||||
#() vFpipipii
|
||||
#() vFpddiidd
|
||||
#() vFpdddddd
|
||||
#() vFppiiipi
|
||||
#() vFppilppi
|
||||
#() vFppipiip
|
||||
#() vFppipipp
|
||||
#() vFppipppp
|
||||
#() vFppLpppi
|
||||
#() vFppLpppp
|
||||
#() vFpppiiii
|
||||
#() vFpppuuuu
|
||||
#() vFppppipi
|
||||
#() iFEpLiLpV
|
||||
#() iFEppLpIi
|
||||
@@ -761,22 +972,37 @@
|
||||
#() iFEpppppp
|
||||
#() iFiiiiiip
|
||||
#() iFpiiuuiu
|
||||
#() iFpiuiipp
|
||||
#() iFpiupiii
|
||||
#() iFpippppp
|
||||
#() iFpuuiuui
|
||||
#() iFpuupppp
|
||||
#() iFpupuuui
|
||||
#() iFpupLpLi
|
||||
#() iFpuppppp
|
||||
#() iFpLipipi
|
||||
#() iFppiiiip
|
||||
#() iFppiiuui
|
||||
#() iFppiipii
|
||||
#() iFppiipiL
|
||||
#() iFppipiip
|
||||
#() iFppipipi
|
||||
#() iFppippip
|
||||
#() iFppipppi
|
||||
#() iFppipppp
|
||||
#() iFppuipiL
|
||||
#() iFpppiiii
|
||||
#() iFpppiiuu
|
||||
#() iFpppiiup
|
||||
#() iFpppiipi
|
||||
#() iFpppiuwu
|
||||
#() iFpppuiii
|
||||
#() iFppppiii
|
||||
#() iFppppdpi
|
||||
#() iFpppppip
|
||||
#() iFppppppp
|
||||
#() uFuippppp
|
||||
#() pFEpLiiiI
|
||||
#() pFEppppip
|
||||
#() pFifffppp
|
||||
#() pFuupupup
|
||||
@@ -785,6 +1011,7 @@
|
||||
#() pFpCuuwwp
|
||||
#() pFpCuuuuu
|
||||
#() pFppuuppp
|
||||
#() pFpppuupp
|
||||
#() pFppppuuu
|
||||
#() pFpppppuu
|
||||
#() pFppppppp
|
||||
@@ -811,8 +1038,14 @@
|
||||
#() vFpippiiuu
|
||||
#() vFpippiipi
|
||||
#() vFppiiipii
|
||||
#() vFppipipii
|
||||
#() vFppippppi
|
||||
#() vFpplppppi
|
||||
#() vFpplppppp
|
||||
#() vFppppiipi
|
||||
#() iFEpippppp
|
||||
#() iFEpuuLppp
|
||||
#() iFEppppipp
|
||||
#() iFiiiiiiip
|
||||
#() iFiiupiupi
|
||||
#() iFuiifpppp
|
||||
@@ -831,6 +1064,8 @@
|
||||
#() pFpCuwwWWu
|
||||
#() pFpCuuuCup
|
||||
#() pFpppuuLLu
|
||||
#() pFpppppupp
|
||||
#() vFiiiiiiiii
|
||||
#() vFuiiiiiiii
|
||||
#() vFuiiiiiuip
|
||||
#() vFuiiiiiuup
|
||||
@@ -846,23 +1081,29 @@
|
||||
#() vFuffffffff
|
||||
#() vFffuuuufff
|
||||
#() vFddddddddd
|
||||
#() vFpipiuiipp
|
||||
#() vFpipppiipi
|
||||
#() vFppiiipiii
|
||||
#() vFpplpppppi
|
||||
#() vFpppppippp
|
||||
#() iFEpiiiiipi
|
||||
#() iFEppplPPPP
|
||||
#() iFiiiiiiiip
|
||||
#() iFiiiipiiip
|
||||
#() iFipiipippi
|
||||
#() iFdddpppppp
|
||||
#() iFpipLpiiip
|
||||
#() iFppiuiippL
|
||||
#() iFpppiiuuii
|
||||
#() iFpppiipiiu
|
||||
#() iFppppppppu
|
||||
#() iFppppppppp
|
||||
#() pFEppiiuuLi
|
||||
#() pFEppuippuu
|
||||
#() pFpiiiiuuuu
|
||||
#() pFpCuWCCuuu
|
||||
#() pFpuuwwWWww
|
||||
#() pFppiiiiiip
|
||||
#() pFppiiuuuLL
|
||||
#() pFppipppppp
|
||||
#() vFiiiiiiiiiu
|
||||
@@ -880,6 +1121,7 @@
|
||||
#() vFuffiiffiip
|
||||
#() vFuddiiddiip
|
||||
#() vFffffffffff
|
||||
#() vFpppppppppp
|
||||
#() iFiiiiiiiiip
|
||||
#() iFpuupiuiipp
|
||||
#() iFppuuiiiiii
|
||||
@@ -905,6 +1147,7 @@
|
||||
#() iFiiiiiiiiiip
|
||||
#() iFpipllippppp
|
||||
#() iFppppiiuuiiL
|
||||
#() pFEppiiLpppip
|
||||
#() pFEppuiipuuii
|
||||
#() vFuuiiiiiiiuip
|
||||
#() vFuuiiiiiiiuup
|
||||
@@ -912,6 +1155,7 @@
|
||||
#() vFffffffffffff
|
||||
#() vFpipppiiiipii
|
||||
#() vFpippppiiiipi
|
||||
#() vFppiiuuuiupup
|
||||
#() iFEppppiiiiuui
|
||||
#() iFpipppppppppp
|
||||
#() iFpppllipppppp
|
||||
@@ -920,6 +1164,7 @@
|
||||
#() pFpCuuWWwwCCup
|
||||
#() pFpuuuWWWWWWWW
|
||||
#() pFppiiuuuiupLp
|
||||
#() pFpppppppppppp
|
||||
#() vFuiiiiiiiiiuup
|
||||
#() vFuuuuuuuuuuuuu
|
||||
#() vFuffffffffffff
|
||||
@@ -932,20 +1177,26 @@
|
||||
#() vFuddiiddiiddiip
|
||||
#() vFuuiiiiuuiiiiiii
|
||||
#() vFfffffffffffffff
|
||||
#() pFppppppppppppppp
|
||||
#() iFpppppppppppppppp
|
||||
#() pFpppppppppppppppp
|
||||
#() vFppuiiiiipuiiiiiiii
|
||||
#() pFiiiippppppppppppppp
|
||||
#() pFipppppppppppppppppppppp
|
||||
#!defined(NOALIGN) iFEpLp
|
||||
#!defined(NOALIGN) iFEppu
|
||||
#defined(HAVE_LD80BITS) DFD
|
||||
#defined(HAVE_LD80BITS) DFDD
|
||||
#defined(HAVE_LD80BITS) DFDp
|
||||
#!defined(HAVE_LD80BITS) KFK
|
||||
#!defined(HAVE_LD80BITS) KFKK
|
||||
#!defined(HAVE_LD80BITS) KFKp
|
||||
#() iFEv -> iFE
|
||||
#() vFEv -> vFE
|
||||
#() lFEv -> lFE
|
||||
#() LFEv -> LFE
|
||||
#() pFEv -> pFE
|
||||
#() pFppv -> pFpp
|
||||
#() iFEvpp -> iFEpp
|
||||
#() pFEppv -> pFEpp
|
||||
#() iFEpvpp -> iFEppp
|
||||
#() iFEpvvppp -> iFEpppp
|
||||
#() iFEpLvvpp -> iFEpLpp
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedbz2TYPES_H_
|
||||
#define __wrappedbz2TYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef int64_t (*iFpi_t)(void*, int64_t);
|
||||
typedef int64_t (*iFpii_t)(void*, int64_t, int64_t);
|
||||
typedef int64_t (*iFpiii_t)(void*, int64_t, int64_t, int64_t);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(BZ2_bzCompressEnd, iFp_t) \
|
||||
GO(BZ2_bzDecompress, iFp_t) \
|
||||
GO(BZ2_bzDecompressEnd, iFp_t) \
|
||||
GO(BZ2_bzCompress, iFpi_t) \
|
||||
GO(BZ2_bzDecompressInit, iFpii_t) \
|
||||
GO(BZ2_bzCompressInit, iFpiii_t)
|
||||
|
||||
#endif // __wrappedbz2TYPES_H_
|
||||
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedcryptoTYPES_H_
|
||||
#define __wrappedcryptoTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void (*vFp_t)(void*);
|
||||
typedef void* (*pFp_t)(void*);
|
||||
typedef void (*vFpp_t)(void*, void*);
|
||||
typedef void* (*pFpppp_t)(void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpiipp_t)(void*, int64_t, int64_t, void*, void*);
|
||||
typedef int64_t (*iFppppipp_t)(void*, void*, void*, void*, int64_t, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(CRYPTO_set_id_callback, vFp_t) \
|
||||
GO(CRYPTO_set_locking_callback, vFp_t) \
|
||||
GO(sk_new, pFp_t) \
|
||||
GO(sk_pop_free, vFpp_t) \
|
||||
GO(PEM_read_bio_DSAPrivateKey, pFpppp_t) \
|
||||
GO(PEM_read_bio_DSA_PUBKEY, pFpppp_t) \
|
||||
GO(PEM_read_bio_ECPrivateKey, pFpppp_t) \
|
||||
GO(PEM_read_bio_EC_PUBKEY, pFpppp_t) \
|
||||
GO(PEM_read_bio_RSAPrivateKey, pFpppp_t) \
|
||||
GO(PEM_read_bio_RSA_PUBKEY, pFpppp_t) \
|
||||
GO(ENGINE_ctrl, iFpiipp_t) \
|
||||
GO(PEM_write_bio_DSAPrivateKey, iFppppipp_t) \
|
||||
GO(PEM_write_bio_ECPrivateKey, iFppppipp_t) \
|
||||
GO(PEM_write_bio_RSAPrivateKey, iFppppipp_t)
|
||||
|
||||
#endif // __wrappedcryptoTYPES_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedcurlTYPES_H_
|
||||
#define __wrappedcurlTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef uint64_t (*uFpup_t)(void*, uint64_t, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(curl_easy_setopt, uFpup_t)
|
||||
|
||||
#endif // __wrappedcurlTYPES_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappeddbusTYPES_H_
|
||||
#define __wrappeddbusTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void (*vFppp_t)(void*, void*, void*);
|
||||
typedef void (*vFpppp_t)(void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
|
||||
typedef int64_t (*iFppip_t)(void*, void*, int64_t, void*);
|
||||
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
|
||||
typedef int64_t (*iFppppp_t)(void*, void*, void*, void*, void*);
|
||||
typedef int64_t (*iFpppppp_t)(void*, void*, void*, void*, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(dbus_connection_remove_filter, vFppp_t) \
|
||||
GO(dbus_timeout_set_data, vFppp_t) \
|
||||
GO(dbus_watch_set_data, vFppp_t) \
|
||||
GO(dbus_connection_set_dispatch_status_function, vFpppp_t) \
|
||||
GO(dbus_connection_set_wakeup_main_function, vFpppp_t) \
|
||||
GO(dbus_connection_set_data, iFpipp_t) \
|
||||
GO(dbus_message_set_data, iFpipp_t) \
|
||||
GO(dbus_pending_call_set_data, iFpipp_t) \
|
||||
GO(dbus_message_get_args_valist, iFppip_t) \
|
||||
GO(dbus_connection_add_filter, iFpppp_t) \
|
||||
GO(dbus_pending_call_set_notify, iFpppp_t) \
|
||||
GO(dbus_connection_try_register_fallback, iFppppp_t) \
|
||||
GO(dbus_connection_try_register_object_path, iFppppp_t) \
|
||||
GO(dbus_connection_set_timeout_functions, iFpppppp_t) \
|
||||
GO(dbus_connection_set_watch_functions, iFpppppp_t)
|
||||
|
||||
#endif // __wrappeddbusTYPES_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedfontconfigTYPES_H_
|
||||
#define __wrappedfontconfigTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFppiLi_t)(void*, void*, int64_t, uintptr_t, int64_t);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(FcPatternAddWeak, iFppiLi_t)
|
||||
|
||||
#endif // __wrappedfontconfigTYPES_H_
|
||||
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedfreetypeTYPES_H_
|
||||
#define __wrappedfreetypeTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFpplp_t)(void*, void*, intptr_t, void*);
|
||||
typedef int64_t (*iFpuuLppp_t)(void*, uint64_t, uint64_t, uintptr_t, void*, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(FT_Open_Face, iFpplp_t) \
|
||||
GO(FTC_Manager_New, iFpuuLppp_t)
|
||||
|
||||
#endif // __wrappedfreetypeTYPES_H_
|
||||
@@ -0,0 +1,22 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedgnutlsTYPES_H_
|
||||
#define __wrappedgnutlsTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void (*vFp_t)(void*);
|
||||
typedef void (*vFpp_t)(void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(gnutls_global_set_log_function, vFp_t) \
|
||||
GO(gnutls_transport_set_pull_function, vFpp_t) \
|
||||
GO(gnutls_transport_set_push_function, vFpp_t)
|
||||
|
||||
#endif // __wrappedgnutlsTYPES_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedldlinuxTYPES_H_
|
||||
#define __wrappedldlinuxTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void* (*pFp_t)(void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(__tls_get_addr, pFp_t)
|
||||
|
||||
#endif // __wrappedldlinuxTYPES_H_
|
||||
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibasoundTYPES_H_
|
||||
#define __wrappedlibasoundTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef void* (*pFppp_t)(void*, void*, void*);
|
||||
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
|
||||
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
|
||||
typedef void* (*pFpipL_t)(void*, int64_t, void*, uintptr_t);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(snd_dlclose, iFp_t) \
|
||||
GO(snd_lib_error_set_handler, iFp_t) \
|
||||
GO(snd_dlsym, pFppp_t) \
|
||||
GO(snd_async_add_handler, iFpipp_t) \
|
||||
GO(snd_async_add_pcm_handler, iFpppp_t) \
|
||||
GO(snd_dlopen, pFpipL_t)
|
||||
|
||||
#endif // __wrappedlibasoundTYPES_H_
|
||||
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************
|
||||
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
|
||||
*******************************************************************/
|
||||
#ifndef __wrappedlibcTYPES_H_
|
||||
#define __wrappedlibcTYPES_H_
|
||||
|
||||
#ifndef LIBNAME
|
||||
#error You should only #include this file inside a wrapped*.c file
|
||||
#endif
|
||||
#ifndef ADDED_FUNCTIONS
|
||||
#define ADDED_FUNCTIONS()
|
||||
#endif
|
||||
|
||||
typedef void (*vFv_t)(void);
|
||||
typedef void (*vFp_t)(void*);
|
||||
typedef int64_t (*iFp_t)(void*);
|
||||
typedef intptr_t (*lFv_t)(void);
|
||||
typedef uintptr_t (*LFv_t)(void);
|
||||
typedef void (*vFpi_t)(void*, int64_t);
|
||||
typedef void (*vFpu_t)(void*, uint64_t);
|
||||
typedef int64_t (*iFpi_t)(void*, int64_t);
|
||||
typedef int64_t (*iFpL_t)(void*, uintptr_t);
|
||||
typedef int64_t (*iFpp_t)(void*, void*);
|
||||
typedef int64_t (*iFpV_t)(void*, void*);
|
||||
typedef int64_t (*iFSp_t)(void*, void*);
|
||||
typedef void* (*pFip_t)(int64_t, void*);
|
||||
typedef void* (*pFpi_t)(void*, int64_t);
|
||||
typedef void* (*pFpp_t)(void*, void*);
|
||||
typedef void (*vFipV_t)(int64_t, void*, void*);
|
||||
typedef void (*vFpii_t)(void*, int64_t, int64_t);
|
||||
typedef void (*vFpup_t)(void*, uint64_t, void*);
|
||||
typedef int64_t (*iFiip_t)(int64_t, int64_t, void*);
|
||||
typedef int64_t (*iFiiN_t)(int64_t, int64_t, ...);
|
||||
typedef int64_t (*iFipp_t)(int64_t, void*, void*);
|
||||
typedef int64_t (*iFipV_t)(int64_t, void*, void*);
|
||||
typedef int64_t (*iFpLi_t)(void*, uintptr_t, int64_t);
|
||||
typedef int64_t (*iFppi_t)(void*, void*, int64_t);
|
||||
typedef int64_t (*iFppp_t)(void*, void*, void*);
|
||||
typedef int64_t (*iFppV_t)(void*, void*, void*);
|
||||
typedef int64_t (*iFpOu_t)(void*, int32_t, uint64_t);
|
||||
typedef intptr_t (*lFppL_t)(void*, void*, uintptr_t);
|
||||
typedef void* (*pFpip_t)(void*, int64_t, void*);
|
||||
typedef void (*vFiipV_t)(int64_t, int64_t, void*, void*);
|
||||
typedef void (*vFpLLp_t)(void*, uintptr_t, uintptr_t, void*);
|
||||
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
|
||||
typedef int64_t (*iFpipV_t)(void*, int64_t, void*, void*);
|
||||
typedef int64_t (*iFpLpp_t)(void*, uintptr_t, void*, void*);
|
||||
typedef int64_t (*iFpLpV_t)(void*, uintptr_t, void*, void*);
|
||||
typedef int64_t (*iFppii_t)(void*, void*, int64_t, int64_t);
|
||||
typedef int64_t (*iFppiV_t)(void*, void*, int64_t, void*);
|
||||
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
|
||||
typedef void (*vFpLLpp_t)(void*, uintptr_t, uintptr_t, void*, void*);
|
||||
typedef int64_t (*iFiippi_t)(int64_t, int64_t, void*, void*, int64_t);
|
||||
typedef int64_t (*iFpilpV_t)(void*, int64_t, intptr_t, void*, void*);
|
||||
typedef int64_t (*iFpuppp_t)(void*, uint64_t, void*, void*, void*);
|
||||
typedef void* (*pFpLLiN_t)(void*, uintptr_t, uintptr_t, int64_t, ...);
|
||||
typedef void* (*pFppLLp_t)(void*, void*, uintptr_t, uintptr_t, void*);
|
||||
typedef void* (*pFpppLp_t)(void*, void*, void*, uintptr_t, void*);
|
||||
typedef int64_t (*iFpLiLpV_t)(void*, uintptr_t, int64_t, uintptr_t, void*, void*);
|
||||
typedef void* (*pFpLiiiI_t)(void*, uintptr_t, int64_t, int64_t, int64_t, int64_t);
|
||||
typedef int64_t (*iFpippppp_t)(void*, int64_t, void*, void*, void*, void*, void*);
|
||||
|
||||
#define SUPER() ADDED_FUNCTIONS() \
|
||||
GO(__stack_chk_fail, vFv_t) \
|
||||
GO(_ITM_deregisterTMCloneTable, vFp_t) \
|
||||
GO(__cxa_finalize, vFp_t) \
|
||||
GO(__sigsetjmp, iFp_t) \
|
||||
GO(_setjmp, iFp_t) \
|
||||
GO(getcontext, iFp_t) \
|
||||
GO(setjmp, iFp_t) \
|
||||
GO(fork, lFv_t) \
|
||||
GO(syscall, LFv_t) \
|
||||
GO(__longjmp_chk, vFpi_t) \
|
||||
GO(_longjmp, vFpi_t) \
|
||||
GO(longjmp, vFpi_t) \
|
||||
GO(_ITM_registerTMCloneTable, vFpu_t) \
|
||||
GO(backtrace, iFpi_t) \
|
||||
GO(munmap, iFpL_t) \
|
||||
GO(__vprintf_chk, iFpp_t) \
|
||||
GO(dl_iterate_phdr, iFpp_t) \
|
||||
GO(execvp, iFpp_t) \
|
||||
GO(sigaltstack, iFpp_t) \
|
||||
GO(swapcontext, iFpp_t) \
|
||||
GO(vprintf, iFpp_t) \
|
||||
GO(execlp, iFpV_t) \
|
||||
GO(printf, iFpV_t) \
|
||||
GO(_IO_file_stat, iFSp_t) \
|
||||
GO(__sysv_signal, pFip_t) \
|
||||
GO(signal, pFip_t) \
|
||||
GO(sigset, pFip_t) \
|
||||
GO(sysv_signal, pFip_t) \
|
||||
GO(backtrace_symbols, pFpi_t) \
|
||||
GO(__realpath_chk, pFpp_t) \
|
||||
GO(fopen, pFpp_t) \
|
||||
GO(fopen64, pFpp_t) \
|
||||
GO(realpath, pFpp_t) \
|
||||
GO(syslog, vFipV_t) \
|
||||
GO(backtrace_symbols_fd, vFpii_t) \
|
||||
GO(_ITM_addUserCommitAction, vFpup_t) \
|
||||
GO(__fxstat, iFiip_t) \
|
||||
GO(__fxstat64, iFiip_t) \
|
||||
GO(__fcntl, iFiiN_t) \
|
||||
GO(fcntl, iFiiN_t) \
|
||||
GO(fcntl64, iFiiN_t) \
|
||||
GO(__lxstat, iFipp_t) \
|
||||
GO(__lxstat64, iFipp_t) \
|
||||
GO(__sigaction, iFipp_t) \
|
||||
GO(__xstat, iFipp_t) \
|
||||
GO(__xstat64, iFipp_t) \
|
||||
GO(sigaction, iFipp_t) \
|
||||
GO(__printf_chk, iFipV_t) \
|
||||
GO(mprotect, iFpLi_t) \
|
||||
GO(ftw, iFppi_t) \
|
||||
GO(ftw64, iFppi_t) \
|
||||
GO(__cxa_atexit, iFppp_t) \
|
||||
GO(__isoc99_vsscanf, iFppp_t) \
|
||||
GO(__vfprintf_chk, iFppp_t) \
|
||||
GO(__vsscanf, iFppp_t) \
|
||||
GO(vasprintf, iFppp_t) \
|
||||
GO(vfprintf, iFppp_t) \
|
||||
GO(vsscanf, iFppp_t) \
|
||||
GO(__isoc99_fscanf, iFppV_t) \
|
||||
GO(__isoc99_sscanf, iFppV_t) \
|
||||
GO(fprintf, iFppV_t) \
|
||||
GO(fscanf, iFppV_t) \
|
||||
GO(sprintf, iFppV_t) \
|
||||
GO(sscanf, iFppV_t) \
|
||||
GO(swscanf, iFppV_t) \
|
||||
GO(__open, iFpOu_t) \
|
||||
GO(open, iFpOu_t) \
|
||||
GO(open64, iFpOu_t) \
|
||||
GO(readlink, lFppL_t) \
|
||||
GO(fts_open, pFpip_t) \
|
||||
GO(__syslog_chk, vFiipV_t) \
|
||||
GO(qsort, vFpLLp_t) \
|
||||
GO(__vasprintf_chk, iFpipp_t) \
|
||||
GO(glob, iFpipp_t) \
|
||||
GO(glob64, iFpipp_t) \
|
||||
GO(__fprintf_chk, iFpipV_t) \
|
||||
GO(__vsnprintf, iFpLpp_t) \
|
||||
GO(__vsnprintf_chk, iFpLpp_t) \
|
||||
GO(vsnprintf, iFpLpp_t) \
|
||||
GO(__snprintf, iFpLpV_t) \
|
||||
GO(snprintf, iFpLpV_t) \
|
||||
GO(swprintf, iFpLpV_t) \
|
||||
GO(nftw64, iFppii_t) \
|
||||
GO(makecontext, iFppiV_t) \
|
||||
GO(__register_atfork, iFpppp_t) \
|
||||
GO(__vsprintf_chk, iFpppp_t) \
|
||||
GO(scandir, iFpppp_t) \
|
||||
GO(scandir64, iFpppp_t) \
|
||||
GO(vsprintf, iFpppp_t) \
|
||||
GO(qsort_r, vFpLLpp_t) \
|
||||
GO(__fxstatat, iFiippi_t) \
|
||||
GO(__fxstatat64, iFiippi_t) \
|
||||
GO(__sprintf_chk, iFpilpV_t) \
|
||||
GO(__vswprintf_chk, iFpuppp_t) \
|
||||
GO(vswprintf, iFpuppp_t) \
|
||||
GO(mremap, pFpLLiN_t) \
|
||||
GO(bsearch, pFppLLp_t) \
|
||||
GO(lfind, pFpppLp_t) \
|
||||
GO(lsearch, pFpppLp_t) \
|
||||
GO(__snprintf_chk, iFpLiLpV_t) \
|
||||
GO(__swprintf_chk, iFpLiLpV_t) \
|
||||
GO(mmap, pFpLiiiI_t) \
|
||||
GO(mmap64, pFpLiiiI_t) \
|
||||
GO(__libc_start_main, iFpippppp_t)
|
||||
|
||||
#endif // __wrappedlibcTYPES_H_
|
||||
Loaded 100 of 218 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user