mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-08 10:10:25 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60c6858916 | ||
|
|
c5e085bc96 | ||
|
|
8dc669bc33 | ||
|
|
8aed75a338 | ||
|
|
e486e2ce8d | ||
|
|
a1705da6da | ||
|
|
0092a029c4 | ||
|
|
176ef90258 | ||
|
|
f82a6b7b41 | ||
|
|
c79c42b62d | ||
|
|
91dd7adbfa | ||
|
|
de82f07277 | ||
|
|
0c8e0b6708 | ||
|
|
c71a840e74 | ||
|
|
2b5c25ef17 | ||
|
|
da34156267 | ||
|
|
113ef45c6c | ||
|
|
67dd40dc08 | ||
|
|
1e0fee739e | ||
|
|
d59a98ffe6 | ||
|
|
5e9429afe8 | ||
|
|
31fd0451d0 | ||
|
|
b56be08f95 | ||
|
|
b1923cadb5 | ||
|
|
0a955c1020 | ||
|
|
791efc9e79 | ||
|
|
f9bc94bfb8 | ||
|
|
72119ddfa4 | ||
|
|
d4afca9b5a | ||
|
|
219ac40a7d | ||
|
|
b9378fe4c1 | ||
|
|
3c05822011 | ||
|
|
02cad7b5fe | ||
|
|
1a85ec5fdb | ||
|
|
3e19cfe58e | ||
|
|
3d3c7437be | ||
|
|
c4b57774f0 | ||
|
|
f7acded7a1 | ||
|
|
cabcca2e31 | ||
|
|
cc3237a77d | ||
|
|
b65e02420f | ||
|
|
5a7761c294 | ||
|
|
ad332494d0 | ||
|
|
eb212cd27e | ||
|
|
b604dd0bcc | ||
|
|
c0b879c998 | ||
|
|
e473af1635 | ||
|
|
8d9c6b2d01 | ||
|
|
7cdcb6c4ef | ||
|
|
ca44d84e55 | ||
|
|
e73a3c3376 | ||
|
|
1f9973e623 | ||
|
|
9077f3d675 | ||
|
|
ce61d27d8d | ||
|
|
5c1dbc0104 | ||
|
|
aa55f67ee3 | ||
|
|
9516694c35 | ||
|
|
c6a9f239c4 | ||
|
|
a922acc4dd | ||
|
|
bfef8c9bbe | ||
|
|
3fe2843bb3 | ||
|
|
42b8378988 | ||
|
|
c6bd721d2e | ||
|
|
83eedef999 | ||
|
|
1411e7f9f6 | ||
|
|
5d42d9212f | ||
|
|
4a1e05524a | ||
|
|
fb5ac9c4cd | ||
|
|
ed4e33d888 | ||
|
|
c6dd73065d | ||
|
|
9ef48de1a8 | ||
|
|
692ad43285 | ||
|
|
d06ff478d1 | ||
|
|
83db04cdce | ||
|
|
d0a724bb08 | ||
|
|
8e9ac1b9ac | ||
|
|
272d4efd4b | ||
|
|
4610f451e9 | ||
|
|
0810859c21 | ||
|
|
93c447051c | ||
|
|
60b3f042a8 | ||
|
|
c5632360d6 | ||
|
|
a379b4aab8 | ||
|
|
3b8d6ef208 | ||
|
|
9705d5e38b | ||
|
|
2e59b56f16 | ||
|
|
d9f9e8e57a | ||
|
|
33a8befbcf | ||
|
|
4f66a419e3 | ||
|
|
65992746d3 | ||
|
|
cbd4c64084 | ||
|
|
081be61f88 | ||
|
|
b89ca87280 | ||
|
|
ca84f10921 | ||
|
|
2200c4af6b | ||
|
|
838dfa453c | ||
|
|
6f3d636226 | ||
|
|
f03792619a | ||
|
|
21b3292fff | ||
|
|
39ebeb2401 | ||
|
|
8f4e8ed1e7 | ||
|
|
0e10ead81a | ||
|
|
476612d8f8 | ||
|
|
bd769c9261 | ||
|
|
831f78a389 | ||
|
|
920edce73e | ||
|
|
7dc7b002c5 | ||
|
|
c74c9bd693 | ||
|
|
1daf15c525 | ||
|
|
108949345f | ||
|
|
69eb309031 | ||
|
|
e7f0c8cbe1 | ||
|
|
9c8b663d5b | ||
|
|
8309b63fb1 | ||
|
|
6d6de880eb | ||
|
|
a65bf79ad9 | ||
|
|
c192188b42 | ||
|
|
a3516ce655 | ||
|
|
8481db4735 | ||
|
|
b6390c3dbd | ||
|
|
0f914cf747 | ||
|
|
5fab7d2993 | ||
|
|
faee142876 | ||
|
|
215c63233a | ||
|
|
e5afcd14a9 | ||
|
|
96a7d1e7ec | ||
|
|
2d2a65b616 | ||
|
|
b5d32fe271 | ||
|
|
8a5a69818e | ||
|
|
56701220e9 | ||
|
|
6bf434a7ab | ||
|
|
d1e767d30c | ||
|
|
4874df25a2 | ||
|
|
f43868e4dc | ||
|
|
bc8227d2bd | ||
|
|
09e748d6c9 | ||
|
|
4038ad5ce5 | ||
|
|
973864e045 | ||
|
|
af694b57a2 | ||
|
|
07be0c6ef4 | ||
|
|
78a336c092 | ||
|
|
649c0f8055 | ||
|
|
87b66b8db8 | ||
|
|
a4ffa3de7a | ||
|
|
dd111f55f6 | ||
|
|
5db6264d8f | ||
|
|
4ce63c8caf | ||
|
|
727f8b1d9b | ||
|
|
35f2bcf296 | ||
|
|
7ebfe84489 | ||
|
|
4e645debaa | ||
|
|
821ab99bf7 | ||
|
|
282e242f5e | ||
|
|
13deb8d8d7 | ||
|
|
389992c330 | ||
|
|
0753c52bed | ||
|
|
24ce9b0f8d | ||
|
|
6e6f8412a5 | ||
|
|
853cdcdd31 | ||
|
|
f24ec20623 | ||
|
|
cdc7d695e9 | ||
|
|
d1cf754c6e | ||
|
|
d1f63fe260 | ||
|
|
53eee70c03 | ||
|
|
7b73ba551e | ||
|
|
af1176274a | ||
|
|
4c2ef9947a | ||
|
|
db7c9e96ea | ||
|
|
ee5398b3be | ||
|
|
3d3ab0fedc | ||
|
|
d21efb51ce | ||
|
|
bd4c742212 | ||
|
|
c821fd938c | ||
|
|
977caba4ca | ||
|
|
8b167a70b8 | ||
|
|
ecca96c03e | ||
|
|
49231a593a | ||
|
|
0338899804 | ||
|
|
810c2250c4 | ||
|
|
5ed210f0f3 | ||
|
|
7508390747 | ||
|
|
67620b7948 | ||
|
|
6c0500d1b6 | ||
|
|
7144efff4e | ||
|
|
3ae31c34f6 | ||
|
|
bc5072ed54 | ||
|
|
2aa7c45ca2 | ||
|
|
73467dc523 | ||
|
|
4ff744ef89 | ||
|
|
b8722b3537 | ||
|
|
caed2ae757 | ||
|
|
5ffdb8eeb4 | ||
|
|
90445f7f1d | ||
|
|
5a298c165e | ||
|
|
63ba377f6f | ||
|
|
a15cdb4c1d | ||
|
|
dff14a868f | ||
|
|
4304301701 | ||
|
|
2dd31b0a44 | ||
|
|
23e01808a2 | ||
|
|
b8300add62 | ||
|
|
97cb1e2080 | ||
|
|
e9d6735e52 | ||
|
|
9d8381041d | ||
|
|
5cf4226c13 | ||
|
|
5bb3d8a24d | ||
|
|
1de683efa4 | ||
|
|
3e705be6c8 | ||
|
|
6548ec1b43 | ||
|
|
e739a74705 | ||
|
|
c0d401fbfc | ||
|
|
7b813d03b9 | ||
|
|
93d06e8680 | ||
|
|
7f22b33f5a | ||
|
|
ceaacba1c2 | ||
|
|
6bee1dcecd | ||
|
|
3c28048038 | ||
|
|
fb02ae0e9a | ||
|
|
ffb293fe0a | ||
|
|
f46522572e | ||
|
|
2ecb87ddc3 | ||
|
|
a34530ebb7 | ||
|
|
0973e7009e | ||
|
|
d0d18441cf | ||
|
|
3f1c37aa76 | ||
|
|
8165342670 | ||
|
|
686c68a90d | ||
|
|
86dbf089cc | ||
|
|
9f3ea84b57 | ||
|
|
3f007d2dbb | ||
|
|
cde68af79a | ||
|
|
574e70642b | ||
|
|
ae156d9326 | ||
|
|
c08268d0ae | ||
|
|
0e4d031054 | ||
|
|
de15ee057a | ||
|
|
1d873cc701 | ||
|
|
bcde60b9e8 | ||
|
|
d6d2b2e756 | ||
|
|
4276573f67 | ||
|
|
fa3481ea8e | ||
|
|
ac54eceea5 | ||
|
|
e1c29bf2af | ||
|
|
0fe560ed7f | ||
|
|
23269040a6 | ||
|
|
b03649748a | ||
|
|
06851f8b98 | ||
|
|
893fc7c940 | ||
|
|
3819aecf07 | ||
|
|
a186b22d6e | ||
|
|
a43186d137 | ||
|
|
554f4889bc | ||
|
|
b584832e75 | ||
|
|
299c911330 | ||
|
|
6318b592a3 | ||
|
|
2b7e7fe6f6 | ||
|
|
bb8983b48a |
No files matched your search
@@ -13,9 +13,9 @@ on:
|
||||
- X64
|
||||
- GENERIC_ARM
|
||||
- PHYTIUM
|
||||
- RK3288
|
||||
- RK3326
|
||||
- RK3399
|
||||
- RK3588
|
||||
- RPI4ARM64
|
||||
- SD845
|
||||
- TEGRAX1
|
||||
|
||||
@@ -27,21 +27,21 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3288, PHYTIUM, SD845]
|
||||
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845]
|
||||
type: [Release, Trace]
|
||||
os: [ubuntu-latest]
|
||||
include:
|
||||
- platform: TEGRAX1
|
||||
type: Release
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
- platform: TEGRAX1
|
||||
type: Trace
|
||||
os: ubuntu-18.04
|
||||
os: ubuntu-20.04
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: "Checkout Box64 Repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: "Environment preparation"
|
||||
run: |
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
ctest -j$(nproc)
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: box64-${{ matrix.platform }}-${{ matrix.type }}
|
||||
path: build/box64
|
||||
+56
-14
@@ -5,9 +5,11 @@ cmake_policy(SET CMP0065 NEW)
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
|
||||
|
||||
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
|
||||
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(RK3588 "Set to ON if targeting an Rockchip RK3588(S) based device" ${RK3588})
|
||||
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
|
||||
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
@@ -21,6 +23,7 @@ option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACH
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
|
||||
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
|
||||
|
||||
if(LARCH64)
|
||||
@@ -40,14 +43,17 @@ if(PPC64LE)
|
||||
set(ARM_DYNAREC OFF CACHE BOOL "")
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR ODROIDN2 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A OR M1)
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A OR M1)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3399 OR ODROIDN2 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A)
|
||||
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A)
|
||||
set(PAGE16K OFF CACHE BOOL "")
|
||||
endif()
|
||||
if(RK3588)
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
if(M1 OR LARCH64)
|
||||
set(PAGE16K ON CACHE BOOL "")
|
||||
endif()
|
||||
@@ -92,7 +98,12 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
if(RPI4ARM64)
|
||||
if(RPI3ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI3ARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a53)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a53")
|
||||
elseif(RPI4ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
|
||||
@@ -103,8 +114,13 @@ elseif(RK3326)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto")
|
||||
elseif(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72.cortex-a53+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72.cortex-a53+crypto")
|
||||
elseif(RK3588)
|
||||
add_definitions(-DRK3588)
|
||||
add_definitions(-pipe -mcpu=cortex-a76.cortex-a55+crypto)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -mcpu=cortex-a76.cortex-a55+crypto")
|
||||
elseif(ODROIDN2)
|
||||
add_definitions(-DODROIDN2)
|
||||
add_definitions(-march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto)
|
||||
@@ -145,6 +161,10 @@ elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
|
||||
endif()
|
||||
|
||||
if(BAD_SIGNAL)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
endif()
|
||||
|
||||
if(PAGE8K)
|
||||
add_definitions(-DPAGE8K)
|
||||
endif()
|
||||
@@ -168,7 +188,7 @@ else()
|
||||
endif()
|
||||
|
||||
#set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
|
||||
set(BOX64_ELF_ADDRESS "0x64800000") #low address
|
||||
set(BOX64_ELF_ADDRESS "0x34800000") #low address
|
||||
|
||||
if(LD80BITS)
|
||||
add_definitions(-DHAVE_LD80BITS)
|
||||
@@ -281,6 +301,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX64_ROOT}/src/tools/gtkclass.c"
|
||||
"${BOX64_ROOT}/src/tools/pathcoll.c"
|
||||
"${BOX64_ROOT}/src/tools/fileutils.c"
|
||||
"${BOX64_ROOT}/src/tools/rcfile.c"
|
||||
"${BOX64_ROOT}/src/tools/wine_tools.c"
|
||||
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
@@ -294,6 +315,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcairogobject.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
@@ -337,12 +359,14 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibdrm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibglx.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibibus.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
|
||||
@@ -377,11 +401,19 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbdri3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbglx.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbicccm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbimage.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbpresent.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrender.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrenderutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshape.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbsync.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbutil.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxinerama.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxkb.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcomposite.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxcursor.c"
|
||||
@@ -393,6 +425,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxi.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxmu.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxpm.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxpresent.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxrandr.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxrender.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlibxss.c"
|
||||
@@ -434,6 +467,7 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtbbmalloc.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
@@ -453,15 +487,20 @@ set(WRAPPEDS
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedlber.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
|
||||
"${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9.c"
|
||||
)
|
||||
|
||||
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
|
||||
# If BOX64_ROOT contains a ".c", the build breaks...
|
||||
string(REPLACE ".c" "_private.h" MODROOT ${BOX64_ROOT})
|
||||
set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_genvate.h")
|
||||
foreach(A ${WRAPPEDS})
|
||||
string(REGEX REPLACE ".c$" "_private.h" B ${A})
|
||||
string(REPLACE ".c" "_private.h" C ${A})
|
||||
string(REPLACE "${MODROOT}" "${BOX64_ROOT}" B ${C})
|
||||
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
|
||||
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
|
||||
endforeach()
|
||||
|
||||
|
||||
set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/wrapped/generated/wrapper.h")
|
||||
|
||||
add_custom_command(
|
||||
@@ -571,13 +610,13 @@ endif()
|
||||
if(DYNAREC)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX64_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
|
||||
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
endif()
|
||||
@@ -632,6 +671,7 @@ if(NOT _x86 AND NOT _x86_64)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET uninstall)
|
||||
@@ -749,17 +789,19 @@ add_test(linkingIndirectNoversion ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINAR
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(linkingIndirectVersion ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
add_test(sse_asm ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile16.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(sse ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
set_tests_properties(sse_asm PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
|
||||
|
||||
add_test(sse_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile17.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0")
|
||||
set_tests_properties(sse_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
|
||||
|
||||
add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
|
||||
|
||||
Vendored
+69
@@ -1,3 +1,72 @@
|
||||
box64 (0.2.2) unstable; urgency=low
|
||||
|
||||
* Added a hacked version for overriden malloc/free functions, enabling libcef (and derivative) to work.
|
||||
* Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters
|
||||
* Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup)
|
||||
* Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!)
|
||||
* Improved memory protection tracking and signal handling, again
|
||||
* Simplified mutex handling (faster, cleaner)
|
||||
* Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case)
|
||||
* Added d3dadaptor9 wrapping
|
||||
* More wrapped libs (especially on the gtk familly)
|
||||
* Improved/fixed some Syscall handling
|
||||
* Refactored Strong Memory Model emulation (faster and more accurate)
|
||||
* Added some more opcode to ARM64 Dynarec, and fixed some other
|
||||
* Some fixes to flags handling in the Dynarec on some special cases
|
||||
* Refactor library loading/unloading, with refcount.
|
||||
* Some special cases fixes for dlopen (fixes deadcells, maybe others too)
|
||||
* Improved mmap mapping, espcially with MAP_32BITS flag
|
||||
* More wrapped functions and syscalls
|
||||
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
|
||||
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
|
||||
* More support on the RV64 port
|
||||
* More support to build under musl environment
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
|
||||
|
||||
box64 (0.2.0) unstable; urgency=low
|
||||
|
||||
* Wrapped more vulkan function, dxvk 2.0 now works
|
||||
* Added support for overriden malloc/free functions
|
||||
* Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size)
|
||||
* Improved elf loader
|
||||
* Improved dlsym handling with RTLD_NEXT
|
||||
* Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
|
||||
* Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world
|
||||
* Added BOX64_ROLLING_LOG to have details log only on crash
|
||||
* Work on alignment for some of pthread structures
|
||||
* More wrapped libraries in the gtk family
|
||||
* Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle)
|
||||
* Improved TLS Size handling (Unity3D games now works)
|
||||
* More PageSize Compile options
|
||||
* Improved execv family of function to have better box64 integration
|
||||
* Added support for wrapped libfuse so AppImage works
|
||||
* Adjusted the binfmt integration so AppImage are automaticaly picked
|
||||
* Improved FAudio, SDL2, GL (and more) wrapping
|
||||
* More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load
|
||||
* Improved Signal Handling and memory protection traking
|
||||
* Some signature fixes to some wrapped functions (in libc)
|
||||
* Added more syscalls
|
||||
* Added a lot of new opcodes to the ARM64 Dynarec
|
||||
* docs: add instructions for Debian-based Linux by @ryanfortner in #306
|
||||
* Fix typos and arch type string by @archanox in #321
|
||||
* Fix grammar by @Jai-JAP in #326
|
||||
* Enable 64k page size by @martinmanyhats in #334
|
||||
* Align address when call mprotect by @wannacu in #336
|
||||
* Add wrapped functions needed for 'ls -l'. by @stiltr in #294
|
||||
* add 18.04 tegra X1 github actions by @theofficialgman in #345
|
||||
* change order of matrix (to preview better under checkmark dropdown by @theofficialgman in #346
|
||||
* Backport SDL_DYNAPI_entry wrapper from box86. by @JohnnyonFlame in #374
|
||||
* Add SW64 base support by @wannacu in #382
|
||||
* fix overzealous replace in wrappers pathnames by @NobodyNada in #415
|
||||
* Create X64WINE.md by @WheezyE in #423
|
||||
* src: asm: Rename lr & fp registers to their x-equivalents by @fredldotme in #426
|
||||
* Malloc override by @ptitSeb in #437
|
||||
* Remove dynablocklist by @ptitSeb in #438
|
||||
* Fix Pkgbuilds by @Jai-JAP in #452
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 17 Nov 2022 11:20:33 -0500
|
||||
|
||||
box64 (0.1.8) unstable; urgency=low
|
||||
|
||||
* Added an option to get generated -NAN on SSE2 operation
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
v0.2.2
|
||||
======
|
||||
* Added a hacked version for overriden malloc/free functions, enabling libcef (and derivative) to work.
|
||||
=> Steam Large mode and new BigPicture are working
|
||||
=> Heroic Launcher is working
|
||||
* Added rcfile handling: box64 now read `/etc/box64.box64rc` and `~/.box64rc` and apply per process parameters
|
||||
=> Every program can be finetuned, for speed or just to make them work
|
||||
* Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup)
|
||||
* Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!)
|
||||
* Improved memory protection tracking and signal handling, again
|
||||
* Box64 now return a custom name for the CPU instal of P4, build with Box64 and the cpu name it's running on
|
||||
* Simplified mutex handling (faster, cleaner)
|
||||
* Reduce memory used by the memory tracking (memory almost divide by 4 is some critical use case)
|
||||
* Added d3dadapter9 wrapping
|
||||
=> gallium nine is now supported on box64 too
|
||||
* More wrapped libs (especially on the gtk familly)
|
||||
* Improved/fixed some Syscall handling
|
||||
* Refactored Strong Memory Model emulation (faster and more accurate)
|
||||
* Added some more opcode to ARM64 Dynarec, and fixed some other
|
||||
* Some fixes to flags handling in the Dynarec on some special cases
|
||||
* Refactor library loading/unloading, with refcount.
|
||||
* Some special cases fixes for dlopen (fixes deadcells, maybe others too)
|
||||
* Improved mmap mapping, espcially with MAP_32BITS flag
|
||||
* More wrapped functions and syscalls
|
||||
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
|
||||
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
|
||||
* More support on the RV64 port
|
||||
* More support to build under musl environment
|
||||
|
||||
v0.2.0
|
||||
======
|
||||
* Wrapped more vulkan function, dxvk 2.0 now works
|
||||
|
||||
+60
-2
@@ -6,7 +6,7 @@ You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to i
|
||||
|
||||
```
|
||||
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
|
||||
wget -O- https://ryanfortner.github.io/box64-debs/KEY.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/box64-debs-archive-keyring.gpg
|
||||
wget -O- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/box64-debs-archive-keyring.gpg
|
||||
sudo apt update && sudo apt install box64 -y
|
||||
```
|
||||
|
||||
@@ -27,7 +27,47 @@ If it's the first install, you also need:
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for PI4
|
||||
#### for RK3588 / RK3588S
|
||||
|
||||
Using a 64bit OS:
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
If it's the first install, you also need:
|
||||
```
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for Raspberry Pi 3
|
||||
|
||||
Warning, you need a 64bit OS:
|
||||
|
||||
If building on the Pi, you will also need a large swap (3 GB+)
|
||||
[optionally reduce GPU memory to a minimum (e.g. 16 MB) using `raspi-config`
|
||||
(and reboot) before starting the build]:
|
||||
|
||||
You can use e.g. '`make -j4`' to speed up the build, but on a Pi 3 with 1GB memory you will likely
|
||||
run out of memory at some point and need to run the build again.
|
||||
Still, this can be faster if your build is attended.
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DRPI3ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make
|
||||
# or e.g. make -j4
|
||||
sudo make install
|
||||
```
|
||||
If it's the first install, you also need:
|
||||
```
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for Raspberry Pi 4
|
||||
|
||||
Warning, you need a 64bit OS:
|
||||
|
||||
@@ -59,6 +99,22 @@ If it's the first install, you also need:
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for ODROID N2/N2+
|
||||
|
||||
Using a 64bit OS:
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box64
|
||||
cd box64
|
||||
mkdir build; cd build; cmake .. -DODROIDN2=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
sudo make install
|
||||
```
|
||||
If it's the first install, you also need:
|
||||
```
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
#### for Snapdragon 845
|
||||
|
||||
Using a 64bit OS:
|
||||
@@ -113,6 +169,8 @@ sudo systemctl restart systemd-binfmt
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
|
||||
|
||||
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
|
||||
|
||||
#### for LoongArch
|
||||
|
||||
Using a 64bit OS:
|
||||
|
||||
@@ -58,6 +58,15 @@ Note that many installer (mojo setup based) will fall back to "x86" when detecti
|
||||
|
||||
----
|
||||
|
||||
Notes about Box64 configuration
|
||||
----
|
||||
|
||||
Box64 now have configurations files. There are 2 files loaded. `/etc/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
|
||||
Note that the priority is: `~/.bashrc` > `/etc/box64.box64rc` > command line
|
||||
So, your settings in `~/.bashrc` may override the setting from your command line...
|
||||
|
||||
----
|
||||
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
|
||||
+117
-44
@@ -3,15 +3,16 @@ Usage
|
||||
----
|
||||
|
||||
There are many environment variables to control Box64 behaviour.
|
||||
Env. var with * can also be put inside box64rc files
|
||||
|
||||
#### BOX64_LOG
|
||||
#### BOX64_LOG *
|
||||
Controls the Verbosity level of the logs
|
||||
* 0: NONE : No message (except some fatal error). (Default.)
|
||||
* 1: INFO : Show some minimum log (Example: librairies not found)
|
||||
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
|
||||
* 3: DUMP : All DEBUG plus DUMP of all ELF Info.
|
||||
|
||||
#### BOX64_ROLLING_LOG
|
||||
#### BOX64_ROLLING_LOG *
|
||||
Show last few wrapped function call when a Signal is caught
|
||||
* 0: No last function call printed (Default.)
|
||||
* 1: Last 16 wrapped functions calls printed when a signal is printed. Incompatible with BOX64_LOG>1 (may need BOX64_SHOWSEGV=1 also)
|
||||
@@ -22,146 +23,196 @@ Disables Box64 printing its version and build
|
||||
* 0 : Enable printing its banner. (Default.)
|
||||
* 1 : Disable printing its banner.
|
||||
|
||||
#### BOX64_LD_LIBRARY_PATH
|
||||
#### BOX64_LD_LIBRARY_PATH *
|
||||
Path to look for x86_64 libraries. Default is current folder and `lib` in current folder.
|
||||
Also, `/usr/lib/x86_64-linux-gnu` and `/lib/x86_64-linux-gnu` are added if they exist.
|
||||
|
||||
#### BOX64_PATH
|
||||
#### BOX64_PATH *
|
||||
Path to look for x86_64 executable. Default is current folder and `bin` in current folder.
|
||||
|
||||
#### BOX64_DLSYM_ERROR
|
||||
#### BOX64_DLSYM_ERROR *
|
||||
Enables/Disables the logging of `dlsym` errors.
|
||||
* 0 : Don't log `dlsym` errors. (Default.)
|
||||
* 1 : Log dlsym errors.
|
||||
|
||||
#### BOX64_TRACE_FILE
|
||||
#### BOX64_TRACE_FILE *
|
||||
Send all log and trace to a file instead of `stdout`
|
||||
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
|
||||
End the filename with `+` to have thetrace appended instead of overwriten
|
||||
Use `stderr` to use this instead of default `stdout`
|
||||
|
||||
#### BOX64_TRACE
|
||||
#### BOX64_TRACE *
|
||||
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
|
||||
* 0 : No trace. (Default.)
|
||||
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done.
|
||||
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found).
|
||||
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
|
||||
|
||||
#### BOX64_TRACE_INIT
|
||||
#### BOX64_TRACE_INIT *
|
||||
Use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
|
||||
* 0 : No trace. (Default.)
|
||||
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
|
||||
|
||||
#### BOX64_TRACE_START
|
||||
#### BOX64_TRACE_START *
|
||||
Only on builds with trace enabled.
|
||||
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`).
|
||||
|
||||
#### BOX64_TRACE_XMM
|
||||
#### BOX64_TRACE_XMM *
|
||||
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
|
||||
#### 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.)
|
||||
* 0 : The EMM (i.e. MMX) register will not be logged with the general and x86 registers. (Default.)
|
||||
* 1 : Dump the EMM registers.
|
||||
|
||||
#### BOX64_TRACE_COLOR
|
||||
#### 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
|
||||
#### BOX64_LOAD_ADDR *
|
||||
Try to load at 0xXXXXXX main binary (if binary is a PIE)
|
||||
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
|
||||
|
||||
#### BOX64_NOSIGSEGV
|
||||
#### BOX64_NOSIGSEGV *
|
||||
Disable handling of SigSEGV. (Very useful for debugging.)
|
||||
* 0 : Let the x86 program set sighandler for SEGV (Default.)
|
||||
* 1 : Disable the handling of SigSEGV.
|
||||
|
||||
#### BOX64_NOSIGILL
|
||||
#### BOX64_NOSIGILL *
|
||||
Disable handling of SigILL (to ease debugging mainly).
|
||||
* 0 : Let x86 program set sighandler for Illegal Instruction
|
||||
* 1 : Disables the handling of SigILL
|
||||
|
||||
#### BOX64_SHOWSEGV
|
||||
#### BOX64_SHOWSEGV *
|
||||
Show Segfault signal even if a signal handler is present
|
||||
* 0 : Don"t force show the SIGSEGV analysis (Default.)
|
||||
* 1 : Show SIGSEGV detail, even if a signal handler is present
|
||||
|
||||
#### BOX64_SHOWBT
|
||||
#### BOX64_SHOWBT *
|
||||
Show some Backtrace (Nativ e and Emulated) whgen a signal (SEGV, ILL or BUS) is caught
|
||||
* 0 : Don"t show backtraces (Default.)
|
||||
* 1 : Show Backtrace detail (for native, box64 is rename as the x86_64 binary run)
|
||||
|
||||
#### BOX64_X11THREADS
|
||||
#### BOX64_X11THREADS *
|
||||
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
|
||||
* 0 : Don't force call XInitThreads. (Default.)
|
||||
* 1 : Call XInitThreads as soon as libX11 is loaded.
|
||||
|
||||
#### BOX64_X11GLX
|
||||
#### BOX64_X11GLX *
|
||||
Force libX11's GLX extension to be present.
|
||||
* 0 : Do not force libX11's GLX extension to be present.
|
||||
* 1 : GLX will always be present when using XQueryExtension. (Default.)
|
||||
|
||||
#### BOX64_DYNAREC_DUMP
|
||||
#### BOX64_DYNAREC_DUMP *
|
||||
Enables/disables Box64's Dynarec's dump.
|
||||
* 0 : Disable Dynarec's blocks dump. (Default.)
|
||||
* 1 : Enable Dynarec's blocks dump.
|
||||
* 2 : Enable Dynarec's blocks dump with some colors.
|
||||
|
||||
#### BOX64_DYNAREC_LOG
|
||||
#### BOX64_DYNAREC_LOG *
|
||||
Set the level of DynaRec's logs.
|
||||
* 0 : NONE : No Logs for DynaRec. (Default.)
|
||||
* 1 :INFO : Minimum Dynarec Logs (only unimplemented OpCode).
|
||||
* 2 : DEBUG : Debug Logs for Dynarec (with details on block created / executed).
|
||||
* 3 : VERBOSE : All of the above plus more.
|
||||
|
||||
#### BOX64_DYNAREC
|
||||
#### BOX64_DYNAREC *
|
||||
Enables/Disables Box64's Dynarec.
|
||||
* 0 : Disables Dynarec.
|
||||
* 1 : Enable Dynarec. (Default.)
|
||||
|
||||
#### BOX64_DYNAREC_TRACE
|
||||
#### BOX64_DYNAREC_TRACE *
|
||||
Enables/Disables trace for generated code.
|
||||
* 0 : Disable trace for generated code. (Default.)
|
||||
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
|
||||
|
||||
#### BOX64_NODYNAREC
|
||||
#### BOX64_NODYNAREC *
|
||||
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
|
||||
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
|
||||
|
||||
#### BOX64_DYNAREC_BIGBLOCK
|
||||
#### BOX64_DYNAREC_BIGBLOCK *
|
||||
Enables/Disables Box64's Dynarec building BigBlock.
|
||||
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 1 : Build Dynarec block as big as possible (Default.)
|
||||
* 2 : Build Dynarec block bigger (don't stop when block overlaps, but only for blocks in elf memory)
|
||||
* 3 : Build Dynarec block bigger (don't stop when block overlaps, for all type of memory)
|
||||
|
||||
#### BOX64_DYNAREC_STRONGMEM
|
||||
#### BOX64_DYNAREC_FORWARD *
|
||||
Define Box64's Dynarec max allowed forward value when building Block.
|
||||
* 0 : No forward value. When current block end, don't try to go further even if there are previous forward jumps
|
||||
* XXX : Allow up to XXXX bytes of gap when building a Block after the block end to next forward jump (Default: 128)
|
||||
|
||||
#### BOX64_DYNAREC_STRONGMEM *
|
||||
Enable/Disable simulation of Strong Memory model
|
||||
* 0 : Don't try anything special (Default.)
|
||||
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model (enabled with dota2 is detected)
|
||||
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
|
||||
|
||||
#### BOX64_DYNAREC_X87DOUBLE
|
||||
#### BOX64_DYNAREC_X87DOUBLE *
|
||||
Force the use of Double for x87 emulation
|
||||
* 0 : Try to use float when possible for x87 emulation (default, faster)
|
||||
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
|
||||
|
||||
#### BOX64_DYNAREC_FASTNAN
|
||||
#### BOX64_DYNAREC_FASTNAN *
|
||||
Enable/Disable generation of -NAN
|
||||
* 0 : Generate -NAN like on x86
|
||||
* 1 : Don't do anything special with NAN, to go as fast as possible (default)
|
||||
* 1 : Don't do anything special with NAN, to go as fast as possible (default, faster)
|
||||
|
||||
#### BOX64_DYNAREC_SAFEFLAGS
|
||||
#### BOX64_DYNAREC_FASTROUND *
|
||||
Enable/Disable generation of precise x86 rounding
|
||||
* 0 : Generate float/double -> int rounding like on x86
|
||||
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (default, faster)
|
||||
|
||||
#### BOX64_DYNAREC_SAFEFLAGS *
|
||||
Handling of flags on CALL/RET opcodes
|
||||
* 0 : Treat CALL/RET as if it never needs any flags (faster but not advised)
|
||||
* 1 : most of RET will need flags, most of CALLS will not (Default)
|
||||
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
|
||||
|
||||
#### BOX64_LIBGL
|
||||
#### BOX64_DYNAREC_CALLRET *
|
||||
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
|
||||
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
|
||||
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (will crash if blacks are invalidate, so probably incompatible with JIT/Dynarec)
|
||||
|
||||
#### BOX64_DYNAREC_HOTPAGE *
|
||||
Handling of HotPage (Page beeing both executed and writen)
|
||||
* 0 : Don't track hotpage
|
||||
* 1-255 : Track HotPage, and disable execution of a page beeing writen for N attempts (default is 4)
|
||||
|
||||
#### BOX64_DYNAREC_FASTPAGE *
|
||||
Will use a faster handling of HotPage (Page beeing both executed and writen)
|
||||
* 0 : use regular hotpage (Default)
|
||||
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
|
||||
|
||||
#### BOX64_DYNAREC_BLEEDING_EDGE *
|
||||
Detect MonoBleedingEdge and apply conservative settings
|
||||
* 0 : Don't detect MonoBleedingEdge
|
||||
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
|
||||
|
||||
#### BOX64_DYNAREC_WAIT *
|
||||
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
|
||||
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
|
||||
* 1 : Dynarec will wait for FillBlock to be ready (Default)
|
||||
|
||||
#### BOX64_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
* 1 : Direct apply of SSE Flush to 0 flag
|
||||
|
||||
#### BOX64_X87_NO80BITS *
|
||||
Handling of x87 80bits long double
|
||||
* 0 : Try to handle 80bits long double as precise as possible (Default)
|
||||
* 1 : Handle them as double
|
||||
|
||||
#### BOX64_LIBCEF *
|
||||
Detect libcef and apply malloc_hack settings
|
||||
* 0 : Don't detect libcef
|
||||
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
|
||||
|
||||
#### BOX64_LIBGL *
|
||||
* libXXXX set the name for libGL (defaults to libGL.so.1).
|
||||
* /PATH/TO/libGLXXX : Sets the name and path for libGL
|
||||
You can also use SDL_VIDEO_GL_DRIVER
|
||||
@@ -170,47 +221,53 @@ Handling of flags on CALL/RET opcodes
|
||||
* XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary
|
||||
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary
|
||||
|
||||
#### BOX64_EMULATED_LIBS
|
||||
#### BOX64_EMULATED_LIBS *
|
||||
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
|
||||
Some games uses an old version of some libraries, with an ABI incompatible with native version.
|
||||
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
|
||||
|
||||
#### BOX64_ALLOWMISSINGLIBS
|
||||
#### BOX64_ALLOWMISSINGLIBS *
|
||||
Allow Box64 to continue even if a library is missing.
|
||||
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
|
||||
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
|
||||
|
||||
#### BOX64_PREFER_WRAPPED
|
||||
#### BOX64_PREFER_WRAPPED *
|
||||
Box64 will use wrapped libs even if the lib is specified with absolute path
|
||||
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
|
||||
* 1 : Use Wrapped native libs even if path is absolute
|
||||
|
||||
#### BOX64_PREFER_EMULATED
|
||||
#### BOX64_PREFER_EMULATED *
|
||||
Box64 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
|
||||
* 0 : Native libs are prefered (Default.)
|
||||
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
|
||||
|
||||
#### BOX64_CRASHHANDLER
|
||||
#### BOX64_CRASHHANDLER *
|
||||
Box64 will use a dummy crashhandler.so library
|
||||
* 0 : Use Emulated crashhandler.so library if needed
|
||||
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut for steam and dota2)
|
||||
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut)
|
||||
|
||||
#### BOX64_NOPULSE
|
||||
#### BOX64_MALLOC_HACK *
|
||||
How Box64 will handle hooking of malloc operators
|
||||
* 0 : Don't allow malloc operator to be redirected, rewriting code to use regular function (Default)
|
||||
* 1 : Allow malloc operator to be redirected (not advised)
|
||||
* 2 : Like 0, but track special mmap / free (some redirected functions were inlined and cannot be redirected)
|
||||
|
||||
#### BOX64_NOPULSE *
|
||||
Disables the load of pulseaudio libraries.
|
||||
* 0 : Load pulseaudio libraries if found. (Default.)
|
||||
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
|
||||
|
||||
#### BOX64_NOGTK
|
||||
#### BOX64_NOGTK *
|
||||
Disables the loading of wrapped GTK libraries.
|
||||
* 0 : Load wrapped GTK libraries if found. (Default.)
|
||||
* 1 : Disables loading wrapped GTK libraries.
|
||||
|
||||
#### BOX64_NOVULKAN
|
||||
#### BOX64_NOVULKAN *
|
||||
Disables the load of vulkan libraries.
|
||||
* 0 : Load vulkan libraries if found.
|
||||
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
|
||||
|
||||
#### BOX64_BASH
|
||||
#### BOX64_BASH *
|
||||
Define x86_64 bash to launch script
|
||||
* yyyy
|
||||
Will use yyyy as x86_64 bash to launch script. yyyy needs to be a full path to a valid x86_64 version of bash
|
||||
@@ -223,7 +280,7 @@ Define x86_64 bash to launch script
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
|
||||
|
||||
#### BOX64_JITGDB
|
||||
#### BOX64_JITGDB *
|
||||
* 0 : Just print the Segfault message on segfault (default)
|
||||
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
|
||||
When in gdb, you need to find the correct thread yourself (the one with `my_box64signalhandler` in is stack)
|
||||
@@ -233,3 +290,19 @@ Define x86_64 bash to launch script
|
||||
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
|
||||
Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`.
|
||||
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
|
||||
|
||||
#### BOX64_NORCFILES
|
||||
If the env var exist, no rc files (like /etc/box64.box64rc and ~/.box64rc) will be loaded
|
||||
|
||||
----
|
||||
|
||||
Those variables are only valid inside a rcfile:
|
||||
----
|
||||
|
||||
#### BOX64_NOSANDBOX
|
||||
* 0 : Nothing special
|
||||
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
|
||||
|
||||
#### BOX64_EXIT
|
||||
* 0 : Nothing special
|
||||
* 1 : Just exit, don't try to run the program
|
||||
+222
-105
@@ -145,10 +145,20 @@ wrappedtestundefs.h:
|
||||
|
||||
# TODO: Add /.F.*A/ automatic generation (and suppression)
|
||||
|
||||
class FunctionConvention(object):
|
||||
def __init__(self, ident: str, convname: str, valid_chars: List[str]) -> None:
|
||||
self.ident = ident
|
||||
self.name = convname
|
||||
self.values = valid_chars
|
||||
# Free letters: B FG J QR T XYZab e gh jk mno qrst xyz
|
||||
conventions = {
|
||||
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A']),
|
||||
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'P', 'A'])
|
||||
}
|
||||
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', '0', '1']
|
||||
assert(all(all(c not in conv.values[:i] and c in sortedvalues for i, c in enumerate(conv.values)) for conv in conventions.values()))
|
||||
|
||||
class FunctionType(str):
|
||||
values: List[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A']
|
||||
|
||||
@staticmethod
|
||||
def validate(s: str, post: str) -> bool:
|
||||
if len(s) < 3:
|
||||
@@ -163,10 +173,13 @@ class FunctionType(str):
|
||||
# TODO: change *FEv into true functions (right now they are redirected to *FE)
|
||||
#chk_type = s[0] + s[3:]
|
||||
|
||||
if s[1] not in ["F"]:
|
||||
if s[1] not in conventions:
|
||||
raise NotImplementedError("Bad middle letter {0}{1}".format(s[1], post))
|
||||
|
||||
return all(c in FunctionType.values for c in chk_type) and (('v' not in chk_type[1:]) or (len(chk_type) == 2))
|
||||
return all(c in conventions[s[1]].values for c in chk_type) and (('v' not in chk_type[1:]) or (len(chk_type) == 2))
|
||||
|
||||
def get_convention(self) -> FunctionConvention:
|
||||
return conventions[self[1]]
|
||||
|
||||
def splitchar(self) -> List[int]:
|
||||
"""
|
||||
@@ -177,9 +190,9 @@ class FunctionType(str):
|
||||
of `values.index`.
|
||||
"""
|
||||
try:
|
||||
ret = [len(self), FunctionType.values.index(self[0])]
|
||||
ret = [len(self), ord(self.get_convention().ident), self.get_convention().values.index(self[0])]
|
||||
for c in self[2:]:
|
||||
ret.append(FunctionType.values.index(c))
|
||||
ret.append(self.get_convention().values.index(c))
|
||||
return ret
|
||||
except ValueError as e:
|
||||
raise ValueError("Value is " + self) from e
|
||||
@@ -187,8 +200,6 @@ class FunctionType(str):
|
||||
def __getitem__(self, i: Union[int, slice]) -> 'FunctionType':
|
||||
return FunctionType(super().__getitem__(i))
|
||||
|
||||
assert(all(c not in FunctionType.values[:i] for i, c in enumerate(FunctionType.values)))
|
||||
|
||||
RedirectType = NewType('RedirectType', FunctionType)
|
||||
DefineType = NewType('DefineType', str)
|
||||
|
||||
@@ -462,7 +473,8 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
|
||||
gotype = ln.split("(")[0].strip()
|
||||
funname = ln.split(",")[0].split("(")[1].strip()
|
||||
ln = ln.split(",")[1].split(")")[0].strip()
|
||||
add_symbol_name(funname)
|
||||
if not filename.endswith("_genvate.h"):
|
||||
add_symbol_name(funname)
|
||||
except IndexError:
|
||||
raise NotImplementedError("Invalid GO command: {0}:{1}".format(
|
||||
filename, line[:-1]
|
||||
@@ -471,26 +483,40 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
|
||||
hasFlatStructure = False
|
||||
origLine = ln
|
||||
if not FunctionType.validate(ln, " ({0}:{1})".format(filename, line[:-1])):
|
||||
if (ln[0] in FunctionType.values) \
|
||||
# This needs more work
|
||||
old = RedirectType(FunctionType(ln))
|
||||
if (ln[0] in old.get_convention().values) \
|
||||
and ('v' not in ln[2:]) \
|
||||
and all((c in FunctionType.values) or (c in mystructs) for c in ln[2:]):
|
||||
and all((c in old.get_convention().values) or (c in mystructs) for c in ln[2:]):
|
||||
hasFlatStructure = True
|
||||
|
||||
for sn in mystructs:
|
||||
ln = ln.replace(sn, mystructs[sn][1])
|
||||
ln = ln[0] + 'F' + ln[2:] # In case a structure named 'F' is used
|
||||
mystructuses[RedirectType(FunctionType(origLine))] = FunctionType(ln)
|
||||
else:
|
||||
# This needs more work
|
||||
old = RedirectType(FunctionType(ln))
|
||||
acceptables = ['0', '1'] + FunctionType.values
|
||||
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[:2] + (ln[2:]
|
||||
.replace("v", "") # void -> nothing
|
||||
.replace("0", "i") # 0 -> integer
|
||||
.replace("1", "i")) # 1 -> integer
|
||||
assert(len(ln) >= 3)
|
||||
if old.get_convention().name == "System V":
|
||||
acceptables = ['0', '1'] + old.get_convention().values
|
||||
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[:2] + (ln[2:]
|
||||
.replace("v", "") # void -> nothing
|
||||
.replace("0", "i") # 0 -> integer
|
||||
.replace("1", "i")) # 1 -> integer
|
||||
assert(len(ln) >= 3)
|
||||
else:
|
||||
acceptables = ['0', '1', 'D', 'H'] + old.get_convention().values
|
||||
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[:2] + (ln[2:]
|
||||
.replace("v", "") # void -> nothing
|
||||
.replace("D", "p") # long double -> pointer
|
||||
.replace("H", "p") # unsigned __int128 -> pointer
|
||||
.replace("0", "i") # 0 -> integer
|
||||
.replace("1", "i")) # 1 -> integer
|
||||
assert(len(ln) >= 3)
|
||||
redirects.setdefault(str(dependants), {})
|
||||
redirects[str(dependants)][old] = FunctionType(ln)
|
||||
|
||||
@@ -525,6 +551,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
|
||||
typedefs.setdefault(RedirectType(FunctionType(origLine)), [])
|
||||
|
||||
# If the line is a structure metadata information...
|
||||
# FIXME: what happens with e.g. a Windows function?
|
||||
elif ln.startswith("//%S"):
|
||||
metadata = [e for e in ln.split() if e]
|
||||
if len(metadata) != 4:
|
||||
@@ -538,12 +565,12 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
|
||||
if metadata[3] == "":
|
||||
# If you need this, please open an issue (this is never actually called, empty strings are removed)
|
||||
raise NotImplementedError("Invalid structure metadata supply (empty replacement) ({0}:{1})".format(filename, line[:-1]))
|
||||
if any(c not in FunctionType.values for c in metadata[3]):
|
||||
if any(c not in conventions['F'].values for c in metadata[3]):
|
||||
# Note that replacement cannot be another structure type
|
||||
raise NotImplementedError("Invalid structure metadata supply (invalid replacement) ({0}:{1})".format(filename, line[:-1]))
|
||||
if metadata[1] in mystructs:
|
||||
raise NotImplementedError("Invalid structure nickname {0} (duplicate) ({1}/{2})".format(metadata[1], filename, line[:-1]))
|
||||
if (metadata[1] in FunctionType.values) or (metadata[1] in ['0', '1']):
|
||||
if (metadata[1] in conventions['F'].values) or (metadata[1] in ['0', '1']):
|
||||
raise NotImplementedError("Invalid structure nickname {0} (reserved) ({1}/{2})".format(metadata[1], filename, line[:-1]))
|
||||
|
||||
# OK, add into the database
|
||||
@@ -678,17 +705,21 @@ def sortArrays(gbl_tmp : JumbledGlobals, red_tmp : JumbledRedirects, filespec: J
|
||||
for k3 in gbl:
|
||||
gbl[k3].sort(key=FunctionType.splitchar)
|
||||
|
||||
FunctionType.values = FunctionType.values + ['0', '1']
|
||||
oldvals = { k: conventions[k].values for k in conventions }
|
||||
for k in conventions:
|
||||
conventions[k].values = sortedvalues
|
||||
for k3 in redirects:
|
||||
redirects[k3].sort(key=lambda v: v[0].splitchar() + v[1].splitchar())
|
||||
FunctionType.values = FunctionType.values[:-2]
|
||||
for k in conventions:
|
||||
conventions[k].values = oldvals[k]
|
||||
|
||||
sortedfilespec: SortedFilesSpecific = {}
|
||||
for fn in filespec:
|
||||
# Maybe do better?
|
||||
mystructs_vals: List[str] = sorted(filespec[fn][1].keys())
|
||||
if mystructs_vals != []:
|
||||
FunctionType.values = FunctionType.values + list(mystructs_vals)
|
||||
for k in conventions:
|
||||
conventions[k].values = conventions[k].values + list(mystructs_vals)
|
||||
|
||||
mytypedefs_vals: List[RedirectType] = sorted(filespec[fn][0].keys(), key=FunctionType.splitchar)
|
||||
sortedfilespec[fn] = (
|
||||
@@ -697,7 +728,8 @@ def sortArrays(gbl_tmp : JumbledGlobals, red_tmp : JumbledRedirects, filespec: J
|
||||
)
|
||||
|
||||
if mystructs_vals != []:
|
||||
FunctionType.values = FunctionType.values[:-len(mystructs_vals)]
|
||||
for k in conventions:
|
||||
conventions[k].values = conventions[k].values[:-len(mystructs_vals)]
|
||||
|
||||
return CustOrderedDict(gbl, gbl_idxs), CustOrderedDict(redirects, redirects_idxs), sortedfilespec
|
||||
|
||||
@@ -784,6 +816,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
|
||||
# Detect simple wrappings
|
||||
simple_wraps: Dict[ClausesStr, List[Tuple[FunctionType, int]]] = {}
|
||||
allowed_conv_ident = "F"
|
||||
allowed_conv = conventions[allowed_conv_ident]
|
||||
|
||||
# H could be allowed maybe?
|
||||
allowed_simply: str = "v"
|
||||
@@ -792,16 +826,18 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
|
||||
# Sanity checks
|
||||
forbidden_simple: str = "EDKVOSNMHPA"
|
||||
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(FunctionType.values))
|
||||
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(allowed_conv.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 FunctionType.values))
|
||||
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in allowed_conv.values))
|
||||
|
||||
def check_simple(v: FunctionType):
|
||||
def check_simple(v: FunctionType) -> Optional[int]:
|
||||
regs_count: int = 0
|
||||
fpr_count : int = 0
|
||||
|
||||
if v.get_convention() is not allowed_conv:
|
||||
return None
|
||||
if v[0] in forbidden_simple:
|
||||
return None
|
||||
for c in v[2:]:
|
||||
@@ -957,15 +993,21 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
|
||||
# Rewrite the wrapper.c file:
|
||||
# i and u should only be 32 bits
|
||||
# E v c w i I C W u U f d D K l L p V O S N M H P A
|
||||
td_types = ["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*", "void*"]
|
||||
if len(FunctionType.values) != len(td_types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(td_types) = {lentypes}".format(lenval=len(FunctionType.values), lentypes=len(td_types)))
|
||||
td_types = {
|
||||
# E v c w i I C W u U f d D K l L p V O S N M H P A
|
||||
'F': ["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*", "void*"],
|
||||
# E v c w i I C W u U f d K l L p V O S N M P A
|
||||
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int64_t", "int64_t", "uint8_t", "uint16_t", "uint64_t", "uint64_t", "float", "double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "void*", "void*"]
|
||||
}
|
||||
assert(all(k in conventions for k in td_types))
|
||||
for k in conventions:
|
||||
if len(conventions[k].values) != len(td_types[k]):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(td_types) = {lentypes}".format(lenval=len(conventions[k].values), lentypes=len(td_types[k])))
|
||||
|
||||
def generate_typedefs(arr: Iterable[FunctionType], file) -> None:
|
||||
for v in arr:
|
||||
file.write("typedef " + td_types[FunctionType.values.index(v[0])] + " (*" + v + "_t)"
|
||||
+ "(" + ', '.join(td_types[FunctionType.values.index(t)] for t in v[2:]) + ");\n")
|
||||
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + v + "_t)"
|
||||
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().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))
|
||||
@@ -984,37 +1026,61 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
|
||||
# Helper variables
|
||||
# Return type template
|
||||
vals = [
|
||||
"\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 should be int32_t
|
||||
"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 should be uint32_t
|
||||
"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
|
||||
"\n#error Invalid return type: va_list\n", # A
|
||||
]
|
||||
vals = {
|
||||
conventions['F']: [
|
||||
"\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 should be int32_t
|
||||
"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 should be uint32_t
|
||||
"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
|
||||
"\n#error Invalid return type: va_list\n", # A
|
||||
],
|
||||
conventions['W']: [
|
||||
"\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 should be int32_t
|
||||
"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 should be uint32_t
|
||||
"R_RAX=fn({0});", # U
|
||||
"emu->xmm[0].f[0]=fn({0});", # f
|
||||
"emu->xmm[0].d[0]=fn({0});", # 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: pointer in the stack\n", # P
|
||||
"\n#error Invalid return type: va_list\n", # A
|
||||
]
|
||||
}
|
||||
|
||||
# Name of the registers
|
||||
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
|
||||
assert(len(reg_arg) == 6)
|
||||
# vreg: value is in a general register
|
||||
# E v c w i I C W u U f d D K l L p V O S N M H P A
|
||||
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1]
|
||||
@@ -1135,26 +1201,35 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
"*(void**)(R_RSP + {p}), ", # P
|
||||
"*(void**)(R_RSP + {p}), ", # A
|
||||
]
|
||||
|
||||
|
||||
# Asserts
|
||||
if len(FunctionType.values) != len(vstack):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vstack) = {lenvstack}".format(lenval=len(FunctionType.values), lenvstack=len(vstack)))
|
||||
if len(FunctionType.values) != len(vreg):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vreg) = {lenvreg}".format(lenval=len(FunctionType.values), lenvreg=len(vreg)))
|
||||
if len(FunctionType.values) != len(vxmm):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vxmm) = {lenvxmm}".format(lenval=len(FunctionType.values), lenvxmm=len(vxmm)))
|
||||
if len(FunctionType.values) != len(vother):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vother) = {lenvother}".format(lenval=len(FunctionType.values), lenvother=len(vother)))
|
||||
if len(FunctionType.values) != len(arg_s):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(FunctionType.values), lenargs=len(arg_s)))
|
||||
if len(FunctionType.values) != len(arg_r):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_r) = {lenargr}".format(lenval=len(FunctionType.values), lenargr=len(arg_r)))
|
||||
if len(FunctionType.values) != len(arg_x):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_x) = {lenargx}".format(lenval=len(FunctionType.values), lenargx=len(arg_x)))
|
||||
if len(FunctionType.values) != len(arg_o):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_o) = {lenargo}".format(lenval=len(FunctionType.values), lenargo=len(arg_o)))
|
||||
if len(FunctionType.values) != len(vals):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(FunctionType.values), lenvals=len(vals)))
|
||||
for k in conventions:
|
||||
assert all(v in conventions['F'].values for v in conventions[k].values), "a convention is not a subset of System V"
|
||||
assert all(vr == vs for (vr, vs) in zip(vreg, vstack) if vr != 0), "vreg and vstack are inconsistent"
|
||||
assert all(vx == vs for (vx, vs) in zip(vxmm, vstack) if vx != 0), "vxmm and vstack are inconsistent"
|
||||
assert all((vo == 0) == (vs != 0) for (vo, vs) in zip(vother, vstack)), "vother and vstack are inconsistent"
|
||||
if len(conventions['F'].values) != len(vstack):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vstack) = {lenvstack}".format(lenval=len(conventions['F'].values), lenvstack=len(vstack)))
|
||||
if len(conventions['F'].values) != len(vreg):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vreg) = {lenvreg}".format(lenval=len(conventions['F'].values), lenvreg=len(vreg)))
|
||||
if len(conventions['F'].values) != len(vxmm):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vxmm) = {lenvxmm}".format(lenval=len(conventions['F'].values), lenvxmm=len(vxmm)))
|
||||
if len(conventions['F'].values) != len(vother):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vother) = {lenvother}".format(lenval=len(conventions['F'].values), lenvother=len(vother)))
|
||||
if len(conventions['F'].values) != len(arg_s):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(conventions['F'].values), lenargs=len(arg_s)))
|
||||
if len(conventions['F'].values) != len(arg_r):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_r) = {lenargr}".format(lenval=len(conventions['F'].values), lenargr=len(arg_r)))
|
||||
if len(conventions['F'].values) != len(arg_x):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_x) = {lenargx}".format(lenval=len(conventions['F'].values), lenargx=len(arg_x)))
|
||||
if len(conventions['F'].values) != len(arg_o):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg_o) = {lenargo}".format(lenval=len(conventions['F'].values), lenargo=len(arg_o)))
|
||||
for k in conventions:
|
||||
c = conventions[k]
|
||||
if c not in vals:
|
||||
raise NotImplementedError("[{k}]values not in vals".format(k=k, lenval=len(c.values), lenvals=len(vals[c])))
|
||||
if len(c.values) != len(vals[c]):
|
||||
raise NotImplementedError("len([{k}]values) = {lenval} != len(vals[...]) = {lenvals}".format(k=k, lenval=len(c.values), lenvals=len(vals[c])))
|
||||
# When arg_* is not empty, v* should not be 0
|
||||
if any(map(lambda v, a: (a != "") and (v == 0), vstack, arg_s)):
|
||||
raise NotImplementedError("Something in the stack has a null offset and a non-empty arg string")
|
||||
@@ -1175,7 +1250,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
raise NotImplementedError("Something can be in an XMM register but not in the stack")
|
||||
|
||||
# Helper functions to write the function definitions
|
||||
def function_args(args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> str:
|
||||
systemVconv = conventions['F']
|
||||
def function_args_systemV(args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> str:
|
||||
# args: string of argument types
|
||||
# d: delta (in the stack)
|
||||
# r: general register no
|
||||
@@ -1185,16 +1261,18 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
|
||||
# Redirections
|
||||
if args[0] == "0":
|
||||
return "0, " + function_args(args[1:], d, r, x)
|
||||
return "0, " + function_args_systemV(args[1:], d, r, x)
|
||||
elif args[0] == "1":
|
||||
return "1, " + function_args(args[1:], d, r, x)
|
||||
return "1, " + function_args_systemV(args[1:], d, r, x)
|
||||
|
||||
idx = FunctionType.values.index(args[0])
|
||||
if (r < 6) and (vreg[idx] > 0):
|
||||
idx = systemVconv.values.index(args[0])
|
||||
# Name of the registers
|
||||
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
|
||||
if (r < len(reg_arg)) and (vreg[idx] > 0):
|
||||
ret = ""
|
||||
for _ in range(vreg[idx]):
|
||||
# There may be values in multiple registers
|
||||
if r < 6:
|
||||
if r < len(reg_arg):
|
||||
# Value is in a general register
|
||||
ret = ret + arg_r[idx].format(p=reg_arg[r])
|
||||
r = r + 1
|
||||
@@ -1202,23 +1280,59 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
# Remaining is in the stack
|
||||
ret = ret + arg_s[idx].format(p=d)
|
||||
d = d + 8
|
||||
return ret + function_args(args[1:], d, r, x)
|
||||
return ret + function_args_systemV(args[1:], d, r, x)
|
||||
elif (x < 8) and (vxmm[idx] > 0):
|
||||
# Value is in an XMM register
|
||||
return arg_x[idx].format(p=x) + function_args(args[1:], d, r, x+1)
|
||||
return arg_x[idx].format(p=x) + function_args_systemV(args[1:], d, r, x+1)
|
||||
elif vstack[idx] > 0:
|
||||
# Value is in the stack
|
||||
return arg_s[idx].format(p=d) + function_args(args[1:], d+8*vstack[idx], r, x)
|
||||
return arg_s[idx].format(p=d) + function_args_systemV(args[1:], d+8*vstack[idx], r, x)
|
||||
else:
|
||||
# Value is somewhere else
|
||||
return arg_o[idx].format(p=d) + function_args(args[1:], d, r, x)
|
||||
return arg_o[idx].format(p=d) + function_args_systemV(args[1:], d, r, x)
|
||||
# windowsconv = conventions['W']
|
||||
def function_args_windows(args: FunctionType, d: int = 40, r: int = 0) -> str:
|
||||
# args: string of argument types
|
||||
# d: delta (in the stack)
|
||||
# r: general register no
|
||||
# We can re-use vstack to know if we need to put a pointer or the value
|
||||
if len(args) == 0:
|
||||
return ""
|
||||
|
||||
# Redirections
|
||||
if args[0] == "0":
|
||||
return "0, " + function_args_windows(args[1:], d, r)
|
||||
elif args[0] == "1":
|
||||
return "1, " + function_args_windows(args[1:], d, r)
|
||||
|
||||
idx = systemVconv.values.index(args[0]) # Little hack to be able to re-use
|
||||
# Name of the registers
|
||||
reg_arg = ["R_RCX", "R_RDX", "R_R8", "R_R9"]
|
||||
if (r < len(reg_arg)) and (vstack[idx] == 1):
|
||||
# We use a register
|
||||
if vreg[idx] == 1:
|
||||
# Value is in a general register
|
||||
return arg_r[idx].format(p=reg_arg[r]) + function_args_windows(args[1:], d, r+1)
|
||||
else:
|
||||
# Remaining is in an XMM register
|
||||
return arg_x[idx].format(p=r) + function_args_windows(args[1:], d, r+1)
|
||||
elif vstack[idx] > 0:
|
||||
# Value is in the stack
|
||||
return arg_s[idx].format(p=d) + function_args_windows(args[1:], d+8*vstack[idx], r)
|
||||
else:
|
||||
# Value is somewhere else
|
||||
return arg_o[idx].format(p=d) + function_args_windows(args[1:], d, r)
|
||||
|
||||
def function_writer(f, N: FunctionType, W: str) -> None:
|
||||
# Write to f the function type N (real type W)
|
||||
|
||||
f.write("void {0}(x64emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
|
||||
# Generic function
|
||||
f.write(vals[FunctionType.values.index(N[0])].format(function_args(N[2:])[:-2]) + " }\n")
|
||||
conv = N.get_convention()
|
||||
if conv is systemVconv:
|
||||
f.write(vals[conv][conv.values.index(N[0])].format(function_args_systemV(N[2:])[:-2]) + " }\n")
|
||||
else:
|
||||
f.write(vals[conv][conv.values.index(N[0])].format(function_args_windows(N[2:])[:-2]) + " }\n")
|
||||
|
||||
for k in gbls:
|
||||
if k != str(Clauses()):
|
||||
@@ -1276,13 +1390,15 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
file.write(files_guard["wrapper.h"].format(lbr="{", rbr="}", version=ver))
|
||||
|
||||
# Rewrite the *types.h files:
|
||||
td_types[FunctionType.values.index('A')] = "va_list"
|
||||
td_types[FunctionType.values.index('V')] = "..."
|
||||
orig_val_len = len(FunctionType.values)
|
||||
for k in conventions:
|
||||
td_types[k][conventions[k].values.index('A')] = "va_list"
|
||||
td_types[k][conventions[k].values.index('V')] = "..."
|
||||
orig_val_len = {k: len(conventions[k].values) for k in conventions}
|
||||
for fn in filesspec:
|
||||
for strc in fsp_tmp[fn][1]:
|
||||
FunctionType.values.append(strc)
|
||||
td_types.append(fsp_tmp[fn][1][strc][0])
|
||||
for k in conventions:
|
||||
conventions[k].values.append(strc)
|
||||
td_types[k].append(fsp_tmp[fn][1][strc][0])
|
||||
|
||||
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))
|
||||
@@ -1306,8 +1422,9 @@ def main(root: str, files: Iterable[Filename], ver: str):
|
||||
file.write("#undef {defined}\n".format(defined=defined))
|
||||
file.write(files_guard["fnundefs.h"].format(lbr="{", rbr="}", version=ver, filename=fn))
|
||||
|
||||
FunctionType.values = FunctionType.values[:orig_val_len]
|
||||
td_types = td_types[:orig_val_len]
|
||||
for k in conventions:
|
||||
conventions[k].values = conventions[k].values[:orig_val_len[k]]
|
||||
td_types[k] = td_types[k][:orig_val_len[k]]
|
||||
|
||||
# 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:
|
||||
@@ -1321,6 +1438,6 @@ if __name__ == '__main__':
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.1.0.16") != 0:
|
||||
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.16") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
+27
-11
@@ -19,6 +19,8 @@
|
||||
#include "wrapper.h"
|
||||
#include "x64emu.h"
|
||||
#include "signals.h"
|
||||
#include "rcfile.h"
|
||||
#include "gltools.h"
|
||||
|
||||
EXPORTDYN
|
||||
void initAllHelpers(box64context_t* context)
|
||||
@@ -39,6 +41,7 @@ void finiAllHelpers(box64context_t* context)
|
||||
static int finied = 0;
|
||||
if(finied)
|
||||
return;
|
||||
DeleteParams();
|
||||
fini_pthread_helper(context);
|
||||
fini_signal_helper();
|
||||
fini_bridge_helper();
|
||||
@@ -73,11 +76,20 @@ int unlockMutex()
|
||||
{
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#ifdef DYNAREC
|
||||
uint32_t tid = (uint32_t)GetTID();
|
||||
#define GO(A, B) \
|
||||
i = (native_lock_storeifref2_d(&A, 0, tid)==tid); \
|
||||
if(i) { \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
#else
|
||||
#define GO(A, B) \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
#endif
|
||||
|
||||
GO(my_context->mutex_trace, 7)
|
||||
#ifdef DYNAREC
|
||||
@@ -98,7 +110,7 @@ void relockMutex(int locks)
|
||||
relockCustommemMutex(locks);
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_trylock(&A); \
|
||||
mutex_trylock(&A); \
|
||||
|
||||
GO(my_context->mutex_trace, 7)
|
||||
#ifdef DYNAREC
|
||||
@@ -114,20 +126,24 @@ void relockMutex(int locks)
|
||||
|
||||
static void init_mutexes(box64context_t* context)
|
||||
{
|
||||
#ifndef DYNAREC
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
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_trace, &attr);
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#else
|
||||
native_lock_store(&context->mutex_trace, 0);
|
||||
native_lock_store(&context->mutex_tls, 0);
|
||||
native_lock_store(&context->mutex_thread, 0);
|
||||
native_lock_store(&context->mutex_bridge, 0);
|
||||
native_lock_store(&context->mutex_dyndump, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void atfork_child_box64context(void)
|
||||
@@ -218,6 +234,7 @@ box64context_t *NewBox64Context(int argc)
|
||||
return context;
|
||||
}
|
||||
|
||||
void freeALProcWrapper(box64context_t* context);
|
||||
EXPORTDYN
|
||||
void FreeBox64Context(box64context_t** context)
|
||||
{
|
||||
@@ -300,22 +317,21 @@ void FreeBox64Context(box64context_t** context)
|
||||
if(ctx->tlsdata)
|
||||
box_free(ctx->tlsdata);
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
free_neededlib(ctx->neededlibs);
|
||||
ctx->neededlibs = NULL;
|
||||
|
||||
if(ctx->emu_sig)
|
||||
FreeX64Emu(&ctx->emu_sig);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
#endif
|
||||
|
||||
freeCycleLog(ctx);
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 2
|
||||
#define BOX64_REVISION 0
|
||||
#define BOX64_REVISION 2
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+464
-531
File diff suppressed because it is too large.
Load diff
@@ -24,6 +24,7 @@
|
||||
#define xR15 25
|
||||
#define xFlags 26
|
||||
#define xRIP 27
|
||||
#define xSavedSP 28
|
||||
// 32bits version
|
||||
#define wEAX xRAX
|
||||
#define wECX xRCX
|
||||
@@ -265,6 +266,13 @@
|
||||
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
|
||||
#define STRxw_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
|
||||
|
||||
#define STU_gen(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | (opc)<<22 | ((imm9)&0x1ff)<<12 | (Rn)<<5 | (Rt))
|
||||
#define STURx_I9(Rt, Rn, imm9) EMIT(STU_gen(0b11, 0b00, imm9, Rn, Rt))
|
||||
#define STURw_I9(Rt, Rn, imm9) EMIT(STU_gen(0b10, 0b00, imm9, Rn, Rt))
|
||||
#define STURxw_I9(Rt, Rn, imm9) EMIT(STU_gen((rex.w)?0b11:0b10, 0b00, imm9, Rn, Rt))
|
||||
#define STURH_I9(Rt, Rn, imm9) EMIT(STU_gen(0b01, 0b00, imm9, Rn, Rt))
|
||||
#define STURB_I9(Rt, Rn, imm9) EMIT(STU_gen(0b00, 0b00, imm9, Rn, Rt))
|
||||
|
||||
#define STR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b00<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
|
||||
#define STRx_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
|
||||
#define STRx_REG_LSL3(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
|
||||
@@ -280,23 +288,23 @@
|
||||
|
||||
#define LDPx_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 1, 0b01, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 1, 0b01, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b01, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b01, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPx_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 1, 0b11, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 1, 0b11, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b11, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b11, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPx_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 1, 0b10, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 1, 0b10, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b10, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define LDPxw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 1, 0b10, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
|
||||
#define STPx_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 0, 0b01, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 0, 0b01, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPxw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b01, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define STPxw_S7_postindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b01, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
#define STPx_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 0, 0b11, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 0, 0b11, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPxw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b11, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define STPxw_S7_preindex(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b11, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
#define STPx_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(1, 0, 0b10, (((uint32_t)(imm))>>3)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(0, 0, 0b10, (((uint32_t)(imm))>>2)&0x7f, Rt2, Rn, Rt))
|
||||
#define STPxw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b10, (((uint32_t)(imm))>>(2+rex.w)), Rt2, Rn, Rt))
|
||||
#define STPxw_S7_offset(Rt, Rt2, Rn, imm) EMIT(MEMPAIR_gen(rex.w, 0, 0b10, (((uint32_t)(imm))>>(2+rex.w))&0x7f, Rt2, Rn, Rt))
|
||||
|
||||
// PUSH / POP helper
|
||||
#define POP1(reg) LDRx_S9_postindex(reg, xRSP, 8)
|
||||
@@ -648,6 +656,10 @@
|
||||
#define REV16w(Rd, Rn) EMIT(REV_gen(0, 0b01, Rn, Rd))
|
||||
#define REV16x(Rd, Rn) EMIT(REV_gen(1, 0b01, Rn, Rd))
|
||||
|
||||
// UDF
|
||||
#define UDF_gen(imm16) ((imm16)&0xffff)
|
||||
#define UDF(imm16) EMIT(UDF_gen(imm16))
|
||||
|
||||
// MRS
|
||||
#define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
|
||||
// mrs x0, nzcv : 1101010100 1 1 1 011 0100 0010 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0010(2) op2=0
|
||||
@@ -1230,7 +1242,9 @@
|
||||
#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))
|
||||
// Convert Vn from i32 to Vd float
|
||||
#define SCVTFSS(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 0, Vn, Vd))
|
||||
// Convert Vn from i64 to Vd double
|
||||
#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))
|
||||
@@ -1351,13 +1365,13 @@
|
||||
//Use Rm[] to pick from Rn, Rn+1, Rn+2, Rn+3 element and store in Rd. Out-of-range element gets 0
|
||||
#define VTBLQ4_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b11, 0, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn element and store in Rd. Out-of-range element stay untouched
|
||||
#define VTBXQ1_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b00, 0, Rn, Rd))
|
||||
#define VTBXQ1_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b00, 1, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn, Rn+1 element and store in Rd. Out-of-range element stay untouched
|
||||
#define VTBXQ2_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b01, 0, Rn, Rd))
|
||||
#define VTBXQ2_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b01, 1, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn, Rn+1, Rn+2 element and store in Rd. Out-of-range element stay untouched
|
||||
#define VTBXQ3_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b10, 0, Rn, Rd))
|
||||
#define VTBXQ3_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b10, 1, Rn, Rd))
|
||||
//Use Rm[] to pick from Rn, Rn+1, Rn+2, Rn+3 element and store in Rd. Out-of-range element stay untouched
|
||||
#define VTBXQ4_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b11, 0, Rn, Rd))
|
||||
#define VTBXQ4_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b11, 1, Rn, Rd))
|
||||
|
||||
// TRN
|
||||
#define TRN_gen(Q, size, Rm, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (size)<<22 | (Rm)<<16 | (op)<<14 | 0b10<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
|
||||
|
||||
@@ -19,12 +19,13 @@ arm64_epilog:
|
||||
stp x24, x25, [x0, (8 * 14)]
|
||||
stp x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
|
||||
//restore all used register
|
||||
add sp, x28, 0
|
||||
//vpop {d8-d15}
|
||||
ldp x19, x20, [sp, (8 * 0)]
|
||||
ldp x21, x22, [sp, (8 * 2)]
|
||||
ldp x23, x24, [sp, (8 * 4)]
|
||||
ldp x25, x26, [sp, (8 * 6)]
|
||||
ldr x27, [sp, (8 * 8)]
|
||||
ldp x27, x28, [sp, (8 * 8)]
|
||||
ldp d8, d9, [sp, (8 *10)]
|
||||
ldp d10, d11, [sp, (8 *12)]
|
||||
ldp d12, d13, [sp, (8 *14)]
|
||||
@@ -38,12 +39,13 @@ arm64_epilog:
|
||||
.global arm64_epilog_fast
|
||||
arm64_epilog_fast:
|
||||
//restore all used register
|
||||
add sp, x28, 0
|
||||
//vpop {d8-d15}
|
||||
ldp x19, x20, [sp, (8 * 0)]
|
||||
ldp x21, x22, [sp, (8 * 2)]
|
||||
ldp x23, x24, [sp, (8 * 4)]
|
||||
ldp x25, x26, [sp, (8 * 6)]
|
||||
ldr x27, [sp, (8 * 8)]
|
||||
ldp x27, x28, [sp, (8 * 8)]
|
||||
ldp d8, d9, [sp, (8 *10)]
|
||||
ldp d10, d11, [sp, (8 *12)]
|
||||
ldp d12, d13, [sp, (8 *14)]
|
||||
|
||||
+108
-17
@@ -18,8 +18,15 @@
|
||||
.global arm64_lock_xchg
|
||||
.global arm64_lock_xchg_d
|
||||
.global arm64_lock_storeifnull
|
||||
.global arm64_lock_storeifnull_d
|
||||
.global arm64_lock_storeifref
|
||||
|
||||
.global arm64_lock_storeifref_d
|
||||
.global arm64_lock_storeifref2_d
|
||||
.global arm64_lock_decifnot0b
|
||||
.global arm64_lock_storeb
|
||||
.global arm64_lock_incif0
|
||||
.global arm64_lock_decifnot0
|
||||
.global arm64_lock_store
|
||||
|
||||
arm64_lock_read_b:
|
||||
dmb ish
|
||||
@@ -97,7 +104,6 @@ arm64_lock_xchg_0:
|
||||
ldaxr x2, [x0]
|
||||
stlxr w3, x1, [x0]
|
||||
cbnz w3, arm64_lock_xchg_0
|
||||
dmb ish
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
@@ -108,36 +114,121 @@ arm64_lock_xchg_d_0:
|
||||
ldaxr w2, [x0]
|
||||
stlxr w3, w1, [x0]
|
||||
cbnz w3, arm64_lock_xchg_d_0
|
||||
dmb ish
|
||||
mov w0, w2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull:
|
||||
dmb ish
|
||||
arm64_lock_storeifnull_0:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
|
||||
1:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return old [x0] value
|
||||
ldaxr x2, [x0]
|
||||
cbnz x2, arm64_lock_storeifnull_exit
|
||||
mov x2, x1
|
||||
stlxr w3, x2, [x0]
|
||||
cbnz w3, arm64_lock_storeifnull_0
|
||||
arm64_lock_storeifnull_exit:
|
||||
dmb ish
|
||||
cbnz x2, 2f
|
||||
stlxr w3, x1, [x0]
|
||||
cbnz w3, 1b
|
||||
2:
|
||||
mov x0, x2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifnull_d:
|
||||
dmb ish
|
||||
1:
|
||||
// address is x0, value is w1, w1 store to x0 only if [x0] is 0. return old [x0] value
|
||||
ldaxr w2, [x0]
|
||||
cbnz w2, 2f
|
||||
stlxr w3, w1, [x0]
|
||||
cbnz w3, 1b
|
||||
2:
|
||||
dmb ish
|
||||
mov w0, w2
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref:
|
||||
dmb ish
|
||||
arm64_lock_storeifref_0:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
|
||||
1:
|
||||
// address is x0, value is x1, x1 store to x0 only if [x0] is x2. return new [x0] value (so x1 or old value)
|
||||
ldaxr x3, [x0]
|
||||
cmp x2, x3
|
||||
bne arm64_lock_storeifref_exit
|
||||
bne 2f
|
||||
stlxr w4, x1, [x0]
|
||||
cbnz w4, arm64_lock_storeifref_0
|
||||
cbnz w4, 1b
|
||||
mov x0, x1
|
||||
ret
|
||||
arm64_lock_storeifref_exit:
|
||||
dmb ish
|
||||
2:
|
||||
mov x0, x3
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref_d:
|
||||
dmb ish
|
||||
1:
|
||||
// address is x0, value is w1, w1 store to x0 only if [x0] is w2. return new [x0] value (so x1 or old value)
|
||||
ldaxr w3, [x0]
|
||||
cmp w2, w3
|
||||
bne 2f
|
||||
stlxr w4, w1, [x0]
|
||||
cbnz w4, 1b
|
||||
mov w0, w1
|
||||
ret
|
||||
2:
|
||||
mov w0, w3
|
||||
ret
|
||||
|
||||
arm64_lock_storeifref2_d:
|
||||
dmb ish
|
||||
1:
|
||||
// address is x0, value is w1, w1 store to x0 only if [x0] is w2. return old [x0] value
|
||||
ldaxr w3, [x0]
|
||||
cmp w2, w3
|
||||
bne 2f
|
||||
stlxr w4, w1, [x0]
|
||||
cbnz w4, 1b
|
||||
2:
|
||||
mov w0, w3
|
||||
ret
|
||||
|
||||
arm64_lock_decifnot0b:
|
||||
dmb ish
|
||||
1:
|
||||
ldaxrb w1, [x0]
|
||||
cmp w1, #0
|
||||
beq 2f
|
||||
sub w1, w1, #1
|
||||
stlxrb w2, w1, [x0]
|
||||
cbnz w2, 1b
|
||||
2:
|
||||
ret
|
||||
|
||||
arm64_lock_storeb:
|
||||
strb w1, [x0]
|
||||
dmb ish
|
||||
ret
|
||||
|
||||
arm64_lock_decifnot0:
|
||||
dmb ish
|
||||
1:
|
||||
ldaxr w1, [x0]
|
||||
cmp w1, #0
|
||||
beq 2f
|
||||
sub w3, w1, #1
|
||||
stlxr w2, w3, [x0]
|
||||
cbnz w2, 1b
|
||||
2:
|
||||
mov w0, w1
|
||||
ret
|
||||
|
||||
arm64_lock_incif0:
|
||||
dmb ish
|
||||
1:
|
||||
ldaxr w1, [x0]
|
||||
cmp w1, #0
|
||||
bne 2f
|
||||
add w3, w1, #1
|
||||
stlxr w2, w3, [x0]
|
||||
cbnz w2, 1b
|
||||
2:
|
||||
mov w0, w1
|
||||
ret
|
||||
|
||||
arm64_lock_store:
|
||||
str w1, [x0]
|
||||
dmb ish
|
||||
ret
|
||||
@@ -33,10 +33,34 @@ extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
|
||||
// Atomicaly exchange value at [p] with val, return old p
|
||||
extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern uint32_t arm64_lock_storeifnull_d(void*p, uint32_t val);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
|
||||
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);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern uint32_t arm64_lock_storeifref2_d(void*p, uint32_t val, uint32_t ref);
|
||||
|
||||
// decrement atomicaly the byte at [p] (but only if p not 0)
|
||||
extern void arm64_lock_decifnot0b(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_storeb(void*p, uint8_t b);
|
||||
|
||||
// increment atomicaly the int at [p] only if it was 0. Return the old value of [p]
|
||||
extern int arm64_lock_incif0(void*p);
|
||||
|
||||
// decrement atomicaly the int at [p] (but only if p not 0)
|
||||
extern int arm64_lock_decifnot0(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm64_lock_store(void*p, uint32_t v);
|
||||
|
||||
#endif //__ARM64_LOCK__H__
|
||||
@@ -9,6 +9,8 @@
|
||||
.extern LinkNext
|
||||
|
||||
.global arm64_next
|
||||
|
||||
.8byte 0 // NULL pointer before arm64_next, for getDB
|
||||
arm64_next:
|
||||
// emu is r0
|
||||
// IP address is r1
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef struct arm64_print_s {
|
||||
|
||||
uint64_t DecodeBitMasks(int N, int imms, int immr)
|
||||
{
|
||||
int len = 31-__builtin_clz(N<<6 | ((~imms)&0b111111));
|
||||
int len = 31-__builtin_clz((N<<6) | ((~imms)&0b111111));
|
||||
if(len<1) return 0;
|
||||
int levels = (1<<len) - 1;
|
||||
int s = imms & levels;
|
||||
@@ -1140,8 +1140,8 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
else if(sf==0 && type==0 && rmode==0 && opcd==6) {snprintf(buff, sizeof(buff), "FMOV %s, S%d", Wt[Rn], Rd);}
|
||||
else if(sf==1 && type==1 && rmode==0 && opcd==7) {snprintf(buff, sizeof(buff), "FMOV D%d, %s", Rd, Xt[Rn]);}
|
||||
else if(sf==1 && type==2 && rmode==1 && opcd==7) {snprintf(buff, sizeof(buff), "FMOV V%d.D[1], %s", Rd, Xt[Rn]);}
|
||||
else if(sf==1 && type==1 && rmode==0 && opcd==6) {snprintf(buff, sizeof(buff), "FMOV %s, S%d", Xt[Rn], Rd);}
|
||||
else if(sf==1 && type==2 && rmode==1 && opcd==6) {snprintf(buff, sizeof(buff), "FMOV %s, V%d.D[1]", Xt[Rn], Rd);}
|
||||
else if(sf==1 && type==1 && rmode==0 && opcd==6) {snprintf(buff, sizeof(buff), "FMOV %s, D%d", Xt[Rd], Rn);}
|
||||
else if(sf==1 && type==2 && rmode==1 && opcd==6) {snprintf(buff, sizeof(buff), "FMOV %s, V%d.D[1]", Xt[Rd], Rn);}
|
||||
else snprintf(buff, sizeof(buff), "FMOV ????");
|
||||
return buff;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
.text
|
||||
.align 4
|
||||
|
||||
.extern arm64_next
|
||||
|
||||
.global arm64_prolog
|
||||
arm64_prolog:
|
||||
//save all 18 used register
|
||||
@@ -15,7 +17,7 @@ arm64_prolog:
|
||||
stp x21, x22, [sp, (8 * 2)]
|
||||
stp x23, x24, [sp, (8 * 4)]
|
||||
stp x25, x26, [sp, (8 * 6)]
|
||||
str x27, [sp, (8 * 8)]
|
||||
stp x27, X28, [sp, (8 * 8)]
|
||||
stp d8, d9, [sp, (8 *10)]
|
||||
stp d10, d11, [sp, (8 *12)]
|
||||
stp d12, d13, [sp, (8 *14)]
|
||||
@@ -31,5 +33,10 @@ arm64_prolog:
|
||||
ldp x22, x23, [x0, (8 * 12)]
|
||||
ldp x24, x25, [x0, (8 * 14)]
|
||||
ldp x26, x27, [x0, (8 * 16)]
|
||||
// Push a jump next on the stack
|
||||
adr x28, arm64_next
|
||||
stp x28, xzr, [sp, -16]!
|
||||
// Save old xSP in x28
|
||||
add x28, sp, 16
|
||||
//jump to function
|
||||
br x1
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
@@ -40,7 +41,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t wback, wb1, wb2, wb;
|
||||
int64_t fixedaddress;
|
||||
int lock;
|
||||
int cacheupd;
|
||||
int cacheupd = 0;
|
||||
|
||||
opcode = F8;
|
||||
MAYUSE(eb1);
|
||||
@@ -107,7 +108,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETEB(x1, 0);
|
||||
GETGB(x2);
|
||||
emit_or8(dyn, ninst, x1, x2, x4, x2);
|
||||
emit_or8(dyn, ninst, x1, x2, x4, x5);
|
||||
EBBACK;
|
||||
break;
|
||||
case 0x09:
|
||||
@@ -530,6 +531,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) { // reg <= reg
|
||||
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
LDRSW_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -537,6 +539,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) { // reg <= reg
|
||||
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
LDRw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -559,7 +562,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i64 = F32S;
|
||||
if(PK(0)==0xC3) {
|
||||
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
|
||||
TABLE64(x3, ip+1);
|
||||
TABLE64(x3, addr-4);
|
||||
LDRSW_U12(x1, x3, 0);
|
||||
PUSH1(x1);
|
||||
} else {
|
||||
@@ -860,16 +863,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
BFIx(eb1, x4, eb2*8, 8);
|
||||
} else {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETGB(x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
LDAXRB(x1, ed);
|
||||
// do the swap 14 -> strb(ed), 1 -> gd
|
||||
// do the swap 4 -> strb(ed), 1 -> gd
|
||||
STLXRB(x3, x4, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
}
|
||||
break;
|
||||
@@ -885,7 +888,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
@@ -897,7 +900,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRxw_U12(x1, ed, 0);
|
||||
STRxw_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
@@ -931,10 +934,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, &lock, 0, 0);
|
||||
STRB_U12(gd, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x89:
|
||||
@@ -946,10 +946,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
|
||||
STRxw_U12(gd, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x8A:
|
||||
@@ -980,10 +977,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, &lock, 0, 0);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMREADLOCK(lock);
|
||||
LDRB_U12(x4, wback, fixedaddress);
|
||||
ed = x4;
|
||||
}
|
||||
@@ -997,10 +991,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMREADLOCK(lock);
|
||||
LDRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1013,6 +1004,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_U12(x3, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x8D:
|
||||
@@ -1037,6 +1029,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 0, rex, NULL, 0, 0);
|
||||
LDRH_U12(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1047,7 +1040,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
POP1(xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else {
|
||||
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
|
||||
@@ -1144,12 +1137,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRB_U12(xRAX, x1, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od,EAX");
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRxw_U12(xRAX, x1, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA4:
|
||||
if(rep) {
|
||||
@@ -1570,9 +1565,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETED(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) {
|
||||
WBACK;
|
||||
}
|
||||
if(u8) { WBACK; }
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, Ib");
|
||||
@@ -1580,9 +1573,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETED(1);
|
||||
u8 = (F8)&(rex.w?0x3f:0x1f);
|
||||
emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);
|
||||
if(u8) {
|
||||
WBACK;
|
||||
}
|
||||
if(u8) { WBACK; }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1630,10 +1621,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
STRB_U12(x3, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
@@ -1648,10 +1636,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i64 = F32S;
|
||||
MOV64xw(x3, i64);
|
||||
STRxw_U12(x3, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1682,7 +1667,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
x87_forget(dyn, ninst, x3, x4, 0);
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
tmp = isSimpleWrapper(*(wrapper_t*)(addr));
|
||||
if((box64_log<2 || !cycle_log) && tmp) {
|
||||
if((box64_log<2 && !cycle_log) && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(addr+8), tmp);
|
||||
addr+=8+8;
|
||||
@@ -2131,7 +2116,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
|
||||
// calling a native function
|
||||
sse_purge07cache(dyn, ninst, x3);
|
||||
if((box64_log<2 || !cycle_log) && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall)
|
||||
tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2));
|
||||
else
|
||||
tmp=0;
|
||||
if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall && tmp) {
|
||||
//GETIP(ip+3+8+8); // read the 0xCC
|
||||
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
|
||||
POP1(xRIP); // pop the return address
|
||||
@@ -2168,12 +2157,29 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
// regular call
|
||||
BARRIER(BARRIER_FULL);
|
||||
//BARRIER_NEXT(1);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
TABLE64(x2, addr);
|
||||
PUSH1(x2);
|
||||
if(box64_dynarec_callret) {
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
} else {
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
TABLE64(x4, j64);
|
||||
LDRx_U12(x4, x4, 0);
|
||||
}
|
||||
STPx_S7_preindex(x4, x2, xSP, -16);
|
||||
}
|
||||
if(addr+i32==0) { // self modifying code maybe? so use indirect address fetching
|
||||
TABLE64(x4, addr-4);
|
||||
LDRx_U12(x4, x4, 0);
|
||||
@@ -2297,7 +2303,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
GETED(4);
|
||||
GETED(0);
|
||||
MVNxw_REG(ed, ed);
|
||||
WBACK;
|
||||
break;
|
||||
@@ -2501,19 +2507,34 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDx(0);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
//BARRIER_NEXT(BARRIER_FULL);
|
||||
if(!dyn->insts || ninst==dyn->size-1) {
|
||||
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
GETIP_(addr);
|
||||
if(box64_dynarec_callret) {
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
} else {
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
TABLE64(x4, j64);
|
||||
LDRx_U12(x4, x4, 0);
|
||||
}
|
||||
STPx_S7_preindex(x4, xRIP, xSP, -16);
|
||||
}
|
||||
PUSH1(xRIP);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
break;
|
||||
case 4: // JMP Ed
|
||||
INST_NAME("JMP Ed");
|
||||
BARRIER(BARRIER_FULL);
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
GETEDx(0);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
*need_epilog = 0;
|
||||
|
||||
@@ -24,44 +24,6 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
#define GETG \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3) \
|
||||
|
||||
#define GETGX(a, w) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
#define GETGX_empty(a) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETEX(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR128_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
|
||||
|
||||
#define GETEM(a, D) \
|
||||
if(MODREG) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7)); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
@@ -72,7 +34,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t wback, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
int32_t i32, i32_;
|
||||
int cacheupd;
|
||||
int cacheupd = 0;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
@@ -104,10 +66,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETIP(ip);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL(arm_ud, -1);
|
||||
LOAD_XEMU_CALL(xRIP);
|
||||
jump_to_epilog(dyn, 0, xRIP, ninst);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
INST_NAME("SYSCALL");
|
||||
SMEND();
|
||||
GETIP(addr);
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
CALL_S(x64Syscall, -1);
|
||||
@@ -170,6 +137,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
|
||||
}
|
||||
@@ -186,6 +154,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -198,6 +167,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
INST_NAME("MOVLPS Gx,Ex");
|
||||
GETGX(v0, 1);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(v0, 0, ed);
|
||||
}
|
||||
@@ -212,11 +182,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("UNPCKLPS Gx, Ex");
|
||||
nextop = F8;
|
||||
SMREAD();
|
||||
GETEX(q0, 0, 0);
|
||||
GETGX(v0, 1);
|
||||
VZIP1Q_32(v0, v0, q0);
|
||||
@@ -224,6 +196,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x15:
|
||||
INST_NAME("UNPCKHPS Gx, Ex");
|
||||
nextop = F8;
|
||||
SMREAD();
|
||||
GETEX(q0, 0, 0);
|
||||
GETGX(v0, 1);
|
||||
VZIP2Q_32(v0, v0, q0);
|
||||
@@ -237,6 +210,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVeD(v0, 1, v1, 0);
|
||||
} else {
|
||||
INST_NAME("MOVHPS Gx,Ex");
|
||||
SMREAD();
|
||||
GETGX(v0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(v0, 1, ed);
|
||||
@@ -252,6 +226,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VST1_64(v0, 1, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x18:
|
||||
@@ -303,6 +278,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -319,6 +295,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -348,6 +325,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
}
|
||||
@@ -407,6 +385,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) {
|
||||
REVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
LDRxw_U12(gd, ed, fixedaddress);
|
||||
REVxw(gd, gd);
|
||||
@@ -422,6 +401,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
REVxw(x1, gd);
|
||||
STRxw_U12(x1, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -476,7 +456,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
MOV32w(gd, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
// EX is an xmm reg
|
||||
GETEX(q0, 0, 0);
|
||||
VMOVQDto(x1, q0, 0);
|
||||
@@ -491,6 +471,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFIx(gd, x1, 3, 1);
|
||||
} else {
|
||||
// EX is memory
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, NULL, 0, 0);
|
||||
LDRx_U12(x1, ed, fixedaddress+0);
|
||||
LSRx(x1, x1, 31);
|
||||
@@ -703,37 +684,36 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("PUNPCKHBW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
GETEM(q1, 0);
|
||||
VZIP2_8(q0, q0, q1);
|
||||
break;
|
||||
case 0x69:
|
||||
INST_NAME("PUNPCKHWD Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
GETEM(q1, 0);
|
||||
VZIP2_16(q0, q0, q1);
|
||||
break;
|
||||
case 0x6A:
|
||||
INST_NAME("PUNPCKHDQ Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(q0);
|
||||
GETEM(q1, 1);
|
||||
GETEM(q1, 0);
|
||||
VZIP2_32(q0, q0, q1);
|
||||
break;
|
||||
case 0x6B:
|
||||
INST_NAME("PACKSSDW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
if(MODREG) {
|
||||
GETEM(v1, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VMOVeD(q0, 1, v1, 0);
|
||||
} else {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(q0, 1, ed);
|
||||
}
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
SQXTN_16(v0, q0);
|
||||
break;
|
||||
|
||||
@@ -747,6 +727,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(rex.w) {
|
||||
FMOVDx(v0, ed);
|
||||
} else {
|
||||
VEOR(v0, v0, v0);
|
||||
FMOVSw(v0, ed);
|
||||
}
|
||||
} else {
|
||||
@@ -867,9 +848,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else if(u8) {
|
||||
VSHR_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(q0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -880,9 +859,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(u8) {
|
||||
VSSHR_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(q0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLW Em, Ib");
|
||||
@@ -894,9 +871,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
VSHL_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(q0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -917,9 +892,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else if(u8) {
|
||||
VSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(d0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -930,9 +903,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(u8) {
|
||||
VSSHR_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(d0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLD Em, Ib");
|
||||
@@ -944,9 +915,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
VSHL_32(d0, d0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR64_U12(d0, ed, fixedaddress);
|
||||
}
|
||||
PUTEM(d0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1022,9 +991,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX + (nextop&7) + (rex.b<<3);
|
||||
if(rex.w) {
|
||||
VMOVQDto(ed, v0, 0);
|
||||
FMOVxD(ed, v0);
|
||||
} else {
|
||||
VMOVSto(ed, v0, 0);
|
||||
FMOVwS(ed, v0);
|
||||
MOVxw_REG(ed, ed);
|
||||
}
|
||||
} else {
|
||||
@@ -1034,6 +1003,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
VSTR32_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x7F:
|
||||
@@ -1046,6 +1016,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1096,6 +1067,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0); \
|
||||
STRB_U12(x3, ed, fixedaddress); \
|
||||
SMWRITE(); \
|
||||
}
|
||||
|
||||
GOCOND(0x90, "SET", "Eb");
|
||||
@@ -1115,6 +1087,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
@@ -1162,6 +1135,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
@@ -1187,6 +1161,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CSELxw(ed, ed, x4, cNE);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
@@ -1216,12 +1191,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
if((nextop&0xF8)==0xE8) {
|
||||
INST_NAME("LFENCE");
|
||||
SMDMB();
|
||||
} else
|
||||
if((nextop&0xF8)==0xF0) {
|
||||
INST_NAME("MFENCE");
|
||||
SMDMB();
|
||||
} else
|
||||
if((nextop&0xF8)==0xF8) {
|
||||
INST_NAME("SFENCE");
|
||||
SMDMB();
|
||||
} else {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
@@ -1252,17 +1230,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("LDMXCSR Md");
|
||||
GETED(0);
|
||||
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
if(box64_sse_flushto0) {
|
||||
MRS_fpcr(x1); // get fpscr
|
||||
LSRw_IMM(x3, ed, 15); // get FZ bit
|
||||
BFIw(x1, x3, 24, 1); // inject FZ bit
|
||||
EORw_REG_LSR(x3, x3, ed, 1); // FZ xor DAZ
|
||||
BFIw(x1, x3, 1, 1); // inject AH bit
|
||||
MSR_fpcr(x1); // put new fpscr
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("STMXCSR Md");
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
LDRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
STRw_U12(x4, ed, fixedaddress);
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
STRw_U12(x4, ed, fixedaddress);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("CLFLUSH Ed");
|
||||
@@ -1320,6 +1301,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
@@ -1345,6 +1327,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CSELxw(ed, ed, x4, cEQ);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1363,6 +1346,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
UBFXxw(gd, eb1, eb2*8, 8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
|
||||
LDRB_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -1375,6 +1359,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UBFXxw(gd, ed, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
|
||||
LDRH_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -1391,6 +1376,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1407,6 +1393,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1419,6 +1406,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1430,6 +1418,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1442,6 +1431,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1453,6 +1443,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
|
||||
LDRxw_U12(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
@@ -1464,6 +1455,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
EORxw_REG_LSL(ed, ed, x4, u8);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1481,6 +1473,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
|
||||
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
|
||||
@@ -1505,6 +1498,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
EORxw_REG(ed, ed, x4);
|
||||
if(wback) {
|
||||
STRxw_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
@@ -1553,6 +1547,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
SBFXxw(gd, wback, wb2, 8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
|
||||
LDRSBxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -1565,6 +1560,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
SXTHxw(gd, ed);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
|
||||
LDRSHxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
@@ -1644,27 +1640,33 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("SHUFPS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
if(!MODREG)
|
||||
if(!MODREG) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
|
||||
else
|
||||
v1 = -1; // to avoid a warning
|
||||
} else
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
u8 = F8;
|
||||
if(MODREG && v0==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
|
||||
if(v0==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
|
||||
VDUPQ_32(v0, v0, u8&3);
|
||||
} else if(v0==v1 && (u8==0xe0)) { // easy special case
|
||||
VMOVeS(v0, 1, v0, 0);
|
||||
} else if(v0==v1 && (u8==0xe5)) { // easy special case
|
||||
VMOVeS(v0, 0, v0, 1);
|
||||
} else {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
// first two elements from Gx
|
||||
for(int i=0; i<2; ++i) {
|
||||
VMOVeS(d0, i, v0, (u8>>(i*2)&3));
|
||||
VMOVeS(d0, i, v0, (u8>>(i*2))&3);
|
||||
}
|
||||
// second two from Ex
|
||||
if(MODREG) {
|
||||
for(int i=2; i<4; ++i) {
|
||||
VMOVeS(d0, i, v1, (u8>>(i*2)&3));
|
||||
VMOVeS(d0, i, v1, (u8>>(i*2))&3);
|
||||
}
|
||||
} else {
|
||||
SMREAD();
|
||||
for(int i=2; i<4; ++i) {
|
||||
ADDx_U12(x2, ed, (u8>>(i*2)&3)*4);
|
||||
ADDx_U12(x2, ed, ((u8>>(i*2))&3)*4);
|
||||
VLD1_32(d0, i, x2);
|
||||
}
|
||||
}
|
||||
@@ -1805,10 +1807,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0xE7:
|
||||
INST_NAME("MOVNTQ Em, Gm"); // Non Temporal par not handled for now
|
||||
INST_NAME("MOVNTQ Em, Gm");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
|
||||
@@ -1858,7 +1860,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
gd = ((nextop&0x38)>>3);
|
||||
if(MODREG && ((nextop&7))==gd) {
|
||||
// special case for PXOR Gx, Gx
|
||||
// special case for PXOR Gm, Gm
|
||||
q0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
VEOR(q0, q0, q0);
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "emu/x64run_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "arm64_printer.h"
|
||||
#include "dynarec_arm64_private.h"
|
||||
@@ -91,6 +92,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
|
||||
@@ -101,12 +103,14 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETG;
|
||||
if(MODREG) {
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, ed, 0);
|
||||
VMOVeS(v0, 0, q0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR32_U12(v0, x4, fixedaddress);
|
||||
@@ -132,6 +136,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR128_U12(v0, x4, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@@ -148,6 +153,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR64_U12(v0, x4, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -156,13 +162,15 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if(MODREG) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
|
||||
ed = (nextop&7)+ (rex.b<<3);
|
||||
q0 = sse_get_reg(dyn, ninst, x1, ed, 1);
|
||||
VMOVeS(q0, 0, v0, 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VSTR32_U12(v0, x4, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -182,6 +190,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
ADDx_REG(x4, x4, ed);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
@@ -194,56 +203,69 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
|
||||
case 0xAF:
|
||||
INST_NAME("IMUL Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
if(rex.w) {
|
||||
// 64bits imul
|
||||
UFLAG_IF {
|
||||
SMULH(x3, gd, ed);
|
||||
MULx(gd, gd, ed);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_RES(gd);
|
||||
UFLAG_DF(x3, d_imul64);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
} else {
|
||||
// 32bits imul
|
||||
UFLAG_IF {
|
||||
SMULL(gd, gd, ed);
|
||||
UFLAG_RES(gd);
|
||||
LSRx(x3, gd, 32);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
MOVw_REG(gd, gd);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("IMUL Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_PENDING);
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
GETGD;
|
||||
GETEDO(x4, 0);
|
||||
if(rex.w) {
|
||||
// 64bits imul
|
||||
UFLAG_IF {
|
||||
SMULH(x3, gd, ed);
|
||||
MULx(gd, gd, ed);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_RES(gd);
|
||||
UFLAG_DF(x3, d_imul64);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
} else {
|
||||
// 32bits imul
|
||||
UFLAG_IF {
|
||||
SMULL(gd, gd, ed);
|
||||
UFLAG_RES(gd);
|
||||
LSRx(x3, gd, 32);
|
||||
UFLAG_OP1(x3);
|
||||
UFLAG_DF(x3, d_imul32);
|
||||
MOVw_REG(gd, gd);
|
||||
} else {
|
||||
MULxw(gd, gd, ed);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6:
|
||||
INST_NAME("MOVZX Gd, Eb");
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
}
|
||||
UBFXxw(gd, eb1, eb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRB_REG(gd, ed, x4);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("MOVZX Gd, Eb");
|
||||
nextop = F8;
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
eb2 = 0; \
|
||||
} else {
|
||||
ed = (nextop&7);
|
||||
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
}
|
||||
UBFXxw(gd, eb1, eb2*8, 8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRB_REG(gd, ed, x4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -301,6 +323,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRSW_REG(gd, ed, x4);
|
||||
}
|
||||
@@ -309,6 +332,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRw_REG(gd, ed, x4);
|
||||
}
|
||||
@@ -316,7 +340,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
@@ -510,6 +534,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRB_REG(x4, wback, x4);
|
||||
ed = x4;
|
||||
@@ -526,6 +551,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
STRxw_REG(gd, ed, x4);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -537,6 +563,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(MODREG) { // reg <= reg
|
||||
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
LDRxw_REG(gd, ed, x4);
|
||||
}
|
||||
@@ -563,6 +590,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
MOV32w(x3, u8);
|
||||
STRB_REG(x3, ed, x4);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
@@ -578,6 +606,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i64 = F32S;
|
||||
MOV64xw(x3, i64);
|
||||
STRxw_REG(x3, ed, x4);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -799,7 +828,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("NOT Ed");
|
||||
GETEDO(x6, 4);
|
||||
GETEDO(x6, 0);
|
||||
MVNxw_REG(ed, ed);
|
||||
WBACKO(x6);
|
||||
break;
|
||||
@@ -956,18 +985,34 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
}
|
||||
GETEDOx(x6, 0);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
if(!dyn->insts || ninst==dyn->size-1) {
|
||||
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
GETIP_(addr);
|
||||
if(box64_dynarec_callret) {
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
} else {
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
TABLE64(x4, j64);
|
||||
LDRx_U12(x4, x4, 0);
|
||||
}
|
||||
STPx_S7_preindex(x4, xRIP, xSP, -16);
|
||||
}
|
||||
PUSH1(xRIP);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
break;
|
||||
case 4: // JMP Ed
|
||||
INST_NAME("JMP Ed");
|
||||
BARRIER(1);
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
GETEDOx(x6, 0);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
*need_epilog = 0;
|
||||
|
||||
@@ -295,9 +295,11 @@ 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);
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
|
||||
break;
|
||||
case 0x65:
|
||||
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
|
||||
break;
|
||||
@@ -444,7 +446,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
TSTx_mask(ed, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
@@ -456,7 +458,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRH_U12(x1, ed, 0);
|
||||
STRH_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
@@ -473,10 +475,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
|
||||
STRH_U12(gd, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x8B:
|
||||
@@ -490,10 +489,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMREADLOCK(lock);
|
||||
LDRH_U12(x1, ed, fixedaddress);
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
@@ -537,6 +533,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u64 = F64;
|
||||
MOV64x(x1, u64);
|
||||
STRH_U12(xRAX, x1, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
|
||||
case 0xA5:
|
||||
@@ -714,10 +711,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u16 = F16;
|
||||
MOV32w(x1, u16);
|
||||
STRH_U12(x1, ed, fixedaddress);
|
||||
if(lock || (box64_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -22,26 +22,6 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// Get EX as a quad
|
||||
#define GETEX(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR128_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
#define GETGX(a, w) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
#define GETGX_empty(a) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
@@ -81,6 +61,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
@@ -97,6 +78,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -108,6 +90,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(v0, 0, ed);
|
||||
break;
|
||||
@@ -122,6 +105,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VST1_64(v0, 0, ed);
|
||||
SMWRITE2();
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("UNPCKLPD Gx, Ex");
|
||||
@@ -131,6 +115,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
VMOVeD(v0, 1, v1, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(v0, 1, ed);
|
||||
}
|
||||
@@ -144,6 +129,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
VMOVeD(v0, 1, v1, 1);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
ADDx_U12(ed, ed, 8);
|
||||
@@ -159,6 +145,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VLD1_64(v0, 1, ed);
|
||||
break;
|
||||
@@ -173,6 +160,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VST1_64(v0, 1, ed);
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
@@ -191,6 +179,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
@@ -208,6 +197,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -673,9 +663,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("PINSRB Gx, ED, Ib");
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEB(x1, 1);
|
||||
GETED(1);
|
||||
u8 = F8;
|
||||
VMOVQBfrom(q0, (u8&15), x1);
|
||||
VMOVQBfrom(q0, (u8&15), ed);
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
@@ -772,6 +762,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0); \
|
||||
LDRH_U12(x1, ed, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -803,13 +794,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
// check if any input value was NAN
|
||||
VFCMEQQD(v0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFSQRTQD(q1, q0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
VFSQRTQD(q1, q0);
|
||||
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
} else {
|
||||
VFSQRTQD(q1, q0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -893,25 +884,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETEX(v1, 0, 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);
|
||||
// Construct a "switch case", with each case 2 instructions, so 8 bytes
|
||||
ADR(xLR, GETMARK);
|
||||
ADDx_REG(xLR, xLR, x1);
|
||||
B(xLR);
|
||||
MARK;
|
||||
VFCVTNSQS(v0, v1); // 0: Nearest (even)
|
||||
B_NEXT_nocond;
|
||||
VFCVTMSQS(v0, v1); // 1: Toward -inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTPSQS(v0, v1); // 2: Toward +inf
|
||||
B_NEXT_nocond;
|
||||
VFCVTZSQS(v0, v1); // 3: Toward 0
|
||||
#else
|
||||
VFCVTNSQS(v0, v1);
|
||||
#endif
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
VFRINTISQ(v0, v1);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
VFCVTZSQS(v0, v0);
|
||||
break;
|
||||
case 0x5C:
|
||||
INST_NAME("SUBPD Gx, Ex");
|
||||
@@ -1113,6 +1089,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -1187,6 +1164,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
|
||||
u8 = F8;
|
||||
if (u8) {
|
||||
@@ -1216,9 +1194,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else if(u8) {
|
||||
VSHRQ_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -1229,9 +1205,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(u8) {
|
||||
VSSHRQ_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLW Ex, Ib");
|
||||
@@ -1243,9 +1217,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
VSHLQ_16(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1266,9 +1238,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else if(u8) {
|
||||
VSHRQ_32(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -1279,9 +1249,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(u8) {
|
||||
VSSHRQ_32(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("PSLLD Ex, Ib");
|
||||
@@ -1293,9 +1261,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
VSHLQ_32(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1315,9 +1281,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else if(u8) {
|
||||
VSHRQ_64(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@@ -1332,9 +1296,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEORQ(q1, q1, q1);
|
||||
VEXTQ_8(q0, q0, q1, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1347,9 +1309,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
VSHLQ_64(q0, q0, u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
@@ -1364,9 +1324,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEORQ(q1, q1, q1);
|
||||
VEXTQ_8(q0, q1, q0, 16-u8);
|
||||
}
|
||||
if(!MODREG) {
|
||||
VSTR128_U12(q0, ed, fixedaddress);
|
||||
}
|
||||
PUTEX(q0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1431,6 +1389,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
} else {
|
||||
if(MODREG) {
|
||||
@@ -1439,6 +1398,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VSTR32_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1452,6 +1412,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1464,6 +1425,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
|
||||
@@ -1566,6 +1528,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
@@ -1583,6 +1546,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1600,6 +1564,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
UBFXxw(x1, eb1, eb2*8, 8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
|
||||
LDRB_U12(x1, ed, fixedaddress);
|
||||
}
|
||||
@@ -1613,6 +1578,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
eb1 = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UBFXxw(x1, eb1, 0, 16);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff>>1, 1, rex, NULL, 0, 0);
|
||||
LDRH_U12(x1, ed, fixedaddress);
|
||||
}
|
||||
@@ -1631,6 +1597,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
|
||||
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
|
||||
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
|
||||
@@ -1647,6 +1614,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
EORx_REG(ed, ed, x1);
|
||||
if(wback) {
|
||||
STRH_U12(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
@@ -1699,6 +1667,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
SBFXw(x1, eb1, eb2, 8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
|
||||
LDRSBw_U12(x1, ed, fixedaddress);
|
||||
}
|
||||
@@ -1746,6 +1715,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
VMOVQHfrom(v0, u8, ed);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
|
||||
u8 = (F8)&7;
|
||||
VLD1_16(v0, u8, wback);
|
||||
@@ -1760,6 +1730,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
u8 = (F8)&7;
|
||||
VMOVHto(gd, v0, u8);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
|
||||
u8 = (F8)&7;
|
||||
LDRH_U12(gd, wback, u8*2);
|
||||
@@ -1858,6 +1829,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0xD7:
|
||||
@@ -2012,7 +1984,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETEX(v1, 0, 0);
|
||||
GETGX_empty(v0);
|
||||
VFCVTNSQD(v0, v1); // convert double -> int64
|
||||
VFCVTZSQD(v0, v1); // convert double -> int64
|
||||
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
|
||||
break;
|
||||
case 0xE7:
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
|
||||
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)rep; (void)need_epilog;
|
||||
(void)ip; (void)need_epilog;
|
||||
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
@@ -53,7 +53,6 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x0F:
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
/* //Something is wrong, and this gives a SIGILL
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
@@ -61,18 +60,19 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETG;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
|
||||
if(MODREG) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
v1 = fpu_get_scratch(dyn); \
|
||||
VLDR128_REG(v1, ed, x4);
|
||||
VLDR64_REG(v1, ed, x4);
|
||||
}
|
||||
FCMPD(v0, v1);
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
*/
|
||||
case 0xD6:
|
||||
INST_NAME("MOVQ Ex, Gx");
|
||||
nextop = F8;
|
||||
@@ -82,9 +82,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
|
||||
FMOVD(v1, v0);
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
VSTR64_REG(v0, ed, x4);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -107,13 +108,14 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
if(rex.w) {
|
||||
STRx_REG(gd, ed, x4);
|
||||
} else {
|
||||
STRH_REG(gd, ed, x4);
|
||||
}
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -131,7 +133,8 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
}
|
||||
} else { // mem <= reg
|
||||
grab_segdata(dyn, addr, ninst, x4, _FS);
|
||||
grab_segdata(dyn, addr, ninst, x4, seg);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
if(rex.w) {
|
||||
LDRx_REG(gd, ed, x4);
|
||||
|
||||
@@ -57,7 +57,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x5);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -71,7 +71,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
@@ -83,13 +83,12 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
UXTHw(x6, xRAX);
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
UXTHw(x1, ed);
|
||||
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
|
||||
CMPSxw_REG(x6, x1);
|
||||
B_MARK(cNE);
|
||||
BFIx(ed, gd, 0, 16);
|
||||
@@ -120,9 +119,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
MARK;
|
||||
// Common part (and fallback for EAX != Ed)
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, x6, x1, x3, x4, x5);}
|
||||
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
|
||||
BFIx(xRAX, x1, 0, 16);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
@@ -131,7 +130,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
|
||||
UXTHx(x5, gd);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
BFIx(gd, ed, 0, 16);
|
||||
@@ -150,7 +149,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
BFIx(gd, x1, 0, 16);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -161,7 +160,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -347,15 +346,13 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(opcode==0x81) i32 = F16S; else i32 = F8S;
|
||||
if(i32) {
|
||||
MOV32w(x5, i32);
|
||||
UXTHw(x6, ed);
|
||||
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
|
||||
BFIx(ed, x6, 0, 16);
|
||||
} else {
|
||||
emit_cmp16_0(dyn, ninst, ed, x3, x4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
@@ -365,7 +362,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0: // INC Ew
|
||||
INST_NAME("LOCK INC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -379,12 +376,12 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 1: //DEC Ew
|
||||
INST_NAME("LOCK DEC Ew");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
UXTHw(x6, ed);
|
||||
@@ -398,7 +395,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -44,7 +44,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int64_t j64, i64;
|
||||
int cacheupd;
|
||||
int cacheupd = 0;
|
||||
int lock;
|
||||
int v0, v1, s0;
|
||||
MAYUSE(i32);
|
||||
@@ -175,50 +175,67 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0x2E:
|
||||
// no special check...
|
||||
case 0x2F:
|
||||
if(rep) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if(MODREG) {
|
||||
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
}
|
||||
FCMPS(v0, s0);
|
||||
FCOMI(x1, x2);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
if(MODREG) {
|
||||
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
|
||||
} else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
}
|
||||
FCMPS(v0, s0);
|
||||
FCOMI(x1, x2);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6F:
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
GETGm;
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); // no rex.b on MMX
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
VMOV(v0, v1);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
GETGm;
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); // no rex.b on MMX
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
VMOV(v0, v1);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
SMREAD();
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7F:
|
||||
INST_NAME("MOVQ Em, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
VMOV(v1, v0);
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("MOVQ Em, Gm");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
if(MODREG) {
|
||||
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
VMOV(v1, v0);
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -633,7 +650,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else { // mem <= reg
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
|
||||
STRxw_U12(gd, ed, fixedaddress);
|
||||
if(lock) {DMB_ISH();}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -645,7 +662,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
|
||||
} else {
|
||||
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
|
||||
if(lock) {DMB_ISH();}
|
||||
SMREADLOCK(lock);
|
||||
LDRxw_U12(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -750,7 +767,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
i64 = F32S;
|
||||
MOV64xw(x3, i64);
|
||||
STRxw_U12(x3, ed, fixedaddress);
|
||||
if(lock) {DMB_ISH();}
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -281,7 +281,11 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
#else
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x3);
|
||||
FRINTID(v1, v1);
|
||||
if(ST_IS_F(0)) {
|
||||
FRINTIS(v1, v1);
|
||||
} else {
|
||||
FRINTID(v1, v1);
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
#endif
|
||||
break;
|
||||
@@ -324,14 +328,10 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0:
|
||||
INST_NAME("FLD ST0, float[ED]");
|
||||
v1 = x87_do_push(dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
VLDR32_U12(v1, ed, fixedaddress);
|
||||
if(!ST_IS_F(0)) {
|
||||
FCVT_D_S(v1, s0);
|
||||
FCVT_D_S(v1, v1);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -349,14 +349,11 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 3:
|
||||
INST_NAME("FSTP float[ED], ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
if(ST_IS_F(0))
|
||||
s0 = v1;
|
||||
else {
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
FCVT_S_D(s0, v1);
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VSTR32_U12(s0, ed, fixedaddress);
|
||||
if(!ST_IS_F(0)) {
|
||||
FCVT_S_D(v1, v1);
|
||||
}
|
||||
VSTR32_U12(v1, ed, fixedaddress);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 4:
|
||||
|
||||
@@ -189,24 +189,18 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ed");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(s0, ed, fixedaddress);
|
||||
SXTL_32(v1, s0);
|
||||
SCVTFDD(v1, v1);
|
||||
VLDR32_U12(v1, ed, fixedaddress);
|
||||
SXTL_32(v1, v1); // i32 -> i64
|
||||
SCVTFDD(v1, v1); // i64 -> double
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
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, NULL, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
ed = x1;
|
||||
FRINT32ZD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
@@ -230,15 +224,10 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FIST Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
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, NULL, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
ed = x1;
|
||||
FRINT32XD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
@@ -262,15 +251,10 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FISTP Ed, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
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, NULL, 0, 0);
|
||||
ed = x1;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
s0 = fpu_get_scratch(dyn);
|
||||
#if 0
|
||||
ed = x1;
|
||||
FRINT32XD(s0, v1);
|
||||
FCVTZSwD(ed, s0);
|
||||
WBACK;
|
||||
@@ -294,33 +278,101 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
if((PK(0)==0xDB && ((PK(1)>>3)&7)==7) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDRx_U12(x5, ed, 0);
|
||||
LDRH_U12(x6, ed, 8);
|
||||
// no persistant scratch register, so unrool both instruction here...
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; // 0xDB or rex
|
||||
if(nextop>=0x40 && nextop<=0x4f) {
|
||||
rex.rex = nextop;
|
||||
nextop = F8; //0xDB
|
||||
} else
|
||||
rex.rex = 0;
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
STRx_U12(x5, ed, 0);
|
||||
STRH_U12(x6, ed, 8);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
if(box64_x87_no80bits) {
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v1, ed, fixedaddress);
|
||||
} else {
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
CALL(arm_fld, -1);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
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, NULL, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
if(box64_x87_no80bits) {
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v1, wback, fixedaddress);
|
||||
} else {
|
||||
#if 0
|
||||
x87_forget(dyn, ninst, x1, x3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOVx_REG(x1, ed);
|
||||
}
|
||||
CALL(arm_fstp, -1);
|
||||
#else
|
||||
// Painfully long, straight conversion from the C code, shoud be optimized
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
|
||||
FMOVxD(x1, v1);
|
||||
// do special value first
|
||||
TSTx_mask(x1, 1, 0b00000, 0b111110); //0x7fffffffffffffffL
|
||||
B_MARK(cNE);
|
||||
// Zero
|
||||
LSRx(x3, x1, 63-15); //x3 = sign+exp
|
||||
MOVZw(x5, 0); // x5 = mantisse
|
||||
B_MARK3_nocond;
|
||||
MARK;
|
||||
// get sign, in main ouput x5 for sign+exp
|
||||
ANDx_mask(x5, x1, 1, 1, 0); //0x8000000000000000
|
||||
LSRx(x5, x5, 63-15); // x5 = sign
|
||||
// get exp
|
||||
LSRx(x3, x1, 52); // x3 = exp11
|
||||
ANDw_mask(x3, x3, 0, 0b1010); //0x7ff
|
||||
MOV32w(x4, 0x7ff);
|
||||
CMPSw_REG(x3, x4);
|
||||
B_MARK2(cNE);
|
||||
// NaN and Infinite
|
||||
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
|
||||
TSTx_mask(x1, 1, 0, 0b110011); //0x000fffffffffffffL
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
ORRx_mask(x4, xZR, 1, 0b10, 0b01); //0xc000000000000000
|
||||
CSELx(x5, x5, x4, cEQ); // x5 = mantisse
|
||||
B_MARK3_nocond;
|
||||
MARK2;
|
||||
// regular / denormals
|
||||
ANDx_mask(x1, x1, 1, 0, 0b110011); //0x000fffffffffffffL
|
||||
LSLx_IMM(x1, x1, 11); //x1 = mantisse missing "1"
|
||||
MOVZw(x4, 16383-1023); //BIAS80 - BIAS64
|
||||
CBZw(x3, 4+3*4); // exp11 == 0?
|
||||
// normals
|
||||
ADDw_REG(x3, x3, x4); // x3 = exp16
|
||||
ORRw_REG(x3, x3, x5); // x3 = sign | exp
|
||||
ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000 x5 = mantisse
|
||||
B_MARK3_nocond;
|
||||
// denormals
|
||||
CLZx(x6, x1);
|
||||
ADDw_U12(x6, x6, 1); // "one"
|
||||
SUBw_REG(x3, x4, x6); // x3 = exp16
|
||||
ORRw_REG(x3, x3, x5); // x3 = sign | exp16
|
||||
LSLx_REG(x5, x1, x6); // x5 = mantisse
|
||||
MARK3;
|
||||
STRx_U12(x5, wback, 0);
|
||||
STRH_U12(x3, wback, 8);
|
||||
#endif
|
||||
}
|
||||
CALL(arm_fstp, -1);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -182,7 +182,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FADD ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FADDD(v1, v1, v2);
|
||||
break;
|
||||
@@ -190,7 +190,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FMUL ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FMULD(v1, v1, v2);
|
||||
break;
|
||||
@@ -198,7 +198,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FCOM ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
@@ -207,7 +207,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FCOMP ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FCMPD(v1, v2);
|
||||
FCOM(x1, x2, x3);
|
||||
@@ -217,7 +217,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FSUB ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v1, v2);
|
||||
break;
|
||||
@@ -225,7 +225,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FSUBR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FSUBD(v1, v2, v1);
|
||||
break;
|
||||
@@ -233,7 +233,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FDIV ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v1, v2);
|
||||
break;
|
||||
@@ -241,7 +241,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("FDIVR ST0, double[ED]");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v2, wback, fixedaddress);
|
||||
FDIVD(v1, v2, v1);
|
||||
break;
|
||||
|
||||
@@ -33,10 +33,12 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
int64_t fixedaddress;
|
||||
int v1, v2;
|
||||
int s0;
|
||||
int64_t j64;
|
||||
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(j64);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -170,11 +172,21 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
#if 0
|
||||
// those are ARM 8.5 opcode!
|
||||
FRINT64ZD(s0, v1);
|
||||
#else
|
||||
FRINTRRD(s0, v1, 3); // not ideal, might averflow and not set 0x8000000000000000 correctly
|
||||
#endif
|
||||
FCVTZSxD(x2, s0);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
#else
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
FRINTRRD(s0, v1, 3);
|
||||
FCVTZSxD(x2, s0);
|
||||
STRx_U12(x2, ed, fixedaddress);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
STRw_U12(x5, ed, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
case 2:
|
||||
|
||||
@@ -308,7 +308,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VSTR64_U12(s0, wback, fixedaddress);
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_MARK3(x5, FPSR_IOC);
|
||||
MOV64x(x5, 0x8000000000000000LL);
|
||||
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
|
||||
STRx_U12(x5, wback, fixedaddress);
|
||||
MARK3;
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -78,7 +78,7 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -109,7 +109,7 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -140,7 +140,7 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -174,7 +174,7 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -208,7 +208,7 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIx(xFlags, s3, F_SF, 1);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
@@ -579,9 +579,6 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_CF | X_AF | X_OF) {
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw_REG(xFlags, xFlags, s3);
|
||||
|
||||
@@ -157,8 +157,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
IFX(X_AF) {
|
||||
MVNxw_REG(s3, s1);
|
||||
ORRxw_REG(s3, s3, s2); // s3 = ~op1 | op2
|
||||
ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2
|
||||
BICxw(s4, s2, s1); // s4 = ~op1 & op2
|
||||
}
|
||||
IFX(X_ALL) {
|
||||
@@ -612,8 +611,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
MVNw_REG(s3, s1);
|
||||
ORRw_REG(s3, s3, s2); // s3 = ~op1 | op2
|
||||
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
|
||||
BICw_REG(s4, s2, s1); // s4 = ~op1 & op2
|
||||
}
|
||||
|
||||
@@ -920,7 +918,11 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
ANDw_mask(s4, s3, 0, 0); // s4 = ~op1 & op2
|
||||
ORRw_mask(s3, s3, 0, 0); // s3 = ~op1 | op2
|
||||
}
|
||||
SUBSw_U12(s1, s1, 1);
|
||||
IFX(X_ZF) {
|
||||
SUBSw_U12(s1, s1, 1);
|
||||
} else {
|
||||
SUBw_U12(s1, s1, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
@@ -962,7 +964,11 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_AF|X_OF) {
|
||||
MVNw_REG(s4, s1);
|
||||
}
|
||||
SUBSw_U12(s1, s1, 1);
|
||||
IFX(X_ZF) {
|
||||
SUBSw_U12(s1, s1, 1);
|
||||
} else {
|
||||
SUBw_U12(s1, s1, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
@@ -1177,54 +1183,7 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s5, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s4, d_adc8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
MOVw_REG(s4, s1);
|
||||
}
|
||||
MRS_nzvc(s3);
|
||||
BFIx(s3, xFlags, 29, 1); // set C
|
||||
MSR_nzvc(s3); // load CC into ARM CF
|
||||
ADCw_REG(s1, s1, s5);
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORRw_REG(s3, s4, s5); // s3 = op1 | op2
|
||||
ANDw_REG(s4, s4, s5); // s4 = op1 & op2
|
||||
BICw_REG(s3, s3, s1); // s3 = (op1 | op2) & ~ res
|
||||
ORRw_REG(s3, s3, s4); // s4 = (op1 & op2) | ((op1 | op2) & ~ res)
|
||||
IFX(X_AF) {
|
||||
LSRw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_OF) {
|
||||
LSRw(s4, s3, 6);
|
||||
EORw_REG_LSR(s4, s4, s4, 1);
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_CF) {
|
||||
LSRw(s3, s1, 8);
|
||||
BFIw(xFlags, s3, F_CF, 1);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
emit_adc8(dyn, ninst, s1, s5, s3, s4);
|
||||
}
|
||||
|
||||
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
@@ -1246,7 +1205,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) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
STRw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORRw_REG(s3, s4, s2); // s3 = op1 | op2
|
||||
@@ -1536,55 +1495,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
|
||||
{
|
||||
MAYUSE(s5);
|
||||
MOV32w(s5, c&0xff);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
|
||||
STRB_U12(s5, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s3, d_sbb8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
EORw_mask(s4, xFlags, 0, 0); // invert CC because it's reverted for SUB on ARM
|
||||
MRS_nzvc(s3);
|
||||
BFIx(s3, s4, 29, 1); // set C, bit 29
|
||||
MSR_nzvc(s3); // load CC into ARM CF
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
MVNw_REG(s4, s1);
|
||||
}
|
||||
SBCw_REG(s1, s1, s5);
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
ORRw_REG(s3, s4, s5); // s3 = ~op1 | op2
|
||||
ANDw_REG(s4, s4, s5); // s4 = ~op1 & op2
|
||||
ANDw_REG(s3, s3, s1); // s3 = (~op1 | op2) & res
|
||||
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
|
||||
IFX(X_CF) {
|
||||
LSRw(s4, s3, 7);
|
||||
BFIw(xFlags, s4, F_CF, 1); // CF : bc & 0x80
|
||||
}
|
||||
IFX(X_AF) {
|
||||
LSRw(s4, s3, 3);
|
||||
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
|
||||
}
|
||||
IFX(X_OF) {
|
||||
LSRw(s4, s3, 6);
|
||||
EORw_REG_LSR(s4, s4, s4, 1);
|
||||
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRw(s3, s1, 7);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
}
|
||||
IFX(X_PF) {
|
||||
emit_pf(dyn, ninst, s1, s3, s4);
|
||||
}
|
||||
emit_sbb8(dyn, ninst, s1, s5, s3, s4);
|
||||
}
|
||||
|
||||
// emit SBB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
|
||||
@@ -1773,7 +1684,11 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_AF|X_OF) {
|
||||
MOVw_REG(s3, s1);
|
||||
}
|
||||
NEGSw_REG(s1, s1);
|
||||
IFX(X_ZF) {
|
||||
NEGSw_REG(s1, s1);
|
||||
} else {
|
||||
NEGw_REG(s1, s1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
@@ -1819,7 +1734,11 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_AF|X_OF) {
|
||||
MOVw_REG(s3, s1);
|
||||
}
|
||||
NEGSw_REG(s1, s1);
|
||||
IFX(X_ZF) {
|
||||
NEGSw_REG(s1, s1);
|
||||
} else {
|
||||
NEGw_REG(s1, s1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
|
||||
@@ -37,14 +37,11 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(F_OF) {
|
||||
IFX(X_OF) {
|
||||
CMPSxw_U12(s2, 0);
|
||||
IFX(F_OF) {
|
||||
Bcond(cNE, +8);
|
||||
BFCx(xFlags, F_OF, 1);
|
||||
}
|
||||
Bcond(cNE, +8+((dyn->insts[ninst].x64.gen_flags&X_PEND)?4:0));
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
IFX(X_PEND) {
|
||||
Bcond(cNE, +8);
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
B_NEXT(cEQ);
|
||||
@@ -81,7 +78,7 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
|
||||
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
@@ -92,8 +89,8 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c==0) {
|
||||
IFX(F_OF) {
|
||||
BFCx(xFlags, F_OF, 1);
|
||||
IFX(X_OF) {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
@@ -175,11 +172,7 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
IFX(X_OF) {
|
||||
CMPSxw_U12(s2, 1); // if s2==1
|
||||
Bcond(cNE, 4+3*4);
|
||||
if(rex.w) {
|
||||
LSRx(s4, s1, 62);
|
||||
} else {
|
||||
LSRw(s4, s1, 30);
|
||||
}
|
||||
LSRxw(s4, s1, rex.w?62:30);
|
||||
EORw_REG_LSR(s4, s4, s4, 1);
|
||||
BFIw(xFlags, s4, F_OF, 1);
|
||||
}
|
||||
@@ -189,7 +182,7 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
|
||||
}
|
||||
|
||||
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
@@ -206,10 +199,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
|
||||
LSRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
@@ -237,7 +228,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
@@ -254,10 +245,8 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c>1) {
|
||||
ASRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
|
||||
ASRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
ASRxw(s1, s1, c);
|
||||
IFX(X_PEND) {
|
||||
@@ -278,13 +267,13 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
MOV32w(s3, c);
|
||||
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
|
||||
SET_DF(s4, d_rol32);
|
||||
SET_DF(s4, rex.w?d_rol64:d_rol32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
@@ -310,7 +299,7 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
|
||||
{
|
||||
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
|
||||
IFX(X_PEND) {
|
||||
@@ -344,7 +333,7 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
|
||||
}
|
||||
|
||||
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
@@ -363,10 +352,8 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
if(c>1) {
|
||||
LSRxw(s3, s1, c-1);
|
||||
}
|
||||
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
|
||||
LSRxw(s3, s1, c-1);
|
||||
BFIw(xFlags, s3, 0, 1);
|
||||
}
|
||||
LSRxw(s3, s1, c);
|
||||
ORRxw_REG_LSL(s1, s3, s2, (rex.w?64:32)-c);
|
||||
@@ -394,7 +381,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
|
||||
}
|
||||
}
|
||||
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
|
||||
{
|
||||
c&=(rex.w?0x3f:0x1f);
|
||||
IFX(X_PEND) {
|
||||
@@ -407,8 +394,8 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
if(c==0) {
|
||||
IFX(F_OF) {
|
||||
BFCx(xFlags, F_OF, 1);
|
||||
IFX(X_OF) {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
|
||||
|
||||
@@ -85,19 +85,14 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
|
||||
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
|
||||
// and now the tricky ones (and mostly unused), PF and AF
|
||||
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
|
||||
IFX(X_OF|X_AF) {
|
||||
MOV32w(s4, (1<<F_OF)|(1<<F_AF));
|
||||
IFX(X_OF|X_AF|X_CF) {
|
||||
MOV32w(s4, (1<<F_OF)|(1<<F_AF)|(1<<F_CF));
|
||||
BICw(xFlags, xFlags, s4);
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
CSETw(s4, cEQ);
|
||||
BFIw(xFlags, s4, F_ZF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
// inverted carry
|
||||
CSETw(s4, cCC);
|
||||
BFIw(xFlags, s4, F_CF, 1);
|
||||
}
|
||||
IFX(X_SF) {
|
||||
LSRxw(s3, s1, (rex.w)?63:31);
|
||||
BFIw(xFlags, s3, F_SF, 1);
|
||||
@@ -118,12 +113,15 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
} else {
|
||||
SET_DFNONE(s3);
|
||||
}
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
IFX(X_ZF) {
|
||||
SUBSw_REG(s5, s1, s2); // res = s1 - s2
|
||||
} else {
|
||||
SUBw_REG(s5, s1, s2); // res = s1 - s2
|
||||
}
|
||||
IFX_PENDOR0 {
|
||||
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTw_mask(s5, 0, 15); //mask=0xffff
|
||||
CSETw(s3, cEQ);
|
||||
BFIw(xFlags, s3, F_ZF, 1);
|
||||
}
|
||||
@@ -316,11 +314,9 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
BFCw(xFlags, F_CF, 1);
|
||||
IFX(X_CF | X_AF | X_OF) {
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
ANDSw_REG(s5, s1, s2); // res = s1 & s2
|
||||
IFX_PENDOR0 {
|
||||
@@ -349,11 +345,9 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
} else {
|
||||
SET_DFNONE(s4);
|
||||
}
|
||||
IFX(X_OF) {
|
||||
BFCw(xFlags, F_OF, 1);
|
||||
}
|
||||
IFX(X_CF) {
|
||||
BFCw(xFlags, F_CF, 1);
|
||||
IFX(X_CF | X_AF | X_OF) {
|
||||
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
|
||||
BICw(xFlags, xFlags, s3);
|
||||
}
|
||||
ANDSw_REG(s5, s1, s2); // res = s1 & s2
|
||||
IFX_PENDOR0 {
|
||||
|
||||
@@ -58,7 +58,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
INST_NAME("LOCK ADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(rex.rex) {
|
||||
@@ -76,18 +76,18 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_add8(dyn, ninst, x1, x2, x4, x3);
|
||||
emit_add8(dyn, ninst, x1, x2, x4, x5);
|
||||
STLXRB(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("LOCK ADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -99,14 +99,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
INST_NAME("LOCK OR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(rex.rex) {
|
||||
@@ -124,18 +124,18 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_or8(dyn, ninst, x1, x2, x4, x3);
|
||||
emit_or8(dyn, ninst, x1, x2, x4, x5);
|
||||
STLXRB(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x09:
|
||||
INST_NAME("LOCK OR Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -147,169 +147,297 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
|
||||
case 0xB0:
|
||||
INST_NAME("LOCK CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x1);
|
||||
UBFXx(x6, xRAX, 0, 8);
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2)*8;
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
UBFXx(x2, wback, wb2, 8);
|
||||
wb1 = 0;
|
||||
ed = x2;
|
||||
UFLAG_IF {emit_cmp8(dyn, ninst, x6, ed, x3, x4, x5);}
|
||||
CMPSxw_REG(x6, x2);
|
||||
B_MARK2(cNE);
|
||||
BFIx(wback, x2, wb2, 8);
|
||||
MOVxw_REG(ed, gd);
|
||||
MARK2;
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
B_NEXT_nocond;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
// Aligned version
|
||||
MARKLOCK;
|
||||
LDAXRB(x2, wback);
|
||||
CMPSxw_REG(x6, x2);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
MARK;
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, x6, x2, x3, x4, x5);}
|
||||
BFIx(xRAX, x2, 0, 8); // upper par of RAX will be erase on 32bits, no mater what
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 0xB1:
|
||||
INST_NAME("LOCK CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
case 0xAB:
|
||||
INST_NAME("LOCK BTS Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
|
||||
MOVxw_REG(x1, ed); // save value
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK2(cNE);
|
||||
MOVxw_REG(ed, gd);
|
||||
MARK2;
|
||||
MOVxw_REG(xRAX, x1);
|
||||
B_NEXT_nocond;
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
} else {
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLxw_REG(x4, x4, x2);
|
||||
EORxw_REG(x4, ed, x4);
|
||||
CSELxw(ed, ed, x4, cNE);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK3(cNE);
|
||||
// Aligned version
|
||||
// Will fetch only 1 byte, to avoid alignment issue
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00010); //mask=0x0000000000000007
|
||||
} else {
|
||||
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
|
||||
}
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
ASRxw(x1, gd, 3); // r1 = (gd>>3)
|
||||
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRxw(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
B_MARK_nocond;
|
||||
// Unaligned version
|
||||
MARK3;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x3, wback); // dummy read, to arm the write...
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARK3(x4);
|
||||
STRxw_U12(gd, wback, 0);
|
||||
MARK;
|
||||
// Common part (and fallback for EAX != 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
|
||||
LDAXRB(x1, wback);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
LSRw_REG(x4, ed, x2);
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLw_REG(x4, x4, x2);
|
||||
EORw_REG(x4, ed, x4);
|
||||
CSELw(ed, ed, x4, cNE);
|
||||
STLXRB(x4, ed, wback);
|
||||
CBNZw_MARKLOCK(x4);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 0xB0:
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("LOCK CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x1);
|
||||
UBFXx(x6, xRAX, 0, 8);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
if(rex.rex) {
|
||||
wback = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wb2 = 0;
|
||||
} else {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2)*8;
|
||||
wback = xRAX+(wback&3);
|
||||
}
|
||||
UBFXx(x2, wback, wb2, 8);
|
||||
wb1 = 0;
|
||||
ed = x2;
|
||||
UFLAG_IF {emit_cmp8(dyn, ninst, x6, ed, x3, x4, x5);}
|
||||
CMPSxw_REG(x6, x2);
|
||||
B_MARK2(cNE);
|
||||
BFIx(wback, x2, wb2, 8);
|
||||
MOVxw_REG(ed, gd);
|
||||
MARK2;
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
B_NEXT_nocond;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x2, wback);
|
||||
CMPSxw_REG(x6, x2);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
MARK;
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, x6, x2, x3, x4, x5);}
|
||||
BFIx(xRAX, x2, 0, 8);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xB1:
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("LOCK CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
|
||||
MOVxw_REG(x1, ed); // save value
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK2(cNE);
|
||||
MOVxw_REG(ed, gd);
|
||||
MARK2;
|
||||
MOVxw_REG(xRAX, x1);
|
||||
B_NEXT_nocond;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK3(cNE);
|
||||
// Aligned version
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRxw(x4, gd, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
// done
|
||||
B_MARK_nocond;
|
||||
// Unaligned version
|
||||
MARK3;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x3, wback); // dummy read, to arm the write...
|
||||
CMPSxw_REG(xRAX, x1);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STLXRB(x4, gd, wback);
|
||||
CBNZx_MARK3(x4);
|
||||
STRxw_U12(gd, wback, 0);
|
||||
MARK;
|
||||
// Common part (and fallback for EAX != 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
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB3:
|
||||
INST_NAME("LOCK BTR Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
wback = 0;
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00101); //mask=0x000000000000003f
|
||||
} else {
|
||||
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
|
||||
}
|
||||
LSRxw_REG(x4, ed, x2);
|
||||
if(rex.w) {
|
||||
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
|
||||
} else {
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
}
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLxw_REG(x4, x4, x2);
|
||||
EORxw_REG(x4, ed, x4);
|
||||
CSELxw(ed, ed, x4, cEQ);
|
||||
} else {
|
||||
// Will fetch only 1 byte, to avoid alignment issue
|
||||
if(rex.w) {
|
||||
ANDx_mask(x2, gd, 1, 0, 0b00010); //mask=0x0000000000000007
|
||||
} else {
|
||||
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
|
||||
}
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
ASRxw(x1, gd, 3); // r1 = (gd>>3)
|
||||
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
LSRw_REG(x4, ed, x2);
|
||||
ANDSw_mask(x4, x4, 0, 0); //mask=1
|
||||
BFIw(xFlags, x4, F_CF, 1);
|
||||
MOV32w(x4, 1);
|
||||
LSLw_REG(x4, x4, x2);
|
||||
EORw_REG(x4, ed, x4);
|
||||
CSELw(ed, ed, x4, cEQ);
|
||||
STLXRB(x4, ed, wback);
|
||||
CBNZw_MARKLOCK(x4);
|
||||
SMDMB();
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0xC1:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOVxw_REG(x1, ed);
|
||||
MOVxw_REG(ed, gd);
|
||||
MOVxw_REG(gd, x1);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
ADDxw_REG(x4, x1, gd);
|
||||
STLXRxw(x3, x4, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8);
|
||||
ADDxw_REG(x4, x1, gd);
|
||||
STLXRB(x3, x4, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRxw_U12(x4, wback, 0);
|
||||
MARK2;
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOVxw_REG(x2, x1);
|
||||
emit_add32(dyn, ninst, rex, x2, gd, x3, x4);
|
||||
}
|
||||
MOVxw_REG(gd, x1);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
MOVxw_REG(x1, ed);
|
||||
MOVxw_REG(ed, gd);
|
||||
MOVxw_REG(gd, x1);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
ADDxw_REG(x4, x1, gd);
|
||||
STLXRxw(x3, x4, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
LDAXRB(x4, wback);
|
||||
BFIxw(x1, x4, 0, 8);
|
||||
ADDxw_REG(x4, x1, gd);
|
||||
STLXRB(x3, x4, wback);
|
||||
CBNZx_MARK(x3);
|
||||
STRxw_U12(x4, wback, 0);
|
||||
MARK2;
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOVxw_REG(x2, x1);
|
||||
emit_add32(dyn, ninst, rex, x2, gd, x3, x4);
|
||||
}
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
DMB_ISH();
|
||||
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;
|
||||
DMB_ISH();
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
switch(rep) {
|
||||
case 0:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
SMDMB();
|
||||
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;
|
||||
SMDMB();
|
||||
BFIw(xFlags, x1, F_ZF, 1);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -322,7 +450,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -334,7 +462,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x29:
|
||||
@@ -342,7 +470,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
|
||||
@@ -354,7 +482,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
@@ -362,7 +490,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
|
||||
case 0x80:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD Eb, Ib");
|
||||
@@ -372,6 +500,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
@@ -382,7 +511,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR Eb, Ib");
|
||||
@@ -392,6 +520,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
@@ -402,7 +531,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC Eb, Ib");
|
||||
@@ -413,17 +541,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x3);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB Eb, Ib");
|
||||
@@ -434,17 +562,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x3);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND Eb, Ib");
|
||||
@@ -454,6 +582,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
@@ -464,7 +593,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB Eb, Ib");
|
||||
@@ -474,17 +602,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x3);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR Eb, Ib");
|
||||
@@ -494,6 +622,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
|
||||
wb1 = 0;
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
@@ -504,7 +633,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
EBBACK;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP Eb, Ib");
|
||||
@@ -521,12 +649,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
@@ -550,7 +678,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
@@ -658,7 +786,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT_nocond;
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
@@ -703,7 +831,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x86:
|
||||
@@ -726,7 +854,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
BFIx(eb1, x4, eb2*8, 8);
|
||||
} else {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETGB(x4);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
@@ -735,7 +863,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// do the swap 14 -> strb(ed), 1 -> gd
|
||||
STLXRB(x3, x4, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
BFIx(gb1, x1, gb2*8, 8);
|
||||
}
|
||||
break;
|
||||
@@ -750,7 +878,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVxw_REG(ed, x1);
|
||||
} else {
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
|
||||
B_MARK(cNE);
|
||||
@@ -763,11 +891,90 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRxw_U12(x1, ed, 0);
|
||||
STRxw_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
MOVxw_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF6:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
case 1:
|
||||
INST_NAME("LOCK TEST Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
GETEB(x1, 1);
|
||||
u8 = F8;
|
||||
MOV32w(x2, u8);
|
||||
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("LOCK NOT Eb");
|
||||
if(MODREG) {
|
||||
GETEB(x1, 0);
|
||||
MVNw_REG(x1, x1);
|
||||
EBBACK;
|
||||
} else {
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
MVNw_REG(x1, x1);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFE:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Eb
|
||||
INST_NAME("LOCK INC Eb");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
GETEB(x1, 0);
|
||||
emit_inc8(dyn, ninst, x1, x2, x4);
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_inc8(dyn, ninst, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("LOCK DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
GETEB(x1, 0);
|
||||
emit_dec8(dyn, ninst, x1, x2, x4);
|
||||
EBBACK;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MARKLOCK;
|
||||
LDAXRB(x1, wback);
|
||||
emit_dec8(dyn, ninst, x1, x3, x4);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7)
|
||||
@@ -775,7 +982,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
case 0: // INC Ed
|
||||
INST_NAME("LOCK INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_inc32(dyn, ninst, rex, ed, x3, x4);
|
||||
@@ -788,6 +995,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_inc32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
@@ -797,13 +1005,13 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("LOCK DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if(MODREG) {
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3);
|
||||
emit_dec32(dyn, ninst, rex, ed, x3, x4);
|
||||
@@ -816,6 +1024,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
emit_dec32(dyn, ninst, rex, x1, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
SMDMB();
|
||||
B_NEXT_nocond;
|
||||
MARK;
|
||||
LDRxw_U12(x1, wback, 0);
|
||||
@@ -825,8 +1034,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZw_MARK(x3);
|
||||
STRxw_U12(x1, wback, 0);
|
||||
SMDMB();
|
||||
}
|
||||
DMB_ISH();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -22,28 +22,6 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// Get Ex as a double, not a quad (warning, x2 get used)
|
||||
#define GETEX(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
VLDR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
#define GETGX(a, w) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
#define GETGX_empty(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, 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)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
@@ -59,10 +37,6 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int d0, d1;
|
||||
int64_t fixedaddress;
|
||||
|
||||
#ifdef PRECISE_CVT
|
||||
int j32;
|
||||
MAYUSE(j32);
|
||||
#endif
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(q0);
|
||||
@@ -81,6 +55,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
d0 = sse_get_reg(dyn, ninst, x1, ed, 0);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress); // upper part reseted
|
||||
@@ -98,6 +73,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VSTR64_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -109,6 +85,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
@@ -134,33 +111,47 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("CVTTSD2SI Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEX(q0, 0, 0);
|
||||
GETEXSD(q0, 0, 0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
}
|
||||
FCVTZSxwD(gd, q0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
if(rex.w) {
|
||||
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
|
||||
} else {
|
||||
MOV32w(gd, 0x80000000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("CVTSD2SI Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEX(q0, 0, 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);
|
||||
// Construct a "switch case", with each case 2 instructions, so 8 bytes
|
||||
ADR(xLR, GETMARK);
|
||||
ADDx_REG(xLR, xLR, x1);
|
||||
B(xLR);
|
||||
MARK;
|
||||
FCVTNSxwD(gd, q0); // 0: Nearest (even)
|
||||
B_NEXT_nocond;
|
||||
FCVTMSxwD(gd, q0); // 1: Toward -inf
|
||||
B_NEXT_nocond;
|
||||
FCVTPSxwD(gd, q0); // 2: Toward +inf
|
||||
B_NEXT_nocond;
|
||||
FCVTZSxwD(gd, q0); // 3: Toward 0
|
||||
#else
|
||||
FCVTNSxwD(gd, q0);
|
||||
#endif
|
||||
GETEXSD(q0, 0, 0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
}
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FRINTID(d1, q0);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
FCVTZSxwD(gd, d1);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
if(rex.w) {
|
||||
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
|
||||
} else {
|
||||
MOV32w(gd, 0x80000000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -169,15 +160,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSD(d0, 0, 0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
FCMLTD_0(v1, d0);
|
||||
SHL_64(v1, v1, 63);
|
||||
}
|
||||
FSQRTD(d1, d0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
FSQRTD(d1, d0);
|
||||
VORR(d1, d1, v1);
|
||||
} else {
|
||||
FSQRTD(d1, d0);
|
||||
}
|
||||
VMOVeD(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -187,20 +178,20 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(d1, 1);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSD(d0, 0, 0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
FADDD(v1, d1, d0); // the high part of the vector is erased...
|
||||
if(!box64_dynarec_fastnan) {
|
||||
FADDD(v1, d1, d0); // the high part of the vector is erased...
|
||||
FCMEQD(q0, v1, v1); // 0 => out is NAN
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
} else {
|
||||
FADDD(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
VMOVeD(d1, 0, v1, 0);
|
||||
break;
|
||||
@@ -209,20 +200,20 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(d1, 1);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSD(d0, 0, 0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
FMULD(v1, d1, d0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
FMULD(v1, d1, d0);
|
||||
FCMEQD(q0, v1, v1); // 0 => out is NAN
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
} else {
|
||||
FMULD(v1, d1, d0);
|
||||
}
|
||||
VMOVeD(d1, 0, v1, 0);
|
||||
break;
|
||||
@@ -230,7 +221,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("CVTSD2SS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSD(d0, 0, 0);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCVT_S_D(d1, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
@@ -241,20 +232,20 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(d1, 1);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSD(d0, 0, 0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
FSUBD(v1, d1, d0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
FSUBD(v1, d1, d0);
|
||||
FCMEQD(q0, v1, v1); // 0 => out is NAN
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
} else {
|
||||
FSUBD(v1, d1, d0);
|
||||
}
|
||||
VMOVeD(d1, 0, v1, 0);
|
||||
break;
|
||||
@@ -262,7 +253,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("MINSD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
@@ -279,20 +270,20 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
// check if any input value was NAN
|
||||
FMAXD(d0, v0, v1); // propagate NAN
|
||||
FCMEQD(d0, d0, d0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
FDIVD(d1, v0, v1);
|
||||
if(!box64_dynarec_fastnan) {
|
||||
FDIVD(d1, v0, v1);
|
||||
FCMEQD(q0, d1, d1); // 0 => out is NAN
|
||||
VBIC(q0, d0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(d1, d1, q0); // NAN -> -NAN
|
||||
} else {
|
||||
FDIVD(d1, v0, v1);
|
||||
}
|
||||
VMOVeD(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -300,7 +291,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("MAXSD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
@@ -354,7 +345,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("CMPSD Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 1);
|
||||
GETEXSD(v1, 0, 1);
|
||||
u8 = F8;
|
||||
FCMPD(v0, v1);
|
||||
switch(u8&7) {
|
||||
@@ -374,7 +365,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("ADDSUBPS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
|
||||
MAYUSE(addsubps);
|
||||
@@ -387,14 +378,14 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("MOVDQ2Q Gm, Ex");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
VMOV(v0, v1);
|
||||
break;
|
||||
|
||||
case 0xE6:
|
||||
INST_NAME("CVTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSD(v1, 0, 0);
|
||||
GETGX_empty(v0);
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
VFRINTIDQ(v0, v1);
|
||||
@@ -413,6 +404,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
|
||||
@@ -22,34 +22,6 @@
|
||||
#include "dynarec_arm64_functions.h"
|
||||
#include "dynarec_arm64_helper.h"
|
||||
|
||||
// Get Ex as a single, not a quad (warning, x2 get used)
|
||||
#define GETEX(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
|
||||
VLDR32_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get EX as a quad
|
||||
#define GETEXQ(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR128_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
#define GETGX(a, w) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
#define GETGX_empty(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
|
||||
{
|
||||
(void)ip; (void)need_epilog;
|
||||
@@ -85,6 +57,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVeS(v0, 0, q0, 0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VLDR32_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -100,6 +73,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
|
||||
VSTR32_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -108,6 +82,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VLDR128_U12(q1, ed, fixedaddress);
|
||||
@@ -122,6 +97,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(MODREG) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VLDR128_U12(q1, ed, fixedaddress);
|
||||
@@ -154,39 +130,54 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("CVTTSS2SI Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
}
|
||||
FCVTZSxwS(gd, d0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
if(rex.w) {
|
||||
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
|
||||
} else {
|
||||
MOV32w(gd, 0x80000000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("CVTSS2SI Gd, Ex");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEX(q0, 0, 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);
|
||||
// Construct a "switch case", with each case 2 instructions, so 8 bytes
|
||||
ADR(xLR, GETMARK);
|
||||
ADDx_REG(xLR, xLR, x1);
|
||||
B(xLR);
|
||||
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
|
||||
GETEXSS(q0, 0, 0);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
}
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x3);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FRINTIS(d1, q0);
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
FCVTZSxwS(gd, d1);
|
||||
if(!box64_dynarec_fastround) {
|
||||
MRS_fpsr(x5); // get back FPSR to check the IOC bit
|
||||
TBZ_NEXT(x5, FPSR_IOC);
|
||||
if(rex.w) {
|
||||
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
|
||||
} else {
|
||||
MOV32w(gd, 0x80000000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x51:
|
||||
INST_NAME("SQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FSQRTS(d1, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -194,7 +185,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("RSQRTSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSS(v1, 0, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
|
||||
@@ -211,7 +202,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("RCPSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSS(v1, 0, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMOVS_8(d0, 0b01110000); //1.0f
|
||||
FDIVS(d0, d0, v1);
|
||||
@@ -223,7 +214,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FADDS(d1, v0, d0); // the high part of the vector is erased...
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -232,7 +223,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FMULS(d1, v0, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -240,7 +231,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("CVTSS2SD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSS(v1, 0, 0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FCVT_D_S(d0, v1);
|
||||
VMOVeD(v0, 0, d0, 0);
|
||||
@@ -248,7 +239,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x5B:
|
||||
INST_NAME("CVTTPS2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
GETEXQ(d0, 0, 0);
|
||||
GETEX(d0, 0, 0) ;
|
||||
GETGX_empty(v0);
|
||||
VFCVTZSQS(v0, d0);
|
||||
break;
|
||||
@@ -258,7 +249,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FSUBS(d1, v0, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -266,7 +257,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("MINSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSS(v1, 0, 0);
|
||||
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
@@ -283,7 +274,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEX(d0, 0, 0);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FDIVS(d1, v0, d0);
|
||||
VMOVeS(v0, 0, d1, 0);
|
||||
break;
|
||||
@@ -291,7 +282,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
INST_NAME("MAXSS Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
GETEXSS(v1, 0, 0);
|
||||
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
|
||||
#if 0
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
@@ -313,6 +304,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VLDR128_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -320,7 +312,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0x70:
|
||||
INST_NAME("PSHUFHW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETEXQ(v1, 0, 1);
|
||||
GETEX(v1, 0, 1) ;
|
||||
GETGX(v0, 1);
|
||||
u8 = F8;
|
||||
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
|
||||
@@ -348,6 +340,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
FMOVD(v0, v1);
|
||||
} else {
|
||||
GETGX_empty(v0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -362,6 +355,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
|
||||
VSTR128_U12(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -373,12 +367,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETED(0);
|
||||
GETGD;
|
||||
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
|
||||
CSETw(x3, cEQ);
|
||||
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
|
||||
RBITxw(x3, ed); // reverse
|
||||
CLZxw(gd, x3); // x2 gets leading 0 == TZCNT
|
||||
TSTxw_REG(gd, gd);
|
||||
CSETw(x1, cEQ);
|
||||
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
|
||||
CSETw(x3, cEQ);
|
||||
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
|
||||
break;
|
||||
case 0xBD:
|
||||
INST_NAME("LZCNT Gd, Ed");
|
||||
@@ -388,18 +383,19 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETED(0);
|
||||
GETGD;
|
||||
TSTxw_REG(ed, ed);
|
||||
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
|
||||
CLZxw(gd, x1); // x2 gets leading 0 == LZCNT
|
||||
CSETw(x3, cEQ);
|
||||
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
|
||||
CLZxw(gd, ed); // x2 gets leading 0 == LZCNT
|
||||
TSTxw_REG(gd, gd);
|
||||
CSETw(x1, cEQ);
|
||||
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
|
||||
CSETw(x3, cEQ);
|
||||
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
|
||||
break;
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSS Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 1);
|
||||
GETEXSS(v1, 0, 1);
|
||||
u8 = F8;
|
||||
FCMPS(v0, v1);
|
||||
switch(u8&7) {
|
||||
@@ -424,6 +420,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VEORQ(v0, v0, v0); // usefull?
|
||||
VMOV(v0, v1);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v0, ed, fixedaddress);
|
||||
}
|
||||
@@ -432,14 +429,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
case 0xE6:
|
||||
INST_NAME("CVTDQ2PD Gx, Ex");
|
||||
nextop = F8;
|
||||
// cannot use GETEX because we want 64bits not 32bits
|
||||
if(MODREG) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
|
||||
} else {
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
|
||||
VLDR64_U12(v1, ed, fixedaddress);
|
||||
}
|
||||
GETEXSD(v1, 0, 0);
|
||||
GETGX_empty(v0);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
SXTL_32(v0, v1);
|
||||
|
||||
@@ -389,6 +389,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
GETIP_(ip);
|
||||
}
|
||||
TABLE64(x2, (uintptr_t)arm64_epilog);
|
||||
SMEND();
|
||||
BR(x2);
|
||||
}
|
||||
|
||||
@@ -404,13 +405,13 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MAYUSE(tbl);
|
||||
TABLE64(x3, tbl);
|
||||
UBFXx(x2, xRIP, 48, JMPTABL_SHIFT);
|
||||
UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x3, x3, x2);
|
||||
UBFXx(x2, xRIP, 32, JMPTABL_SHIFT);
|
||||
UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
LDRx_REG_LSL3(x3, x3, x2);
|
||||
UBFXx(x2, xRIP, 16, JMPTABL_SHIFT);
|
||||
UBFXx(x2, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
|
||||
LDRx_REG_LSL3(x3, x3, x2);
|
||||
UBFXx(x2, xRIP, 0, JMPTABL_SHIFT);
|
||||
UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
|
||||
LDRx_REG_LSL3(x2, x3, x2);
|
||||
} else {
|
||||
uintptr_t p = getJumpTableAddress64(ip);
|
||||
@@ -426,6 +427,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
#ifdef HAVE_TRACE
|
||||
//MOVx(x3, 15); no access to PC reg
|
||||
#endif
|
||||
SMEND();
|
||||
BLR(x2); // save LR...
|
||||
}
|
||||
|
||||
@@ -434,17 +436,28 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Ret to epilog\n");
|
||||
POP1(xRIP);
|
||||
MOVx_REG(x1, xRIP);
|
||||
SMEND();
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
}
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MOV64x(x2, tbl);
|
||||
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
MOVx_REG(x1, xRIP);
|
||||
BLR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -460,17 +473,28 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
} else {
|
||||
ADDx_U12(xRSP, xRSP, n);
|
||||
}
|
||||
MOVx_REG(x1, xRIP);
|
||||
SMEND();
|
||||
if(box64_dynarec_callret) {
|
||||
// pop the actual return address for ARM stack
|
||||
LDPx_S7_offset(x2, x6, xSP, 0);
|
||||
CBZx(x6, 5*4);
|
||||
ADDx_U12(xSP, xSP, 16);
|
||||
SUBx_REG(x6, x6, xRIP); // is it the right address?
|
||||
CBNZx(x6, 2*4);
|
||||
BLR(x2);
|
||||
// not the correct return address, regular jump
|
||||
}
|
||||
uintptr_t tbl = getJumpTable64();
|
||||
MOV64x(x2, tbl);
|
||||
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START1, JMPTABL_SHIFT1);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
|
||||
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
|
||||
LDRx_REG_LSL3(x2, x2, x3);
|
||||
MOVx_REG(x1, xRIP);
|
||||
BLR(x2); // save LR
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -503,6 +527,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
|
||||
MOVx_REG(xRSP, x3);
|
||||
// Ret....
|
||||
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
|
||||
SMEND();
|
||||
BR(x2);
|
||||
CLEARIP();
|
||||
}
|
||||
@@ -1092,7 +1117,7 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
MAYUSE(dyn); MAYUSE(ninst);
|
||||
MAYUSE(s1); MAYUSE(s2);
|
||||
LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
LDRw_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
|
||||
RBITw(s2, s1); // round is on bits 13-14 on x64,
|
||||
LSRw(s2, s2, 17); // but we want the reverse of that
|
||||
MRS_fpcr(s1); // get fpscr
|
||||
@@ -1448,7 +1473,7 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
|
||||
}
|
||||
*s3_top += a;
|
||||
*s2_val = 0;
|
||||
ADDw_REG_LSL(s2, xEmu, s3, 3);
|
||||
ADDx_REG_LSL(s2, xEmu, s3, 3);
|
||||
VLDR64_U12(i, s2, offsetof(x64emu_t, x87));
|
||||
if(t==NEON_CACHE_ST_F) {
|
||||
FCVT_S_D(i, i);
|
||||
@@ -1495,7 +1520,7 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
|
||||
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + i)&7
|
||||
}
|
||||
*s3_top += a;
|
||||
ADDw_REG_LSL(s2, xEmu, s3, 3);
|
||||
ADDx_REG_LSL(s2, xEmu, s3, 3);
|
||||
*s2_val = 0;
|
||||
if(t==NEON_CACHE_ST_F) {
|
||||
FCVT_D_S(i, i);
|
||||
|
||||
@@ -32,6 +32,30 @@
|
||||
#define PK64(a) *(uint64_t*)(addr+a)
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
|
||||
// Strong mem emulation helpers
|
||||
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
|
||||
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
|
||||
// Opcode will read
|
||||
#define SMREAD() if(!dyn->smread && box64_dynarec_strongmem>1) {SMDMB();}
|
||||
// Opcode will read with option forced lock
|
||||
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box64_dynarec_strongmem>1)) {SMDMB();}
|
||||
// Opcode migh read (depend on nextop)
|
||||
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
|
||||
// Opcode has wrote
|
||||
#define SMWRITE() dyn->smwrite=1
|
||||
// Opcode has wrote (strongmem>1 only)
|
||||
#define SMWRITE2() if(box64_dynarec_strongmem>1) dyn->smwrite=1
|
||||
// Opcode has wrote with option forced lock
|
||||
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
|
||||
// Opcode migh have wrote (depend on nextop)
|
||||
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
|
||||
// Start of sequence
|
||||
#define SMSTART() SMEND()
|
||||
// End of sequence
|
||||
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
|
||||
// Force a Data memory barrier (for LOCK: prefix)
|
||||
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
|
||||
|
||||
//LOCK_* define
|
||||
#define LOCK_LOCK (int*)1
|
||||
|
||||
@@ -42,6 +66,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD() \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
LDRxw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -50,6 +75,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
LDRx_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -58,6 +84,7 @@
|
||||
ed = xEAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL,0, D); \
|
||||
LDRw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -68,6 +95,7 @@
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
|
||||
LDRSW_U12(x1, wback, fixedaddress); \
|
||||
wb = ed = x1; \
|
||||
@@ -76,6 +104,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
LDRxw_U12(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
@@ -86,6 +115,7 @@
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
|
||||
LDRSW_U12(x1, wback, fixedaddress); \
|
||||
wb = ed = x1; \
|
||||
@@ -95,6 +125,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
LDRxw_U12(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
@@ -103,6 +134,7 @@
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
LDRxw_U12(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
@@ -113,6 +145,7 @@
|
||||
MOVxw_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
ed = ret; \
|
||||
LDRxw_U12(ed, wback, fixedaddress); \
|
||||
@@ -122,31 +155,34 @@
|
||||
MOVxw_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
|
||||
ed = ret; \
|
||||
LDRxw_U12(ed, wback, fixedaddress); \
|
||||
}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress);}
|
||||
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress); SMWRITE();}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
#define WBACKx if(wback) {STRx_U12(ed, wback, fixedaddress);}
|
||||
#define WBACKx if(wback) {STRx_U12(ed, wback, fixedaddress); SMWRITE();}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
#define WBACKw if(wback) {STRw_U12(ed, wback, fixedaddress);}
|
||||
#define WBACKw if(wback) {STRw_U12(ed, wback, fixedaddress); SMWRITE();}
|
||||
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDO(O, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
|
||||
LDRxw_REG(x1, wback, O); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O);}
|
||||
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O); SMWRITE2();}
|
||||
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDOx(O, D) if(MODREG) { \
|
||||
ed = xRAX+(nextop&7)+(rex.b<<3); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
|
||||
LDRx_REG(x1, wback, O); \
|
||||
ed = x1; \
|
||||
@@ -157,6 +193,7 @@
|
||||
wb = x1; \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
|
||||
LDRSW_REG(x1, wback, O); \
|
||||
wb = ed = x1; \
|
||||
@@ -176,6 +213,7 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
|
||||
LDRH_U12(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
@@ -188,6 +226,7 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
|
||||
LDRH_U12(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
@@ -200,15 +239,16 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
|
||||
LDRSHx_U12(i, wback, fixedaddress);\
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
}
|
||||
// Write ed back to original register / memory
|
||||
#define EWBACK if(wb1) {STRH_U12(ed, wback, fixedaddress);} else {BFIx(wback, ed, 0, 16);}
|
||||
#define EWBACK if(wb1) {STRH_U12(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, 0, 16);}
|
||||
// Write w back to original register / memory
|
||||
#define EWBACKW(w) if(wb1) {STRH_U12(w, wback, fixedaddress);} else {BFIx(wback, w, 0, 16);}
|
||||
#define EWBACKW(w) if(wb1) {STRH_U12(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);}
|
||||
// Write back gd in correct register
|
||||
#define GWBACK BFIx((xRAX+((nextop&0x38)>>3)+(rex.r<<3)), gd, 0, 16);
|
||||
//GETEB will use i for ed, and can use r3 for wback.
|
||||
@@ -225,6 +265,7 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
|
||||
LDRB_U12(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
@@ -244,7 +285,8 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, D); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
|
||||
ADDx_REG(x3, wback, i); \
|
||||
if(wback!=x3) wback = x3; \
|
||||
LDRB_U12(i, wback, fixedaddress); \
|
||||
@@ -265,6 +307,7 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
|
||||
LDRSBx_U12(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
@@ -284,13 +327,14 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
|
||||
LDRB_U12(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
// Write eb (ed) back to original register / memory
|
||||
#define EBBACK if(wb1) {STRB_U12(ed, wback, fixedaddress);} else {BFIx(wback, ed, wb2, 8);}
|
||||
#define EBBACK if(wb1) {STRB_U12(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);}
|
||||
//GETGB will use i for gd
|
||||
#define GETGB(i) if(rex.rex) { \
|
||||
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
@@ -316,6 +360,84 @@
|
||||
// Write gb (gd) back to original register / memory
|
||||
#define GBBACK BFIx(gb1, gd, gb2, 8);
|
||||
|
||||
// Generic get GD, but reg value in gd (R_RAX is not added)
|
||||
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
|
||||
|
||||
// Get GX as a quad (might use x1)
|
||||
#define GETGX(a, w) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg(dyn, ninst, x1, gd, w)
|
||||
|
||||
// Get an empty GX (use x1)
|
||||
#define GETGX_empty(a) \
|
||||
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
|
||||
a = sse_get_reg_empty(dyn, ninst, x1, gd)
|
||||
|
||||
// Get EX as a quad, (x1 is used)
|
||||
#define GETEX(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR128_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Put Back EX if it was a memory and not an emm register
|
||||
#define PUTEX(a) \
|
||||
if(!MODREG) { \
|
||||
VSTR128_U12(a, ed, fixedaddress); \
|
||||
SMWRITE2(); \
|
||||
}
|
||||
|
||||
|
||||
// Get Ex as a double, not a quad (warning, x1 get used)
|
||||
#define GETEXSD(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
VLDR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get Ex as a single, not a quad (warning, x1 get used)
|
||||
#define GETEXSS(a, w, D) \
|
||||
if(MODREG) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
|
||||
VLDR32_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Get GM, might use x1, x2 and x3
|
||||
#define GETGM(a) \
|
||||
gd = ((nextop&0x38)>>3); \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
|
||||
|
||||
// Get EM, might use x1, x2 and x3
|
||||
#define GETEM(a, D) \
|
||||
if(MODREG) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7)); \
|
||||
} else { \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
|
||||
a = fpu_get_scratch(dyn); \
|
||||
VLDR64_U12(a, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
// Put Back EM if it was a memory and not an emm register
|
||||
#define PUTEM(a) \
|
||||
if(!MODREG) { \
|
||||
VSTR64_U12(a, ed, fixedaddress); \
|
||||
SMWRITE2(); \
|
||||
}
|
||||
|
||||
|
||||
// Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
|
||||
// F_DF is 1<<10, so 1 ROR 11*2 (so F_OF)
|
||||
#define GETDIR(r, A) \
|
||||
@@ -471,6 +593,10 @@
|
||||
j64 = GETMARKLOCK-(dyn->native_size); \
|
||||
Bcond(cond, j64)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j64)
|
||||
#define CBNZw_MARKLOCK(reg) \
|
||||
j64 = GETMARKLOCK-(dyn->native_size); \
|
||||
CBNZw(reg, j64)
|
||||
// Branch to MARKLOCK if reg is not 0 (use j64)
|
||||
#define CBNZx_MARKLOCK(reg) \
|
||||
j64 = GETMARKLOCK-(dyn->native_size); \
|
||||
CBNZx(reg, j64)
|
||||
@@ -932,14 +1058,14 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
|
||||
void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
|
||||
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
|
||||
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
|
||||
|
||||
@@ -1056,7 +1182,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
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_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_66F0(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);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
#define INIT dyn->native_size = 0
|
||||
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
|
||||
#define FINI \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>dyn->insts[ninst].size)?dyn->insts[ninst].x64.size:dyn->insts[ninst].size)/15; \
|
||||
}
|
||||
|
||||
#define MESSAGE(A, ...)
|
||||
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->native_size+=4
|
||||
#define NEW_INST \
|
||||
if(ninst) { \
|
||||
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
|
||||
if(ninst && isInstClean(dyn, ninst)) { \
|
||||
if(dyn->last_ip!=ip) dyn->last_ip = 0; \
|
||||
} \
|
||||
if(isInstClean(dyn, ninst) && dyn->last_ip!=ip) \
|
||||
dyn->last_ip = 0; \
|
||||
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>dyn->insts[ninst-1].size)?dyn->insts[ninst-1].x64.size:dyn->insts[ninst-1].size)/15; \
|
||||
}
|
||||
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
|
||||
#define INST_NAME(name)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#define INIT
|
||||
#define FINI
|
||||
#define FINI \
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x64.size, dyn->insts[ninst].size/4); \
|
||||
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
|
||||
#define EMIT(A) \
|
||||
if(box64_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (uint32_t)(A), arm64_print(A, (uintptr_t)dyn->block));} \
|
||||
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
|
||||
@@ -10,12 +13,14 @@
|
||||
#define NEW_INST \
|
||||
if(ninst && isInstClean(dyn, ninst)) { \
|
||||
if(dyn->last_ip!=ip) dyn->last_ip = 0; \
|
||||
}
|
||||
} \
|
||||
if(ninst) \
|
||||
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4);
|
||||
#define INST_EPILOG
|
||||
#define INST_NAME(name) \
|
||||
if(box64_dynarec_dump) {\
|
||||
printf_x64_instruction(my_context->dec, &dyn->insts[ninst].x64, name); \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X", \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d/%d", \
|
||||
(box64_dynarec_dump>1)?"\e[32m":"", \
|
||||
(void*)(dyn->native_start+dyn->insts[ninst].address), \
|
||||
dyn->insts[ninst].size/4, \
|
||||
@@ -29,7 +34,8 @@
|
||||
dyn->insts[ninst].x64.gen_flags, \
|
||||
dyn->insts[ninst].x64.use_flags, \
|
||||
dyn->insts[ninst].x64.need_before, \
|
||||
dyn->insts[ninst].x64.need_after); \
|
||||
dyn->insts[ninst].x64.need_after, \
|
||||
dyn->smread, dyn->smwrite); \
|
||||
if(dyn->insts[ninst].pred_sz) { \
|
||||
dynarec_log(LOG_NONE, ", pred="); \
|
||||
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef struct instruction_arm64_s {
|
||||
} instruction_arm64_t;
|
||||
|
||||
typedef struct dynarec_arm_s {
|
||||
instruction_arm64_t *insts;
|
||||
instruction_arm64_t*insts;
|
||||
int32_t size;
|
||||
int32_t cap;
|
||||
uintptr_t start; // start of the block
|
||||
@@ -91,7 +91,7 @@ typedef struct dynarec_arm_s {
|
||||
uintptr_t native_start; // start of the arm code
|
||||
size_t native_size; // size of emitted arm code
|
||||
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state) TODO: move to a cache something
|
||||
uint64_t *table64; // table of 64bits value
|
||||
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;
|
||||
@@ -103,6 +103,13 @@ typedef struct dynarec_arm_s {
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
instsize_t* instsize;
|
||||
size_t insts_size; // size of the instruction size array (calculated)
|
||||
uint8_t smread; // for strongmem model emulation
|
||||
uint8_t smwrite; // for strongmem model emulation
|
||||
uintptr_t forward; // address of the last end of code while testing forward
|
||||
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
|
||||
int32_t forward_size; // size at the forward point
|
||||
int forward_ninst; // ninst at the forward point
|
||||
} dynarec_arm_t;
|
||||
|
||||
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
|
||||
|
||||
+33
-37
@@ -28,8 +28,6 @@
|
||||
#include "custommem.h"
|
||||
#include "khash.h"
|
||||
|
||||
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
|
||||
|
||||
uint32_t X31_hash_code(void* addr, int len)
|
||||
{
|
||||
if(!len) return 0;
|
||||
@@ -46,16 +44,16 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
// remove jumptable
|
||||
setJumpTableDefault64(db->x64_addr);
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
FreeDynarecMap(db, (uintptr_t)db->actual_block, db->size);
|
||||
FreeDynarecMap((uintptr_t)db->actual_block);
|
||||
customFree(db);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +68,7 @@ void MarkDynablock(dynablock_t* db)
|
||||
}
|
||||
}
|
||||
|
||||
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
|
||||
{
|
||||
if(start1 > end2 || start2 > end1)
|
||||
return 0;
|
||||
@@ -110,20 +108,6 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return NULL;
|
||||
dynablock_t* db;
|
||||
kh_foreach_value(dynablocks, db,
|
||||
const uintptr_t s = (uintptr_t)db->block;
|
||||
const uintptr_t e = (uintptr_t)db->block+db->size;
|
||||
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
|
||||
return db;
|
||||
)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
{
|
||||
dynablock_t* block;
|
||||
@@ -136,14 +120,9 @@ dynablock_t *AddNewDynablock(uintptr_t addr)
|
||||
}
|
||||
|
||||
#endif
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
|
||||
// create and add new block
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
|
||||
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -167,13 +146,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(block || !create)
|
||||
return block;
|
||||
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(need_lock) {
|
||||
if(box64_dynarec_wait) {
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
} else {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
block = getDB(addr); // just in case
|
||||
if(block) {
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -184,7 +169,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock64(block, filladdr);
|
||||
@@ -200,7 +185,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
my_context->max_db_size = blocksz;
|
||||
// fill-in jumptable
|
||||
if(!addJumpTableIfDefault64(block->x64_addr, block->block)) {
|
||||
FreeDynablock(block, 1);
|
||||
FreeDynablock(block, 0);
|
||||
block = getDB(addr);
|
||||
} else {
|
||||
if(block->x64_size)
|
||||
@@ -208,7 +193,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
|
||||
}
|
||||
}
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0);
|
||||
|
||||
@@ -220,11 +205,22 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
|
||||
if(db && db->done && db->block && db->need_test) {
|
||||
if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
|
||||
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, (void*)addr);
|
||||
return NULL;
|
||||
if(box64_dynarec_fastpage) {
|
||||
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
if(hash==db->hash) // seems ok, run it without reprotecting it
|
||||
return db;
|
||||
db->done = 0; // invalidating the block, it's already not good
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
FreeDynablock(db, 1);
|
||||
return NULL; // not building a new one, it's still a hotpage
|
||||
} else {
|
||||
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) {
|
||||
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
@@ -242,7 +238,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
|
||||
// fill back jumptable
|
||||
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -253,7 +249,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
|
||||
if(db && db->done && db->block && db->need_test) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
|
||||
if(hash!=db->hash) {
|
||||
@@ -269,7 +265,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
// fill back jumptable
|
||||
addJumpTableIfDefault64(db->x64_addr, db->block);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "bridge.h"
|
||||
#include "dynarec_next.h"
|
||||
#endif
|
||||
#ifdef HAVE_TRACE
|
||||
#include "elfloader.h"
|
||||
#endif
|
||||
|
||||
#ifdef DYNAREC
|
||||
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
|
||||
@@ -40,6 +43,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
// no block, let link table as is...
|
||||
if(hasAlternate((void*)addr)) {
|
||||
printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
|
||||
if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
|
||||
addr = (uintptr_t)getAlternate((void*)addr); // set new address
|
||||
R_RIP = addr; // but also new RIP!
|
||||
*x3 = addr; // and the RIP in x27 register
|
||||
@@ -49,7 +53,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
if(!block) {
|
||||
#ifdef HAVE_TRACE
|
||||
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
|
||||
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
|
||||
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
|
||||
#endif
|
||||
//tableupdate(native_epilog, addr, table);
|
||||
return native_epilog;
|
||||
|
||||
@@ -240,7 +240,7 @@ int is_instructions(dynarec_native_t *dyn, uintptr_t addr, int n)
|
||||
return (i==n)?1:0;
|
||||
}
|
||||
|
||||
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x64_size, int native_size)
|
||||
void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size)
|
||||
{
|
||||
// x64 instruction is <16 bytes
|
||||
int toadd;
|
||||
@@ -248,10 +248,6 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x64_size,
|
||||
toadd = 1 + x64_size/15;
|
||||
else
|
||||
toadd = 1 + native_size/15;
|
||||
if((*size)+toadd>(*cap)) {
|
||||
*cap = (*size)+toadd;
|
||||
insts = (instsize_t*)customRealloc(insts, (*cap)*sizeof(instsize_t));
|
||||
}
|
||||
while(toadd) {
|
||||
if(x64_size>15)
|
||||
insts[*size].x64 = 15;
|
||||
@@ -266,7 +262,6 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x64_size,
|
||||
++(*size);
|
||||
--toadd;
|
||||
}
|
||||
return insts;
|
||||
}
|
||||
|
||||
// add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
|
||||
@@ -376,23 +371,29 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
return ninst;
|
||||
}
|
||||
|
||||
__thread void* current_helper = NULL;
|
||||
void* current_helper = NULL;
|
||||
|
||||
void CancelBlock64()
|
||||
void CancelBlock64(int need_lock)
|
||||
{
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
dynarec_native_t* helper = (dynarec_native_t*)current_helper;
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
if(!helper) {
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return;
|
||||
}
|
||||
customFree(helper->next);
|
||||
customFree(helper->insts);
|
||||
customFree(helper->instsize);
|
||||
customFree(helper->predecessor);
|
||||
customFree(helper->table64);
|
||||
if(helper->dynablock && helper->dynablock->actual_block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->actual_block, helper->dynablock->size);
|
||||
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
|
||||
else if(helper->dynablock && helper->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->block-sizeof(void*), helper->dynablock->size);
|
||||
FreeDynarecMap((uintptr_t)helper->block-sizeof(void*));
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
|
||||
uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr);
|
||||
@@ -404,11 +405,11 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->isize = 0;
|
||||
block->done = 0;
|
||||
size_t sz = 4*sizeof(void*);
|
||||
void* actual_p = (void*)AllocDynarecMap(block, sz);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock64();
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
block->size = sz;
|
||||
@@ -425,6 +426,19 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
}
|
||||
|
||||
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
/*
|
||||
A Block must have this layout:
|
||||
|
||||
0x0000..0x0007 : dynablock_t* : self
|
||||
0x0008..8+4*n : actual Native instructions, (n is the total number)
|
||||
A .. A+8*n : Table64: n 64bits values
|
||||
B .. B+7 : dynablock_t* : self (as part of JmpNext, that simulate another block)
|
||||
B+8 .. B+15 : 2 Native code for jmpnext (or jmp epilog in case of empty block)
|
||||
B+16 .. B+23 : jmpnext (or jmp_epilog) address
|
||||
B+24 .. B+31 : empty (in case an architecture needs more than 2 opcodes)
|
||||
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x64 and native side)
|
||||
|
||||
*/
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
@@ -433,6 +447,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(current_helper) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
// protect the 1st page
|
||||
protectDB(addr, 1);
|
||||
// init the helper
|
||||
@@ -452,16 +470,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
// basic checks
|
||||
if(!helper.size) {
|
||||
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
|
||||
CancelBlock64();
|
||||
CancelBlock64(0);
|
||||
return CreateEmptyBlock(block, addr);;
|
||||
}
|
||||
if(!isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
|
||||
CancelBlock64();
|
||||
AddHotPage(addr);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
// protect the block of it goes over the 1st page
|
||||
if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
|
||||
if((addr&~box64_pagesize)!=(end&~box64_pagesize)) // need to protect some other pages too
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
// compute hash signature
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
@@ -469,7 +488,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x64.jmp) {
|
||||
uintptr_t j = helper.insts[i].x64.jmp;
|
||||
if(j<start || j>=end) {
|
||||
if(j<start || j>=end || j==helper.insts[i].x64.addr) {
|
||||
helper.insts[i].x64.jmp_insts = -1;
|
||||
helper.insts[i].x64.need_after |= X_PEND;
|
||||
} else {
|
||||
@@ -497,34 +516,25 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
// pass 2, instruction size
|
||||
native_pass2(&helper, addr);
|
||||
// keep size of instructions for signal handling
|
||||
size_t insts_rsize = 0;
|
||||
{
|
||||
size_t insts_size = 0;
|
||||
size_t cap = 1;
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
|
||||
helper.instsize = (instsize_t*)customCalloc(cap, sizeof(instsize_t));
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
helper.instsize = addInst(helper.instsize, &insts_size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
|
||||
helper.instsize = addInst(helper.instsize, &insts_size, &cap, 0, 0); // add a "end of block" mark, just in case
|
||||
insts_rsize = insts_size*sizeof(instsize_t);
|
||||
}
|
||||
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
// ok, now allocate mapped memory, with executable flag on
|
||||
size_t sz = sizeof(void*) + helper.native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
|
||||
// dynablock_t* block (arm insts) table64 jmpnext code instsize
|
||||
void* actual_p = (void*)AllocDynarecMap(block, sz);
|
||||
void* actual_p = (void*)AllocDynarecMap(sz);
|
||||
void* p = actual_p + sizeof(void*);
|
||||
void* next = p + helper.native_size + helper.table64size*sizeof(uint64_t);
|
||||
void* instsize = next + 4*sizeof(void*);
|
||||
if(actual_p==NULL) {
|
||||
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
|
||||
CancelBlock64();
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
helper.block = p;
|
||||
helper.native_start = (uintptr_t)p;
|
||||
helper.tablestart = helper.native_start + helper.native_size;
|
||||
helper.insts_size = 0; // reset
|
||||
helper.instsize = (instsize_t*)instsize;
|
||||
*(dynablock_t**)actual_p = block;
|
||||
// pass 3, emit (log emit native opcode)
|
||||
if(box64_dynarec_dump) {
|
||||
@@ -556,14 +566,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
|
||||
}
|
||||
// keep size of instructions for signal handling
|
||||
memcpy(instsize, helper.instsize, insts_rsize);
|
||||
block->instsize = instsize;
|
||||
// ok, free the helper now
|
||||
customFree(helper.insts);
|
||||
helper.insts = NULL;
|
||||
customFree(helper.table64);
|
||||
helper.table64 = NULL;
|
||||
customFree(helper.instsize);
|
||||
helper.instsize = NULL;
|
||||
customFree(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
@@ -583,14 +591,15 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
|
||||
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
|
||||
// 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);
|
||||
CancelBlock64();
|
||||
dynarec_log(LOG_DEBUG, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
|
||||
AddHotPage(addr);
|
||||
CancelBlock64(0);
|
||||
return NULL;
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_INFO, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
|
||||
CancelBlock64();
|
||||
return NULL;
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
|
||||
AddHotPage(addr);
|
||||
block->need_test = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
current_helper = NULL;
|
||||
|
||||
@@ -40,6 +40,10 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
// Clean up (because there are multiple passes)
|
||||
dyn->f.pending = 0;
|
||||
dyn->f.dfnone = 0;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
fpu_reset(dyn);
|
||||
int reset_n = -1;
|
||||
dyn->last_ip = (dyn->insts && dyn->insts[0].pred_sz)?0:ip; // RIP is always set at start of block unless there is a predecessor!
|
||||
@@ -124,6 +128,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
dyn->n.stack_push = 0;
|
||||
dyn->n.swapped = 0;
|
||||
NEW_INST;
|
||||
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
|
||||
fpu_reset_scratch(dyn);
|
||||
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
|
||||
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
|
||||
@@ -176,6 +181,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
dyn->last_ip = 0;
|
||||
}
|
||||
}
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
#if STEP != 0
|
||||
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
|
||||
ok = 1;
|
||||
@@ -194,7 +202,29 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM)
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr && !need_epilog) {
|
||||
// we made it!
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
ok = 1; // in case it was 0
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
// something when wrong! rollback
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
ok = 0;
|
||||
dyn->size = dyn->forward_size;
|
||||
ninst = dyn->forward_ninst;
|
||||
addr = dyn->forward;
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
}
|
||||
// else just continue
|
||||
} else if(!ok && !need_epilog && box64_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
|
||||
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
|
||||
uintptr_t next = get_closest_next(dyn, addr);
|
||||
if(next && (
|
||||
@@ -210,8 +240,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
|
||||
ii=ninst;
|
||||
}
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
|
||||
} else if(next && (next-addr)<30) {
|
||||
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
|
||||
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,15 @@
|
||||
#define native_lock_xchg(A, B) arm64_lock_xchg(A, B)
|
||||
#define native_lock_xchg_d(A, B) arm64_lock_xchg_d(A, B)
|
||||
#define native_lock_storeifref(A, B, C) arm64_lock_storeifref(A, B, C)
|
||||
#define native_lock_storeifref_d(A, B, C) arm64_lock_storeifref_d(A, B, C)
|
||||
#define native_lock_storeifref2_d(A, B, C) arm64_lock_storeifref2_d(A, B, C)
|
||||
#define native_lock_storeifnull(A, B) arm64_lock_storeifnull(A, B)
|
||||
#define native_lock_storeifnull_d(A, B) arm64_lock_storeifnull_d(A, B)
|
||||
#define native_lock_decifnot0b(A) arm64_lock_decifnot0b(A)
|
||||
#define native_lock_storeb(A, B) arm64_lock_storeb(A, B)
|
||||
#define native_lock_incif0(A) arm64_lock_incif0(A)
|
||||
#define native_lock_decifnot0(A) arm64_lock_decifnot0(A)
|
||||
#define native_lock_store(A, B) arm64_lock_store(A, B)
|
||||
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
|
||||
+139
-55
@@ -10,6 +10,9 @@
|
||||
#include <link.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifndef _DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "custommem.h"
|
||||
#include "box64version.h"
|
||||
@@ -62,6 +65,7 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
|
||||
h->mapsymbols = NewMapSymbols();
|
||||
h->weaksymbols = NewMapSymbols();
|
||||
h->localsymbols = NewMapSymbols();
|
||||
h->refcnt = 1;
|
||||
|
||||
return h;
|
||||
}
|
||||
@@ -153,7 +157,7 @@ int CalcLoadAddr(elfheader_t* head)
|
||||
const char* ElfName(elfheader_t* head)
|
||||
{
|
||||
if(!head)
|
||||
return "(noelf)";
|
||||
return "box64";
|
||||
return head->name;
|
||||
}
|
||||
const char* ElfPath(elfheader_t* head)
|
||||
@@ -305,7 +309,7 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
|
||||
char* dest = (char*)e->p_paddr + head->delta;
|
||||
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
|
||||
void* p = (void*)-1;
|
||||
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
|
||||
if(e->p_memsz==e->p_filesz && !(e->p_align&(box64_pagesize-1))) {
|
||||
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
|
||||
p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
|
||||
}
|
||||
@@ -428,8 +432,15 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
|
||||
if(bind==STB_LOCAL) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
if(!symname || !symname[0]) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
} else {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
}
|
||||
} else {
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
|
||||
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
|
||||
@@ -482,7 +493,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
|
||||
end = globend;
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
|
||||
printf_log(LOG_NONE, "%s: Global Symbol %s (ver=%d/%s) not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, version, vername?vername:"(none)", p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
@@ -601,8 +612,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
const char* vername = GetSymbolVersion(head, version);
|
||||
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
|
||||
if(bind==STB_LOCAL) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
if(!symname || !symname[0]) {
|
||||
offs = sym->st_value + head->delta;
|
||||
end = offs + sym->st_size;
|
||||
} else {
|
||||
if(!offs && !end && local_maplib)
|
||||
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
|
||||
if(!offs && !end)
|
||||
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
|
||||
}
|
||||
} else {
|
||||
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
|
||||
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
|
||||
@@ -684,7 +702,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
end = globend;
|
||||
}
|
||||
if (!offs) {
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
|
||||
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
|
||||
printf_log((bind==STB_WEAK)?LOG_INFO:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
|
||||
} else {
|
||||
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
|
||||
@@ -794,7 +812,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
|
||||
}
|
||||
// return -1;
|
||||
} else {
|
||||
if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
|
||||
if(!symname || symname[0]=='\0')
|
||||
offs = sym->st_value;
|
||||
if(p) {
|
||||
int64_t tlsoffset = offs; // it's not an offset in elf memory
|
||||
@@ -956,7 +974,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
int vis = h->SymTab[i].st_other&0x3;
|
||||
size_t sz = h->SymTab[i].st_size;
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
|
||||
if(sz && strstr(symname, "@@")) {
|
||||
char symnameversionned[strlen(symname)+1];
|
||||
strcpy(symnameversionned, symname);
|
||||
@@ -1004,7 +1022,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
int type = ELF64_ST_TYPE(h->DynSym[i].st_info);
|
||||
int vis = h->DynSym[i].st_other&0x3;
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
|
||||
size_t sz = h->DynSym[i].st_size;
|
||||
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
@@ -1045,8 +1063,10 @@ $PLATFORM – Expands to the processor type of the current machine (see the
|
||||
uname(1) man page description of the -i option). For more details of this token
|
||||
expansion, see “System Specific Shared Objects”
|
||||
*/
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu)
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu)
|
||||
{
|
||||
if(h->needed) // already done
|
||||
return 0;
|
||||
DumpDynamicRPath(h);
|
||||
// update RPATH first
|
||||
for (size_t i=0; i<h->numDynamic; ++i)
|
||||
@@ -1105,22 +1125,21 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib
|
||||
box_free(rpath);
|
||||
}
|
||||
|
||||
if(!h->neededlibs && neededlibs)
|
||||
h->neededlibs = neededlibs;
|
||||
|
||||
DumpDynamicNeeded(h);
|
||||
int cnt = 0;
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
++cnt;
|
||||
const char* nlibs[cnt];
|
||||
h->needed = new_neededlib(cnt);
|
||||
if(h == my_context->elfs[0])
|
||||
my_context->neededlibs = h->needed;
|
||||
int j=0;
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED)
|
||||
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
|
||||
|
||||
// TODO: Add LD_LIBRARY_PATH and RPATH handling
|
||||
if(AddNeededLib(maplib, neededlibs, deplib, local, bindnow, nlibs, cnt, box64, emu)) {
|
||||
if(AddNeededLib(maplib, local, bindnow, h->needed, box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading one of needed lib\n");
|
||||
if(!allow_missing_libs)
|
||||
return 1; //error...
|
||||
@@ -1165,6 +1184,36 @@ void MarkElfInitDone(elfheader_t* h)
|
||||
if(h)
|
||||
h->init_done = 1;
|
||||
}
|
||||
void RunElfInitPltResolver(elfheader_t* h, x64emu_t *emu)
|
||||
{
|
||||
if(!h || h->init_done)
|
||||
return;
|
||||
uintptr_t p = h->initentry + h->delta;
|
||||
h->init_done = 1;
|
||||
for(int i=0; i<h->needed->size; ++i) {
|
||||
library_t *lib = h->needed->libs[i];
|
||||
elfheader_t *lib_elf = GetElf(lib);
|
||||
if(lib_elf)
|
||||
RunElfInitPltResolver(lib_elf, emu);
|
||||
}
|
||||
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunSafeFunction(my_context, p, 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
|
||||
for (size_t i=0; i<h->initarray_sz; ++i) {
|
||||
if(addr[i]) {
|
||||
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunSafeFunction(my_context, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
|
||||
}
|
||||
}
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
}
|
||||
|
||||
void RunElfInit(elfheader_t* h, x64emu_t *emu)
|
||||
{
|
||||
if(!h || h->init_done)
|
||||
@@ -1184,22 +1233,28 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
|
||||
context->deferedInitList[context->deferedInitSz++] = h;
|
||||
return;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
h->init_done = 1;
|
||||
for(int i=0; i<h->needed->size; ++i) {
|
||||
library_t *lib = h->needed->libs[i];
|
||||
elfheader_t *lib_elf = GetElf(lib);
|
||||
if(lib_elf)
|
||||
RunElfInit(lib_elf, emu);
|
||||
}
|
||||
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
|
||||
if(h->initentry)
|
||||
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
|
||||
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
|
||||
// and check init array now
|
||||
Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
|
||||
for (size_t i=0; i<h->initarray_sz; ++i) {
|
||||
if(addr[i]) {
|
||||
printf_log(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
|
||||
}
|
||||
}
|
||||
|
||||
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
|
||||
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1229,16 +1284,18 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
|
||||
// first check fini array
|
||||
Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
|
||||
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]);
|
||||
printf_dump(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
|
||||
}
|
||||
// then the "old-style" fini
|
||||
if(h->finientry) {
|
||||
uintptr_t p = h->finientry + h->delta;
|
||||
printf_log(LOG_DEBUG, "Calling Fini for %s @%p\n", ElfName(h), (void*)p);
|
||||
printf_dump(LOG_DEBUG, "Calling Fini for %s @%p\n", ElfName(h), (void*)p);
|
||||
RunFunctionWithEmu(emu, 0, p, 0);
|
||||
}
|
||||
h->init_done = 0; // can be re-inited again...
|
||||
for(int i=0; i<h->needed->size; ++i)
|
||||
FiniLibrary(h->needed->libs[i], emu);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1296,6 +1353,22 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
|
||||
const char* ret = NULL;
|
||||
uintptr_t s = 0;
|
||||
uint64_t size = 0;
|
||||
#ifdef HAVE_TRACE
|
||||
if(!h) {
|
||||
if(getProtection((uintptr_t)p)&(PROT_READ)) {
|
||||
if(*(uint8_t*)(p)==0xCC && *(uint8_t*)(p+1)=='S' && *(uint8_t*)(p+2)=='C') {
|
||||
ret = getBridgeName(*(void**)(p+3+8));
|
||||
if(ret) {
|
||||
if(start)
|
||||
*start = (uintptr_t)p;
|
||||
if(sz)
|
||||
*sz = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if(!h || h->fini_done)
|
||||
return ret;
|
||||
|
||||
@@ -1542,39 +1615,44 @@ void ResetSpecialCaseMainElf(elfheader_t* h)
|
||||
|
||||
void CreateMemorymapFile(box64context_t* context, int fd)
|
||||
{
|
||||
// this will tranform current memory map
|
||||
// by anotating anonymous entry that belong to emulated elf
|
||||
// also anonymising current stack
|
||||
// and setting emulated stack as the current one
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
char buff[1024];
|
||||
struct stat st;
|
||||
int dummy;
|
||||
FILE* f = fopen("/proc/self/maps", "r");
|
||||
if(!f)
|
||||
return;
|
||||
while(getline(&line, &len, f)>0) {
|
||||
// line is like
|
||||
// aaaadd750000-aaaadd759000 r-xp 00000000 103:02 13386730 /usr/bin/cat
|
||||
uintptr_t start, end;
|
||||
if (sscanf(line, "%zx-%zx", &start, &end)==2) {
|
||||
elfheader_t* h = FindElfAddress(my_context, start);
|
||||
int l = strlen(line);
|
||||
if(h && l<73) {
|
||||
sprintf(buff, "%s%*s\n", line, 74-l, h->name);
|
||||
dummy = write(fd, buff, strlen(buff));
|
||||
} else if(start==(uintptr_t)my_context->stack) {
|
||||
sprintf(buff, "%s%*s\n", line, 74-l, "[stack]");
|
||||
dummy = write(fd, buff, strlen(buff));
|
||||
} else if (strstr(line, "[stack]")) {
|
||||
char* p = strstr(line, "[stack]")-1;
|
||||
while (*p==' ' || *p=='\t') --p;
|
||||
p[1]='\0';
|
||||
strcat(line, "\n");
|
||||
dummy = write(fd, line, strlen(line));
|
||||
} else {
|
||||
dummy = write(fd, line, strlen(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
(void)dummy;
|
||||
|
||||
elfheader_t *h = context->elfs[0];
|
||||
|
||||
if (stat(h->path, &st)) {
|
||||
printf_log(LOG_INFO, "Failed to stat file %s (creating memory maps \"file\")!", h->path);
|
||||
// Some constants, to have "valid" values
|
||||
st.st_dev = makedev(0x03, 0x00);
|
||||
st.st_ino = 0;
|
||||
}
|
||||
|
||||
// TODO: create heap entry?
|
||||
|
||||
for (size_t i=0; i<h->numPHEntries; ++i) {
|
||||
if (h->PHEntries[i].p_memsz == 0) continue;
|
||||
|
||||
sprintf(buff, "%016lx-%016lx %c%c%c%c %016lx %02x:%02x %ld %s\n", (uintptr_t)h->PHEntries[i].p_vaddr + h->delta,
|
||||
(uintptr_t)h->PHEntries[i].p_vaddr + h->PHEntries[i].p_memsz + h->delta,
|
||||
(h->PHEntries[i].p_type & (PF_R|PF_X) ? 'r':'-'), (h->PHEntries[i].p_type & PF_W ? 'w':'-'),
|
||||
(h->PHEntries[i].p_type & PF_X ? 'x':'-'), 'p', // p for private or s for shared
|
||||
(uintptr_t)h->PHEntries[i].p_offset,
|
||||
major(st.st_dev), minor(st.st_dev), st.st_ino, h->path);
|
||||
|
||||
dummy = write(fd, buff, strlen(buff));
|
||||
}
|
||||
// create stack entry
|
||||
sprintf(buff, "%16lx-%16lx %c%c%c%c %16lx %02x:%02x %ld %s\n",
|
||||
(uintptr_t)context->stack, (uintptr_t)context->stack+context->stacksz,
|
||||
'r','w','-','p', 0L, 0, 0, 0L, "[stack]");
|
||||
dummy = write(fd, buff, strlen(buff));
|
||||
}
|
||||
|
||||
void ElfAttachLib(elfheader_t* head, library_t* lib)
|
||||
@@ -1708,8 +1786,14 @@ EXPORT void PltResolver(x64emu_t* emu)
|
||||
emu->quit = 1;
|
||||
return;
|
||||
} else {
|
||||
elfheader_t* sym_elf = FindElfAddress(my_context, offs);
|
||||
if(sym_elf && sym_elf!=my_context->elfs[0] && !sym_elf->init_done) {
|
||||
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
|
||||
RunElfInitPltResolver(sym_elf, emu);
|
||||
}
|
||||
|
||||
if(p) {
|
||||
printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
|
||||
printf_dump(LOG_DEBUG, " Apply %s R_X86_64_JUMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(sym_elf));
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:"");
|
||||
|
||||
@@ -83,15 +83,16 @@ struct elfheader_s {
|
||||
|
||||
int init_done;
|
||||
int fini_done;
|
||||
int refcnt; // ref count for the elf
|
||||
|
||||
char* memory; // char* and not void* to allow math on memory pointer
|
||||
char* memory; // char* and not void* to allow math on memory pointer
|
||||
void** multiblock;
|
||||
uintptr_t* multiblock_offs;
|
||||
uint64_t* multiblock_size;
|
||||
int multiblock_n;
|
||||
|
||||
library_t *lib;
|
||||
needed_libs_t *neededlibs;
|
||||
library_t *lib; // attached lib (exept on main elf)
|
||||
needed_libs_t* needed;
|
||||
|
||||
kh_mapsymbols_t *mapsymbols;
|
||||
kh_mapsymbols_t *weaksymbols;
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
#ifdef DYNAREC
|
||||
#define STEP if(step) return 0;
|
||||
#define STEP2 if(step) {R_RIP = addr; return 0;}
|
||||
#define STEP3 if(*step) *(step)++;
|
||||
#define STEP3 if(*step) (*step)++;
|
||||
#else
|
||||
#define STEP
|
||||
#define STEP2
|
||||
|
||||
+35
-3
@@ -23,6 +23,16 @@
|
||||
#ifdef DYNAREC
|
||||
#include "custommem.h"
|
||||
#endif
|
||||
// for the applyFlushTo0
|
||||
#ifdef __x86_64__
|
||||
#include <immintrin.h>
|
||||
#elif defined(__aarch64__)
|
||||
#else
|
||||
#warning Architecture cannot follow SSE Flush to 0 flag
|
||||
#endif
|
||||
|
||||
// from src/wrapped/wrappedlibc.c
|
||||
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
|
||||
|
||||
typedef struct cleanup_s {
|
||||
void* f;
|
||||
@@ -81,7 +91,7 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
|
||||
emu->segs[_GS] = default_gs;
|
||||
// setup fpu regs
|
||||
reset_fpu(emu);
|
||||
emu->mxcsr = 0x1f80;
|
||||
emu->mxcsr.x32 = 0x1f80;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -175,9 +185,9 @@ void CallAllCleanup(x64emu_t *emu)
|
||||
printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
|
||||
for(int i=my_context->clean_sz-1; i>=0; --i) {
|
||||
printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
|
||||
--my_context->clean_sz;
|
||||
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
|
||||
}
|
||||
my_context->clean_sz = 0;
|
||||
box_free(my_context->cleanups);
|
||||
my_context->cleanups = NULL;
|
||||
}
|
||||
@@ -185,7 +195,7 @@ void CallAllCleanup(x64emu_t *emu)
|
||||
static void internalFreeX64(x64emu_t* emu)
|
||||
{
|
||||
if(emu && emu->stack2free)
|
||||
munmap(emu->stack2free, emu->size_stack);
|
||||
my_munmap(NULL, emu->stack2free, emu->size_stack);
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
@@ -505,3 +515,25 @@ void ResetSegmentsCache(x64emu_t *emu)
|
||||
return;
|
||||
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
|
||||
}
|
||||
|
||||
void applyFlushTo0(x64emu_t* emu)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
_mm_setcsr(_mm_getcsr() | (emu->mxcsr.x32&0x8040));
|
||||
#elif defined(__aarch64__)
|
||||
#ifdef __ANDROID__
|
||||
uint64_t fpcr;
|
||||
__asm__ __volatile__ ("mrs %0, fpcr":"=r"(fpcr));
|
||||
#else
|
||||
uint64_t fpcr = __builtin_aarch64_get_fpcr();
|
||||
#endif
|
||||
fpcr &= ~((1<<24) | (1<<1)); // clear bit FZ (24) and AH (1)
|
||||
fpcr |= (emu->mxcsr.f.MXCSR_FZ)<<24; // set FZ as mxcsr FZ
|
||||
fpcr |= ((emu->mxcsr.f.MXCSR_DAZ)^(emu->mxcsr.f.MXCSR_FZ))<<1; // set AH if DAZ different from FZ
|
||||
#ifdef __ANDROID__
|
||||
__asm__ __volatile__ ("msr fpcr, %0"::"r"(fpcr));
|
||||
#else
|
||||
__builtin_aarch64_set_fpcr(fpcr);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -39,7 +39,7 @@ typedef struct x64emu_s {
|
||||
x87flags_t sw;
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
uint32_t mxcsr;
|
||||
mmxcontrol_t mxcsr;
|
||||
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
|
||||
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
|
||||
fpu_p_reg_t p_regs[8];
|
||||
@@ -97,4 +97,6 @@ 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
|
||||
|
||||
void applyFlushTo0(x64emu_t* emu);
|
||||
|
||||
#endif //__X86EMU_PRIVATE_H_
|
||||
+73
-62
@@ -11,6 +11,7 @@
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box64stack.h"
|
||||
@@ -54,8 +55,13 @@ x64emu_t* x64emu_fork(x64emu_t* emu, int forktype)
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
if(my_context->atforks[i].parent)
|
||||
EmuCall(emu, my_context->atforks[i].parent);
|
||||
if(forktype==3) {
|
||||
// vfork, the parent wait the end or execve of the son
|
||||
waitpid(v, NULL, WEXITED);
|
||||
}
|
||||
|
||||
} else if(v==0) {
|
||||
ResetSegmentsCache(emu);
|
||||
// execute atforks child functions
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
if(my_context->atforks[i].child)
|
||||
@@ -74,7 +80,7 @@ static uint8_t Peek8(uintptr_t addr, uintptr_t offset)
|
||||
{
|
||||
return *(uint8_t*)(addr+offset);
|
||||
}
|
||||
extern int errno;
|
||||
|
||||
void x64Int3(x64emu_t* emu, uintptr_t* addr)
|
||||
{
|
||||
if(Peek8(*addr, 0)=='S' && Peek8(*addr, 1)=='C') // Signature for "Out of x86 door"
|
||||
@@ -95,16 +101,17 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr)
|
||||
int have_trace = 0;
|
||||
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
|
||||
if(box64_log>=LOG_DEBUG || cycle_log) {
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
int tid = GetTID();
|
||||
char t_buff[256] = "\0";
|
||||
char buff2[64] = "\0";
|
||||
char buff3[64] = "\0";
|
||||
char* buff = cycle_log?my_context->log_call[my_context->current_line]:t_buff;
|
||||
char* buffret = cycle_log?my_context->log_ret[my_context->current_line]:NULL;
|
||||
if(buffret) buffret[0] = '\0';
|
||||
if(cycle_log)
|
||||
int cycle_line = my_context->current_line;
|
||||
if(cycle_log) {
|
||||
my_context->current_line = (my_context->current_line+1)%cycle_log;
|
||||
}
|
||||
char* buff = cycle_log?my_context->log_call[cycle_line]:t_buff;
|
||||
char* buffret = cycle_log?my_context->log_ret[cycle_line]:NULL;
|
||||
if(buffret) buffret[0] = '\0';
|
||||
char *tmp;
|
||||
int post = 0;
|
||||
int perr = 0;
|
||||
@@ -116,170 +123,174 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr)
|
||||
snprintf(buff, 256, "%s", cycle_log?"PltResolver ":" ... ");
|
||||
} else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ") || !strcmp(s, "open64")) {
|
||||
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));
|
||||
snprintf(buff, 256, "%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 (!strcmp(s, "shm_open")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
|
||||
snprintf(buff, 256, "%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 (!strcmp(s, "fopen") || !strcmp(s, "fopen64")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)(R_RSI));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)(R_RSI));
|
||||
perr = 2;
|
||||
} else if (!strcmp(s, "__openat64") || !strcmp(s, "openat64") || !strcmp(s, "__openat64_2")) {
|
||||
tmp = (char*)(R_RSI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
|
||||
perr = 1;
|
||||
} else if (strstr(s, "readlink")==s) {
|
||||
} else if (!strcmp(s, "readlink")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p, %zd)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (void*)(R_RSI), (size_t)R_RDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p, %zd)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (void*)(R_RSI), (size_t)R_RDX);
|
||||
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));
|
||||
snprintf(buff, 256, "%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)");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
perr = 2;
|
||||
} else if (!strcmp(s, "read")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "write")) {
|
||||
if(R_EDI==2 || R_EDI==3)
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p\"%s\", %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, (char*)R_RSI, R_RDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p\"%s\", %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, (char*)R_RSI, R_RDX);
|
||||
else
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "access")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "waitpid")==s) {
|
||||
pu32 = (uint32_t*)R_RSI;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %d)", tid, *(void**)(R_RSP), s, R_EDI, pu32, R_EDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %d)", tid, *(void**)(R_RSP), s, R_EDI, pu32, R_EDX);
|
||||
perr = 1;
|
||||
post = 6;
|
||||
} else if (!strcmp(s, "lseek64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "lseek")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
|
||||
perr = 1;
|
||||
} else if (!strcmp(s, "recvmsg")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_EDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_EDX);
|
||||
perr = 1;
|
||||
} else if (strstr(s, "puts")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} 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)");
|
||||
snprintf(buff, 256, "%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);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)R_RSI);
|
||||
} else if (strstr(s, "getenv")==s) {
|
||||
tmp = (char*)(R_RDI);
|
||||
post = 2;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (strstr(s, "setenv")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %d)", tid, *(void**)(R_RSP), s, (char*)R_RDI, (char*)R_RSI, R_EDX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", %d)", tid, *(void**)(R_RSP), s, (char*)R_RDI, (char*)R_RSI, R_EDX);
|
||||
} 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);
|
||||
snprintf(buff, 256, "%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, "__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));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
|
||||
} else if (strstr(s, "__snprintf_chk")) {
|
||||
tmp = (char*)(R_R8);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, R_EDX, R_RCX, (tmp)?tmp:"(nil)", (void*)(R_R9));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %d, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, R_EDX, R_RCX, (tmp)?tmp:"(nil)", (void*)(R_R9));
|
||||
} else if (!strcmp(s, "snprintf")) {
|
||||
tmp = (char*)(R_RDX);
|
||||
pu64 = (uint64_t*)R_RDI;
|
||||
post = 3;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (tmp)?tmp:"(nil)", (void*)(R_RCX));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (tmp)?tmp:"(nil)", (void*)(R_RCX));
|
||||
} else if (!strcmp(s, "getcwd")) {
|
||||
post = 2;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI);
|
||||
} else if (!strcmp(s, "ftok")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
perr = 1;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, tmp?tmp:"nil", R_ESI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, tmp?tmp:"nil", R_ESI);
|
||||
} else if (!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress") || !strcmp(s, "glXGetProcAddressARB")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glLabelObjectEXT")) {
|
||||
tmp = (char*)(R_RCX);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, \"%s\")", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_ECX, (tmp)?tmp:"(nil)");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(0x%x, %d, %d, \"%s\")", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_ECX, (tmp)?tmp:"(nil)");
|
||||
} else if (!strcmp(s, "glGetStringi")) {
|
||||
post = 2;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
|
||||
} else if (!strcmp(s, "_dl_tlsdesc_undefweak")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(RAX=%p)", tid, *(void**)(R_RSP), s, (void*)R_RAX);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(RAX=%p)", tid, *(void**)(R_RSP), s, (void*)R_RAX);
|
||||
} 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);
|
||||
snprintf(buff, 256, "%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));
|
||||
snprintf(buff, 256, "%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));
|
||||
snprintf(buff, 256, "%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);
|
||||
snprintf(buff, 256, "%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);
|
||||
snprintf(buff, 256, "%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]);
|
||||
snprintf(buff, 256, "%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,
|
||||
snprintf(buff, 256, "%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));
|
||||
snprintf(buff, 256, "%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,
|
||||
snprintf(buff, 256, "%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);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
|
||||
}
|
||||
if(!cycle_log) {
|
||||
mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, "%s =>", buff);
|
||||
mutex_unlock(&emu->context->mutex_trace);
|
||||
}
|
||||
if(!cycle_log) printf_log(LOG_NONE, "%s =>", buff);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
w(emu, a); // some function never come back, so unlock the mutex first!
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
if(post)
|
||||
switch(post) { // Only ever 2 for now...
|
||||
case 1: snprintf(buff2, 63, " [%llu sec %llu nsec]", pu64?pu64[0]:~0ull, pu64?pu64[1]:~0ull);
|
||||
case 1: snprintf(buff2, 64, " [%llu sec %llu nsec]", pu64?pu64[0]:~0ull, pu64?pu64[1]:~0ull);
|
||||
break;
|
||||
case 2: snprintf(buff2, 63, "(%s)", R_RAX?((char*)R_RAX):"nil");
|
||||
case 2: snprintf(buff2, 64, "(%s)", R_RAX?((char*)R_RAX):"nil");
|
||||
break;
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu64?((char*)pu64):"nil");
|
||||
case 3: snprintf(buff2, 64, "(%s)", pu64?((char*)pu64):"nil");
|
||||
break;
|
||||
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
|
||||
case 4: snprintf(buff2, 64, " (%f)", ST0.d);
|
||||
break;
|
||||
case 5: {
|
||||
uint32_t* p = (uint32_t*)R_RAX; // uint64_t? (case never used)
|
||||
if(p)
|
||||
snprintf(buff2, 63, " size=%ux%u, pitch=%u, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
snprintf(buff2, 64, " size=%ux%u, pitch=%u, pixels=%p", p[2], p[3], p[4], p+5);
|
||||
else
|
||||
snprintf(buff2, 63, "NULL Surface");
|
||||
snprintf(buff2, 64, "NULL Surface");
|
||||
}
|
||||
break;
|
||||
case 6: if(pu32) snprintf(buff2, 63, " [0x%x] ", pu32[0]);
|
||||
case 6: if(pu32) snprintf(buff2, 64, " [0x%x] ", pu32[0]);
|
||||
break;
|
||||
}
|
||||
if(perr==1 && ((int)R_EAX)<0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
snprintf(buff3, 64, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
else if(perr==2 && R_EAX==0)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
snprintf(buff3, 64, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
if(cycle_log)
|
||||
snprintf(buffret, 127, "0x%lX%s%s", R_RAX, buff2, buff3);
|
||||
else
|
||||
snprintf(buffret, 128, "0x%lX%s%s", R_RAX, buff2, buff3);
|
||||
else {
|
||||
mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, " return 0x%lX%s%s\n", R_RAX, buff2, buff3);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
mutex_unlock(&emu->context->mutex_trace);
|
||||
}
|
||||
} else
|
||||
w(emu, a);
|
||||
}
|
||||
|
||||
+6
-3
@@ -1189,8 +1189,9 @@ uint16_t sbb16(x64emu_t *emu, uint16_t d, uint16_t s)
|
||||
|
||||
if (ACCESS_FLAG(F_CF))
|
||||
res = d - s - 1;
|
||||
else
|
||||
else {
|
||||
res = d - s;
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
|
||||
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
|
||||
@@ -1211,8 +1212,9 @@ uint32_t sbb32(x64emu_t *emu, uint32_t d, uint32_t s)
|
||||
|
||||
if (ACCESS_FLAG(F_CF))
|
||||
res = d - s - 1;
|
||||
else
|
||||
else {
|
||||
res = d - s;
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
|
||||
CONDITIONAL_SET_FLAG(!res, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
|
||||
@@ -1233,8 +1235,9 @@ uint64_t sbb64(x64emu_t *emu, uint64_t d, uint64_t s)
|
||||
|
||||
if (ACCESS_FLAG(F_CF))
|
||||
res = d - s - 1;
|
||||
else
|
||||
else {
|
||||
res = d - s;
|
||||
}
|
||||
CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
|
||||
CONDITIONAL_SET_FLAG(!res, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
|
||||
|
||||
+3
-1
@@ -168,7 +168,7 @@ x64emurun:
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x2E: /* segments are ignored */
|
||||
case 0x2E: /* segments are ignored */
|
||||
case 0x36: /* SS: (ignored) */
|
||||
break;
|
||||
|
||||
@@ -1414,10 +1414,12 @@ x64emurun:
|
||||
case 4: /* MUL EAX,Ed */
|
||||
mul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
case 5: /* IMUL EAX,Ed */
|
||||
imul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
case 6: /* DIV Ed */
|
||||
div32(emu, ED->dword[0]);
|
||||
|
||||
+52
-40
@@ -37,6 +37,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
int32_t tmp32s, tmp32s2;
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int64_t tmp64s;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx, eax1;
|
||||
mmx87_regs_t *opem, *opgm, eam1;
|
||||
@@ -193,32 +194,38 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGM;
|
||||
GM->sd[1] = EX->f[1];
|
||||
GM->sd[0] = EX->f[0];
|
||||
if(isnanf(EX->f[1]) || isinff(EX->f[1]) || EX->f[1]>0x7fffffff)
|
||||
GM->sd[1] = 0x80000000;
|
||||
else
|
||||
GM->sd[1] = EX->f[1];
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
|
||||
GM->sd[0] = 0x80000000;
|
||||
else
|
||||
GM->sd[0] = EX->f[0];
|
||||
break;
|
||||
case 0x2D: /* CVTPS2PI Gm, Ex */
|
||||
// rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGM;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GM->sd[1] = floorf(EX->f[1]+0.5f);
|
||||
GM->sd[0] = floorf(EX->f[0]+0.5f);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GM->sd[1] = floorf(EX->f[1]);
|
||||
GM->sd[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GM->sd[1] = ceilf(EX->f[1]);
|
||||
GM->sd[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GM->sd[1] = EX->f[1];
|
||||
GM->sd[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
for(int i=1; i>=0; --i)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
|
||||
GM->sd[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GM->sd[i] = nearbyintf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GM->sd[i] = floorf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GM->sd[i] = ceilf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GM->sd[i] = EX->f[i];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2E: /* UCOMISS Gx, Ex */
|
||||
// same for now
|
||||
@@ -831,12 +838,12 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
tmp64s = rex.w?GD->sq[0]:GD->sdword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:31);
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -897,14 +904,17 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
fpu_fxrstor32(emu, ED);
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr = ED->dword[0];
|
||||
emu->mxcsr.x32 = ED->dword[0];
|
||||
if(box64_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
break;
|
||||
case 3: /* STMXCSR Md */
|
||||
ED->dword[0] = emu->mxcsr;
|
||||
ED->dword[0] = emu->mxcsr.x32;
|
||||
break;
|
||||
case 7: /* CLFLUSH Ed */
|
||||
#ifdef DYNAREC
|
||||
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
|
||||
if(box64_dynarec)
|
||||
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
@@ -944,12 +954,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
}
|
||||
} 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];
|
||||
R_RAX = R_EAX; // to erase upper part of RAX
|
||||
} else {
|
||||
R_RAX = ED->dword[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -958,12 +970,12 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
tmp64s = rex.w?GD->sq[0]:GD->sdword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:31);
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u)) {
|
||||
@@ -1088,12 +1100,12 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp32s = GD->sdword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:31);
|
||||
tmp32s >>= (rex.w?6:5);
|
||||
tmp64s = rex.w?GD->sq[0]:GD->sdword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:31);
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(ED->q[0] & (1LL<<tmp8u))
|
||||
@@ -1247,14 +1259,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
break;
|
||||
case 0xC4: /* PINSRW Gm,Ew,Ib */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETED(1);
|
||||
GETGM;
|
||||
tmp8u = F8;
|
||||
GM->uw[tmp8u&3] = ED->word[0]; // only low 16bits
|
||||
break;
|
||||
case 0xC5: /* PEXTRW Gw,Em,Ib */
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETEM(1);
|
||||
GETGD;
|
||||
tmp8u = F8;
|
||||
GD->q[0] = EM->uw[tmp8u&3]; // 16bits extract, 0 extended
|
||||
@@ -1369,7 +1381,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETEM(0);
|
||||
GETGD;
|
||||
GD->dword[0] = 0;
|
||||
GD->q[0] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(EM->ub[i]&0x80)
|
||||
GD->dword[0] |= (1<<i);
|
||||
@@ -1448,7 +1460,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEM(0);
|
||||
GETGM;
|
||||
if(EM->q>15)
|
||||
tmp8u = 16;
|
||||
tmp8u = 15;
|
||||
else
|
||||
tmp8u = EM->ub[0];
|
||||
for(int i=0; i<4; ++i)
|
||||
|
||||
+40
-28
@@ -119,7 +119,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->q[0] = EX->q[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
if(!MODREG) {
|
||||
// EX is not a register
|
||||
GX->q[1] = 0;
|
||||
}
|
||||
@@ -129,7 +129,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
GX->ud[0] = EX->ud[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
if(!MODREG) {
|
||||
// EX is not a register (reg to reg only move 31:0)
|
||||
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x29: /* MOVAPS Ex,Gx */
|
||||
case 0x29: /* MOVAPS FS:Ex,Gx */
|
||||
switch(rep) {
|
||||
case 0:
|
||||
nextop = F8;
|
||||
@@ -179,7 +179,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
|
||||
case 0x59:
|
||||
switch(rep) {
|
||||
case 2: /* MULSS Gx, Ex */
|
||||
case 2: /* MULSS Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
@@ -192,7 +192,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
break;
|
||||
case 0x5A:
|
||||
switch(rep) {
|
||||
case 2: /* CVTSS2SD Gx, Ex */
|
||||
case 2: /* CVTSS2SD Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
@@ -206,7 +206,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
|
||||
case 0x6F:
|
||||
switch(rep) {
|
||||
case 2: /* MOVDQU Gx, Ex */
|
||||
case 2: /* MOVDQU Gx, FS:Ex */
|
||||
nextop = F8;
|
||||
GETEX_OFFS(0, tlsdata);
|
||||
GETGX;
|
||||
@@ -218,21 +218,33 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xAF: /* IMUL Gd,Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
case 0xAF:
|
||||
switch(rep) {
|
||||
case 0: /* IMUL Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
|
||||
else
|
||||
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB6: /* MOVZX Gd,Eb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
GD->q[0] = EB->byte[0];
|
||||
case 0xB6:
|
||||
switch(rep) {
|
||||
case 0: /* MOVZX Gd, FS:Eb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
GD->q[0] = EB->byte[0];
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -267,7 +279,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
break;
|
||||
|
||||
|
||||
case 0x63: /* MOVSXD Gd,Ed */
|
||||
case 0x63: /* MOVSXD Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
@@ -281,7 +293,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
return Run6664(emu, rex, addr);
|
||||
return Run6664(emu, rex, seg, addr);
|
||||
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
nextop = F8;
|
||||
@@ -308,7 +320,7 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
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;
|
||||
@@ -346,13 +358,13 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x88: /* MOV Eb,Gb */
|
||||
case 0x88: /* MOV FS:Eb,Gb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGB;
|
||||
EB->byte[0] = GB;
|
||||
break;
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
case 0x89: /* MOV FS:Ed,Gd */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
@@ -366,13 +378,13 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
ED->dword[0] = GD->dword[0];
|
||||
}
|
||||
break;
|
||||
case 0x8A: /* MOV Gb,Eb */
|
||||
case 0x8A: /* MOV Gb, FS:Eb */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(0, tlsdata);
|
||||
GETGB;
|
||||
GB = EB->byte[0];
|
||||
break;
|
||||
case 0x8B: /* MOV Gd,Ed */
|
||||
case 0x8B: /* MOV Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
GETED_OFFS(0, tlsdata);
|
||||
GETGD;
|
||||
@@ -382,12 +394,12 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
GD->q[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0xC6: /* MOV Eb,Ib */
|
||||
case 0xC6: /* MOV FS:Eb, Ib */
|
||||
nextop = F8;
|
||||
GETEB_OFFS(1, tlsdata);
|
||||
EB->byte[0] = F8;
|
||||
break;
|
||||
case 0xC7: /* MOV Ed,Id */
|
||||
case 0xC7: /* MOV FS:Ed, Id */
|
||||
nextop = F8;
|
||||
GETED_OFFS(4, tlsdata);
|
||||
if(rex.w)
|
||||
|
||||
+3
-1
@@ -133,7 +133,9 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
break;
|
||||
|
||||
case 0x64: /* FS: */
|
||||
return Run6664(emu, rex, addr);
|
||||
return Run6664(emu, rex, _FS, addr);
|
||||
case 0x65: /* GS: */
|
||||
return Run6664(emu, rex, _GS, addr);
|
||||
|
||||
case 0x69: /* IMUL Gw,Ew,Iw */
|
||||
nextop = F8;
|
||||
|
||||
+66
-68
@@ -54,6 +54,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uint64_t tmp64u;
|
||||
int64_t tmp64s;
|
||||
float tmpf;
|
||||
#ifndef NOALIGN
|
||||
int is_nan;
|
||||
@@ -197,10 +198,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGM;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GM->sd[0] = floor(EX->d[0]+0.5);
|
||||
GM->sd[1] = floor(EX->d[1]+0.5);
|
||||
GM->sd[0] = nearbyint(EX->d[0]);
|
||||
GM->sd[1] = nearbyint(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GM->sd[0] = floor(EX->d[0]);
|
||||
@@ -668,18 +669,18 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETGX;
|
||||
tmp8u = F8; // ignoring bit 3 interupt thingy
|
||||
if(tmp8u&4)
|
||||
tmp8u = (emu->mxcsr>>13)&3;
|
||||
tmp8u = emu->mxcsr.f.MXCSR_RC;
|
||||
else
|
||||
tmp8u &= 3;
|
||||
switch(tmp8u) {
|
||||
case ROUND_Nearest:
|
||||
GX->f[0] = floor(EX->f[0]+0.5);
|
||||
GX->f[0] = nearbyintf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->f[0] = floor(EX->f[0]);
|
||||
GX->f[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->f[0] = ceil(EX->f[0]);
|
||||
GX->f[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->f[0] = EX->f[0];
|
||||
@@ -692,12 +693,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETGX;
|
||||
tmp8u = F8; // ignoring bit 3 interupt thingy
|
||||
if(tmp8u&4)
|
||||
tmp8u = (emu->mxcsr>>13)&3;
|
||||
tmp8u = emu->mxcsr.f.MXCSR_RC;
|
||||
else
|
||||
tmp8u &= 3;
|
||||
switch(tmp8u) {
|
||||
case ROUND_Nearest:
|
||||
GX->d[0] = floor(EX->d[0]+0.5);
|
||||
GX->d[0] = nearbyint(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->d[0] = floor(EX->d[0]);
|
||||
@@ -762,12 +763,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
ED->dword[0] = GX->ud[tmp8u&3];
|
||||
if(MODREG && rex.w) ED->dword[1] = 0;
|
||||
if(MODREG) ED->dword[1] = 0;
|
||||
break;
|
||||
|
||||
case 0x20: // PINSRB GX, ED, u8
|
||||
nextop = F8;
|
||||
GETED(1);
|
||||
GETED(1); // It's ED, and not EB
|
||||
GETGX;
|
||||
tmp8u = F8;
|
||||
GX->ub[tmp8u&0xf] = ED->byte[0];
|
||||
@@ -865,7 +866,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
GD->dword[0] = 0;
|
||||
GD->q[0] = 0;
|
||||
for(int i=0; i<2; ++i)
|
||||
GD->dword[0] |= ((EX->q[i]>>63)&1)<<i;
|
||||
break;
|
||||
@@ -951,32 +952,24 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GX->sd[0] = floorf(EX->f[0]+0.5f);
|
||||
GX->sd[1] = floorf(EX->f[1]+0.5f);
|
||||
GX->sd[2] = floorf(EX->f[2]+0.5f);
|
||||
GX->sd[3] = floorf(EX->f[3]+0.5f);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->sd[0] = floorf(EX->f[0]);
|
||||
GX->sd[1] = floorf(EX->f[1]);
|
||||
GX->sd[2] = floorf(EX->f[2]);
|
||||
GX->sd[3] = floorf(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->sd[0] = ceilf(EX->f[0]);
|
||||
GX->sd[1] = ceilf(EX->f[1]);
|
||||
GX->sd[2] = ceilf(EX->f[2]);
|
||||
GX->sd[3] = ceilf(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->sd[0] = EX->f[0];
|
||||
GX->sd[1] = EX->f[1];
|
||||
GX->sd[2] = EX->f[2];
|
||||
GX->sd[3] = EX->f[3];
|
||||
break;
|
||||
}
|
||||
for(int i=0; i<4; ++i)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff || EX->f[i]<-0x80000000)
|
||||
GX->sd[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GX->sd[i] = nearbyintf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->sd[i] = floorf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX->sd[i] = ceilf(EX->f[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX->sd[i] = EX->f[i];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x5C: /* SUBPD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -1214,6 +1207,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 4: /* PSRAW Ex, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>15) tmp8u=15;
|
||||
for (int i=0; i<8; ++i) EX->sw[i] >>= tmp8u;
|
||||
break;
|
||||
case 6: /* PSLLW Ex, Ib */
|
||||
@@ -1240,10 +1234,8 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 4: /* PSRAD Ex, Ib */
|
||||
tmp8u = F8;
|
||||
if(tmp8u>31) {
|
||||
for (int i=0; i<4; ++i) EX->sd[i] = (EX->sd[i]<0)?-1:0;
|
||||
} else
|
||||
for (int i=0; i<4; ++i) EX->sd[i] >>= tmp8u;
|
||||
if(tmp8u>31) tmp8u=31;
|
||||
for (int i=0; i<4; ++i) EX->sd[i] >>= tmp8u;
|
||||
break;
|
||||
case 6: /* PSLLD Ex, Ib */
|
||||
tmp8u = F8;
|
||||
@@ -1545,13 +1537,19 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEB(0);
|
||||
GETGW;
|
||||
GW->word[0] = EB->byte[0];
|
||||
if(rex.w)
|
||||
GW->q[0] = EB->byte[0];
|
||||
else
|
||||
GW->word[0] = EB->byte[0];
|
||||
break;
|
||||
case 0xB7: /* MOVZX Gw,Ew */
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
GW->word[0] = EW->word[0];
|
||||
if(rex.w)
|
||||
GW->q[0] = EW->word[0];
|
||||
else
|
||||
GW->word[0] = EW->word[0];
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
@@ -1559,7 +1557,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* BT Ew,Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETEW(1);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
@@ -1578,7 +1576,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 5: /* BTS Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETEW(1);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
@@ -1601,7 +1599,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 6: /* BTR Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETEW(1);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
@@ -1622,7 +1620,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 7: /* BTC Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GETEW(0);
|
||||
GETEW(1);
|
||||
GETGW;
|
||||
tmp8u = F8;
|
||||
if(rex.w) {
|
||||
@@ -1650,12 +1648,12 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEW(0);
|
||||
GETGW;
|
||||
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
|
||||
tmp8u=tmp32s&(rex.w?63:15);
|
||||
tmp32s >>= (rex.w?6:4);
|
||||
tmp64s = rex.w?GW->sq[0]:GW->sword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:15);
|
||||
tmp64s >>= (rex.w?6:4);
|
||||
if(!MODREG)
|
||||
{
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
|
||||
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp64s<<(rex.w?3:1)));
|
||||
}
|
||||
if(rex.w) {
|
||||
if(EW->q[0] & (1LL<<tmp8u))
|
||||
@@ -1782,7 +1780,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEX(1);
|
||||
GETGD;
|
||||
tmp8u = F8;
|
||||
GD->dword[0] = EX->uw[tmp8u&7]; // 16bits extract, 0 extended
|
||||
GD->q[0] = EX->uw[tmp8u&7]; // 16bits extract, 0 extended
|
||||
break;
|
||||
case 0xC6: /* SHUFPD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
@@ -1955,7 +1953,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
tmp8u=(EX->q[0]>15)?16:EX->ub[0];
|
||||
tmp8u=(EX->q[0]>15)?15:EX->ub[0];
|
||||
for (int i=0; i<8; ++i)
|
||||
GX->sw[i] >>= tmp8u;
|
||||
break;
|
||||
@@ -1963,13 +1961,9 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
|
||||
if(tmp8u>31)
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sd[i] = (GX->sd[i]<0)?-1:0;
|
||||
else
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sd[i] >>= tmp8u;
|
||||
tmp8u=(EX->q[0]>31)?31:EX->ub[0];
|
||||
for (int i=0; i<4; ++i)
|
||||
GX->sd[i] >>= tmp8u;
|
||||
break;
|
||||
case 0xE3: /* PAVGW Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -2000,8 +1994,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->sd[0] = EX->d[0];
|
||||
GX->sd[1] = EX->d[1];
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
GX->sd[0] = 0x80000000;
|
||||
else
|
||||
GX->sd[0] = EX->d[0];
|
||||
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
|
||||
GX->sd[1] = 0x80000000;
|
||||
else
|
||||
GX->sd[1] = EX->d[1];
|
||||
GX->q[1] = 0;
|
||||
break;
|
||||
case 0xE7: /* MOVNTDQ Ex, Gx */
|
||||
@@ -2040,10 +2040,8 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->ud[0] |= EX->ud[0];
|
||||
GX->ud[1] |= EX->ud[1];
|
||||
GX->ud[2] |= EX->ud[2];
|
||||
GX->ud[3] |= EX->ud[3];
|
||||
GX->q[0] |= EX->q[0];
|
||||
GX->q[1] |= EX->q[1];
|
||||
break;
|
||||
case 0xEC: /* PADDSB Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -2103,7 +2101,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
if(EX->q[0]>63)
|
||||
{GX->q[0] = GX->q[1] = 0;}
|
||||
else
|
||||
{tmp8u=EX->q[0]; for (int i=0; i<2; ++i) GX->q[i] <<= tmp8u;}
|
||||
{tmp8u=EX->ub[0]; for (int i=0; i<2; ++i) GX->q[i] <<= tmp8u;}
|
||||
break;
|
||||
case 0xF4: /* PMULUDQ Gx,Ex */
|
||||
nextop = F8;
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
uintptr_t Run6664(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
uintptr_t Run6664(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg64_t *oped, *opgd;
|
||||
sse_regs_t *opex, *opgx;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
|
||||
|
||||
opcode = F8;
|
||||
// REX prefix before the F0 are ignored
|
||||
|
||||
+6
-11
@@ -133,16 +133,14 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETGW; \
|
||||
if(rex.w) { \
|
||||
do { \
|
||||
tmp64u = native_lock_read_dd(ED); \
|
||||
tmp64u = native_lock_read_dd(ED); \
|
||||
tmp64u = OP##64(emu, tmp64u, GD->q[0]); \
|
||||
} while (native_lock_write_dd(ED, tmp64u)); \
|
||||
} while (native_lock_write_dd(ED, tmp64u)); \
|
||||
} else { \
|
||||
do { \
|
||||
tmp16u = native_lock_read_h(ED); \
|
||||
tmp16u = native_lock_read_h(ED); \
|
||||
tmp16u = OP##16(emu, tmp16u, GW->word[0]); \
|
||||
} while (native_lock_write_d(ED, tmp16u)); \
|
||||
if(MODREG) \
|
||||
EW->word[1] = 0; \
|
||||
} while (native_lock_write_h(ED, tmp16u)); \
|
||||
} \
|
||||
break; \
|
||||
case B+3: \
|
||||
@@ -170,10 +168,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
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 \
|
||||
EW->word[0] = OP##16(emu, EW->word[0], GW->word[0]); \
|
||||
EW->word[0] = OP##16(emu, EW->word[0], GW->word[0]);\
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock); \
|
||||
break; \
|
||||
case B+3: \
|
||||
@@ -278,7 +273,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp16u &=~0xff;
|
||||
tmp16u |= native_lock_read_b(ED);
|
||||
tmp16u = inc16(emu, tmp16u);
|
||||
} while(native_lock_write_b(ED, tmp16u&0xff));
|
||||
} while(native_lock_write_b(ED, tmp16u&0xff));
|
||||
ED->word[0] = tmp16u;
|
||||
} else {
|
||||
do {
|
||||
|
||||
+6
-4
@@ -394,20 +394,22 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
case 4: /* MUL EAX,Ed */
|
||||
mul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
case 5: /* IMUL EAX,Ed */
|
||||
imul32_eax(emu, ED->dword[0]);
|
||||
emu->regs[_AX].dword[1] = 0;
|
||||
emu->regs[_DX].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;
|
||||
//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;
|
||||
//emu->regs[_AX].dword[1] = 0;
|
||||
//emu->regs[_DX].dword[1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+56
-28
@@ -19,6 +19,7 @@
|
||||
#include "x87emu_private.h"
|
||||
#include "box64context.h"
|
||||
#include "bridge.h"
|
||||
#include "signals.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/native_lock.h"
|
||||
#endif
|
||||
@@ -43,40 +44,67 @@ uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x2E: /* UCOMISS Gx, Ex */
|
||||
case 0x2E:
|
||||
// same for now
|
||||
case 0x2F: /* COMISS Gx, Ex */
|
||||
if(rep) {
|
||||
return 0;
|
||||
case 0x2F:
|
||||
switch(rep) {
|
||||
case 0: /* (U)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 0;
|
||||
}
|
||||
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;
|
||||
|
||||
case 0x6F: /* MOVQ Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
GM->q = EM->q;
|
||||
case 0x6F:
|
||||
switch(rep) {
|
||||
case 0: /* MOVQ Gm, Em */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
GM->q = EM->q;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7F: /* MOVQ Em, Gm */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
EM->q = GM->q;
|
||||
case 0x7F:
|
||||
switch(rep) {
|
||||
case 0: /* MOVQ Em, Gm */
|
||||
nextop = F8;
|
||||
GETEM32(0);
|
||||
GETGM;
|
||||
EM->q = GM->q;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB9:
|
||||
switch(rep) {
|
||||
case 0: /* UD1 Ed */
|
||||
nextop = F8;
|
||||
GETED32(0);
|
||||
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1033,7 +1033,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
(trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) ) {
|
||||
int tid = syscall(SYS_gettid);
|
||||
pthread_mutex_lock(&my_context->mutex_trace);
|
||||
mutex_lock(&my_context->mutex_trace);
|
||||
#ifdef DYNAREC
|
||||
if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
|
||||
printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
|
||||
@@ -1050,7 +1050,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
|
||||
if(R_RIP==0) {
|
||||
printf_log(LOG_NONE, "Running at NULL address\n");
|
||||
pthread_mutex_unlock(&my_context->mutex_trace);
|
||||
mutex_unlock(&my_context->mutex_trace);
|
||||
return;
|
||||
}
|
||||
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
|
||||
@@ -1076,8 +1076,9 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
|
||||
printFunctionAddr(ip, "here: ");
|
||||
} else if(peek==0x55 || peek==0x53) {
|
||||
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
|
||||
printFunctionAddr(ip, "here: ");
|
||||
printFunctionAddr(*(uintptr_t*)(R_RSP), " STACK_TOP: ");
|
||||
} else if(peek==0xF3 && PK(1)==0x0F && PK(2)==0x1E && PK(3)==0xFA) {
|
||||
printFunctionAddr(*(uintptr_t*)(R_RSP), " STACK_TOP: ");
|
||||
} else if(peek==0xE8) { // Call
|
||||
uintptr_t nextaddr = ip + 5 + PK64(1);
|
||||
printFunctionAddr(nextaddr, "=> ");
|
||||
@@ -1089,7 +1090,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
|
||||
}
|
||||
printf_log(LOG_NONE, "\n");
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_trace);
|
||||
mutex_unlock(&my_context->mutex_trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step);
|
||||
uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr);
|
||||
uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr);
|
||||
uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Run6664(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Run6664(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr);
|
||||
uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr);
|
||||
|
||||
+8
-48
@@ -116,76 +116,36 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d += *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d += f;
|
||||
}
|
||||
ST0.d += *(float*)ED;
|
||||
break;
|
||||
case 1: /* FMUL ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d *= *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d *= f;
|
||||
}
|
||||
ST0.d *= *(float*)ED;
|
||||
break;
|
||||
case 2: /* FCOM ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
fpu_fcom(emu, f);
|
||||
}
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
break;
|
||||
case 3: /* FCOMP */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
fpu_fcom(emu, f);
|
||||
}
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FSUB ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d -= *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d -= f;
|
||||
}
|
||||
ST0.d -= *(float*)ED;
|
||||
break;
|
||||
case 5: /* FSUBR ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d = *(float*)ED - ST0.d;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f - ST0.d;
|
||||
}
|
||||
ST0.d = *(float*)ED - ST0.d;
|
||||
break;
|
||||
case 6: /* FDIV ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d /= *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d /= f;
|
||||
}
|
||||
ST0.d /= *(float*)ED;
|
||||
break;
|
||||
case 7: /* FDIVR ST0, float */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d = *(float*)ED / ST0.d;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f / ST0.d;
|
||||
}
|
||||
ST0.d = *(float*)ED / ST0.d;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
||||
+3
-18
@@ -232,30 +232,15 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0: /* FLD ST0, Ed float */
|
||||
GETED(0);
|
||||
fpu_do_push(emu);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d = *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f;
|
||||
}
|
||||
ST0.d = *(float*)ED;
|
||||
break;
|
||||
case 2: /* FST Ed, ST0 */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
f = ST0.d;
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
*(float*)ED = ST0.d;
|
||||
break;
|
||||
case 3: /* FSTP Ed, ST0 */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
f = ST0.d;
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
*(float*)ED = ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FLDENV m */
|
||||
|
||||
+7
-7
@@ -133,15 +133,15 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 1: /* FISTTP Ed, ST0 */
|
||||
GETED(0);
|
||||
tmp32s = ST0.d; // TODO: Handling of FPU Exception
|
||||
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
|
||||
tmp32s = 0x80000000;
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, (double)(int32_t)0x80000000) || !isfinite(ST0.d))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else
|
||||
ED->sdword[0] = ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
ED->sdword[0] = tmp32s;
|
||||
break;
|
||||
case 2: /* FIST Ed, ST0 */
|
||||
GETED(0);
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, (double)(int32_t)0x80000000) || !isfinite(ST0.d))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
@@ -150,7 +150,7 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 3: /* FISTP Ed, ST0 */
|
||||
GETED(0);
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, (double)(int32_t)0x80000000) || !isfinite(ST0.d))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
@@ -178,4 +178,4 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
+4
-21
@@ -114,37 +114,20 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
case 0: /* FLD double */
|
||||
GETED(0);
|
||||
fpu_do_push(emu);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED;
|
||||
else {
|
||||
memcpy(&ST0.d, ED, sizeof(double));
|
||||
}
|
||||
ST0.d = *(double*)ED;
|
||||
break;
|
||||
case 1: /* FISTTP ED qword */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(int64_t*)ED = ST0.d;
|
||||
else {
|
||||
int64_t i64 = ST0.d;
|
||||
memcpy(ED, &i64, sizeof(int64_t));
|
||||
}
|
||||
*(int64_t*)ED = ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FST double */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
memcpy(ED, &ST0.d, sizeof(double));
|
||||
}
|
||||
*(double*)ED = ST0.d;
|
||||
break;
|
||||
case 3: /* FSTP double */
|
||||
GETED(0);
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
memcpy(ED, &ST0.d, sizeof(double));
|
||||
}
|
||||
*(double*)ED = ST0.d;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FRSTOR m108byte */
|
||||
|
||||
+3
-3
@@ -129,14 +129,14 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
case 2: /* FIST Ew, ST0 */
|
||||
GETEW(0);
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
|
||||
EW->sword[0] = 0x8000;
|
||||
else
|
||||
EW->sword[0] = fpu_round(emu, ST0.d);
|
||||
break;
|
||||
case 3: /* FISTP Ew, ST0 */
|
||||
GETEW(0);
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
|
||||
EW->sword[0] = 0x8000;
|
||||
else
|
||||
EW->sword[0] = fpu_round(emu, ST0.d);
|
||||
@@ -165,7 +165,7 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
if(STll(0).sref==ST(0).sq)
|
||||
ED->sq[0] = STll(0).sq;
|
||||
else {
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
|
||||
ED->sq[0] = 0x8000000000000000LL;
|
||||
else
|
||||
ED->sq[0] = fpu_round(emu, ST0.d);
|
||||
|
||||
+44
-10
@@ -173,10 +173,12 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp64s = rex.w?GD->sq[0]:GD->sdword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:31);
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(rex.w) {
|
||||
@@ -350,10 +352,12 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
tmp8u = GD->byte[0];
|
||||
tmp64s = rex.w?GD->sq[0]:GD->sdword[0];
|
||||
tmp8u=tmp64s&(rex.w?63:31);
|
||||
tmp64s >>= (rex.w?6:5);
|
||||
if(!MODREG)
|
||||
{
|
||||
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp64s<<(rex.w?3:2)));
|
||||
}
|
||||
tmp8u&=rex.w?63:31;
|
||||
#ifdef DYNAREC
|
||||
@@ -595,6 +599,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp8u = native_lock_read_b(EB);
|
||||
tmp8u2 = add8(emu, tmp8u, GB);
|
||||
} while(native_lock_write_b(EB, tmp8u2));
|
||||
GB = tmp8u;
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp8u = add8(emu, EB->byte[0], GB);
|
||||
@@ -858,7 +863,6 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
} while(native_lock_write_b(EB, GB));
|
||||
GB = tmp8u;
|
||||
}
|
||||
// dynarec use need it's own mecanism
|
||||
#else
|
||||
GETEB(0);
|
||||
GETGB;
|
||||
@@ -890,10 +894,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
if(rex.w) {
|
||||
GD->q[0] = native_lock_xchg(ED, GD->q[0]);
|
||||
} else {
|
||||
do {
|
||||
tmp32u = native_lock_read_d(ED);
|
||||
} while(native_lock_write_d(ED, GD->dword[0]));
|
||||
GD->q[0] = tmp32u;
|
||||
GD->dword[0] = native_lock_xchg_d(ED, GD->dword[0]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -938,6 +939,39 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFE: /* GRP 5 Eb */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Eb */
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp8u = native_lock_read_b(ED);
|
||||
} while(native_lock_write_b(ED, inc8(emu, tmp8u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->byte[0] = inc8(emu, ED->byte[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp8u = native_lock_read_b(ED);
|
||||
} while(native_lock_write_b(ED, dec8(emu, tmp8u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->byte[0] = dec8(emu, ED->byte[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFE 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
@@ -966,7 +1000,7 @@ uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
tmp32u &=~0xff;
|
||||
tmp32u |= native_lock_read_b(ED);
|
||||
tmp32u = inc32(emu, tmp32u);
|
||||
} while(native_lock_write_b(ED, tmp32u&0xff));
|
||||
} while(native_lock_write_b(ED, tmp32u&0xff));
|
||||
ED->dword[0] = tmp32u;
|
||||
} else {
|
||||
do {
|
||||
|
||||
+46
-34
@@ -45,7 +45,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GX->q[0] = EX->q[0];
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
if(!MODREG) {
|
||||
// EX is not a register
|
||||
GX->q[1] = 0;
|
||||
}
|
||||
@@ -84,9 +84,15 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
if(rex.w)
|
||||
GD->sq[0] = EX->d[0];
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffffffffffffLL)
|
||||
GD->q[0] = 0x8000000000000000LL;
|
||||
else
|
||||
GD->sq[0] = EX->d[0];
|
||||
else {
|
||||
GD->sdword[0] = EX->d[0];
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
GD->dword[0] = 0x80000000;
|
||||
else
|
||||
GD->sdword[0] = EX->d[0];
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
@@ -95,35 +101,41 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GD->q[0] = floor(EX->d[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->q[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->q[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->q[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffffffffffffLL)
|
||||
GD->q[0] = 0x8000000000000000LL;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GD->sq[0] = nearbyint(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sq[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sq[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sq[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GD->sdword[0] = floor(EX->d[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sdword[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sdword[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sdword[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
GD->dword[0] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GD->sdword[0] = nearbyint(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sdword[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sdword[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sdword[0] = EX->d[0];
|
||||
break;
|
||||
}
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
@@ -300,10 +312,10 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GX->sd[0] = floor(EX->d[0]+0.5);
|
||||
GX->sd[1] = floor(EX->d[1]+0.5);
|
||||
GX->sd[0] = nearbyint(EX->d[0]);
|
||||
GX->sd[1] = nearbyint(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX->sd[0] = floor(EX->d[0]);
|
||||
|
||||
+44
-34
@@ -90,9 +90,15 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
if (rex.w)
|
||||
GD->sq[0] = EX->f[0];
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffffffffffffLL)
|
||||
GD->q[0] = 0x8000000000000000LL;
|
||||
else
|
||||
GD->sq[0] = EX->f[0];
|
||||
else {
|
||||
GD->sdword[0] = EX->f[0];
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
|
||||
GD->dword[0] = 0x80000000;
|
||||
else
|
||||
GD->sdword[0] = EX->f[0];
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
@@ -101,35 +107,41 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEX(0);
|
||||
GETGD;
|
||||
if(rex.w) {
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GD->sq[0] = floorf(EX->f[0]+0.5f);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sq[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sq[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sq[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffffffffffffLL)
|
||||
GD->q[0] = 0x8000000000000000LL;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GD->sq[0] = nearbyintf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sq[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sq[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sq[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GD->sdword[0] = floorf(EX->f[0]+0.5f);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sdword[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sdword[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sdword[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
|
||||
GD->dword[0] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GD->sdword[0] = nearbyintf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD->sdword[0] = floorf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD->sdword[0] = ceilf(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GD->sdword[0] = EX->f[0];
|
||||
break;
|
||||
}
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
break;
|
||||
@@ -269,7 +281,6 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
if(rex.w) {
|
||||
tmp64u = ED->q[0];
|
||||
if(tmp64u) {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
tmp8u = 0;
|
||||
while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;
|
||||
GD->q[0] = tmp8u;
|
||||
@@ -283,16 +294,15 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
} else {
|
||||
tmp32u = ED->dword[0];
|
||||
if(tmp32u) {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
tmp8u = 0;
|
||||
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
|
||||
GD->dword[0] = 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->dword[0] = 32;
|
||||
GD->q[0] = 32;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+232
-66
@@ -55,9 +55,13 @@ void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int f
|
||||
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
|
||||
int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
|
||||
void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr);
|
||||
#ifndef NO_ALIGN
|
||||
#ifndef NOALIGN
|
||||
int32_t my_epoll_ctl(x64emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void* event);
|
||||
int32_t my_epoll_wait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
|
||||
int32_t my_epoll_pwait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout, const sigset_t *sigmask);
|
||||
pid_t my_vfork(x64emu_t* emu);
|
||||
#endif
|
||||
int32_t my_fcntl(x64emu_t* emu, int32_t a, int32_t b, void* c);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
@@ -92,6 +96,8 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 13, __NR_rt_sigaction, 4}, // wrapped to use my_ version
|
||||
{ 14, __NR_rt_sigprocmask, 4},
|
||||
{ 16, __NR_ioctl, 3},
|
||||
{ 17, __NR_pread64, 4},
|
||||
{ 18, __NR_pwrite64, 4},
|
||||
{ 20, __NR_writev, 3},
|
||||
#ifdef __NR_access
|
||||
{ 21, __NR_access, 2},
|
||||
@@ -105,6 +111,10 @@ scwrap_t syscallwrap[] = {
|
||||
#endif
|
||||
//{ 25, __NR_mremap, 5}, // wrapped to track protection
|
||||
{ 27, __NR_mincore, 3},
|
||||
{ 28, __NR_madvise, 3},
|
||||
#ifdef __NR_dup2
|
||||
{ 33, __NR_dup2, 2},
|
||||
#endif
|
||||
{ 35, __NR_nanosleep, 2},
|
||||
{ 39, __NR_getpid, 0},
|
||||
{ 41, __NR_socket, 3},
|
||||
@@ -114,19 +124,24 @@ scwrap_t syscallwrap[] = {
|
||||
{ 45, __NR_recvfrom, 6},
|
||||
{ 46, __NR_sendmsg, 3},
|
||||
{ 47, __NR_recvmsg, 3},
|
||||
{ 51, __NR_getsockname, 3},
|
||||
{ 52, __NR_getpeername, 3},
|
||||
{ 53, __NR_socketpair, 4},
|
||||
{ 54, __NR_setsockopt, 5},
|
||||
{ 55, __NR_getsockopt, 5},
|
||||
//{56, __NR_clone, 5},
|
||||
#ifdef __NR_fork
|
||||
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
|
||||
#endif
|
||||
#ifdef __NR_vfork
|
||||
{58, __NR_vfork, 0},
|
||||
#endif
|
||||
//{58, __NR_vfork, 0},
|
||||
{ 60, __NR_exit, 1}, // Nees wrapping?
|
||||
{ 61, __NR_wait4, 4},
|
||||
{ 62, __NR_kill, 2 },
|
||||
//{ 63, __NR_uname, 1}, // Needs wrapping, use old_utsname
|
||||
{ 66, __NR_semctl, 4},
|
||||
//{ 72, __NR_fnctl, 3}, // Needs wrapping, and not always defined anyway
|
||||
{ 73, __NR_flock, 2},
|
||||
{ 74, __NR_fsync, 1},
|
||||
#ifdef __NR_getdents
|
||||
{ 78, __NR_getdents, 3},
|
||||
#endif
|
||||
@@ -164,6 +179,11 @@ scwrap_t syscallwrap[] = {
|
||||
{ 202, __NR_futex, 6},
|
||||
{ 203, __NR_sched_setaffinity, 3},
|
||||
{ 204, __NR_sched_getaffinity, 3},
|
||||
{ 206, __NR_io_setup, 2},
|
||||
{ 207, __NR_io_destroy, 1},
|
||||
{ 208, __NR_io_getevents, 4},
|
||||
{ 209, __NR_io_submit, 3},
|
||||
{ 210, __NR_io_cancel, 3},
|
||||
#ifdef __NR_epoll_create
|
||||
{ 213, __NR_epoll_create, 1},
|
||||
#endif
|
||||
@@ -174,23 +194,36 @@ scwrap_t syscallwrap[] = {
|
||||
{ 229, __NR_clock_getres, 2},
|
||||
{ 230, __NR_clock_nanosleep, 4},
|
||||
{ 231, __NR_exit_group, 1},
|
||||
#ifdef __NR_epoll_wait
|
||||
#if defined(__NR_epoll_wait) && defined(NOALIGN)
|
||||
{ 232, __NR_epoll_wait, 4},
|
||||
#endif
|
||||
#if defined(__NR_epoll_ctl) && defined(NOALIGN)
|
||||
{ 233, __NR_epoll_ctl, 4},
|
||||
#endif
|
||||
{ 234, __NR_tgkill, 3},
|
||||
{ 247, __NR_waitid, 5},
|
||||
#ifdef __NR_inotify_init
|
||||
{ 253, __NR_inotify_init, 0}, //0xFD
|
||||
#endif
|
||||
{ 254, __NR_inotify_add_watch, 3},
|
||||
{ 255, __NR_inotify_rm_watch, 2},
|
||||
#ifdef NOALIGN
|
||||
{ 257, __NR_openat, 4},
|
||||
#endif
|
||||
{ 258, __NR_mkdirat, 3},
|
||||
//{ 262, __NR_fstatat, 4},
|
||||
{ 263, __NR_unlinkat, 3},
|
||||
#ifdef __NR_renameat
|
||||
{ 264, __NR_renameat, 4},
|
||||
#endif
|
||||
{ 267, __NR_readlinkat, 4},
|
||||
{ 270, __NR_pselect6, 6},
|
||||
{ 272, __NR_unshare, 1},
|
||||
{ 273, __NR_set_robust_list, 2},
|
||||
{ 274, __NR_get_robust_list, 3},
|
||||
#ifdef NOALIGN
|
||||
{ 281, __NR_epoll_pwait, 6},
|
||||
#endif
|
||||
#ifdef _NR_eventfd
|
||||
{ 284, __NR_eventfd, 1},
|
||||
#endif
|
||||
@@ -204,7 +237,7 @@ scwrap_t syscallwrap[] = {
|
||||
{ 302, __NR_prlimit64, 4},
|
||||
{ 309, __NR_getcpu, 3}, // need wrapping?
|
||||
{ 315, __NR_sched_getattr, 4},
|
||||
{ 317, __NR_seccomp, 3},
|
||||
//{ 317, __NR_seccomp, 3},
|
||||
{ 318, __NR_getrandom, 3},
|
||||
{ 319, __NR_memfd_create, 2},
|
||||
{ 324, __NR_membarrier, 2},
|
||||
@@ -273,7 +306,7 @@ ssize_t DirentFromDirent64(void* dest, void* source, ssize_t count)
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return (count<0)?count:ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -347,7 +380,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
case 0: *(int64_t*)&R_RAX = syscall(sc); break;
|
||||
case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
|
||||
case 2: if(s==33) {if(log) snprintf(buff2, 63, " [sys_access(\"%s\", %ld)]", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
|
||||
case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
|
||||
case 3: if(s==42) {if(log) snprintf(buff2, 63, " [sys_connect(%d, %p[type=%d], %d)]", R_EDI, (void*)R_RSI, *(unsigned short*)R_RSI, R_EDX);}; if(s==258) {if(log) snprintf(buff2, 63, " [sys_mkdirat(%d, %s, 0x%x]", R_EDI, (char*)R_RSI, R_EDX);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
|
||||
case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
|
||||
case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
|
||||
case 6: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8, R_R9); break;
|
||||
@@ -356,6 +389,8 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
emu->quit = 1;
|
||||
return;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
if(log) snprintf(buffret, 127, "0x%x%s", R_EAX, buff2);
|
||||
if(log && !cycle_log) printf_log(LOG_NONE, "=> %s\n", buffret);
|
||||
return;
|
||||
@@ -364,30 +399,46 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
switch (s) {
|
||||
case 0: // sys_read
|
||||
*(int64_t*)&R_RAX = read((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 1: // sys_write
|
||||
*(int64_t*)&R_RAX = write((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 2: // sys_open
|
||||
if(s==5) {if (log) snprintf(buff2, 63, " [sys_open(\"%s\", %d, %d)]", (char*)R_RDI, of_convert(R_ESI), R_EDX);};
|
||||
//*(int64_t*)&R_RAX = open((void*)R_EDI, of_convert(R_ESI), R_EDX);
|
||||
*(int64_t*)&R_RAX = my_open(emu, (void*)R_RDI, of_convert(R_ESI), R_EDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 3: // sys_close
|
||||
*(int64_t*)&R_RAX = close((int)R_EDI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 4: // sys_stat
|
||||
*(int64_t*)&R_RAX = my_stat(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 5: // sys_fstat
|
||||
*(int64_t*)&R_RAX = my_fstat(emu, (int)R_EDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 6: // sys_lstat
|
||||
*(int64_t*)&R_RAX = my_lstat(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_poll
|
||||
case 7: // sys_poll
|
||||
*(int64_t*)&R_RAX = poll((struct pollfd*)R_RDI, (nfds_t)R_RSI, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 9: // sys_mmap
|
||||
@@ -395,9 +446,13 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
break;
|
||||
case 10: // sys_mprotect
|
||||
*(int64_t*)&R_RAX = my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 11: // sys_munmap
|
||||
*(int64_t*)&R_RAX = my_munmap(emu, (void*)R_RDI, R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 13: // sys_rt_sigaction
|
||||
#if 1
|
||||
@@ -423,93 +478,124 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_access
|
||||
case 21: // sys_access
|
||||
*(int64_t*)&R_RAX = access((void*)R_RDI, R_ESI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_pipe
|
||||
case 22:
|
||||
*(int64_t*)&R_RAX = pipe((void*)R_RDI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
case 23: // sys_select
|
||||
R_EAX = (uint32_t)select(R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 25: // sys_mremap
|
||||
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
|
||||
break;
|
||||
#ifndef __NR_dup2
|
||||
case 33: // sys_dup2
|
||||
R_EAX = (uint32_t)dup2((int)R_EDI, (int)R_ESI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 56: // sys_clone
|
||||
// x86_64 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
|
||||
// so flags=R_RDI, stack=R_RSI, parent_tid=R_RDX, child_tid=R_R10, tls=R_R8
|
||||
if(R_RSI)
|
||||
{
|
||||
void* stack_base = (void*)R_RSI;
|
||||
int stack_size = 0;
|
||||
if(!R_RSI) {
|
||||
// allocate a new stack...
|
||||
int currstack = 0;
|
||||
if((R_RSP>=(uintptr_t)emu->init_stack) && (R_RSP<=((uintptr_t)emu->init_stack+emu->size_stack)))
|
||||
currstack = 1;
|
||||
stack_size = (currstack)?emu->size_stack:(1024*1024);
|
||||
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
// copy value from old stack to new stack
|
||||
if(currstack)
|
||||
memcpy(stack_base, emu->init_stack, stack_size);
|
||||
else {
|
||||
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_RSP);
|
||||
memcpy(stack_base+stack_size-size_to_copy, (void*)R_RSP, size_to_copy);
|
||||
if((R_EDI&~0xff)==0x4100) {
|
||||
// this is a case of vfork...
|
||||
R_EAX = my_vfork(emu);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
} else {
|
||||
if(R_RSI)
|
||||
{
|
||||
void* stack_base = (void*)R_RSI;
|
||||
int stack_size = 0;
|
||||
if(!R_RSI) {
|
||||
// allocate a new stack...
|
||||
int currstack = 0;
|
||||
if((R_RSP>=(uintptr_t)emu->init_stack) && (R_RSP<=((uintptr_t)emu->init_stack+emu->size_stack)))
|
||||
currstack = 1;
|
||||
stack_size = (currstack && emu->size_stack)?emu->size_stack:(1024*1024);
|
||||
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
|
||||
// copy value from old stack to new stack
|
||||
if(currstack)
|
||||
memcpy(stack_base, emu->init_stack, stack_size);
|
||||
else {
|
||||
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_RSP);
|
||||
memcpy(stack_base+stack_size-size_to_copy, (void*)R_RSP, size_to_copy);
|
||||
}
|
||||
}
|
||||
x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack_base, stack_size, (R_RSI)?0:1);
|
||||
SetupX64Emu(newemu);
|
||||
CloneEmu(newemu, emu);
|
||||
Push64(newemu, 0);
|
||||
PushExit(newemu);
|
||||
void* mystack = NULL;
|
||||
if(my_context->stack_clone_used) {
|
||||
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
|
||||
} else {
|
||||
if(!my_context->stack_clone)
|
||||
my_context->stack_clone = box_malloc(1024*1024);
|
||||
mystack = my_context->stack_clone;
|
||||
my_context->stack_clone_used = 1;
|
||||
}
|
||||
int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_RDI, newemu, R_RDX, R_R8, R_R10);
|
||||
R_RAX = (uint64_t)ret;
|
||||
}
|
||||
x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack_base, stack_size, (R_RSI)?0:1);
|
||||
SetupX64Emu(newemu);
|
||||
CloneEmu(newemu, emu);
|
||||
Push64(newemu, 0);
|
||||
PushExit(newemu);
|
||||
void* mystack = NULL;
|
||||
if(my_context->stack_clone_used) {
|
||||
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
|
||||
} else {
|
||||
if(!my_context->stack_clone)
|
||||
my_context->stack_clone = box_malloc(1024*1024);
|
||||
mystack = my_context->stack_clone;
|
||||
my_context->stack_clone_used = 1;
|
||||
}
|
||||
int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_RDI, newemu, R_RDX, R_R8, R_R10);
|
||||
R_RAX = (uint64_t)ret;
|
||||
else
|
||||
#ifdef NOALIGN
|
||||
R_RAX = (uint64_t)syscall(__NR_clone, R_RDI, R_RSI, R_RDX, R_R10, R_R8);
|
||||
#else
|
||||
R_RAX = (uint64_t)syscall(__NR_clone, R_RDI, R_RSI, R_RDX, R_R8, R_R10); // invert R_R8/R_R10 on Aarch64 and most other
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#ifdef NOALIGN
|
||||
R_RAX = (uint64_t)syscall(__NR_clone, R_RDI, R_RSI, R_RDX, R_R10, R_R8);
|
||||
#else
|
||||
R_RAX = (uint64_t)syscall(__NR_clone, R_RDI, R_RSI, R_RDX, R_R8, R_R10); // invert R_R8/R_R10 on Aarch64 and most other
|
||||
#endif
|
||||
break;
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
R_RAX = fork();
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_vfork
|
||||
case 58: // vfork
|
||||
{
|
||||
int64_t r = vfork();
|
||||
int64_t r = my_vfork(emu);
|
||||
R_RAX = r;
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 63: //uname
|
||||
{
|
||||
old_utsname_t *old = (old_utsname_t*)R_RDI;
|
||||
struct utsname uts;
|
||||
R_RAX = uname(&uts);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
memcpy(old, &uts, sizeof(*old)); // old_uts is just missing a field from new_uts
|
||||
strcpy(old->machine, "x86_64");
|
||||
}
|
||||
break;
|
||||
case 72: //fcntl
|
||||
R_RAX = (uint64_t)my_fcntl(emu, (int)R_EDI, (int)R_ESI, (void*)R_RDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
@@ -518,60 +604,114 @@ void EXPORT x64Syscall(x64emu_t *emu)
|
||||
ssize_t ret = syscall(__NR_getdents64, R_EDI, d64, count);
|
||||
ret = DirentFromDirent64((void*)R_RSI, d64, ret);
|
||||
R_RAX = (uint64_t)ret;
|
||||
if(ret==-1)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_rename
|
||||
case 82: // sys_rename
|
||||
*(int64_t*)&R_RAX = rename((void*)R_RDI, (void*)R_RSI);
|
||||
*(int64_t*)&R_RAX = rename((void*)R_RDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_mkdir
|
||||
case 83: // sys_mkdir
|
||||
*(int64_t*)&R_RAX = mkdir((void*)R_RDI, R_ESI);
|
||||
break;
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_unlink
|
||||
case 87: //sys_unlink
|
||||
*(int64_t*)&R_RAX = unlink((void*)R_RDI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 89: // sys_readlink
|
||||
R_RAX = (ssize_t)my_readlink(emu,(void*)R_RDI, (void*)R_RSI, (size_t)R_RDX);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 131: // sys_sigaltstack
|
||||
*(int64_t*)&R_RAX = my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
case 158: // sys_arch_prctl
|
||||
*(int64_t*)&R_RAX = my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 201: // sys_time
|
||||
R_RAX = (uintptr_t)time((void*)R_RDI);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#if !defined(__NR_epoll_wait) && !defined(NO_ALIGN)
|
||||
#if !defined(__NR_epoll_wait) || !defined(NOALIGN)
|
||||
case 232:
|
||||
R_RAX = my_epoll_wait(emu, (int)R_EDI, (void*)R_RSI, (int)R_EDX, (int)R_R8d);
|
||||
R_RAX = my_epoll_wait(emu, (int)R_EDI, (void*)R_RSI, (int)R_EDX, (int)R_R10d);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#if !defined(__NR_epoll_ctl) || !defined(NOALIGN)
|
||||
case 233:
|
||||
R_EAX = my_epoll_ctl(emu, (int)R_EDI, (int)R_ESI, (int)R_EDX, (void*)R_R10);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
R_EAX = (int)syscall(__NR_inotify_init1, 0);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
case 257:
|
||||
R_EAX = (int)syscall(__NR_openat, (int)R_EDI, (void*)R_RSI, of_convert((int)R_EDX), R_R10d);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 262:
|
||||
R_EAX = (uint64_t)(int64_t)my_fstatat(emu, (int)R_RDI, (char*)R_RSI, (void*)R_RDX, (int)R_R10d);
|
||||
R_EAX = (uint32_t)my_fstatat(emu, (int)R_RDI, (char*)R_RSI, (void*)R_RDX, (int)R_R10d);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_renameat
|
||||
case 264:
|
||||
R_EAX = (uint32_t)renameat((int)R_RDI, (const char*)R_RSI, (int)R_EDX, (const char*)R_R10);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
case 281: // sys_epool_pwait
|
||||
R_EAX = (uint32_t)my_epoll_pwait(emu, (int)R_EDI, (void*)R_RSI, (int)R_EDX, (int)R_R10d, (void*)R_R8);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 317: // sys_seccomp
|
||||
R_RAX = 0; // ignoring call
|
||||
break;
|
||||
case 334: // It is helpeful to run static binary
|
||||
R_RAX = -1;
|
||||
errno = ENOSYS;
|
||||
R_RAX = -ENOSYS;
|
||||
break;
|
||||
#ifndef __NR_fchmodat4
|
||||
case 434:
|
||||
*(int64_t*)R_RAX = fchmodat((int)R_EDI, (void*)R_RSI, (mode_t)R_RDX, (int)R_R10d);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_fchmodat4
|
||||
case 434:
|
||||
*(int64_t*)R_RAX = fchmodat((int)R_EDI, (void*)R_RSI, (mode_t)R_RDX, (int)R_R10d);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_RAX = (uint64_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
|
||||
emu->quit = 1;
|
||||
@@ -726,14 +866,16 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
return (uintptr_t)syscall(__NR_clone, R_RSI, R_RDX, R_RCX, R_R9, R_R8); // invert R_R8/R_R9 on Aarch64 and most other
|
||||
#endif
|
||||
break;
|
||||
#ifndef __NR_dup2
|
||||
case 33:
|
||||
return dup2((int)R_ESI, (int)R_EDX);
|
||||
#endif
|
||||
#ifndef __NR_fork
|
||||
case 57:
|
||||
return fork();
|
||||
#endif
|
||||
#ifndef __NR_vfork
|
||||
case 58: // vfork
|
||||
return vfork();
|
||||
#endif
|
||||
return my_vfork(emu);
|
||||
case 63: //uname
|
||||
{
|
||||
old_utsname_t *old = (old_utsname_t*)R_RSI;
|
||||
@@ -743,6 +885,9 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
strcpy(old->machine, "x86_64");
|
||||
return ret;
|
||||
}
|
||||
case 72: //fcntl
|
||||
R_RAX = (uint64_t)my_fcntl(emu, (int)R_ESI, (int)R_EDX, (void*)R_RCX);
|
||||
break;
|
||||
#ifndef __NR_getdents
|
||||
case 78:
|
||||
{
|
||||
@@ -771,17 +916,38 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
|
||||
case 201: // sys_time
|
||||
return (uintptr_t)time((void*)R_RSI);
|
||||
#endif
|
||||
#if !defined(__NR_epoll_wait) && !defined(NO_ALIGN)
|
||||
#if !defined(__NR_epoll_wait) || !defined(NOALIGN)
|
||||
case 232:
|
||||
R_RAX = my_epoll_wait(emu, (int)R_ESI, (void*)R_RDX, (int)R_ECX, (int)R_R8d);
|
||||
break;
|
||||
#endif
|
||||
#if !defined(__NR_epoll_ctl) || !defined(NOALIGN)
|
||||
case 233:
|
||||
R_EAX = my_epoll_ctl(emu, (int)R_ESI, (int)R_EDX, (int)R_ECX, (void*)R_R8);
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_inotify_init
|
||||
case 253:
|
||||
return (int)syscall(__NR_inotify_init1, 0);
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
case 257:
|
||||
R_EAX = (int)syscall(__NR_openat, (int)R_ESI, (void*)R_RDX, of_convert((int)R_ECX), R_R8d);
|
||||
break;
|
||||
#endif
|
||||
case 262:
|
||||
return (uint64_t)(int64_t)my_fstatat(emu, (int)R_RSI, (char*)R_RDX, (void*)R_RCX, (int)R_R8d);
|
||||
#ifndef __NR_renameat
|
||||
case 264:
|
||||
return (uint64_t)(int64_t)renameat((int)R_RSI, (const char*)R_RDX, (int)R_ECX, (const char*)R_R8);
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
case 281: // sys_epool_pwait
|
||||
return (uint64_t)(int64_t)my_epoll_pwait(emu, (int)R_ESI, (void*)R_RDX, (int)R_ECX, (int)R_R8d, (void*)R_R9);
|
||||
break;
|
||||
#endif
|
||||
case 317: // sys_seccomp
|
||||
return 0; // ignoring call
|
||||
#ifndef __NR_fchmodat4
|
||||
case 434:
|
||||
return (int)fchmodat((int)R_ESI, (void*)R_RDX, (mode_t)R_RCX, (int)R_R8d);
|
||||
|
||||
+6
-5
@@ -152,6 +152,7 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
|
||||
my_context->segtls[3].limit = 0;
|
||||
my_context->segtls[3].present = 1;
|
||||
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
|
||||
ResetSegmentsCache(emu);
|
||||
return 0;
|
||||
case ARCH_GET_FS:
|
||||
*(void**)addr = GetSegmentBase(emu->segs[_FS]);
|
||||
@@ -228,15 +229,15 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
|
||||
|
||||
void* fillTLSData(box64context_t *context)
|
||||
{
|
||||
pthread_mutex_lock(&context->mutex_tls);
|
||||
mutex_lock(&context->mutex_tls);
|
||||
tlsdatasize_t *data = setupTLSData(context);
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
mutex_unlock(&context->mutex_tls);
|
||||
return data;
|
||||
}
|
||||
|
||||
void* resizeTLSData(box64context_t *context, void* oldptr)
|
||||
{
|
||||
pthread_mutex_lock(&context->mutex_tls);
|
||||
mutex_lock(&context->mutex_tls);
|
||||
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
|
||||
if(sizeTLSData(oldata->tlssize)!=sizeTLSData(context->tlssize) || (oldata->n_elfs/0xff)!=(context->elfsize/0xff)) {
|
||||
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
|
||||
@@ -244,7 +245,7 @@ void* resizeTLSData(box64context_t *context, void* oldptr)
|
||||
// copy the relevent old part, in case something changed
|
||||
memcpy((void*)((uintptr_t)data->data-oldata->tlssize), (void*)((uintptr_t)oldata->data-oldata->tlssize), oldata->tlssize);
|
||||
// all done, update new size, free old pointer and exit
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
mutex_unlock(&context->mutex_tls);
|
||||
free_tlsdatasize(oldptr);
|
||||
return data;
|
||||
} else {
|
||||
@@ -266,7 +267,7 @@ void* resizeTLSData(box64context_t *context, void* oldptr)
|
||||
}
|
||||
oldata->n_elfs = context->elfsize;
|
||||
}
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
mutex_unlock(&context->mutex_tls);
|
||||
return oldata;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,10 @@ void fpu_fbld(x64emu_t* emu, uint8_t* s) {
|
||||
// long double (80bits) -> double (64bits)
|
||||
void LD2D(void* ld, void* d)
|
||||
{
|
||||
if(box64_x87_no80bits) {
|
||||
*(uint64_t*)d = *(uint64_t*)ld;
|
||||
return;
|
||||
}
|
||||
FPU_t result;
|
||||
#pragma pack(push, 1)
|
||||
struct {
|
||||
@@ -122,7 +126,7 @@ void LD2D(void* ld, void* d)
|
||||
*(uint64_t*)d = result.q;
|
||||
return;
|
||||
}
|
||||
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<=0)) {
|
||||
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) {
|
||||
//if(val.f.q==0)
|
||||
// zero
|
||||
//if(val.f.q!=0)
|
||||
@@ -134,6 +138,18 @@ void LD2D(void* ld, void* d)
|
||||
return;
|
||||
}
|
||||
|
||||
if(exp64<=0 && val.f.q) {
|
||||
// try to see if it can be a denormal
|
||||
int one = -exp64-1022;
|
||||
uint64_t r = 0;
|
||||
if(val.b&0x8000)
|
||||
r |= 0x8000000000000000L;
|
||||
r |= val.f.q>>one;
|
||||
*(uint64_t*)d = r;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if(exp64>=0x7ff) {
|
||||
// to big value...
|
||||
result.d = HUGE_VAL;
|
||||
@@ -154,6 +170,10 @@ void LD2D(void* ld, void* d)
|
||||
// double (64bits) -> long double (80bits)
|
||||
void D2LD(void* d, void* ld)
|
||||
{
|
||||
if(box64_x87_no80bits) {
|
||||
*(uint64_t*)ld = *(uint64_t*)d;
|
||||
return;
|
||||
}
|
||||
#pragma pack(push, 1)
|
||||
struct {
|
||||
FPU_t f;
|
||||
@@ -190,6 +210,12 @@ void D2LD(void* d, void* ld)
|
||||
if(exp80!=0){
|
||||
mant80final |= 0x8000000000000000L;
|
||||
exp80final += (BIAS80 - BIAS64);
|
||||
} else if(mant80final!=0) {
|
||||
// denormals -> normal
|
||||
exp80final = BIAS80-1023;
|
||||
int one = __builtin_clz(mant80final) + 1;
|
||||
exp80final -= one;
|
||||
mant80final<<=one;
|
||||
}
|
||||
}
|
||||
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
|
||||
@@ -201,7 +227,9 @@ void D2LD(void* d, void* ld)
|
||||
|
||||
double FromLD(void* ld)
|
||||
{
|
||||
double ret;
|
||||
if(box64_x87_no80bits)
|
||||
return *(double*)ld;
|
||||
double ret; // cannot add = 0; it break factorio (issue when calling fmodl)
|
||||
LD2D(ld, &ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -210,7 +238,7 @@ double FromLD(void* ld)
|
||||
long double LD2localLD(void* ld)
|
||||
{
|
||||
// local implementation may not be try Quad precision, but double-double precision, so simple way to keep the 80bits precision in the conversion
|
||||
double ret;
|
||||
double ret; // cannot add = 0; it break factorio (issue when calling fmodl)
|
||||
LD2D(ld, &ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -301,6 +329,7 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
p->MxCsr = emu->mxcsr.x32;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
|
||||
@@ -330,6 +359,7 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
p->MxCsr = emu->mxcsr.x32;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
|
||||
@@ -351,6 +381,9 @@ void fpu_fxrstor32(x64emu_t* emu, void* ed)
|
||||
xsave32_t *p = (xsave32_t*)ed;
|
||||
emu->cw.x16 = p->ControlWord;
|
||||
emu->sw.x16 = p->StatusWord;
|
||||
emu->mxcsr.x32 = p->MxCsr;
|
||||
if(box64_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
@@ -371,6 +404,9 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed)
|
||||
xsave64_t *p = (xsave64_t*)ed;
|
||||
emu->cw.x16 = p->ControlWord;
|
||||
emu->sw.x16 = p->StatusWord;
|
||||
emu->mxcsr.x32 = p->MxCsr;
|
||||
if(box64_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
|
||||
+31
-13
@@ -4,6 +4,9 @@
|
||||
#include <pthread.h>
|
||||
#include "pathcoll.h"
|
||||
#include "dictionnary.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynarec/native_lock.h"
|
||||
#endif
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -30,9 +33,8 @@ typedef struct mmaplist_s mmaplist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
#endif
|
||||
#define DYNAMAP_SHIFT 16
|
||||
#define JMPTABL_SHIFT 16
|
||||
|
||||
typedef void* (*procaddess_t)(const char* name);
|
||||
typedef void* (*procaddress_t)(const char* name);
|
||||
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
|
||||
|
||||
#define MAX_SIGNAL 64
|
||||
@@ -49,10 +51,13 @@ void free_tlsdatasize(void* p);
|
||||
typedef struct needed_libs_s {
|
||||
int cap;
|
||||
int size;
|
||||
library_t **libs;
|
||||
char** names;
|
||||
library_t** libs;
|
||||
} needed_libs_t;
|
||||
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
needed_libs_t* new_neededlib(int n);
|
||||
void add1_neededlib(needed_libs_t* needed);
|
||||
|
||||
typedef struct base_segment_s {
|
||||
uintptr_t base;
|
||||
@@ -95,7 +100,8 @@ typedef struct box64context_s {
|
||||
int elfsize; // number of elf loaded
|
||||
|
||||
|
||||
needed_libs_t neededlibs; // needed libs for main elf
|
||||
needed_libs_t *neededlibs; // needed libs for main elf
|
||||
needed_libs_t *preload;
|
||||
|
||||
uintptr_t ep; // entry point
|
||||
|
||||
@@ -108,9 +114,6 @@ typedef struct box64context_s {
|
||||
uintptr_t vsyscall; // vsyscall bridge value
|
||||
uintptr_t vsyscalls[3]; // the 3 x86 VSyscall pseudo bridges (mapped at 0xffffffffff600000+)
|
||||
dlprivate_t *dlprivate; // dlopen library map
|
||||
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
|
||||
kh_symbolmap_t *glmymap; // link to the mysymbolmap of libGL
|
||||
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)
|
||||
@@ -119,17 +122,21 @@ typedef struct box64context_s {
|
||||
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
|
||||
vkprocaddess_t vkprocaddress;
|
||||
|
||||
pthread_mutex_t mutex_trace;
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
|
||||
#else
|
||||
pthread_mutex_t mutex_dyndump;
|
||||
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
|
||||
int trace_dynarec;
|
||||
#endif
|
||||
pthread_mutex_t mutex_trace;
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
pthread_mutex_t mutex_bridge;
|
||||
#else
|
||||
uint32_t mutex_dyndump;
|
||||
uint32_t mutex_trace;
|
||||
uint32_t mutex_tls;
|
||||
uint32_t mutex_thread;
|
||||
uint32_t mutex_bridge;
|
||||
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
|
||||
int trace_dynarec;
|
||||
#endif
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
library_t *sdl1mixerlib;
|
||||
@@ -184,6 +191,17 @@ typedef struct box64context_s {
|
||||
|
||||
} box64context_t;
|
||||
|
||||
#ifndef DYNAREC
|
||||
#define mutex_lock(A) pthread_mutex_lock(A)
|
||||
#define mutex_trylock(A) pthread_mutex_trylock(A)
|
||||
#define mutex_unlock(A) pthread_mutex_unlock(A)
|
||||
#else
|
||||
int GetTID();
|
||||
#define mutex_lock(A) {uint32_t tid = (uint32_t)GetTID(); while(native_lock_storeifnull_d(A, tid)) sched_yield();}
|
||||
#define mutex_trylock(A) native_lock_storeifnull_d(A, (uint32_t)GetTID())
|
||||
#define mutex_unlock(A) native_lock_storeifref_d(A, 0, (uint32_t)GetTID())
|
||||
#endif
|
||||
|
||||
extern box64context_t *my_context; // global context
|
||||
|
||||
box64context_t *NewBox64Context(int argc);
|
||||
|
||||
@@ -10,5 +10,8 @@ uint64_t RunFunction(box64context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
uint64_t RunSafeFunction(box64context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
// use emu state to run function
|
||||
uint64_t RunFunctionWithEmu(x64emu_t *emu, int QuitOnLongJumpExit, uintptr_t fnc, int nargs, ...);
|
||||
// using the Windows x64 calling convention
|
||||
uint64_t RunFunctionWindows(box64context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
|
||||
|
||||
#endif //__CALLBACK_H__
|
||||
+21
-4
@@ -19,8 +19,8 @@ void customFree(void* p);
|
||||
#ifdef DYNAREC
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
// custom protection flag to mark Page that are Write protected for Dynarec purpose
|
||||
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size);
|
||||
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size);
|
||||
uintptr_t AllocDynarecMap(size_t size);
|
||||
void FreeDynarecMap(uintptr_t addr);
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, size_t size);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy);
|
||||
@@ -34,17 +34,34 @@ int isJumpTableDefault64(void* addr);
|
||||
uintptr_t getJumpTable64();
|
||||
uintptr_t getJumpTableAddress64(uintptr_t addr);
|
||||
uintptr_t getJumpAddress64(uintptr_t addr);
|
||||
|
||||
#define JMPTABL_SHIFT3 18
|
||||
#define JMPTABL_SHIFT2 18
|
||||
#define JMPTABL_SHIFT1 18
|
||||
#define JMPTABL_SHIFT0 10
|
||||
#define JMPTABL_START3 (JMPTABL_START2+JMPTABL_SHIFT2)
|
||||
#define JMPTABL_START2 (JMPTABL_START1+JMPTABL_SHIFT1)
|
||||
#define JMPTABL_START1 (JMPTABL_START0+JMPTABL_SHIFT0)
|
||||
#define JMPTABL_START0 0
|
||||
#define JMPTABLE_MASK3 ((1<<JMPTABL_SHIFT3)-1)
|
||||
#define JMPTABLE_MASK2 ((1<<JMPTABL_SHIFT2)-1)
|
||||
#define JMPTABLE_MASK1 ((1<<JMPTABL_SHIFT1)-1)
|
||||
#define JMPTABLE_MASK0 ((1<<JMPTABL_SHIFT0)-1)
|
||||
#endif
|
||||
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R)
|
||||
#define PROT_MMAP 0x20
|
||||
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R)
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP)
|
||||
|
||||
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot);
|
||||
void freeProtection(uintptr_t addr, size_t size);
|
||||
void refreshProtection(uintptr_t addr);
|
||||
uint32_t getProtection(uintptr_t addr);
|
||||
int getMmapped(uintptr_t addr);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, size_t size);
|
||||
@@ -55,7 +72,7 @@ int AreaInHotPage(uintptr_t start, uintptr_t end);
|
||||
void AddHotPage(uintptr_t addr);
|
||||
#endif
|
||||
void* find32bitBlock(size_t size);
|
||||
void* findBlockNearHint(void* hint, size_t size);
|
||||
void* find31bitBlockNearHint(void* hint, size_t size);
|
||||
void* find47bitBlock(size_t size);
|
||||
void* find47bitBlockNearHint(void* hint, size_t size);
|
||||
|
||||
|
||||
+24
-6
@@ -7,7 +7,7 @@ extern int box64_log; // log level
|
||||
extern int box64_dump; // dump elf or not
|
||||
extern int box64_dynarec_log;
|
||||
extern int box64_dynarec;
|
||||
extern int box64_pagesize;
|
||||
extern uintptr_t box64_pagesize;
|
||||
extern uintptr_t box64_load_addr;
|
||||
#ifdef DYNAREC
|
||||
extern int box64_dynarec_dump;
|
||||
@@ -15,10 +15,17 @@ extern int box64_dynarec_trace;
|
||||
extern int box64_dynarec_forced;
|
||||
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
|
||||
extern int box64_dynarec_bigblock;
|
||||
extern int box64_dynarec_forward;
|
||||
extern int box64_dynarec_strongmem;
|
||||
extern int box64_dynarec_fastnan;
|
||||
extern int box64_dynarec_fastround;
|
||||
extern int box64_dynarec_x87double;
|
||||
extern int box64_dynarec_safeflags;
|
||||
extern int box64_dynarec_callret;
|
||||
extern int box64_dynarec_bleeding_edge;
|
||||
extern int box64_dynarec_hotpage;
|
||||
extern int box64_dynarec_fastpage;
|
||||
extern int box64_dynarec_wait;
|
||||
#ifdef ARM64
|
||||
extern int arm64_asimd;
|
||||
extern int arm64_aes;
|
||||
@@ -27,6 +34,7 @@ extern int arm64_crc32;
|
||||
extern int arm64_atomics;
|
||||
#endif
|
||||
#endif
|
||||
extern int box64_libcef;
|
||||
extern int dlsym_error; // log dlsym error
|
||||
extern int cycle_log; // if using rolling logs
|
||||
#ifdef HAVE_TRACE
|
||||
@@ -35,8 +43,15 @@ 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;
|
||||
extern char* trace_init;
|
||||
extern char* box64_trace;
|
||||
extern uint64_t start_cnt;
|
||||
#endif
|
||||
extern int box64_nosandbox;
|
||||
extern int box64_malloc_hack;
|
||||
extern int box64_dummy_crashhandler;
|
||||
extern int box64_sse_flushto0;
|
||||
extern int box64_x87_no80bits;
|
||||
extern int allow_missing_libs;
|
||||
extern int box64_mapclean;
|
||||
extern int box64_prefer_wrapped;
|
||||
@@ -50,6 +65,9 @@ extern int box64_novulkan; // disabling the use of wrapped vulkan
|
||||
extern int box64_showsegv; // show sigv, even if a signal handler is present
|
||||
extern int box64_showbt; // show a backtrace if a signal is caught
|
||||
extern int box64_isglibc234; // is the program linked with glibc 2.34+
|
||||
extern int box64_x11threads;
|
||||
extern int box64_x11glx;
|
||||
extern char* box64_libGL;
|
||||
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
|
||||
@@ -60,15 +78,15 @@ extern int box64_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
#define LOG_NEVER 3
|
||||
#define LOG_VERBOSE 3
|
||||
|
||||
extern FILE* ftrace;
|
||||
void printf_ftrace(const char* fmt, ...);
|
||||
|
||||
#define printf_log(L, ...) do {if((L)<=box64_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_log(L, ...) do {if((L)<=box64_log) {printf_ftrace(__VA_ARGS__);}} while(0)
|
||||
|
||||
#define printf_dump(L, ...) do {if(box64_dump || ((L)<=box64_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_dump(L, ...) do {if(box64_dump || ((L)<=box64_log)) {printf_ftrace(__VA_ARGS__);}} while(0)
|
||||
|
||||
#define printf_dlsym(L, ...) do {if(dlsym_error || ((L)<=box64_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_dlsym(L, ...) do {if(dlsym_error || ((L)<=box64_log)) {printf_ftrace(__VA_ARGS__);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if((L)<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define dynarec_log(L, ...) do {if((L)<=box64_dynarec_log) {printf_ftrace(__VA_ARGS__);}} while(0)
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#ifdef BUILD_DYNAMIC
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
|
||||
uint32_t X31_hash_code(void* addr, int len);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock);
|
||||
@@ -12,7 +11,6 @@ void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
|
||||
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
|
||||
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x64 translated code)
|
||||
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x64emu_s x64emu_t;
|
||||
typedef struct instsize_s instsize_t;
|
||||
|
||||
void CancelBlock64();
|
||||
void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size);
|
||||
|
||||
void CancelBlock64(int need_lock);
|
||||
void* FillBlock64(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
#endif //__DYNAREC_ARM_H_
|
||||
@@ -31,7 +31,7 @@ void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
|
||||
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
|
||||
uintptr_t GetLastByte(elfheader_t* h);
|
||||
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu);
|
||||
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu);
|
||||
uintptr_t GetElfInit(elfheader_t* h);
|
||||
uintptr_t GetElfFini(elfheader_t* h);
|
||||
void RefreshElfTLS(elfheader_t* h);
|
||||
|
||||
@@ -21,6 +21,9 @@ int FileIsShell(const char* filename);
|
||||
// return temp folder (will return /tmp if nothing is correct)
|
||||
const char* GetTmpDir();
|
||||
|
||||
// will lower case the string and return a copy. Nothing fancy here, just A..Z transformed to a..z, rest is untouched
|
||||
char* LowerCase(const char* s);
|
||||
|
||||
#if defined(RPI) || defined(RK3399) || defined(RK3326)
|
||||
void sanitize_mojosetup_gtk_background();
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __GL_TOOLS_H__
|
||||
#define __GL_TOOLS_H__
|
||||
|
||||
typedef struct box64context_s box64context_t;
|
||||
|
||||
typedef void* (*glprocaddress_t)(const char* name);
|
||||
|
||||
void freeGLProcWrapper(box64context_t* context);
|
||||
|
||||
void* getGLProcAddress(x64emu_t* emu, glprocaddress_t procaddr, const char* rname);
|
||||
|
||||
#endif //__GL_TOOLS_H__
|
||||
@@ -585,6 +585,20 @@ typedef struct my_AtkUtilClass_s
|
||||
void* (* get_toolkit_version) (void);
|
||||
} my_AtkUtilClass_t;
|
||||
|
||||
typedef struct my_GstObjectClass_s {
|
||||
my_GInitiallyUnownedClass_t parent;
|
||||
const char* path_string_separator;
|
||||
void (*deep_notify) (void* object, void* orig, void* pspec);
|
||||
void* _gst_reserved[4];
|
||||
} my_GstObjectClass_t;
|
||||
|
||||
typedef struct my_GstAllocatorClass_s {
|
||||
my_GstObjectClass_t parent;
|
||||
void* (*alloc) (void *allocator, size_t size, void *params);
|
||||
void (*free) (void *allocator, void *memory);
|
||||
void* _gst_reserved[4];
|
||||
} my_GstAllocatorClass_t;
|
||||
|
||||
|
||||
// GTypeValueTable
|
||||
typedef struct my_GTypeValueTable_s {
|
||||
@@ -673,6 +687,8 @@ GTKCLASS(MetaFrames2) \
|
||||
GTKCLASS(GDBusObjectManagerClient) \
|
||||
GTKCLASS(AtkObject) \
|
||||
GTKCLASS(AtkUtil) \
|
||||
GTKCLASS(GstObject) \
|
||||
GTKCLASS(GstAllocator) \
|
||||
|
||||
#define GTKCLASS(A) void Set##A##ID(size_t id);
|
||||
GTKCLASSES()
|
||||
|
||||
@@ -21,7 +21,7 @@ void FreeDLPrivate(dlprivate_t **lib);
|
||||
|
||||
box64context_t* GetLibrarianContext(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name);
|
||||
library_t* GetLibInternal(const char* name);
|
||||
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
|
||||
|
||||
@@ -19,6 +19,7 @@ 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, int bindnow, x64emu_t* emu);
|
||||
int ReloadLibrary(library_t* lib, x64emu_t* emu);
|
||||
int FiniLibrary(library_t* lib, x64emu_t* emu);
|
||||
void InactiveLibrary(library_t* lib);
|
||||
void Free1Library(library_t **lib, x64emu_t* emu);
|
||||
|
||||
@@ -27,17 +28,14 @@ int IsSameLib(library_t* lib, const char* path); // check if lib is same (pat
|
||||
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
|
||||
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
|
||||
void fillGLProcWrapper(box64context_t* context);
|
||||
void freeGLProcWrapper(box64context_t* context);
|
||||
void fillALProcWrapper(box64context_t* context);
|
||||
void freeALProcWrapper(box64context_t* context);
|
||||
needed_libs_t* GetNeededLibs(library_t* lib);
|
||||
int GetNeededLibN(library_t* lib);
|
||||
char** GetNeededLibsNames(library_t* lib);
|
||||
int GetNeededLibsN(library_t* lib);
|
||||
library_t* GetNeededLib(library_t* lib, int idx);
|
||||
lib_t* GetMaplib(library_t* lib);
|
||||
|
||||
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped)
|
||||
elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped)
|
||||
void* GetHandle(library_t* lib); // NULL if not wrapped
|
||||
void IncRefCount(library_t* lib, x64emu_t* emu);
|
||||
|
||||
#endif //__LIBRARY_H_
|
||||
@@ -50,7 +50,7 @@ typedef struct {
|
||||
memcpy(&p[6], emu->xmm, 8*16); \
|
||||
}
|
||||
|
||||
|
||||
#define PREFER_CONVERT_VAARG
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
// aarch64: 8 64bits general regs and 8 128bits float regs
|
||||
@@ -92,6 +92,8 @@ typedef struct va_list {
|
||||
memcpy(&p[6], emu->xmm, 8*16); \
|
||||
}
|
||||
|
||||
#define PREFER_CONVERT_VAARG
|
||||
|
||||
#elif defined(__sw_64__) /* or Alpha */
|
||||
/*
|
||||
typdef struct {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __RCFILE_H__
|
||||
#define __RCFILE_H__
|
||||
|
||||
void LoadRCFile(const char* filename);
|
||||
void DeleteParams();
|
||||
void ApplyParams(const char* name);
|
||||
|
||||
#endif //__RCFILE_H__
|
||||
+47
-25
@@ -223,41 +223,63 @@ typedef enum {
|
||||
|
||||
typedef union {
|
||||
struct __attribute__ ((__packed__)) {
|
||||
unsigned int F87_IE:1;
|
||||
unsigned int F87_DE:1;
|
||||
unsigned int F87_ZE:1;
|
||||
unsigned int F87_OE:1;
|
||||
unsigned int F87_UE:1;
|
||||
unsigned int F87_PE:1;
|
||||
unsigned int F87_SF:1;
|
||||
unsigned int F87_ES:1;
|
||||
unsigned int F87_C0:1;
|
||||
unsigned int F87_C1:1;
|
||||
unsigned int F87_C2:1;
|
||||
unsigned int F87_TOP:3;
|
||||
unsigned int F87_C3:1;
|
||||
unsigned int F87_B:1;
|
||||
uint16_t F87_IE:1;
|
||||
uint16_t F87_DE:1;
|
||||
uint16_t F87_ZE:1;
|
||||
uint16_t F87_OE:1;
|
||||
uint16_t F87_UE:1;
|
||||
uint16_t F87_PE:1;
|
||||
uint16_t F87_SF:1;
|
||||
uint16_t F87_ES:1;
|
||||
uint16_t F87_C0:1;
|
||||
uint16_t F87_C1:1;
|
||||
uint16_t F87_C2:1;
|
||||
uint16_t F87_TOP:3;
|
||||
uint16_t F87_C3:1;
|
||||
uint16_t F87_B:1;
|
||||
} f;
|
||||
uint16_t x16;
|
||||
} x87flags_t;
|
||||
|
||||
typedef union {
|
||||
struct __attribute__ ((__packed__)) {
|
||||
unsigned int C87_IM:1; // interupt masks
|
||||
unsigned int C87_DM:1;
|
||||
unsigned int C87_ZM:1;
|
||||
unsigned int C87_OM:1;
|
||||
unsigned int C87_UM:1;
|
||||
unsigned int C87_PM:1;
|
||||
unsigned int C87_R1:2; // reserved
|
||||
unsigned int C87_PC:2; // precision control (24bits, reserved, 53bits, 64bits)
|
||||
unsigned int C87_RD:2; // Rounds
|
||||
unsigned int C87_IC:1;
|
||||
unsigned int C87_R2:3; // reserved
|
||||
uint16_t C87_IM:1; // interupt masks
|
||||
uint16_t C87_DM:1;
|
||||
uint16_t C87_ZM:1;
|
||||
uint16_t C87_OM:1;
|
||||
uint16_t C87_UM:1;
|
||||
uint16_t C87_PM:1;
|
||||
uint16_t C87_R1:2; // reserved
|
||||
uint16_t C87_PC:2; // precision control (24bits, reserved, 53bits, 64bits)
|
||||
uint16_t C87_RD:2; // Rounds
|
||||
uint16_t C87_IC:1;
|
||||
uint16_t C87_R2:3; // reserved
|
||||
} f;
|
||||
uint16_t x16;
|
||||
} x87control_t;
|
||||
|
||||
typedef union {
|
||||
struct __attribute__ ((__packed__)) {
|
||||
uint32_t MXCSR_IE:1;
|
||||
uint32_t MXCSR_DE:1;
|
||||
uint32_t MXCSR_ZE:1;
|
||||
uint32_t MXCSR_OE:1;
|
||||
uint32_t MXCSR_UE:1;
|
||||
uint32_t MXCSR_PE:1;
|
||||
uint32_t MXCSR_DAZ:1;
|
||||
uint32_t MXCSR_IM:1;
|
||||
uint32_t MXCSR_DM:1;
|
||||
uint32_t MXCSR_ZM:1;
|
||||
uint32_t MXCSR_OM:1;
|
||||
uint32_t MXCSR_UM:1;
|
||||
uint32_t MXCSR_PM:1;
|
||||
uint32_t MXCSR_RC:2;
|
||||
uint32_t MXCSR_FZ:1;
|
||||
uint32_t MXCSR_RES:16;
|
||||
} f;
|
||||
uint32_t x32;
|
||||
} mmxcontrol_t;
|
||||
|
||||
typedef union {
|
||||
uint64_t q;
|
||||
int64_t sq;
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef void (*sighandler_t)(int);
|
||||
|
||||
typedef struct x64_sigaction_s {
|
||||
union {
|
||||
__sighandler_t _sa_handler;
|
||||
sighandler_t _sa_handler;
|
||||
void (*_sa_sigaction)(int, siginfo_t *, void *);
|
||||
} _u;
|
||||
sigset_t sa_mask;
|
||||
@@ -16,7 +16,7 @@ typedef struct x64_sigaction_s {
|
||||
|
||||
typedef struct x64_sigaction_restorer_s {
|
||||
union {
|
||||
__sighandler_t _sa_handler;
|
||||
sighandler_t _sa_handler;
|
||||
void (*_sa_sigaction)(int, siginfo_t *, void *);
|
||||
} _u;
|
||||
uint32_t sa_flags;
|
||||
@@ -38,4 +38,4 @@ void fini_signal_helper();
|
||||
|
||||
void emit_signal(x64emu_t* emu, int sig, void* addr, int code);
|
||||
|
||||
#endif //__SIGNALS_H__
|
||||
#endif //__SIGNALS_H__
|
||||
@@ -20,7 +20,9 @@ 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);
|
||||
|
||||
#ifndef DYNAREC
|
||||
//check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
|
||||
int checkUnlockMutex(void* m);
|
||||
#endif
|
||||
|
||||
#endif //_THREADS_H_
|
||||
+57
-84
@@ -29,39 +29,7 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
|
||||
|
||||
return maplib;
|
||||
}
|
||||
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed, library_t* owner) {
|
||||
if (freed[idx]) return; // Already freed
|
||||
|
||||
library_t *lib = maplib->libraries[idx];
|
||||
if(lib==owner) return; // don't free owner of maplib
|
||||
freed[idx] = 1; // Avoid infinite loops
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", lib->name);
|
||||
for (int i = lib->dependedby.size - 1; i >= 0; --i) {
|
||||
int j;
|
||||
for (j = 0; j < maplib->libsz; ++j) {
|
||||
if (lib->dependedby.libs[i] == maplib->libraries[j]) break;
|
||||
}
|
||||
if (j == maplib->libsz) {
|
||||
// dependant lib already freed
|
||||
// library as been freed already
|
||||
continue;
|
||||
}
|
||||
if (freed[j] == 1) {
|
||||
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->dependedby.libs[i]->name);
|
||||
continue;
|
||||
}
|
||||
freeLibraryRecurse(maplib, emu, j, freed, owner);
|
||||
if (freed[idx] != 1) {
|
||||
printf_log(LOG_DEBUG, "Note: library already freed (cyclic dependancy break)\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
library_t *ptr = maplib->libraries[idx];
|
||||
if(maplib->ownlibs/* && (!maplib->owner || ptr->maplib==maplib)*/)
|
||||
Free1Library(&ptr, emu);
|
||||
freed[idx] = 2;
|
||||
}
|
||||
|
||||
void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
|
||||
{
|
||||
// should that be in reverse order?
|
||||
@@ -70,24 +38,14 @@ void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
|
||||
|
||||
library_t* owner = (*maplib)->owner;
|
||||
(*maplib)->owner = NULL; // to avoid recursive free...
|
||||
|
||||
// free the memory only. All the uninit logic is elsewhere
|
||||
|
||||
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
|
||||
char *freed = (char*)box_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)
|
||||
if((*maplib)->libraries[i]!=owner) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
} else {
|
||||
for (int i=(*maplib)->libsz-1; i>=0; --i) {
|
||||
freeLibraryRecurse(*maplib, emu, i, freed, owner);
|
||||
}
|
||||
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
|
||||
(*maplib)->libsz = 0;
|
||||
box_free(freed);
|
||||
for(int i=0; i<(*maplib)->libsz; ++i) {
|
||||
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
|
||||
Free1Library(&(*maplib)->libraries[i], emu);
|
||||
}
|
||||
}
|
||||
box_free((*maplib)->libraries);
|
||||
@@ -203,14 +161,15 @@ static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
|
||||
}
|
||||
}
|
||||
|
||||
int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
|
||||
int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
const char* path = needed->names[n];
|
||||
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_dependedbylib(&lib->dependedby, deplib);
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
needed->libs[n] = lib;
|
||||
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -218,6 +177,8 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
lib = getLib(my_context->local_maplib, path);
|
||||
if(lib) {
|
||||
printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
|
||||
needed->libs[n] = lib;
|
||||
IncRefCount(lib, emu); // increment cntref
|
||||
if(local) {
|
||||
// add lib to maplib...
|
||||
if(maplib) {
|
||||
@@ -239,20 +200,15 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
MapLibAddLib(my_context->maplib, lib);
|
||||
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
|
||||
}
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
|
||||
return 0;
|
||||
}
|
||||
// load a new one
|
||||
lib = NewLibrary(path, box64);
|
||||
needed->libs[n] = lib = NewLibrary(path, box64);
|
||||
if(!lib) {
|
||||
printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
|
||||
return 1; //Error
|
||||
}
|
||||
|
||||
add_neededlib(neededlibs, lib);
|
||||
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
|
||||
|
||||
// add lib now
|
||||
if(local) {
|
||||
MapLibAddLib(my_context->local_maplib, lib);
|
||||
@@ -291,8 +247,10 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu)
|
||||
int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!lib) // no lib, error is already detected, no need to return a new one
|
||||
return 0;
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
|
||||
@@ -303,18 +261,28 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
|
||||
} else {
|
||||
// it's an emulated lib,
|
||||
// load dependancies and launch init sequence
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box64, emu)) {
|
||||
if(LoadNeededLibs(box64->elfs[mainelf], maplib, 0, bindnow, box64, emu)) {
|
||||
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
|
||||
return 1;
|
||||
}
|
||||
// some special case, where dependancies may not be correct
|
||||
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
|
||||
const char* libs[] = {"libGL.so.1"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box64, emu);
|
||||
char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit...
|
||||
library_t* libs[] = { NULL };
|
||||
needed_libs_t tmp = {0};
|
||||
tmp.size = tmp.cap = 1;
|
||||
tmp.names = names;
|
||||
tmp.libs = libs;
|
||||
AddNeededLib(maplib, 0, 0, &tmp, box64, emu);
|
||||
}
|
||||
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
|
||||
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
|
||||
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box64, emu);
|
||||
char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit...
|
||||
library_t* libs[] = { NULL, NULL };
|
||||
needed_libs_t tmp = {0};
|
||||
tmp.size = tmp.cap = 2;
|
||||
tmp.names = names;
|
||||
tmp.libs = libs;
|
||||
AddNeededLib(maplib, 0, 0, &tmp, box64, emu);
|
||||
}
|
||||
|
||||
// finalize the lib
|
||||
@@ -330,28 +298,26 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu)
|
||||
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu)
|
||||
{
|
||||
if(!needed) // no needed libs, no problems
|
||||
return 0;
|
||||
box64_mapclean = 0;
|
||||
if(!neededlibs) {
|
||||
neededlibs = box_calloc(1, sizeof(needed_libs_t));
|
||||
}
|
||||
int idx = neededlibs->size;
|
||||
int ret = 0;
|
||||
// Add libs and symbol
|
||||
for(int i=0; i<npath; ++i) {
|
||||
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box64, emu)) {
|
||||
printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]);
|
||||
return 1;
|
||||
for(int i=0; i<needed->size; ++i) {
|
||||
if(AddNeededLib_add(maplib, local, needed, i, box64, emu)) {
|
||||
printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
int idx_end = neededlibs->size;
|
||||
// add dependant libs and init them
|
||||
for (int i=idx; i<idx_end; ++i)
|
||||
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
|
||||
if(!allow_missing_libs) return 1;
|
||||
for (int i=0; i<needed->size; ++i)
|
||||
if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], box64, emu)) {
|
||||
printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]);
|
||||
if(!allow_missing_libs) ret = 1;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
library_t* GetLibMapLib(lib_t* maplib, const char* name)
|
||||
@@ -442,16 +408,23 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
|
||||
size_t size = 0;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
// search in needed libs from preloaded first, in order
|
||||
if(my_context->preload)
|
||||
for(int i=0; i<my_context->preload->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins)
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
|
||||
if(*start)
|
||||
return 1;
|
||||
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
|
||||
// search in needed libs from neededlibs first, in order
|
||||
for(int i=0; i<my_context->neededlibs.size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(my_context->neededlibs)
|
||||
for(int i=0; i<my_context->neededlibs->size; ++i)
|
||||
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
// search in global symbols
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
@@ -606,7 +579,7 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(*start)
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
return 0;
|
||||
|
||||
+90
-75
@@ -110,10 +110,8 @@ void WrappedLib_FinishFini(library_t* lib)
|
||||
box_free(lib->w.altprefix);
|
||||
if(lib->w.altmy)
|
||||
box_free(lib->w.altmy);
|
||||
if(lib->w.neededlibs) {
|
||||
for(int i=0; i<lib->w.needed; ++i)
|
||||
box_free(lib->w.neededlibs[i]);
|
||||
box_free(lib->w.neededlibs);
|
||||
if(lib->w.needed) {
|
||||
free_neededlib(lib->w.needed);
|
||||
}
|
||||
FreeBridge(&lib->w.bridge);
|
||||
}
|
||||
@@ -221,8 +219,9 @@ static void initWrappedLib(library_t *lib, box64context_t* context) {
|
||||
lib->getweak = WrappedLib_GetWeak;
|
||||
lib->getlocal = WrappedLib_GetLocal;
|
||||
lib->type = LIB_WRAPPED;
|
||||
lib->w.refcnt = 1;
|
||||
// Call librarian to load all dependant elf
|
||||
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, 0, (const char**)lib->w.neededlibs, lib->w.needed, context, thread_get_emu())) {
|
||||
if(AddNeededLib(context->maplib, 0, 0, lib->w.needed, context, thread_get_emu())) {
|
||||
printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name);
|
||||
return;
|
||||
}
|
||||
@@ -301,12 +300,16 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
|
||||
|
||||
printf_log(LOG_INFO, "Using emulated %s\n", libname);
|
||||
#ifdef DYNAREC
|
||||
if(libname && strstr(libname, "libmonobdwgc-2.0.so")) {
|
||||
if(libname && box64_dynarec_bleeding_edge && strstr(libname, "libmonobdwgc-2.0.so")) {
|
||||
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
|
||||
box64_dynarec_bigblock = 0;
|
||||
box64_dynarec_strongmem = 1;
|
||||
}
|
||||
#endif
|
||||
if(libname && box64_libcef && strstr(libname, "libcef.so")) {
|
||||
printf_log(LOG_INFO, "libcef detected, using malloc_hack_2\n");
|
||||
box64_malloc_hack = 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -349,7 +352,6 @@ static int isEssentialLib(const char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern char* libGL;
|
||||
library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
|
||||
@@ -357,13 +359,12 @@ library_t *NewLibrary(const char* path, box64context_t* context)
|
||||
lib->path = box_realpath(path, NULL);
|
||||
if(!lib->path)
|
||||
lib->path = box_strdup(path);
|
||||
if(libGL && !strcmp(path, libGL))
|
||||
if(box64_libGL && !strcmp(path, box64_libGL))
|
||||
lib->name = box_strdup("libGL.so.1");
|
||||
else
|
||||
lib->name = Path2Name(path);
|
||||
lib->nbdot = NbDot(lib->name);
|
||||
lib->type = LIB_UNNKNOW;
|
||||
lib->refcnt = 1;
|
||||
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
if(box64_nopulse) {
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
@@ -511,6 +512,26 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FiniLibrary(library_t* lib, x64emu_t* emu)
|
||||
{
|
||||
if(!lib->active)
|
||||
return 0; // nothing to do
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED:
|
||||
if(!--lib->w.refcnt)
|
||||
lib->active = 0;
|
||||
return 0;
|
||||
case LIB_EMULATED:
|
||||
if(!--lib->e.elf->refcnt) {
|
||||
if(emu)
|
||||
RunElfFini(lib->e.elf, emu);
|
||||
lib->active = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1; // bad type
|
||||
}
|
||||
|
||||
void InactiveLibrary(library_t* lib)
|
||||
{
|
||||
lib->active = 0;
|
||||
@@ -520,14 +541,7 @@ void Free1Library(library_t **lib, x64emu_t* emu)
|
||||
{
|
||||
if(!(*lib)) return;
|
||||
|
||||
if(--(*lib)->refcnt)
|
||||
return;
|
||||
|
||||
if((*lib)->type==LIB_EMULATED && emu) {
|
||||
elfheader_t *elf_header = (*lib)->e.elf;
|
||||
RunElfFini(elf_header, emu);
|
||||
}
|
||||
|
||||
// No "Fini" logic here, only memory handling
|
||||
if((*lib)->maplib)
|
||||
FreeLibrarian(&(*lib)->maplib, emu);
|
||||
|
||||
@@ -578,8 +592,6 @@ void Free1Library(library_t **lib, x64emu_t* emu)
|
||||
if((*lib)->w.symbol2map)
|
||||
kh_destroy(symbol2map, (*lib)->w.symbol2map);
|
||||
}
|
||||
free_neededlib(&(*lib)->needed);
|
||||
free_neededlib(&(*lib)->dependedby);
|
||||
|
||||
box_free(*lib);
|
||||
*lib = NULL;
|
||||
@@ -643,7 +655,7 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start,
|
||||
}
|
||||
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local)
|
||||
{
|
||||
if(!name[0] || !lib->active)
|
||||
if(!name[0] || !lib || !lib->active)
|
||||
return 0;
|
||||
khint_t k;
|
||||
// get a new symbol
|
||||
@@ -916,18 +928,34 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNeededLibN(library_t* lib) {
|
||||
return lib->needed.size;
|
||||
int GetNeededLibsN(library_t* lib) {
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->size:0;
|
||||
case LIB_EMULATED: return lib->e.elf->needed->size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
library_t* GetNeededLib(library_t* lib, int idx)
|
||||
{
|
||||
if(idx<0 || idx>=lib->needed.size)
|
||||
return NULL;
|
||||
return lib->needed.libs[idx];
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED:
|
||||
if(idx<0 || !lib->w.needed || idx>=lib->w.needed->size)
|
||||
return NULL;
|
||||
return lib->w.needed->libs[idx];
|
||||
case LIB_EMULATED:
|
||||
if(idx<0 || idx>=lib->e.elf->needed->size)
|
||||
return NULL;
|
||||
return lib->e.elf->needed->libs[idx];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
needed_libs_t* GetNeededLibs(library_t* lib)
|
||||
char** GetNeededLibs(library_t* lib)
|
||||
{
|
||||
return &lib->needed;
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->names:NULL;
|
||||
case LIB_EMULATED: return lib->e.elf->needed->names;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* GetHandle(library_t* lib)
|
||||
@@ -991,74 +1019,61 @@ void AddMainElfToLinkmap(elfheader_t* elf)
|
||||
lm->l_ld = GetDynamicSection(elf);
|
||||
}
|
||||
|
||||
static int is_neededlib_present(needed_libs_t* needed, library_t* lib)
|
||||
needed_libs_t* new_neededlib(int n)
|
||||
{
|
||||
if(!needed || !lib)
|
||||
return 0;
|
||||
if(!needed->size)
|
||||
return 0;
|
||||
for(int i=0; i<needed->size; ++i)
|
||||
if(needed->libs[i] == lib)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void add_neededlib(needed_libs_t* needed, library_t* lib)
|
||||
{
|
||||
++lib->refcnt;
|
||||
if(!needed)
|
||||
return;
|
||||
if(is_neededlib_present(needed, lib))
|
||||
return;
|
||||
if(needed->size == needed->cap) {
|
||||
needed->cap += 8;
|
||||
needed->libs = (library_t**)box_realloc(needed->libs, needed->cap*sizeof(library_t*));
|
||||
}
|
||||
needed->libs[needed->size++] = lib;
|
||||
needed_libs_t* ret = (needed_libs_t*)calloc(1, sizeof(needed_libs_t));
|
||||
ret->cap = ret->size = n;
|
||||
ret->libs = (library_t**)calloc(n, sizeof(library_t*));
|
||||
ret->names = (char**)calloc(n, sizeof(char*));
|
||||
return ret;
|
||||
}
|
||||
void free_neededlib(needed_libs_t* needed)
|
||||
{
|
||||
if(!needed)
|
||||
return;
|
||||
needed->cap = 0;
|
||||
needed->size = 0;
|
||||
if(needed->libs)
|
||||
box_free(needed->libs);
|
||||
free(needed->libs);
|
||||
free(needed->names);
|
||||
needed->libs = NULL;
|
||||
needed->names = NULL;
|
||||
needed->cap = needed->size = 0;
|
||||
free(needed);
|
||||
}
|
||||
void add_dependedbylib(needed_libs_t* dependedby, library_t* lib)
|
||||
void add1_neededlib(needed_libs_t* needed)
|
||||
{
|
||||
if(!dependedby)
|
||||
if(!needed)
|
||||
return;
|
||||
if(is_neededlib_present(dependedby, lib))
|
||||
if(needed->size+1<=needed->cap)
|
||||
return;
|
||||
if(dependedby->size == dependedby->cap) {
|
||||
dependedby->cap += 8;
|
||||
dependedby->libs = (library_t**)box_realloc(dependedby->libs, dependedby->cap*sizeof(library_t*));
|
||||
}
|
||||
dependedby->libs[dependedby->size++] = lib;
|
||||
}
|
||||
void free_dependedbylib(needed_libs_t* dependedby)
|
||||
{
|
||||
if(!dependedby)
|
||||
return;
|
||||
dependedby->cap = 0;
|
||||
dependedby->size = 0;
|
||||
if(dependedby->libs)
|
||||
box_free(dependedby->libs);
|
||||
dependedby->libs = NULL;
|
||||
needed->cap = needed->size+1;
|
||||
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
|
||||
needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*));
|
||||
needed->size++;
|
||||
}
|
||||
|
||||
void setNeededLibs(library_t* lib, int n, ...)
|
||||
{
|
||||
if(lib->type!=LIB_WRAPPED && lib->type!=LIB_UNNKNOW)
|
||||
return;
|
||||
lib->w.needed = n;
|
||||
lib->w.neededlibs = (char**)box_calloc(n, sizeof(char*));
|
||||
lib->w.needed = new_neededlib(n);
|
||||
va_list va;
|
||||
va_start (va, n);
|
||||
for (int i=0; i<n; ++i) {
|
||||
lib->w.neededlibs[i] = box_strdup(va_arg(va, char*));
|
||||
lib->w.needed->names[i] = va_arg(va, char*);
|
||||
}
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
void IncRefCount(library_t* lib, x64emu_t* emu)
|
||||
{
|
||||
if(lib->type==LIB_UNNKNOW)
|
||||
return;
|
||||
if(!lib->active)
|
||||
ReloadLibrary(lib, emu);
|
||||
switch (lib->type) {
|
||||
case LIB_WRAPPED:
|
||||
++lib->w.refcnt;
|
||||
break;
|
||||
case LIB_EMULATED:
|
||||
++lib->e.elf->refcnt;
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,7 @@ typedef struct wlib_s {
|
||||
void* lib; // dlopen result
|
||||
void* priv; // actual private
|
||||
char* altprefix; // if function names are mangled..
|
||||
int needed;
|
||||
char** neededlibs;
|
||||
needed_libs_t* needed;
|
||||
kh_symbolmap_t *symbolmap;
|
||||
kh_symbolmap_t *wsymbolmap;
|
||||
kh_symbolmap_t *mysymbolmap;
|
||||
@@ -49,6 +48,7 @@ typedef struct wlib_s {
|
||||
kh_datamap_t *wdatamap;
|
||||
kh_datamap_t *mydatamap;
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
int refcnt; // refcounting the lib
|
||||
} wlib_t;
|
||||
|
||||
typedef struct elib_s {
|
||||
@@ -71,18 +71,11 @@ typedef struct library_s {
|
||||
wlib_t w;
|
||||
elib_t e;
|
||||
}; // private lib data
|
||||
needed_libs_t needed;
|
||||
needed_libs_t dependedby; // used to free library
|
||||
int refcnt; // refcounting the lib
|
||||
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
|
||||
kh_bridgemap_t *gbridgemap; // global symbol bridgemap
|
||||
kh_bridgemap_t *wbridgemap; // weak symbol bridgemap
|
||||
kh_bridgemap_t *lbridgemap; // local symbol bridgemap
|
||||
} library_t;
|
||||
void add_neededlib(needed_libs_t* needed, library_t* lib);
|
||||
void free_neededlib(needed_libs_t* needed);
|
||||
void add_dependedbylib(needed_libs_t* dependedby, library_t* lib);
|
||||
void free_dependedbylib(needed_libs_t* dependedby);
|
||||
|
||||
// type for map elements
|
||||
typedef struct map_onesymbol_s {
|
||||
|
||||
@@ -122,7 +122,7 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
|
||||
if(!ret) ret = FindNoVersion(s, size);
|
||||
if(!ret) ret = FindVersionGlobal(s, size);
|
||||
if(!ret && defver) ret = FindVersion(s, size, defver);
|
||||
//if(!ret) ret = FindFirstVersion(s);
|
||||
//if(!ret) ret = FindFirstVersion(s, size);
|
||||
return ret;
|
||||
}
|
||||
if(ver==-2) {
|
||||
@@ -289,5 +289,6 @@ const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
|
||||
khint_t k = kh_get(defaultversion, def, symname);
|
||||
if(k==kh_end(def))
|
||||
return NULL;
|
||||
return kh_value(def, k);
|
||||
else
|
||||
return kh_value(def, k);
|
||||
}
|
||||
@@ -11,6 +11,8 @@ GO("libGL.so.1", libgl)
|
||||
GO("libGL.so", libgl)
|
||||
GO("libOpenGL.so.0", libgl)
|
||||
GO("libGLU.so.1", libglu)
|
||||
GO("libGLX.so.0", libglx)
|
||||
GO("libGLX.so", libglx)
|
||||
GO("libX11.so.6", libx11)
|
||||
GO("libasound.so.2", libasound)
|
||||
GO("libdl.so.2", libdl)
|
||||
@@ -58,17 +60,26 @@ GO("libxcb-xfixes.so.0", libxcbxfixes)
|
||||
GO("libxcb-shape.so.0", libxcbshape)
|
||||
GO("libxcb-shm.so.0", libxcbshm)
|
||||
GO("libxcb-randr.so.0", libxcbrandr)
|
||||
GO("libxcb-present.so.0", libxcbpresent)
|
||||
GO("libxcb-image.so.0", libxcbimage)
|
||||
GO("libxcb-keysyms.so.1", libxcbkeysyms)
|
||||
GO("libxcb-xtest.so.0", libxcbxtest)
|
||||
GO("libxcb-glx.so.0", libxcbglx)
|
||||
GO("libxcb-dri2.so.0", libxcbdri2)
|
||||
GO("libxcb-dri3.so.0", libxcbdri3)
|
||||
GO("libxcb-icccm.so.4", libxcbicccm)
|
||||
GO("libxcb-util.so.1", libxcbutil)
|
||||
GO("libxcb-render-util.so.0", libxcbrenderutil)
|
||||
GO("libxcb-render.so.0", libxcbrender)
|
||||
GO("libxcb-sync.so.1", libxcbsync)
|
||||
GO("libxcb-xinerama.so.0", libxcbxinerama)
|
||||
GO("libxcb-xkb.so.1", libxcbxkb)
|
||||
//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("libXpresent.so.1", libxpresent)
|
||||
GO("libXmu.so.6", libxmu)
|
||||
GO("libxkbcommon.so.0", xkbcommon)
|
||||
GO("libxkbcommon-x11.so.0", xkbcommonx11)
|
||||
@@ -130,11 +141,13 @@ GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
GO("libcairo.so.2", cairo)
|
||||
GO("libcairo.so", cairo)
|
||||
GO("libcairo-gobject.so.2", cairogobject)
|
||||
GO("libpango-1.0.so.0", pango)
|
||||
GO("libpango-1.0.so", pango)
|
||||
//GO("libnm.so.0", libnm)
|
||||
//GO("libnm-glib.so.4", libnm)
|
||||
//GO("libnm-util.so.2", libnm)
|
||||
GO("libibus-1.0.so.5", libibus)
|
||||
GO("libfontconfig.so.1", fontconfig)
|
||||
GO("libfreetype.so.6", freetype)
|
||||
GO("libbz2.so.1", bz2)
|
||||
@@ -151,6 +164,7 @@ GO("libtinfo.so.5", libtinfo)
|
||||
GO("libpanel.so.5", libpanel)
|
||||
GO("libncurses.so.6", libncurses6)
|
||||
GO("libtinfo.so.6", libtinfo6)
|
||||
GO("libtbbmalloc.so.2", tbbmalloc)
|
||||
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
|
||||
GO("libtcmalloc_minimal.so.0", tcmallocminimal)
|
||||
GO("libtcmalloc_minimal.so.4", tcmallocminimal)
|
||||
@@ -206,6 +220,7 @@ GO("libva-drm.so.2", libvadrm)
|
||||
GO("libva-x11.so.2", libvax11)
|
||||
GO("libva-wayland.so.2", libvawayland)
|
||||
GO("libvdpau.so.1", libvdpau)
|
||||
GO("d3dadapter9.so.1", d3dadapter9)
|
||||
|
||||
GO("ld-linux-x86-64.so.2", ldlinux)
|
||||
|
||||
|
||||
Loaded 100 of 750 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user