mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-08 02:08:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d698861478 | ||
|
|
be02c88792 | ||
|
|
99059ffb19 | ||
|
|
a4752afacf | ||
|
|
a320c37681 | ||
|
|
42a9a40ac4 | ||
|
|
6320a07d17 | ||
|
|
5e251cf478 | ||
|
|
355a2fa8e5 | ||
|
|
78ed9d07f2 | ||
|
|
8c38d5dd36 | ||
|
|
f682ca6bf0 | ||
|
|
70a2a2dd1b | ||
|
|
3678f44945 | ||
|
|
5bb473158b | ||
|
|
3f549749c1 | ||
|
|
11535dabe0 | ||
|
|
1c2d36f98a | ||
|
|
8563ba8b70 | ||
|
|
4b43da2081 | ||
|
|
49c650781f | ||
|
|
36e5bf731c | ||
|
|
f4d4116590 | ||
|
|
11281589e0 | ||
|
|
756811a901 | ||
|
|
dd405c7c49 | ||
|
|
20237019e4 | ||
|
|
7682cdce57 | ||
|
|
1dcac1b868 | ||
|
|
5f0add0e82 | ||
|
|
8f2ef48e25 | ||
|
|
4f98f568a7 | ||
|
|
0e0e346e45 | ||
|
|
4388092f11 | ||
|
|
b83c693192 | ||
|
|
9de1bd884f | ||
|
|
1b462b8200 | ||
|
|
d7c75be001 | ||
|
|
957fcc2449 | ||
|
|
328794e4d6 | ||
|
|
af519f6046 | ||
|
|
fa9a059921 | ||
|
|
771d65dc10 | ||
|
|
1dc92c216f | ||
|
|
db4ff551cc | ||
|
|
7abb9a1893 | ||
|
|
60f987ff90 | ||
|
|
f38d122b67 | ||
|
|
a654193f1d | ||
|
|
632a01dbe6 | ||
|
|
ae2e3aed0f | ||
|
|
244b273250 | ||
|
|
27756113ef | ||
|
|
d550293ccc | ||
|
|
74bb2e84f2 | ||
|
|
09d2b067b5 | ||
|
|
6d7f901167 | ||
|
|
bdc839ef87 | ||
|
|
52f7e89fdb | ||
|
|
6a2b45ec5c | ||
|
|
ac0fd0278b | ||
|
|
db06cec325 | ||
|
|
d93e7f92f2 | ||
|
|
d8e94908ff | ||
|
|
8e9d31e670 | ||
|
|
6ed7bbdb21 | ||
|
|
8338ebaa46 | ||
|
|
d4c08eb083 | ||
|
|
c62dc24155 | ||
|
|
f8e2b81160 | ||
|
|
06b38df650 | ||
|
|
00e6ed3feb | ||
|
|
6ffbacd808 | ||
|
|
8e88ca6985 | ||
|
|
ada65fc0da | ||
|
|
52002ebc64 | ||
|
|
a3e25e32a4 | ||
|
|
8aedf8957e | ||
|
|
db7924e26a | ||
|
|
2b2478381a | ||
|
|
59b1e323f7 | ||
|
|
31e7957362 | ||
|
|
917a9ba11f | ||
|
|
71f6654062 | ||
|
|
5b1670390a | ||
|
|
f4999d71f3 | ||
|
|
64f52cb1b9 | ||
|
|
905780e47d | ||
|
|
6f176bceae | ||
|
|
21a8e20b94 | ||
|
|
20b2b083f5 | ||
|
|
bfeedef03b | ||
|
|
d42767414d | ||
|
|
c83f21cc38 | ||
|
|
f1ce0668f8 | ||
|
|
20e6869e53 | ||
|
|
75a3fb0d89 | ||
|
|
0145c5bb34 | ||
|
|
8e3d0835a2 | ||
|
|
9fe432ac60 | ||
|
|
5e46f8825b | ||
|
|
359ba4836d | ||
|
|
fe57003477 | ||
|
|
067eb6d7da | ||
|
|
69ec807d56 | ||
|
|
8462b62c0b | ||
|
|
3313d7a158 | ||
|
|
47581ddb50 | ||
|
|
ccf1249b24 | ||
|
|
ebab21f211 | ||
|
|
0de956191b | ||
|
|
1e648aa3d6 | ||
|
|
89e5517961 | ||
|
|
a4cfa477d6 | ||
|
|
66d5fa5ef8 | ||
|
|
cb09b0978a | ||
|
|
dbd5e1b565 | ||
|
|
66ef165184 | ||
|
|
f92b5851d0 | ||
|
|
36b62b9464 | ||
|
|
d867acd295 | ||
|
|
f0d525ddcc | ||
|
|
f82ea51a2b | ||
|
|
1be3d617c7 | ||
|
|
8bc26298a0 | ||
|
|
e6cf41c381 | ||
|
|
657f19d357 | ||
|
|
e681acaf36 | ||
|
|
5142245b1f | ||
|
|
6a49000bc5 | ||
|
|
8d06a36508 | ||
|
|
f120154675 | ||
|
|
ef84c8a635 | ||
|
|
33a2716c43 | ||
|
|
3fcdee46b9 | ||
|
|
8b28872b0e | ||
|
|
29158238bc | ||
|
|
a0191247b9 | ||
|
|
f07af5825c | ||
|
|
fcc5528d77 | ||
|
|
ab13305bc0 | ||
|
|
61075afbb9 | ||
|
|
b4ee108c9c | ||
|
|
e31348b6d5 | ||
|
|
d76efc849f | ||
|
|
76700c1dab | ||
|
|
3f58046288 | ||
|
|
069f488f7b | ||
|
|
320977d84a | ||
|
|
2e7af32cd9 | ||
|
|
c10c86e1d4 | ||
|
|
a4bf1d2c72 | ||
|
|
b3d45c348d | ||
|
|
a4ce2bd549 | ||
|
|
891593c1c9 | ||
|
|
b43e4acc3e | ||
|
|
9cbc531502 | ||
|
|
41c9d92593 | ||
|
|
c2a782839d | ||
|
|
e7653bdda8 | ||
|
|
00a2b44be3 | ||
|
|
bb2d5d43cd | ||
|
|
97aae9521b | ||
|
|
9f2745ad53 | ||
|
|
ec4783bb6f | ||
|
|
5760c04de4 | ||
|
|
4250c61e0f | ||
|
|
c16317850a | ||
|
|
3d325747a5 | ||
|
|
21abac8b06 | ||
|
|
89f05a35e3 | ||
|
|
116e700248 | ||
|
|
db3a80b089 | ||
|
|
09b234e719 | ||
|
|
5f0ca6f03e | ||
|
|
bf3da2d1b5 | ||
|
|
caf0bb9d4d | ||
|
|
753f738368 | ||
|
|
06a19ba790 | ||
|
|
d63a846748 | ||
|
|
3f46f9fb68 | ||
|
|
521dae4695 | ||
|
|
4b7a3046ce | ||
|
|
b0ac567e7a | ||
|
|
455fce9ff5 | ||
|
|
e0ba315761 | ||
|
|
e41be11e9f | ||
|
|
9f0c33016f | ||
|
|
faa13945eb | ||
|
|
989952a873 | ||
|
|
bc9f8df2c2 | ||
|
|
ddface22a8 | ||
|
|
cf18090431 | ||
|
|
cd27cf03e1 | ||
|
|
c0f643dcbe | ||
|
|
84ffab7354 | ||
|
|
cbfd949756 | ||
|
|
55ce03844f | ||
|
|
1451fa8c65 | ||
|
|
d87f90dca3 | ||
|
|
6f8164da52 | ||
|
|
aace0531ab | ||
|
|
91609788d4 | ||
|
|
b5b7019b79 | ||
|
|
2bcafd6ef7 | ||
|
|
0f1092200c | ||
|
|
ccf612a711 | ||
|
|
d8ec77da69 | ||
|
|
aa3efd01cc | ||
|
|
58ca96e2a5 | ||
|
|
5bf7a15f8e | ||
|
|
7d863efcf8 | ||
|
|
6f43a14ddd | ||
|
|
369aa14bff | ||
|
|
4bd4f320bc | ||
|
|
e0340b2a74 | ||
|
|
508b2aa580 | ||
|
|
b8ec0f910c | ||
|
|
c716b3b481 | ||
|
|
ddecd61771 | ||
|
|
88c490b843 | ||
|
|
5998ae57ea | ||
|
|
94c99353fa | ||
|
|
b993866def | ||
|
|
b292efc741 | ||
|
|
bc78375816 | ||
|
|
82e4997624 | ||
|
|
51c64e7dce | ||
|
|
294adeae11 | ||
|
|
95c4c277a1 | ||
|
|
3d517c0bf5 | ||
|
|
2bd3a670e8 | ||
|
|
a621a2b61f | ||
|
|
bc810d16f1 | ||
|
|
fd3f8f5990 | ||
|
|
c713f64d7e | ||
|
|
ed2a8ff73d | ||
|
|
31524ed90b | ||
|
|
1c5aef19ae | ||
|
|
1932f8320a | ||
|
|
ae590d8378 | ||
|
|
124ca7fdc2 | ||
|
|
21128f51f5 | ||
|
|
1af9666622 | ||
|
|
abf66a9cd7 | ||
|
|
5ba8672ac8 | ||
|
|
4616ed9bc3 | ||
|
|
047b9f2eac | ||
|
|
14113faaba | ||
|
|
03b20c3f52 | ||
|
|
26a6eb1922 | ||
|
|
a2f00c5c91 | ||
|
|
dea480e10f | ||
|
|
b7fc2cd5ba | ||
|
|
2aad95726c | ||
|
|
105c56a817 | ||
|
|
3da1ed0a8e | ||
|
|
f46068314c | ||
|
|
914df83ba5 | ||
|
|
d7f5290f14 | ||
|
|
9d37471e4e | ||
|
|
57e75a2fa3 | ||
|
|
3fab879089 | ||
|
|
16cb3d36ba | ||
|
|
74ef17ee94 | ||
|
|
f1c540d877 | ||
|
|
6018e65ab9 | ||
|
|
43190d413c | ||
|
|
a156166a8e | ||
|
|
c8141c63ad | ||
|
|
8dd940804c | ||
|
|
d16f956068 | ||
|
|
082b25d81f | ||
|
|
a0e29198f6 | ||
|
|
b4c5a4c531 | ||
|
|
3a1e6ae5df | ||
|
|
3f7464bf6c | ||
|
|
6aef4501f8 | ||
|
|
3024f27b7a | ||
|
|
e8e1b52a9b | ||
|
|
1c8c76d389 | ||
|
|
a30eedf1e2 | ||
|
|
0b3314607f | ||
|
|
8e7c203772 | ||
|
|
399854342f | ||
|
|
bb692f26d0 | ||
|
|
da5a4c9fbe | ||
|
|
37fc3d0daf | ||
|
|
76a86e2e45 | ||
|
|
a25c32a60b | ||
|
|
4946642fc4 | ||
|
|
2ac59458f3 | ||
|
|
6d329e885f | ||
|
|
902da5c619 | ||
|
|
e9fcef3de5 | ||
|
|
b43ddd46ea | ||
|
|
9c3002928a | ||
|
|
17ec8d8a75 | ||
|
|
d241c818df | ||
|
|
6ff1375e44 | ||
|
|
bb3a13db3b | ||
|
|
ea439a7183 | ||
|
|
fa8355eccc | ||
|
|
62340ea5d8 | ||
|
|
e6deec89f8 | ||
|
|
65fae25715 | ||
|
|
f735f2cbdd | ||
|
|
f5658a6079 | ||
|
|
2b1580b73f | ||
|
|
3c519517c7 | ||
|
|
7389dc616b | ||
|
|
2ff0562a82 | ||
|
|
2ecdc3bb09 | ||
|
|
c1eb7cbfa8 | ||
|
|
45d2ac757e | ||
|
|
875f1d094d | ||
|
|
dc1c986c2c | ||
|
|
32db820b3d | ||
|
|
7bde8a55b4 | ||
|
|
dd083b1e66 | ||
|
|
6199c17441 | ||
|
|
064eb2112d | ||
|
|
10578fb7ee | ||
|
|
ea57c6a212 | ||
|
|
d38c59d3a0 | ||
|
|
36f82eb364 | ||
|
|
9d01904145 | ||
|
|
bb74a811e8 | ||
|
|
d70961afa3 | ||
|
|
3c8bd9c0fb | ||
|
|
e0f37bdde9 | ||
|
|
b638262e12 | ||
|
|
9cd4e70a42 | ||
|
|
c7a4d7dc6f | ||
|
|
582503697e | ||
|
|
308a546cc7 | ||
|
|
3a8ea7de1e | ||
|
|
e2690480d9 | ||
|
|
a48a0499b7 | ||
|
|
1bc817c48a | ||
|
|
317c2f0bf4 | ||
|
|
c4aacb4348 | ||
|
|
978ed8da50 | ||
|
|
13b7202dbb | ||
|
|
70280b7346 | ||
|
|
f00653f216 | ||
|
|
70982f4807 | ||
|
|
b629bd409b | ||
|
|
68c7902bf3 | ||
|
|
721b4bbaf8 | ||
|
|
67aa570b4d | ||
|
|
4be1b75a89 | ||
|
|
05d499d99b | ||
|
|
432e09c37b | ||
|
|
c33683c9df | ||
|
|
b0ea5de0ae | ||
|
|
3e3744cb94 | ||
|
|
9a7fe334b5 | ||
|
|
11c5982a26 | ||
|
|
d91fdc0dcd | ||
|
|
5f4f7bec6c | ||
|
|
4a2ff61fc8 | ||
|
|
3606ef8814 | ||
|
|
734aa87904 | ||
|
|
367235dbd3 | ||
|
|
8050fbd3ca | ||
|
|
b4c664b979 | ||
|
|
22b66a71f4 | ||
|
|
2ed43c3c16 | ||
|
|
2b3983b2e2 | ||
|
|
b85fd74144 | ||
|
|
58565cb40f | ||
|
|
2e9ce77612 | ||
|
|
6925b89c13 | ||
|
|
7c75cc3af8 | ||
|
|
56c540ae13 | ||
|
|
da19b4461f | ||
|
|
c1c3674519 | ||
|
|
e5297fa81a | ||
|
|
7fcbbbe5b6 | ||
|
|
ea49f740c0 | ||
|
|
d29fcfa667 | ||
|
|
b1c8e3dc93 | ||
|
|
3c8b70f224 | ||
|
|
0600886d22 | ||
|
|
6af8045c46 | ||
|
|
582977f20e | ||
|
|
4c72e3c910 | ||
|
|
a0aa2e2458 | ||
|
|
f6a92d6909 | ||
|
|
11c6afa687 | ||
|
|
062207c1fe | ||
|
|
f49b70750a | ||
|
|
15be8fb329 | ||
|
|
0c96d9ecde | ||
|
|
e01134a9c0 | ||
|
|
770f709a24 | ||
|
|
e2a37141da | ||
|
|
5accd2f847 | ||
|
|
46eaabf722 | ||
|
|
807da66d87 | ||
|
|
06861f8577 | ||
|
|
44ee38a868 | ||
|
|
89652e9ff2 | ||
|
|
6f1f35217f | ||
|
|
22c6e81e68 | ||
|
|
ab57dfc5c7 | ||
|
|
8d609ed881 | ||
|
|
0e9a422335 | ||
|
|
5cdd2d4947 | ||
|
|
f946cddd45 | ||
|
|
d45aa0dae9 | ||
|
|
464c7e6b47 | ||
|
|
9e4468acb6 | ||
|
|
dcb49fe731 | ||
|
|
03259e67d9 | ||
|
|
0ea662f57f | ||
|
|
4b629b9b28 | ||
|
|
a8b5ebba18 | ||
|
|
c904d9f66c | ||
|
|
f52c5bc6da | ||
|
|
a074ea8ba6 | ||
|
|
3a3f55f9a2 | ||
|
|
490cabcbe3 | ||
|
|
367c5bcfb1 | ||
|
|
d10de8d7df | ||
|
|
25e4072fef |
No files matched your search
@@ -29,11 +29,26 @@ jobs:
|
||||
matrix:
|
||||
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
|
||||
type: [Release, Trace]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
include:
|
||||
- platform: TEGRAX1
|
||||
type: Release
|
||||
os: ubuntu-20.04
|
||||
- platform: TEGRAX1
|
||||
type: Trace
|
||||
os: ubuntu-20.04
|
||||
- platform: TEGRAX1ARM32
|
||||
type: Release
|
||||
os: ubuntu-20.04
|
||||
- platform: TEGRAX1ARM32
|
||||
type: Trace
|
||||
os: ubuntu-20.04
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: "Checkout Box86 Repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: "Environment preparation"
|
||||
run: |
|
||||
@@ -96,7 +111,7 @@ jobs:
|
||||
ctest -j$(nproc)
|
||||
|
||||
- name: "Upload Artifact"
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: box86-${{ matrix.platform }}-${{ matrix.type }}
|
||||
path: build/box86
|
||||
|
||||
+2
-1
@@ -5,4 +5,5 @@ build*/
|
||||
src/git_head.h
|
||||
backup/
|
||||
box86_update.sh
|
||||
restore_backup.sh
|
||||
restore_backup.sh
|
||||
.cache
|
||||
+62
-4
@@ -1,31 +1,41 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
|
||||
option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
|
||||
option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
|
||||
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
|
||||
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
|
||||
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(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
|
||||
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
|
||||
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(RK3588 "Set to ON if targeting an Rockchip RK3588 / RK3588S 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 (ARM64) based device" ${TEGRAX1})
|
||||
option(TEGRAX1ARM32 "Set to ON if targeting an Tegra X1 (ARM32) based device" ${TEGRAX1ARM32})
|
||||
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
|
||||
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
|
||||
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
|
||||
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
|
||||
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
|
||||
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
|
||||
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
|
||||
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
|
||||
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
|
||||
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
|
||||
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
|
||||
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
|
||||
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
|
||||
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR ARM64 OR RK3588)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
if(RK3588)
|
||||
set(BAD_SIGNAL ON CACHE BOOL "")
|
||||
endif()
|
||||
endif()
|
||||
if(ANDROID)
|
||||
set(NOLOADADDR ON CACHE BOOL "")
|
||||
@@ -58,7 +68,7 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
|
||||
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
|
||||
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64))
|
||||
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR RK3588 OR ARM64))
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
|
||||
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
|
||||
@@ -78,6 +88,7 @@ endif()
|
||||
if(PANDORA)
|
||||
add_definitions(-DPANDORA)
|
||||
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp")
|
||||
elseif(GAMESHELL)
|
||||
add_definitions(-DGAMESHELL)
|
||||
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
|
||||
@@ -101,6 +112,11 @@ elseif(RPI4)
|
||||
add_definitions(-DRPI4)
|
||||
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(RPI3ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI3ARM64)
|
||||
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(RPI4ARM64)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI4ARM64)
|
||||
@@ -130,14 +146,35 @@ elseif(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(RK3588)
|
||||
add_definitions(-DRK3588)
|
||||
add_definitions(-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ARM64)
|
||||
add_definitions(-DARM64)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ODROIDN2)
|
||||
add_definitions(-DODROIDN2)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(TEGRAX1)
|
||||
add_definitions(-DTEGRAX1)
|
||||
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(TEGRAX1ARM32)
|
||||
add_definitions(-DTEGRAX1ARM32)
|
||||
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(PHYTIUM)
|
||||
add_definitions(-DPHYTIUM)
|
||||
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(LX2160A)
|
||||
add_definitions(-DLX2160A)
|
||||
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
|
||||
elseif(ANDROID)
|
||||
add_definitions(-DANDROID)
|
||||
elseif(ARM_DYNAREC)
|
||||
@@ -145,6 +182,10 @@ elseif(ARM_DYNAREC)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
|
||||
endif()
|
||||
|
||||
if(BAD_SIGNAL)
|
||||
add_definitions(-DBAD_SIGNAL)
|
||||
endif()
|
||||
|
||||
if(POWER9)
|
||||
add_definitions(-mcpu=power9 -mtune=power9)
|
||||
endif()
|
||||
@@ -237,6 +278,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/box86context.c"
|
||||
"${BOX86_ROOT}/src/build_info.c"
|
||||
"${BOX86_ROOT}/src/custommem.c"
|
||||
"${BOX86_ROOT}/src/mallochook.c"
|
||||
"${BOX86_ROOT}/src/tools/bridge.c"
|
||||
"${BOX86_ROOT}/src/tools/pathcoll.c"
|
||||
"${BOX86_ROOT}/src/tools/fileutils.c"
|
||||
@@ -244,6 +286,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/tools/box86stack.c"
|
||||
"${BOX86_ROOT}/src/tools/my_cpuid.c"
|
||||
"${BOX86_ROOT}/src/tools/gtkclass.c"
|
||||
"${BOX86_ROOT}/src/tools/rcfile.c"
|
||||
"${BOX86_ROOT}/src/tools/wine_tools.c"
|
||||
"${BOX86_ROOT}/src/elfs/elfloader.c"
|
||||
"${BOX86_ROOT}/src/elfs/elfparser.c"
|
||||
@@ -311,6 +354,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpng16.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxrandr.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxpresent.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxext.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedxinerama.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxfixes.c"
|
||||
@@ -392,15 +436,18 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgsttag.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgstbase.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgstapp.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibibus.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedappindicator3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatkbridge.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgthread2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcairo.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcairogobject.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpango.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusglib1.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgudev1.c"
|
||||
@@ -442,6 +489,9 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibvkd3d.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgomp.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcap.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpcap.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
|
||||
)
|
||||
if(ANDROID)
|
||||
list(APPEND WRAPPEDS
|
||||
@@ -635,6 +685,7 @@ if(NOT _x86 AND NOT _x86_64)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET uninstall)
|
||||
@@ -764,7 +815,7 @@ add_test(NAME sse COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/$
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0")
|
||||
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
|
||||
|
||||
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
|
||||
@@ -790,4 +841,11 @@ foreach(file ${extension_tests})
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
|
||||
endforeach()
|
||||
|
||||
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
|
||||
|
||||
endif(BOX86LIB)
|
||||
Vendored
+61
@@ -1,3 +1,64 @@
|
||||
box86 (0.3.0) unstable; urgency=low
|
||||
|
||||
* Added rcfile handling: box86 now read "/etc/box86.box86rc" and "~/.box86rc" and apply per process parameters
|
||||
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
|
||||
* Refactored Strong Memory Model emulation (faster and more accurate)
|
||||
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
|
||||
* Improved memory protection tracking and signal handling, again
|
||||
* More wrapped libs (especially on the gtk familly)
|
||||
* More wrapped functions
|
||||
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
|
||||
* Improved dladdr/dladdr1 wrapped function
|
||||
* Some fixes to flags handling in the Dynarec on some special cases
|
||||
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
|
||||
* 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)
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
|
||||
|
||||
box86 (0.2.8) unstable; urgency=low
|
||||
|
||||
* Wrapped more Vulkan functions, dxvk2.0 now works
|
||||
* Added support for overridden malloc/free functions
|
||||
* Improved elf loader
|
||||
* Improved dlsym handling with RTLD_NEXT
|
||||
* Added BOX86_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
|
||||
* Added BOX86_BASH to setup x86 bash binary, so shell script can be run in x86 world
|
||||
* Added BOX86_ROLLING_LOG to have details log only on crash
|
||||
* Improved TLS Size handling (Unity3D games now works)
|
||||
* Improved execv family of function to have better box86 integration
|
||||
* Added a few more wrapped libs, like FAudio
|
||||
* Improved gtk, SDL2, GL, vulkan (and more) wrapping
|
||||
* Improved Signal Handling and memory protection traking
|
||||
* Added some basic support for statically linked program. Thread are not working yet, but memory allocation and file access does.
|
||||
* add LX2160A config by @lizthegrey in #612
|
||||
* Grammar and formatting COMPILE.md by @Radiicall in #615
|
||||
* Update README.md by @everypizza1 in #617
|
||||
* docs: add instructions for Debian-based Linux by @ryanfortner in #622
|
||||
* Fix typoes in readme by @ryanfortner in #621
|
||||
* Various improvements to install_steam.sh by @ryanfortner in #620
|
||||
* docs: remove unnecessary newline by @ryanfortner in #624
|
||||
* fix: the first parameter of realpath may be null by @ye-yeshun in #630
|
||||
* Add 6 wrapped function to libdrm, and 2 to libexpat. by @cjy880927 in #632
|
||||
* Fix #610 by @rajdakin in #634
|
||||
* some floating point instructions by @ye-yeshun in #637
|
||||
* Fix Typo in readme x86_64 -> x86 by @Jai-JAP in #642
|
||||
* Fix grammar by @Jai-JAP in #645
|
||||
* Test wine preload by @ptitSeb in #649
|
||||
* Align address when call mprotect by @wannacu in #651
|
||||
* Added 66 0F 7D HSUBPD opcode by @wannacu in #652
|
||||
* add TEGRAX1 and TEGRAX1ARM32 targets on ubuntu-18.04 by @theofficialgman in #654
|
||||
* automatically install 32 bit libraries if 64 bit OS is detected in install_steam.sh by @Moldytzu in #659
|
||||
* mention gcc-arm-linux-gnueabihf in compile.md by @Moldytzu in #660
|
||||
* Add libc6:armhf install to RPi4 aarch64 build info by @WheezyE in #685
|
||||
* Updated wine install for RPiOS bullseye 32/64bit by @WheezyE in #689
|
||||
* Add atomic add opcodes by @Trass3r in #695
|
||||
* steam: disable modern login and pass arguments to client by @Moldytzu in #700
|
||||
* Modify sizeof(instsize_t) to 1 byte by @liuli0217 in #721
|
||||
* Add MOV GS:od, AL by @liuli0217 in #722
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Thu, 17 Nov 2022 11:20:33 -0500
|
||||
|
||||
box86 (0.2.6) unstable; urgency=low
|
||||
|
||||
* Added an option to get generated -NAN on SSE2 operation
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
v0.3.0
|
||||
======
|
||||
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
|
||||
=> Every program can be finetuned, for speed or just to make them work
|
||||
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
|
||||
* Refactored Strong Memory Model emulation (faster and more accurate)
|
||||
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
|
||||
* Improved memory protection tracking and signal handling, again
|
||||
* More wrapped libs (especially on the gtk familly)
|
||||
* More wrapped functions
|
||||
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
|
||||
* Improved dladdr/dladdr1 wrapped function
|
||||
* Some fixes to flags handling in the Dynarec on some special cases
|
||||
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
|
||||
* 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)
|
||||
|
||||
|
||||
v0.2.8
|
||||
======
|
||||
* Wrapped more vulkan function, dxvk 2.0 now works
|
||||
* Added support for overriden malloc/free functions
|
||||
* Improved elf loader
|
||||
* Improved dlsym handling with RTLD_NEXT
|
||||
* Added BOX86_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
|
||||
* Added BOX86_BASH to setup x86 bash binary, so shell script can be run in x86 world
|
||||
* Added BOX86_ROLLING_LOG to have details log only on crash
|
||||
* Improved TLS Size handling (Unity3D games now works)
|
||||
* Improved `execv` family of function to have better box86 integration
|
||||
* Added a few more wrapped libs, like FAudio
|
||||
* Improved gtk, SDL2, GL, vulkan (and more) wrapping
|
||||
* Improved Signal Handling and memory protection traking
|
||||
* Added some basic support for statically linked program. Thread are not working yet, but memory allocation and file access does.
|
||||
=> with the use of the new SafeFlags, some C# Windows program now runs fine (it's forced when the Vara family of software is detected)
|
||||
=> With the basic support of statcaly linked program, old emulator like modeler for linux works. Program with threads like mugen for linux still doesn't
|
||||
=> The bash integration is usefull for device with no binfmt integration or for script that check the machine it's running on
|
||||
|
||||
v0.2.6
|
||||
======
|
||||
* Added an option to get generated -NAN on SSE2 operation
|
||||
|
||||
+97
-26
@@ -1,5 +1,19 @@
|
||||
Compiling
|
||||
Compiling/Installing
|
||||
----
|
||||
|
||||
#### Debian-based Linux
|
||||
You can use [@Itai-Nelken](https://github.com/Itai-Nelken)'s apt repository to install precompiled box86 debs, updated weekly.
|
||||
|
||||
```
|
||||
sudo wget https://itai-nelken.github.io/weekly-box86-debs/debian/box86.list -O /etc/apt/sources.list.d/box86.list
|
||||
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo apt-key add -
|
||||
sudo apt update && sudo apt install box86 -y
|
||||
```
|
||||
|
||||
**Note:** On a 64bit OS, install the `box86:armhf` package.
|
||||
|
||||
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
|
||||
|
||||
#### for Pandora
|
||||
|
||||
`mkdir build; cd build; cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
|
||||
@@ -14,26 +28,33 @@ Compiling
|
||||
|
||||
#### for Raspberry Pi
|
||||
|
||||
_a build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
|
||||
_A build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
|
||||
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box86
|
||||
cd box86
|
||||
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make
|
||||
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4=1 for Pi4 (use `-DRPI2=1` etc for other models)
|
||||
make # can use `make -j2`, `make -j3`, etc to speed up 1st build (but beware of running out of memory if going too high)
|
||||
sudo make install
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
Note that you can use `make -j2` or more to speed up 1st build, but beware of the memory requirement if you go to high.
|
||||
|
||||
#### for Raspberry Pi on 64bits OS
|
||||
#### for Raspberry Pi on 64bit OS
|
||||
|
||||
_For Pi4. Change to RPI2 or RPI3 for other models. Change `-DRPI4=1` to `-DRPI4ARM64=1` for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
|
||||
_armhf multiarch or chroot required for running box86 (armhf) on aarch64_
|
||||
|
||||
```
|
||||
# example of enabling multiarch & installing libc6:armhf (to run box86:armhf on aarch64)
|
||||
# (running i386-wine on aarch64 requires more armhf libraries)
|
||||
sudo dpkg --add-architecture armhf && sudo apt-get update
|
||||
sudo apt-get install libc6:armhf -y
|
||||
```
|
||||
_Build box86:armhf on RPiOS 64-bit ARM (aarch64)_
|
||||
```
|
||||
sudo apt install gcc-arm-linux-gnueabihf # building 32-bit ARM code on aarch64 requires this armhf gcc cross-compiler toolchain
|
||||
git clone https://github.com/ptitSeb/box86
|
||||
cd box86
|
||||
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI3ARM64=1` for a PI3 model)
|
||||
make -j2
|
||||
sudo make install
|
||||
sudo systemctl restart systemd-binfmt
|
||||
@@ -47,7 +68,25 @@ sudo systemctl restart systemd-binfmt
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
|
||||
As most RK3399 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for RK3588 / RK3588S
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most RK3588 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for ODROID N2/N2+
|
||||
|
||||
`mkdir build; cd build; cmake .. -DODROIDN2=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
As most ODROID N2/N2+ devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for Tinker Board (1/1S) or RK3288
|
||||
|
||||
@@ -57,67 +96,99 @@ As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environme
|
||||
|
||||
`mkdir build; cd build; cmake .. -DA64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
|
||||
As most Allwinner A64 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for Snapdragon 845
|
||||
|
||||
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most Snapdragon 845 device run AARCH64 OS, in most cases you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
#### for Phytium
|
||||
|
||||
`mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
|
||||
As most Phytium (D2000 or FT2000/4) devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for Other ARM64 64bits Linux platform
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM64 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
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
|
||||
|
||||
You'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
|
||||
|
||||
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
|
||||
|
||||
#### for Other ARM Linux platforms
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
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 x86 Linux
|
||||
|
||||
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
|
||||
|
||||
#### use ccmake
|
||||
### use ccmake
|
||||
|
||||
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
|
||||
|
||||
#### Customize your build
|
||||
### Customize your build
|
||||
|
||||
*use ccache if you have it*
|
||||
#### use ccache if you have it
|
||||
|
||||
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
|
||||
|
||||
*have some debug info*
|
||||
#### To have some debug info
|
||||
|
||||
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
|
||||
|
||||
*to have a Trace Enabled build*
|
||||
#### To have a Trace Enabled build
|
||||
|
||||
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
|
||||
To have a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. But you will need the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime.
|
||||
|
||||
*to have ARM Dynarec*
|
||||
#### to have ARM Dynarec
|
||||
|
||||
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode). Note that compiling with `ARM_DYNAREC` but without hardware profile is not advise. If you get error building that "target CPU does not support ARM mode", then try to pick hardware profile (like ODROID for armv7 or PI4 for armv8). Also, if you are using a 64bits with armhf multiarch, it's much easier to pick one of the hardware profile like `RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
|
||||
###### *Note: VFPv3 and NEON are required for Dynarec.*
|
||||
|
||||
*not building from a git clone*
|
||||
###### *Note: Compiling with `ARM_DYNAREC` without selecting a hardware profile is not advised.*
|
||||
|
||||
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box86 print).
|
||||
Dynarec is only available on the ARM architecture (for the meantime anyways). Activate it by using `-DARM_DYNAREC=1`.
|
||||
|
||||
You will most likely need `-marm` in compilation flags (Many compilers default to the Thumb instruction set and Dynarec does not support this).
|
||||
|
||||
###### *Note: If you get error building that "target CPU does not support ARM mode", then try to pick a hardware profile (like ODROID for armv7 or PI4 for armv8).*
|
||||
|
||||
##### 64bit OS with Dynarec
|
||||
|
||||
If you are using a 64bit OS with armhf multiarch, it's much easier to pick one of the hardware profiles.
|
||||
|
||||
`RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
|
||||
|
||||
#### Not building from a git clone
|
||||
If you are not building from a git clone (for example, downloading a release source code zip from github), you need to use `-DNOGIT=1` from cmake to be able to build (box86 uses git SHA1 to show last commit in version number).
|
||||
|
||||
----
|
||||
|
||||
Testing
|
||||
----
|
||||
A few tests are included.
|
||||
They can be launched with `ctest`
|
||||
They are very basic and don't test much for now.
|
||||
A few tests are included with box86.
|
||||
|
||||
They can be launched using the `ctest` command.
|
||||
|
||||
The tests are very basic and only tests some functionality for now.
|
||||
|
||||
----
|
||||
|
||||
Note about devices with Tegra X1 and newer.
|
||||
|
||||
Nvidia don't provide armhf libraries for their GPU drivers at this moment so there is no special variable to compile it for them as it would be missleading for many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. As instalation of Mesa can break Nvidia driver, safest option is usage of chroot.
|
||||
NVIDIA doesn't provide armhf libraries for their GPU drivers at this time. There is no special variable to compile box86 for them, as it would be misleading to many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. Installation of Mesa can break the NVIDIA driver, so the safest option is to use a chroot environment.
|
||||
|
||||
----
|
||||
|
||||
|
||||
+31
-18
@@ -1,6 +1,6 @@
|
||||

|
||||
|
||||
Linux Userspace x86_64 Emulator with a twist
|
||||
Linux Userspace x86 Emulator with a twist
|
||||
|
||||
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
|
||||
|
||||
@@ -12,13 +12,13 @@ Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems,
|
||||
|
||||
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environment).
|
||||
|
||||
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
|
||||
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/). That also means that you will need a 32bits userspace on 64bits OS, like `armhf` on top an `aarch64` 64bits OS.
|
||||
|
||||
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
|
||||
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) might be necessary. (Some ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy. (see OpenGL on Android))
|
||||
|
||||
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
|
||||
|
||||
Many games already work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious)
|
||||
Many games just work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious). Unity3D games also works fine, but the OpenGL requirement might be an issue on some ARM platforms.
|
||||
|
||||
If you are serious about developing Box86, you should install ccache and build Box86 with it. (Use ccmake for example.)
|
||||
To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) available on your system.
|
||||
@@ -56,7 +56,7 @@ There are a few environment variables to control the behaviour of Box86.
|
||||
|
||||
See [here](USAGE.md) for all environment variables and what they do.
|
||||
|
||||
Note: Box86's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
|
||||
Note: Box86's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_box86signalhandler` in `signals.c` if you want to trap SegFaults.
|
||||
|
||||
----
|
||||
|
||||
@@ -76,27 +76,40 @@ If you look at a 64bits version of box86, look at [Box64](https://github.com/pti
|
||||
|
||||
----
|
||||
|
||||
Notes about Box86 configuration
|
||||
----
|
||||
|
||||
Box86 now have configurations files. There are 2 files loaded. `/etc/box4.box86rc` and `~/.box86rc`. 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. Box86 comes with a default file that should be installed for better stability. The file in in `system/box86.box86rc` and should be installed to `/etc/box86.box86rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box86rc` or some game may not function correctly.
|
||||
Note that the priority is: `~/.bashrc` > `/etc/box86.box86rc` > command line
|
||||
So, your settings in `~/.bashrc` may override the setting from your command line...
|
||||
|
||||
----
|
||||
|
||||
Notes about Unity game emulation
|
||||
----
|
||||
|
||||
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with the new "protected memory" mechanism implemented it should be running with correct performance now.
|
||||
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
|
||||
TL;DR: Not all Unity games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct now.
|
||||
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
|
||||
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
|
||||
|
||||
----
|
||||
|
||||
Notes about Steam
|
||||
----
|
||||
|
||||
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works:
|
||||
- First problem is Steam crashing after the sign-in window, if you encounter this issue, you may need to add libappindicator. To install it on Debian, run `sudo apt install libappindicator1`.
|
||||
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm installed. To install it on Debian, run `sudo apt install libnm0`.
|
||||
- Once open, Steam will only work on "Small Mode" and in "Big Picture", not in the regular "Large Mode". This is because some Steam components used in the browser view are only 64-bit now. So go in the "View" menu and switch to "Small view", else the list will stay empty. Alternatively, Steam can be started in small mode directly by using `+open steam://open/minigameslist` command line arguments.
|
||||
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables.
|
||||
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aforementioned feature, it is safer to add it to your system if you intend to play those game. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
|
||||
Linux Steam's can run now with box86. but you also need box64 for it to completly usable.
|
||||
It is advised to run steam in the Small mode, as it use the less memory, but steamwebhelper (a 64bits process) will still be loaded even if not used.
|
||||
The login screen cannot run without steamwebhelper, and will just show a blank windows without box64 properly setup in the system.
|
||||
File note, Steam will use a lot of memory, and barely fit on system with 4GB of RAM. It will not work anymore on system with less memory (as a workaround, create a swap file, login and check "remember me", the use box64rc to disable steamwebhelper and run only in small mode without swap after the 1st login)
|
||||
Final note: the Steam BigPicture will work, but also need steamwebhelper (and so box64), and lots of memory. It will not start on system with only 4GB of RAM without swap.
|
||||
- If you have trouble installing Steam, you can find `install_steam.sh` in the root folder of the box86 repo. This simple script will download and install steam in your home folder, and then create a shortcut to steam in `/usr/local/bin` (and for this it will ask for sudo permission). Simply use `steam` to launch once it's installed. Note that the installation, being in the Home folder, will only work for a single user. Don't use this script if you need a multi-user installation.
|
||||
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables (it's automatically there if you used the `install_steam.sh` script)
|
||||
|
||||
Steam for Windows installs fine but doesn't work yet.
|
||||
to disable `steamwebhelper` when box64 installed and running, create (or edit) `~/.box64rc` and add:
|
||||
```
|
||||
[steamwebhelper]
|
||||
BOX64_EXIT=1
|
||||
```
|
||||
in it and it will be disable. Comment with a `#` those 2 lines to enable it again
|
||||
|
||||
----
|
||||
|
||||
@@ -111,7 +124,7 @@ Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those mod
|
||||
Notes about Vulkan
|
||||
----
|
||||
|
||||
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Note that Vulkan wrapping has not been tested much, due to the limited Vulkan support on the hardware I currently own. Profile 1.0 and 1.1, with some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
|
||||
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Profile 1.0, 1.1, 1.2 and 1.3, with some extensions, should be OK. DXVK, including the 2.0, works. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
|
||||
|
||||
----
|
||||
Final word
|
||||
@@ -121,7 +134,7 @@ I want to thank everyone who has contributed to box86 development.
|
||||
There are many ways to contribute: code, financial, hardware and advertisement!
|
||||
So, in no particular order, I want to thank:
|
||||
* For their major code contribution: rajdakin, icecream95, M-HT
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000
|
||||
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序
|
||||
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
|
||||
以下感谢不分先后:
|
||||
* 代码贡献:rajdakin, icecream95, M-HT
|
||||
* 财务帮助:FlyingFathead, stormchaser3000
|
||||
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
|
||||
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
|
||||
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
|
||||
|
||||
|
||||
+119
-40
@@ -3,195 +3,271 @@ Usage
|
||||
----
|
||||
|
||||
There are many environment variables to control Box86 behaviour.
|
||||
Env. var with * can also be put inside box64rc files
|
||||
|
||||
#### BOX86_LOG
|
||||
#### BOX86_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 (so same as `BOX86_LOG=2 BOX86_DUMP=1`)
|
||||
|
||||
#### BOX86_DUMP
|
||||
#### BOX86_DUMP *
|
||||
Controls the Dump of elf content
|
||||
* 0: No dump of elf information (Default)
|
||||
* 1: Dump elf sections and relocations and other information (also active if using `BOX86_LOG=3`)
|
||||
|
||||
#### BOX86_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 BOX86_LOG>1 (may need BOX86_SHOWSEGV=1 also)
|
||||
* N: Last N wrapped functions calls printed when a signal is printed. Incompatible with BOX86_LOG>1 (may need BOX86_SHOWSEGV=1 also)
|
||||
|
||||
#### BOX86_NOBANNER
|
||||
Disables Box86 printing its version and build
|
||||
* 0 : Enable printing its banner. (Default.)
|
||||
* 1 : Disable printing its banner.
|
||||
|
||||
#### BOX86_LD_LIBRARY_PATH
|
||||
#### BOX86_LD_LIBRARY_PATH *
|
||||
Path to look for x86 libraries. Default is current folder and `lib` in current folder.
|
||||
Also, `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exist.
|
||||
|
||||
#### BOX86_PATH
|
||||
#### BOX86_PATH *
|
||||
Path to look for x86 executable. Default is current folder and `bin` in current folder.
|
||||
|
||||
#### BOX86_DLSYM_ERROR
|
||||
#### BOX86_DLSYM_ERROR *
|
||||
Enables/Disables the logging of `dlsym` errors.
|
||||
* 0 : Don't log `dlsym` errors. (Default.)
|
||||
* 1 : Log dlsym errors.
|
||||
|
||||
#### BOX86_TRACE_FILE
|
||||
#### BOX86_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 box86 instance
|
||||
Use `stderr` to use this instead of default `stdout`
|
||||
|
||||
#### BOX86_TRACE
|
||||
#### BOX86_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.
|
||||
|
||||
#### BOX86_TRACE_INIT
|
||||
#### BOX86_TRACE_INIT *
|
||||
Use BOX86_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.
|
||||
|
||||
#### BOX86_TRACE_START
|
||||
#### BOX86_TRACE_START *
|
||||
Only on builds with trace enabled.
|
||||
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`).
|
||||
|
||||
#### BOX86_TRACE_XMM
|
||||
#### BOX86_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.
|
||||
|
||||
#### BOX86_LOAD_ADDR
|
||||
#### BOX86_TRACE_EMM *
|
||||
Only on builds with trace enabled.
|
||||
* 0 : The EMM (i.e. MMX) register will not be logged with the general and x86 registers. (Default.)
|
||||
* 1 : Dump the EMM registers.
|
||||
|
||||
#### BOX86_LOAD_ADDR *
|
||||
Try to load at 0xXXXXXX main binary (if binary is a PIE)
|
||||
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
|
||||
|
||||
#### BOX86_NOSIGSEGV
|
||||
#### BOX86_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.
|
||||
|
||||
#### BOX86_NOSIGILL
|
||||
#### BOX86_NOSIGILL *
|
||||
Disable handling of SigILL (to ease debugging mainly).
|
||||
* 0 : Let x86 program set sighandler for Illegal Instruction
|
||||
* 1 : Disables the handling of SigILL
|
||||
|
||||
#### BOX86_X11COLOR16
|
||||
#### BOX86_X11COLOR16 *
|
||||
PANDORA only: Try converting X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows).
|
||||
* 0 : Don't touch X11 colors. (Default.)
|
||||
* 1 : Change colors arguments in XSetForeground, XSetBackground and XCreateGC.
|
||||
|
||||
#### BOX86_X11THREADS
|
||||
#### BOX86_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.
|
||||
|
||||
#### BOX86_X11GLX
|
||||
#### BOX86_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.)
|
||||
|
||||
#### BOX86_DYNAREC_DUMP
|
||||
#### BOX86_DYNAREC_DUMP *
|
||||
Enables/disables Box86'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.
|
||||
|
||||
#### BOX86_DYNAREC_LOG
|
||||
#### BOX86_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.
|
||||
|
||||
#### BOX86_DYNAREC
|
||||
#### BOX86_DYNAREC *
|
||||
Enables/Disables Box86's Dynarec.
|
||||
* 0 : Disables Dynarec.
|
||||
* 1 : Enable Dynarec. (Default.)
|
||||
|
||||
#### BOX86_DYNAREC_TRACE
|
||||
#### BOX86_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).
|
||||
|
||||
#### BOX86_NODYNAREC
|
||||
#### BOX86_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)
|
||||
|
||||
#### BOX86_DYNAREC_BIGBLOCK
|
||||
#### BOX86_DYNAREC_BIGBLOCK *
|
||||
Enables/Disables Box86'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)
|
||||
|
||||
#### BOX86_DYNAREC_STRONGMEM
|
||||
#### BOX86_DYNAREC_FORWARD *
|
||||
Define Box86'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)
|
||||
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_DYNAREC_X87DOUBLE
|
||||
#### BOX86_DYNAREC_X87DOUBLE *
|
||||
Force the use of Double for x87 emulation
|
||||
* 0 : Try to use float when possible for x87 emulation (faster)
|
||||
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
|
||||
* 0 : Try to use float when possible for x87 emulation (faster, Default)
|
||||
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis were it's enable automatically)
|
||||
|
||||
#### BOX86_DYNAREC_FASTNAN
|
||||
#### BOX86_DYNAREC_FASTNAN *
|
||||
Enable/Disable generation of -NAN
|
||||
* 0 : Generate -NAN like on x86 (slower, more x86 accurate)
|
||||
* 1 : Don't do anything special with NAN, to go as fast as possible (Default)
|
||||
|
||||
#### BOX86_LIBGL
|
||||
#### BOX86_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) (faster, Default)
|
||||
|
||||
#### BOX86_DYNAREC_SAFEFLAGS *
|
||||
Handling of flags on CALL/RET opcodes
|
||||
* 0 : Treat CALL/RET as if it never needs any flags (faster but may have side-effects)
|
||||
* 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)
|
||||
|
||||
#### BOX86_DYNAREC_HOTPAGE *
|
||||
Handling of HotPage (Page beeing both executed and writen)
|
||||
* 0 : Don't track hotpage
|
||||
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
|
||||
|
||||
#### BOX86_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)
|
||||
|
||||
#### BOX86_SSE_FLUSHTO0 *
|
||||
Handling of SSE Flush to 0 flags
|
||||
* 0 : Just track the flag (Default)
|
||||
* 1 : Direct apply of SSE Flush to 0 flag
|
||||
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_LD_PRELOAD
|
||||
#### BOX86_LD_PRELOAD *
|
||||
* 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
|
||||
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary (not that using this inside a rcfile might not work if the process needs to be renamed, for example for Wine process)
|
||||
|
||||
#### BOX86_EMULATED_LIBS
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_ALLOWMISSING_LIBS
|
||||
#### BOX86_ALLOWMISSING_LIBS *
|
||||
Allow Box86 to continue even if a library is missing (renamed from BOX86_ALLOWMISSINGLIBS).
|
||||
* 0 : Box86 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.
|
||||
|
||||
#### BOX86_ALLOWMISSING_SYMBOLS
|
||||
#### BOX86_ALLOWMISSING_SYMBOLS *
|
||||
Allow dlopen with RTLD_NOW flag to not resolve all symbols.
|
||||
* 0 : Box86 will stop if a library have unresolved symbols. (Default.)
|
||||
* 1 : Continue even if a needed library have unresolved symbols (like symbols not yet wrapped).
|
||||
|
||||
#### BOX86_PREFER_WRAPPED
|
||||
#### BOX86_PREFER_WRAPPED *
|
||||
Box86 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
|
||||
|
||||
#### BOX86_PREFER_EMULATED
|
||||
#### BOX86_PREFER_EMULATED *
|
||||
Box86 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)
|
||||
|
||||
#### BOX86_NOPULSE
|
||||
#### BOX86_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
|
||||
|
||||
#### BOX86_NOGTK
|
||||
#### BOX86_NOGTK *
|
||||
Disables the loading of wrapped GTK libraries.
|
||||
* 0 : Load wrapped GTK libraries if found. (Default.)
|
||||
* 1 : Disables loading wrapped GTK libraries.
|
||||
|
||||
#### BOX86_NOVULKAN
|
||||
#### BOX86_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.)
|
||||
|
||||
#### BOX86_FIX_64BIT_INODES
|
||||
#### BOX86_ENV
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var.
|
||||
|
||||
#### BOX86_ENV1
|
||||
* XXX=yyyy
|
||||
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
|
||||
|
||||
#### BOX86_FIX_64BIT_INODES *
|
||||
Fix/Don't fix 64bit inodes
|
||||
* 0 : Don't fix 64bit inodes. (Default.)
|
||||
* 1 : Fix 64bit inodes. Helps when running on Filesystems with 64bit inodes. Is useful when a program uses API functions which doesn't support it and the program doesn't use inodes information.
|
||||
|
||||
#### BOX86_JITGDB
|
||||
#### BOX86_SHOWSEGV *
|
||||
Show Segfault signal even if a signal handler is present
|
||||
* 0 : Don't force segfault details when a signal handler is install (Default, to limit message spamming)
|
||||
* 1 : Show segfault details
|
||||
|
||||
#### BOX86_SHOWBT *
|
||||
Show a backtrace (native and emulated) on Signal
|
||||
* 0 : Don't show any backtrace (Default.)
|
||||
* 1 : Show native backtrace when a signal is dumped (not available on Andoid build)
|
||||
|
||||
#### BOX86_BASH *
|
||||
Define x86 bash to launch script
|
||||
* yyyy
|
||||
Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a valid x86 version of bash. Note that is Box64 is available, an x86_64 version of bash can also be used. Also, BOX64_BASH env. var. will also be read if BOX86_BASH is not defined.
|
||||
|
||||
#### BOX86_BOX64
|
||||
Define where to find box64 binary
|
||||
* yyyy
|
||||
Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
|
||||
|
||||
#### BOX86_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.
|
||||
@@ -202,3 +278,6 @@ Fix/Don't fix 64bit inodes
|
||||
* 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/box86` 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 ` BOX86_JITGDB=1`.
|
||||
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
|
||||
|
||||
#### BOX86_NORCFILES
|
||||
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
|
||||
+49
-12
@@ -3,10 +3,11 @@ _TwisterOS users: Wine, winetricks, and Box86 are already installed in TwisterOS
|
||||
|
||||
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 already has a 3G/1G split kernel and works with Wine, but **the Pi 3B+ and earlier models have a 2G/2G kernel and require a custom-compiled 3G/1G kernel to get Wine working.**_
|
||||
|
||||
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
|
||||
See installation steps below (in the [Examples](#examples) section).
|
||||
|
||||
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM devices other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
|
||||
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
|
||||
|
||||
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM device's other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
|
||||
|
||||
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) version of Wine even though we are installing it on an ARM processor.
|
||||
|
||||
@@ -15,6 +16,7 @@ The general procedure for installing Wine for Box86 is to...
|
||||
- Download all the install files (.deb, .zip, or even .pol files) for the version of Wine you wish to install
|
||||
- Unzip or dpkg the install files into one folder
|
||||
- Move that folder to the directory that you wish Wine to run from (in TwisterOS, this is `~/wine/` by default)
|
||||
- If you are running box86/i386-wine on a 64bit ARM OS (aarch64), you will also have to install some extra armhf libraries.
|
||||
- Go to `/usr/local/bin` and make symlinks or scripts that will point to your main wine binaries (`wine`, `winecfg`, and `wineserver`).
|
||||
- Boot wine to create a new wineprefix (`wine wineboot`).
|
||||
- Download winetricks (which is simply a very complicated bash script), make it executable, then copy it to `/usr/local/bin`.
|
||||
@@ -50,11 +52,29 @@ sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg
|
||||
wine wineboot
|
||||
```
|
||||
|
||||
### Installing Wine for Box86 on Raspberry Pi OS Buster from WineHQ .deb files
|
||||
### Installing Wine for Box86 on Raspberry Pi OS from WineHQ .deb files
|
||||
_Links from the [WineHQ repo](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/)_
|
||||
|
||||
This install method allows you to install different versions of Wine. You may install any version and any branch of Wine that you wish (wine-devel, wine-stable, or wine-staging).
|
||||
This install method allows you to install different versions of Wine. You may install any version/branch of Wine that you wish.
|
||||
```
|
||||
### User-defined Wine version variables ################
|
||||
# - Replace the variables below with your system's info.
|
||||
# - Note that we need the i386 version for Box86 even though we're installing it on our ARM processor.
|
||||
# - Wine download links from WineHQ: https://dl.winehq.org/wine-builds/
|
||||
|
||||
wbranch="devel" #example: devel, staging, or stable (wine-staging 4.5+ requires libfaudio0:i386 - see below)
|
||||
wversion="7.1" #example: 7.1
|
||||
wid="debian" #example: debian, ubuntu
|
||||
wdist="bullseye" #example (for debian): bullseye, buster, jessie, wheezy, etc
|
||||
wtag="-1" #example: -1 (some wine .deb files have -1 tag on the end and some don't)
|
||||
|
||||
########################################################
|
||||
|
||||
# Clean up any old wine instances
|
||||
wineserver -k # stop any old wine installations from running
|
||||
rm -rf ~/.cache/wine # remove old wine-mono/wine-gecko install files
|
||||
rm -rf ~/.local/share/applications/wine # remove old program shortcuts
|
||||
|
||||
# Backup any old wine installations
|
||||
sudo mv ~/wine ~/wine-old
|
||||
sudo mv ~/.wine ~/.wine-old
|
||||
@@ -64,14 +84,12 @@ sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
|
||||
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
|
||||
|
||||
# Download, extract wine, and install wine
|
||||
# (Replace the links/versions below with links/versions from the WineHQ site for the version of wine you wish to install. Note that we need the i386 version for Box86 even though we're installing it on our ARM processor.)
|
||||
# (Pick an i386 version of wine-devel, wine-staging, or wine-stable)
|
||||
cd ~/Downloads
|
||||
wget https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/wine-devel-i386_5.21~buster_i386.deb # NOTE: Replace this link with the version you want
|
||||
wget https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/wine-devel_5.21~buster_i386.deb # NOTE: Also replace this link with the version you want
|
||||
dpkg-deb -xv wine-devel-i386_5.21~buster_i386.deb wine-installer # NOTE: Make sure these dpkg command matches the filename of the deb package you just downloaded
|
||||
dpkg-deb -xv wine-devel_5.21~buster_i386.deb wine-installer
|
||||
mv ~/Downloads/wine-installer/opt/wine* ~/wine
|
||||
wget https://dl.winehq.org/wine-builds/${wid}/dists/${wdist}/main/binary-i386/wine-${wbranch}-i386_${wversion}~${wdist}${wtag}_i386.deb # download
|
||||
wget https://dl.winehq.org/wine-builds/${wid}/dists/${wdist}/main/binary-i386/wine-${wbranch}_${wversion}~${wdist}${wtag}_i386.deb # (required for wine_i386 if no wine64 / CONFLICTS WITH wine64 support files)
|
||||
dpkg-deb -x wine-${wbranch}-i386_${wversion}~${wdist}${wtag}_i386.deb wine-installer # extract
|
||||
dpkg-deb -x wine-${wbranch}_${wversion}~${wdist}${wtag}_i386.deb wine-installer
|
||||
mv wine-installer/opt/wine* ~/wine # install
|
||||
rm wine*.deb # clean up
|
||||
rm -rf wine-installer # clean up
|
||||
|
||||
@@ -83,7 +101,26 @@ sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
|
||||
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
|
||||
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
|
||||
|
||||
# These packages are needed for running wine-staging on RPi 4 (Credits: chills340)
|
||||
# These packages are needed for running wine on a 64-bit RPiOS via multiarch
|
||||
karch=$(uname -m)
|
||||
if [ "$karch" = "aarch64" ] || [ "$karch" = "aarch64-linux-gnu" ] || [ "$karch" = "arm64" ] || [ "$karch" = "aarch64_be" ]; then
|
||||
sudo dpkg --add-architecture armhf && sudo apt-get update # enable multi-arch
|
||||
sudo apt-get install -y libasound2:armhf libc6:armhf libglib2.0-0:armhf libgphoto2-6:armhf libgphoto2-port12:armhf \
|
||||
libgstreamer-plugins-base1.0-0:armhf libgstreamer1.0-0:armhf libldap-2.4-2:armhf libopenal1:armhf libpcap0.8:armhf \
|
||||
libpulse0:armhf libsane1:armhf libudev1:armhf libusb-1.0-0:armhf libvkd3d1:armhf libx11-6:armhf libxext6:armhf \
|
||||
libasound2-plugins:armhf ocl-icd-libopencl1:armhf libncurses6:armhf libncurses5:armhf libcap2-bin:armhf libcups2:armhf \
|
||||
libdbus-1-3:armhf libfontconfig1:armhf libfreetype6:armhf libglu1-mesa:armhf libglu1:armhf libgnutls30:armhf \
|
||||
libgssapi-krb5-2:armhf libkrb5-3:armhf libodbc1:armhf libosmesa6:armhf libsdl2-2.0-0:armhf libv4l-0:armhf \
|
||||
libxcomposite1:armhf libxcursor1:armhf libxfixes3:armhf libxi6:armhf libxinerama1:armhf libxrandr2:armhf \
|
||||
libxrender1:armhf libxxf86vm1 libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
|
||||
# This list found by downloading...
|
||||
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel-i386_7.1~bullseye-1_i386.deb
|
||||
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/winehq-devel_7.1~bullseye-1_i386.deb
|
||||
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel_7.1~bullseye-1_i386.deb
|
||||
# then `dpkg-deb -I package.deb`. Read output, add `:armhf` to packages in dep list, then try installing them on Pi aarch64.
|
||||
fi
|
||||
|
||||
# These packages are needed for running wine-staging on RPiOS (Credits: chills340)
|
||||
sudo apt install libstb0 -y
|
||||
cd ~/Downloads
|
||||
wget -r -l1 -np -nd -A "libfaudio0_*~bpo10+1_i386.deb" http://ftp.us.debian.org/debian/pool/main/f/faudio/ # Download libfaudio i386 no matter its version number
|
||||
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
# create necessary directories
|
||||
mkdir -p ~/steam
|
||||
mkdir -p ~/steam/tmp
|
||||
cd ~/steam/tmp
|
||||
|
||||
# download latest deb and unpack
|
||||
wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
|
||||
ar x steam.deb
|
||||
tar xf data.tar.xz
|
||||
|
||||
# remove deb archives, not needed anymore
|
||||
rm ./*.tar.xz ./steam.deb
|
||||
|
||||
# move deb contents to steam folder
|
||||
mv ./usr/* ../
|
||||
cd ../ && rm -rf ./tmp/
|
||||
|
||||
# create run script
|
||||
echo "#!/bin/bash
|
||||
export STEAMOS=1
|
||||
export STEAM_RUNTIME=1
|
||||
export DBUS_FATAL_WARNINGS=0
|
||||
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
|
||||
|
||||
# make script executable and move
|
||||
chmod +x steam
|
||||
sudo mv steam /usr/local/bin/
|
||||
|
||||
# detect if we're running on 64 bit Debian
|
||||
MACHINE_TYPE=`uname -m`
|
||||
if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
|
||||
echo "Detected 64 bit ARM Debian. Installing 32 bit libraries"
|
||||
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
|
||||
sudo apt update # update package lists with the newly added arch
|
||||
# install the libraries that Steam requires
|
||||
sudo apt install libc6:armhf libncurses5:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf
|
||||
echo "Don't forget to compile/install Box64!"
|
||||
fi
|
||||
|
||||
echo "Script complete."
|
||||
+277
-285
@@ -106,7 +106,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
alreadyChanged = 0
|
||||
csp = 0
|
||||
while csp < curSplt:
|
||||
if spltln[csp] == '\x00':
|
||||
if spltln[csp] == '\x01':
|
||||
alreadyChanged = 1
|
||||
curSplt = curSplt + 1
|
||||
else:
|
||||
@@ -119,7 +119,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
line = line + spltln[csp] + ">"
|
||||
alreadyChanged = 1
|
||||
csp = csp + 1
|
||||
if spltln[csp] == '\x00':
|
||||
if spltln[csp] == '\x01':
|
||||
alreadyChanged = 1
|
||||
curSplt = curSplt + 1
|
||||
csp = csp + 1
|
||||
@@ -134,7 +134,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
alreadyChanged = 1
|
||||
csp = csp + 1
|
||||
while csp < len(spltln):
|
||||
if spltln[csp] == '\x00':
|
||||
if spltln[csp] == '\x01':
|
||||
alreadyChanged = 1
|
||||
curSplt = curSplt + 1
|
||||
else:
|
||||
@@ -605,7 +605,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
instText = [itp for itp2 in instText for itp in itp2]
|
||||
|
||||
# Make the failures nicer
|
||||
spltln = spltln[:curSplt] + ["\x00"] + instText
|
||||
spltln = spltln[:curSplt] + ["\x01"] + instText
|
||||
|
||||
printf_args = ""
|
||||
for idx, text in enumerate(instText):
|
||||
@@ -858,7 +858,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
instText = [itp for itp2 in instText for itp in itp2]
|
||||
|
||||
# Make the failures nicer
|
||||
spltln = spltln[:curSplt] + ["\x00"] + instText
|
||||
spltln = spltln[:curSplt] + ["\x01"] + instText
|
||||
|
||||
printf_args = ""
|
||||
for idx, text in enumerate(instText):
|
||||
@@ -1156,7 +1156,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
instText = [itp for itp2 in instText for itp in itp2]
|
||||
|
||||
# Make the failures nicer
|
||||
spltln = spltln[:curSplt] + ["\x00"] + instText
|
||||
spltln = spltln[:curSplt] + ["\x01"] + instText
|
||||
|
||||
printf_args = ""
|
||||
for idx, text in enumerate(instText):
|
||||
@@ -1456,7 +1456,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
instText = [itp for itp2 in instText for itp in itp2]
|
||||
|
||||
# Make the failures nicer
|
||||
spltln = spltln[:curSplt] + ["\x00"] + instText
|
||||
spltln = spltln[:curSplt] + ["\x01"] + instText
|
||||
|
||||
# inside '{, '...'}'?
|
||||
hasOpened = False
|
||||
@@ -1675,308 +1675,300 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
|
||||
# Now the files rebuilding part
|
||||
# File header and guard
|
||||
files_header = {
|
||||
"arm_printer.c": """
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
header = """
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arm_printer.h"
|
||||
|
||||
// conditions
|
||||
#define cEQ (0b0000<<28)
|
||||
#define cNE (0b0001<<28)
|
||||
#define cCS (0b0010<<28)
|
||||
#define cCC (0b0011<<28)
|
||||
#define cMI (0b0100<<28)
|
||||
#define cPL (0b0101<<28)
|
||||
#define cVS (0b0110<<28)
|
||||
#define cVC (0b0111<<28)
|
||||
#define cHI (0b1000<<28)
|
||||
#define cLS (0b1001<<28)
|
||||
#define cGE (0b1010<<28)
|
||||
#define cLT (0b1011<<28)
|
||||
#define cGT (0b1100<<28)
|
||||
#define cLE (0b1101<<28)
|
||||
#define c__ (0b1110<<28) // means all
|
||||
|
||||
static const char* conds[16] = {
|
||||
"EQ", "NE", "CS", "CC",
|
||||
"MI", "PL", "VS", "VC",
|
||||
"HI", "LS", "GE", "LT",
|
||||
"GT", "LE", "", "##"
|
||||
};
|
||||
|
||||
static const char* regname[16] = {
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
"r5", "r6", "r7", "r8", "r9",
|
||||
"r10", "r11", "r12", "SP", "LR", "PC"
|
||||
};
|
||||
|
||||
// Single precision are V_:_
|
||||
// Double and quad precision are _:V_
|
||||
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
|
||||
static const char* vecname[96] = {
|
||||
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
|
||||
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
|
||||
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
|
||||
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
|
||||
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
|
||||
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
|
||||
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
|
||||
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
|
||||
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
|
||||
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
|
||||
};
|
||||
|
||||
static const char* dts[16] = {
|
||||
"S8", "S16", "S32", "S64",
|
||||
"U8", "U16", "U32", "U64",
|
||||
"I8", "I16", "I32", "I64",
|
||||
"F8", "F16", "F32", "F64"
|
||||
};
|
||||
|
||||
static const char* shift_type[4] = {
|
||||
"lsl ", "lsr ", "asr ", "ror "
|
||||
};
|
||||
|
||||
const char* print_shift(int shift, int comma) {
|
||||
static __thread char ret[20];
|
||||
ret[0] = '\\0';
|
||||
|
||||
#include "arm_printer.h"
|
||||
|
||||
// conditions
|
||||
#define cEQ (0b0000<<28)
|
||||
#define cNE (0b0001<<28)
|
||||
#define cCS (0b0010<<28)
|
||||
#define cCC (0b0011<<28)
|
||||
#define cMI (0b0100<<28)
|
||||
#define cPL (0b0101<<28)
|
||||
#define cVS (0b0110<<28)
|
||||
#define cVC (0b0111<<28)
|
||||
#define cHI (0b1000<<28)
|
||||
#define cLS (0b1001<<28)
|
||||
#define cGE (0b1010<<28)
|
||||
#define cLT (0b1011<<28)
|
||||
#define cGT (0b1100<<28)
|
||||
#define cLE (0b1101<<28)
|
||||
#define c__ (0b1110<<28) // means all
|
||||
|
||||
static const char* conds[16] = {
|
||||
"EQ", "NE", "CS", "CC",
|
||||
"MI", "PL", "VS", "VC",
|
||||
"HI", "LS", "GE", "LT",
|
||||
"GT", "LE", "", "##"
|
||||
};
|
||||
|
||||
static const char* regname[16] = {
|
||||
"r0", "r1", "r2", "r3", "r4",
|
||||
"r5", "r6", "r7", "r8", "r9",
|
||||
"r10", "r11", "r12", "SP", "LR", "PC"
|
||||
};
|
||||
|
||||
// Single precision are V_:_
|
||||
// Double and quad precision are _:V_
|
||||
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
|
||||
static const char* vecname[96] = {
|
||||
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
|
||||
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
|
||||
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
|
||||
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
|
||||
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
|
||||
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
|
||||
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
|
||||
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
|
||||
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
|
||||
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
|
||||
};
|
||||
|
||||
static const char* dts[16] = {
|
||||
"S8", "S16", "S32", "S64",
|
||||
"U8", "U16", "U32", "U64",
|
||||
"I8", "I16", "I32", "I64",
|
||||
"F8", "F16", "F32", "F64"
|
||||
};
|
||||
|
||||
static const char* shift_type[4] = {
|
||||
"lsl ", "lsr ", "asr ", "ror "
|
||||
};
|
||||
|
||||
const char* print_shift(int shift, int comma) {
|
||||
static __thread char ret[20];
|
||||
ret[0] = '\\0';
|
||||
|
||||
int sh_op = (shift >> 1) & 3;
|
||||
if(shift & 1) {
|
||||
int rs = shift >> 4;
|
||||
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
|
||||
} else {
|
||||
uint8_t amount = shift >> 3;
|
||||
if (!amount) {
|
||||
switch (sh_op) {
|
||||
case 0b00:
|
||||
break;
|
||||
case 0b01:
|
||||
case 0b10:
|
||||
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
|
||||
break;
|
||||
case 0b11:
|
||||
sprintf(ret, "%srrx", (comma ? ", " : ""));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
|
||||
int sh_op = (shift >> 1) & 3;
|
||||
if(shift & 1) {
|
||||
int rs = shift >> 4;
|
||||
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
|
||||
} else {
|
||||
uint8_t amount = shift >> 3;
|
||||
if (!amount) {
|
||||
switch (sh_op) {
|
||||
case 0b00:
|
||||
break;
|
||||
case 0b01:
|
||||
case 0b10:
|
||||
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
|
||||
break;
|
||||
case 0b11:
|
||||
sprintf(ret, "%srrx", (comma ? ", " : ""));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
|
||||
|
||||
const char* print_register_list(int list, int size) {
|
||||
int last = -2;
|
||||
int cnt = 0;
|
||||
static __thread char ret[68];
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (list & (1 << i)) {
|
||||
if (last >= 0) {
|
||||
++cnt;
|
||||
} else {
|
||||
if (last == -1)
|
||||
strcat(ret, ", ");
|
||||
strcat(ret, regname[i]);
|
||||
last = i;
|
||||
}
|
||||
} else {
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[i - 1]);
|
||||
}
|
||||
if (last != -2) last = -1;
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[size - 1]);
|
||||
}
|
||||
strcat(ret, "}");
|
||||
|
||||
const char* print_register_list(int list, int size) {
|
||||
int last = -2;
|
||||
int cnt = 0;
|
||||
static __thread char ret[68];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
|
||||
static __thread char ret[68];
|
||||
|
||||
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
|
||||
if (start + (double_prec + 1) * size > 32) {
|
||||
return "!!!";
|
||||
}
|
||||
if (size == 0) {
|
||||
return "!!!";
|
||||
}
|
||||
if (double_prec && (size % 2 == 1)) {
|
||||
strcpy(ret, "!! {");
|
||||
} else {
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (list & (1 << i)) {
|
||||
if (last >= 0) {
|
||||
++cnt;
|
||||
} else {
|
||||
if (last == -1)
|
||||
strcat(ret, ", ");
|
||||
strcat(ret, regname[i]);
|
||||
last = i;
|
||||
}
|
||||
} else {
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[i - 1]);
|
||||
}
|
||||
if (last != -2) last = -1;
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
if (cnt) {
|
||||
strcat(ret, "-");
|
||||
strcat(ret, regname[size - 1]);
|
||||
}
|
||||
strcat(ret, "}");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
|
||||
static __thread char ret[68];
|
||||
|
||||
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
|
||||
if (start + (double_prec + 1) * size > 32) {
|
||||
return "!!!";
|
||||
}
|
||||
if (size == 0) {
|
||||
return "!!!";
|
||||
}
|
||||
if (double_prec && (size % 2 == 1)) {
|
||||
strcpy(ret, "!! {");
|
||||
} else {
|
||||
ret[0] = '{';
|
||||
ret[1] = '\\0';
|
||||
}
|
||||
|
||||
char regChr;
|
||||
if (double_prec) {
|
||||
regChr = 'D';
|
||||
size /= 2;
|
||||
} else {
|
||||
regChr = 'S';
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
}
|
||||
sprintf(tmp, "%c%d}", regChr, start + size - 1);
|
||||
char regChr;
|
||||
if (double_prec) {
|
||||
regChr = 'D';
|
||||
size /= 2;
|
||||
} else {
|
||||
regChr = 'S';
|
||||
start = (start >> 4) + ((start & 0xF) << 1);
|
||||
}
|
||||
|
||||
char tmp[6];
|
||||
for (int cur = start; cur < start + size - 1; ++cur) {
|
||||
sprintf(tmp, "%c%d, ", regChr, cur);
|
||||
strcat(ret, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
sprintf(tmp, "%c%d}", regChr, start + size - 1);
|
||||
strcat(ret, tmp);
|
||||
|
||||
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
|
||||
|
||||
const char* print_modified_imm_NEON(int op_cmode, int imm) {
|
||||
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
|
||||
|
||||
const char* print_modified_imm_NEON(int op_cmode, int imm) {
|
||||
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
|
||||
|
||||
strcpy(&ret[4], "UNPREDICTABLE");
|
||||
|
||||
switch (op_cmode) {
|
||||
case 0b00000: // VMOV.I32
|
||||
case 0b00001: // VORR.I32
|
||||
case 0b10000: // VMVN.I32
|
||||
case 0b10001: // VBIC.I32
|
||||
strcpy(&ret[4], "UNPREDICTABLE");
|
||||
|
||||
switch (op_cmode) {
|
||||
case 0b00000: // VMOV.I32
|
||||
case 0b00001: // VORR.I32
|
||||
case 0b10000: // VMVN.I32
|
||||
case 0b10001: // VBIC.I32
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b00010: // VMOV.I32
|
||||
case 0b00011: // VORR.I32
|
||||
case 0b10010: // VMVN.I32
|
||||
case 0b10011: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b00010: // VMOV.I32
|
||||
case 0b00011: // VORR.I32
|
||||
case 0b10010: // VMVN.I32
|
||||
case 0b10011: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b00100: // VMOV.I32
|
||||
case 0b00101: // VORR.I32
|
||||
case 0b10100: // VMVN.I32
|
||||
case 0b10101: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X0000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b00110: // VMOV.I32
|
||||
case 0b00111: // VORR.I32
|
||||
case 0b10110: // VMVN.I32
|
||||
case 0b10111: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X000000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01000: // VMOV.I16
|
||||
case 0b01001: // VORR.I16
|
||||
case 0b11000: // VMVN.I16
|
||||
case 0b11001: // VBIC.I16
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01010: // VMOV.I16
|
||||
case 0b01011: // VORR.I16
|
||||
case 0b11010: // VMVN.I16
|
||||
case 0b11011: // VBIC.I16
|
||||
if (imm) {
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01100: // VMOV.I32
|
||||
case 0b11100: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01101: // VMOV.I32
|
||||
case 0b11101: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFFFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01110: // VMOV.I8
|
||||
strcpy(ret, "I8");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01111: // VMOV.F32
|
||||
strcpy(ret, "F32");
|
||||
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
|
||||
break;
|
||||
case 0b11110: // VMOV.I64
|
||||
{
|
||||
strcpy(ret, "I64");
|
||||
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
|
||||
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
|
||||
}
|
||||
break;
|
||||
case 0b11111: // V???.-
|
||||
default:
|
||||
strcpy(ret, "-");
|
||||
strcpy(&ret[4], "UNDEFINED");
|
||||
break;
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
|
||||
return ret;
|
||||
break;
|
||||
case 0b00100: // VMOV.I32
|
||||
case 0b00101: // VORR.I32
|
||||
case 0b10100: // VMVN.I32
|
||||
case 0b10101: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X0000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b00110: // VMOV.I32
|
||||
case 0b00111: // VORR.I32
|
||||
case 0b10110: // VMVN.I32
|
||||
case 0b10111: // VBIC.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02X000000", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01000: // VMOV.I16
|
||||
case 0b01001: // VORR.I16
|
||||
case 0b11000: // VMVN.I16
|
||||
case 0b11001: // VBIC.I16
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01010: // VMOV.I16
|
||||
case 0b01011: // VORR.I16
|
||||
case 0b11010: // VMVN.I16
|
||||
case 0b11011: // VBIC.I16
|
||||
if (imm) {
|
||||
strcpy(ret, "I16");
|
||||
sprintf(&ret[4], "0x%02X00", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01100: // VMOV.I32
|
||||
case 0b11100: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01101: // VMOV.I32
|
||||
case 0b11101: // VMVN.I32
|
||||
if (imm) {
|
||||
strcpy(ret, "I32");
|
||||
sprintf(&ret[4], "0x%02XFFFF", imm);
|
||||
}
|
||||
break;
|
||||
case 0b01110: // VMOV.I8
|
||||
strcpy(ret, "I8");
|
||||
sprintf(&ret[4], "0x%02X", imm);
|
||||
break;
|
||||
case 0b01111: // VMOV.F32
|
||||
strcpy(ret, "F32");
|
||||
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
|
||||
break;
|
||||
case 0b11110: // VMOV.I64
|
||||
{
|
||||
strcpy(ret, "I64");
|
||||
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
|
||||
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
|
||||
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
|
||||
}
|
||||
break;
|
||||
case 0b11111: // V???.-
|
||||
default:
|
||||
strcpy(ret, "-");
|
||||
strcpy(&ret[4], "UNDEFINED");
|
||||
break;
|
||||
}
|
||||
|
||||
const char* arm_print(uint32_t opcode) {
|
||||
static __thread char ret[100];
|
||||
memset(ret, 0, sizeof(ret));
|
||||
|
||||
"""
|
||||
return ret;
|
||||
}
|
||||
files_guard = {
|
||||
"arm_printer.c": """
|
||||
{
|
||||
strcpy(ret, "???");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* arm_print(uint32_t opcode) {
|
||||
static __thread char ret[100];
|
||||
memset(ret, 0, sizeof(ret));
|
||||
|
||||
"""
|
||||
footer = """
|
||||
{
|
||||
strcpy(ret, "???");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
"""
|
||||
banner = "/*******************************************************" + ('*'*len(ver)) + "***\n" \
|
||||
" * File automatically generated by rebuild_printer.py (v" + ver + ") *\n" \
|
||||
" *******************************************************" + ('*'*len(ver)) + "***/\n"
|
||||
trim = lambda string: '\n'.join(line[2:] for line in string.splitlines())[1:]
|
||||
# Yes, the for loops are inverted. This is because both dicts should have the same keys.
|
||||
for fhdr in files_guard:
|
||||
files_header[fhdr] = banner + trim(files_header[fhdr])
|
||||
for fhdr in files_header:
|
||||
files_guard[fhdr] = trim(files_guard[fhdr])
|
||||
trim = lambda string: '\n'.join(line[1:] for line in string.splitlines())[1:]
|
||||
header = banner + trim(header)
|
||||
footer = trim(footer)
|
||||
|
||||
for f in files_header:
|
||||
with open(os.path.join(root, "src", "dynarec", f), 'w') as file:
|
||||
file.write(files_header[f])
|
||||
file.write(output)
|
||||
file.write(files_guard[f])
|
||||
with open(os.path.join(root, "src", "dynarec", "arm_printer.c"), 'w') as file:
|
||||
file.write(header)
|
||||
file.write(output)
|
||||
file.write(footer)
|
||||
# Save the string for the next iteration, writing was successful
|
||||
with open(os.path.join(root, "src", "dynarec", "last_run.txt"), 'w') as file:
|
||||
file.write('\n'.join(insts))
|
||||
@@ -1988,6 +1980,6 @@ if __name__ == '__main__':
|
||||
for i, v in enumerate(sys.argv):
|
||||
if v == "--":
|
||||
limit.append(i)
|
||||
if main(sys.argv[1], "1.2.0.05") != 0:
|
||||
if main(sys.argv[1], "1.2.0.06") != 0:
|
||||
exit(2)
|
||||
exit(0)
|
||||
+17
-15
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -166,8 +166,8 @@ U = TypeVar('U')
|
||||
Filename = str
|
||||
|
||||
class CustOrderedDict(Generic[T, U], Iterable[T]):
|
||||
__keys__: List[T]
|
||||
__actdict__: Dict[T, U]
|
||||
__keys__: List[T] = []
|
||||
__actdict__: Dict[T, U] = {}
|
||||
|
||||
def __init__(self, src: Optional[Dict[T, U]] = None) -> None:
|
||||
if src is None:
|
||||
@@ -195,7 +195,7 @@ class CustOrderedDictList(CustOrderedDict[T, List[U]]):
|
||||
return super().__getitem__(k)
|
||||
|
||||
class FirstArgumentSingletonMeta(Generic[T], type):
|
||||
_singletons: Dict[T, Type['FirstArgumentSingletonMeta']]
|
||||
_singletons: Dict[T, Type['FirstArgumentSingletonMeta']] = {}
|
||||
|
||||
@classmethod
|
||||
def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Dict[str, Any]:
|
||||
@@ -227,10 +227,9 @@ class FileSpec:
|
||||
values: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
|
||||
rvalues: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
|
||||
validrepl: Sequence[str] = ['c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
|
||||
structs: CustOrderedDict[str, Struct]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.structs = CustOrderedDict()
|
||||
self.structs: CustOrderedDict[str, FileSpec.Struct] = CustOrderedDict()
|
||||
|
||||
self.typedefs: CustOrderedDictList[_BareFunctionType, Function] = CustOrderedDictList()
|
||||
self.structsuses: List[FunctionType] = []
|
||||
@@ -441,8 +440,8 @@ class Function:
|
||||
DefineType = NewType('DefineType', str)
|
||||
@final
|
||||
class Define:
|
||||
name: DefineType
|
||||
inverted_: bool
|
||||
name: DefineType = DefineType("")
|
||||
inverted_: bool = False
|
||||
|
||||
defines: List[DefineType] = []
|
||||
|
||||
@@ -480,7 +479,7 @@ class Define:
|
||||
return isinstance(o, Define) and (self.name == o.name) and (self.inverted_ == o.inverted_)
|
||||
@final
|
||||
class Clause:
|
||||
defines: List[Define]
|
||||
defines: List[Define] = []
|
||||
|
||||
def __init__(self, defines: Union[List[Define], str] = []) -> None:
|
||||
if isinstance(defines, str):
|
||||
@@ -528,7 +527,7 @@ class Clauses:
|
||||
Represent a list of clauses, aka a list of or-ed together and-ed "defined()"
|
||||
conditions
|
||||
"""
|
||||
clauses: List[Clause]
|
||||
clauses: List[Clause] = []
|
||||
|
||||
def __init__(self, clauses: Union[List[Clause], str] = []) -> None:
|
||||
if isinstance(clauses, str):
|
||||
@@ -751,9 +750,12 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
|
||||
or match("gstinterfaces010","gstvideo")\
|
||||
or match("gstinterfaces010","gstaudio")\
|
||||
or match("gstreamer010","gstreamer") \
|
||||
or match("appindicator","appindicator3")\
|
||||
\
|
||||
or match("libc", "tcmallocminimal") \
|
||||
or match("libc", "ldlinux") \
|
||||
or match("libc", "tbbmallocproxy") \
|
||||
or match("tcmallocminimal","tbbmallocproxy") \
|
||||
:
|
||||
# libc and ldlinux have some "__libc_" data symbols in common... TODO check if ok
|
||||
continue
|
||||
@@ -1056,8 +1058,8 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
memcpy(value+4, v->data, 2*sizeof(double));
|
||||
{rbr}
|
||||
|
||||
void* VulkanFromx86(void* src, void** save);
|
||||
void VulkanTox86(void* src, void* save);
|
||||
void* VulkanFromx86(void* src);
|
||||
void VulkanTox86(void* src);
|
||||
|
||||
#define ST0val ST0.d
|
||||
|
||||
@@ -1247,7 +1249,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N.orig, W, "{"))
|
||||
|
||||
if N.orig == 'vFv':
|
||||
f.write("(void)fcn; ")
|
||||
f.write("(void)emu; ")
|
||||
|
||||
args = N.orig[2:]
|
||||
if args == 'Ev': args = 'E'
|
||||
@@ -1257,7 +1259,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("void* save{d} = NULL; void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d}), &save{d}); ".format(d=delta))
|
||||
f.write("void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d})); ".format(d=delta))
|
||||
if c == 'G':
|
||||
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_ESP + {d})); ".format(d=delta))
|
||||
delta = delta + deltas[FileSpec.values.index(c)]
|
||||
@@ -1265,7 +1267,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
|
||||
f.write("VulkanTox86(arg{d}); ".format(d=delta))
|
||||
if c == 'G':
|
||||
f.write("unalignGValue(*(void**)(R_ESP + {d}), &arg{d}); ".format(d=delta))
|
||||
delta = delta + deltas[FileSpec.values.index(c)]
|
||||
|
||||
+80
-33
@@ -22,6 +22,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include "custommem.h"
|
||||
#include "dictionnary.h"
|
||||
#include "rcfile.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
@@ -48,6 +49,7 @@ void finiAllHelpers(box86context_t* context)
|
||||
static int finied = 0;
|
||||
if(finied)
|
||||
return;
|
||||
DeleteParams();
|
||||
fini_pthread_helper(context);
|
||||
fini_signal_helper();
|
||||
fini_bridge_helper();
|
||||
@@ -74,19 +76,28 @@ void free_tlsdatasize(void* p)
|
||||
if(!p)
|
||||
return;
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)p;
|
||||
free(data->tlsdata);
|
||||
free(p);
|
||||
box_free(data->ptr);
|
||||
box_free(p);
|
||||
}
|
||||
|
||||
int unlockMutex()
|
||||
{
|
||||
int ret = unlockCustommemMutex();
|
||||
int i;
|
||||
#ifdef DYNAREC
|
||||
void* tid = (void*)GetTID();
|
||||
#define GO(A, B) \
|
||||
i = (arm_lock_storeifref2(&A, NULL, 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_once, 5)
|
||||
GO(my_context->mutex_once2, 6)
|
||||
@@ -100,7 +111,6 @@ int unlockMutex()
|
||||
GO(my_context->mutex_thread, 10)
|
||||
GO(my_context->mutex_bridge, 11)
|
||||
#undef GO
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -108,7 +118,7 @@ void relockMutex(int locks)
|
||||
{
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_lock(&A); \
|
||||
mutex_lock(&A); \
|
||||
|
||||
GO(my_context->mutex_once, 5)
|
||||
GO(my_context->mutex_once2, 6)
|
||||
@@ -127,22 +137,29 @@ void relockMutex(int locks)
|
||||
|
||||
static void init_mutexes(box86context_t* context)
|
||||
{
|
||||
|
||||
#ifdef DYNAREC
|
||||
arm_lock_stored(&context->mutex_dyndump, 0);
|
||||
arm_lock_stored(&context->mutex_once, 0);
|
||||
arm_lock_stored(&context->mutex_once2, 0);
|
||||
arm_lock_stored(&context->mutex_trace, 0);
|
||||
arm_lock_stored(&context->mutex_tls, 0);
|
||||
arm_lock_stored(&context->mutex_thread, 0);
|
||||
arm_lock_stored(&context->mutex_bridge, 0);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&context->mutex_once, &attr);
|
||||
pthread_mutex_init(&context->mutex_once2, &attr);
|
||||
pthread_mutex_init(&context->mutex_trace, &attr);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_dyndump, &attr);
|
||||
#else
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, &attr);
|
||||
pthread_mutex_init(&context->mutex_thread, &attr);
|
||||
pthread_mutex_init(&context->mutex_bridge, &attr);
|
||||
pthread_mutex_init(&context->mutex_lock, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void atfork_child_box64context(void)
|
||||
@@ -151,6 +168,31 @@ static void atfork_child_box64context(void)
|
||||
init_mutexes(my_context);
|
||||
}
|
||||
|
||||
void freeCycleLog(box86context_t* ctx)
|
||||
{
|
||||
if(cycle_log) {
|
||||
for(int i=0; i<cycle_log; ++i) {
|
||||
box_free(ctx->log_call[i]);
|
||||
box_free(ctx->log_ret[i]);
|
||||
}
|
||||
box_free(ctx->log_call);
|
||||
box_free(ctx->log_ret);
|
||||
ctx->log_call = NULL;
|
||||
ctx->log_ret = NULL;
|
||||
}
|
||||
}
|
||||
void initCycleLog(box86context_t* context)
|
||||
{
|
||||
if(cycle_log) {
|
||||
context->log_call = (char**)box_calloc(cycle_log, sizeof(char*));
|
||||
context->log_ret = (char**)box_calloc(cycle_log, sizeof(char*));
|
||||
for(int i=0; i<cycle_log; ++i) {
|
||||
context->log_call[i] = (char*)box_calloc(256, 1);
|
||||
context->log_ret[i] = (char*)box_calloc(128, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
box86context_t *NewBox86Context(int argc)
|
||||
{
|
||||
@@ -161,7 +203,9 @@ box86context_t *NewBox86Context(int argc)
|
||||
}
|
||||
#endif
|
||||
// init and put default values
|
||||
box86context_t *context = my_context = (box86context_t*)calloc(1, sizeof(box86context_t));
|
||||
box86context_t *context = my_context = (box86context_t*)box_calloc(1, sizeof(box86context_t));
|
||||
|
||||
initCycleLog(context);
|
||||
|
||||
#ifdef BUILD_LIB
|
||||
context->deferedInit = 0;
|
||||
@@ -176,7 +220,8 @@ box86context_t *NewBox86Context(int argc)
|
||||
context->local_maplib = NewLibrarian(context, 1);
|
||||
context->versym = NewDictionnary();
|
||||
context->system = NewBridge();
|
||||
context->defver = NewDefaultVersion();
|
||||
context->globaldefver = NewDefaultVersion();
|
||||
context->weakdefver = NewDefaultVersion();
|
||||
// create vsyscall
|
||||
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
|
||||
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
|
||||
@@ -188,7 +233,7 @@ box86context_t *NewBox86Context(int argc)
|
||||
context->dlprivate = NewDLPrivate();
|
||||
|
||||
context->argc = argc;
|
||||
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
|
||||
context->argv = (char**)box_calloc(context->argc+1, sizeof(char*));
|
||||
|
||||
init_mutexes(context);
|
||||
pthread_atfork(NULL, NULL, atfork_child_box64context);
|
||||
@@ -230,7 +275,7 @@ void FreeBox86Context(box86context_t** context)
|
||||
for(int i=0; i<ctx->elfsize; ++i) {
|
||||
FreeElfHeader(&ctx->elfs[i]);
|
||||
}
|
||||
free(ctx->elfs);
|
||||
box_free(ctx->elfs);
|
||||
|
||||
FreeFTSMap(ctx);
|
||||
|
||||
@@ -244,16 +289,16 @@ void FreeBox86Context(box86context_t** context)
|
||||
DeleteX86Trace(ctx);
|
||||
|
||||
if(ctx->deferedInitList)
|
||||
free(ctx->deferedInitList);
|
||||
box_free(ctx->deferedInitList);
|
||||
|
||||
free(ctx->argv);
|
||||
/*box_free(ctx->argv);*/
|
||||
|
||||
for (int i=0; i<ctx->envc; ++i)
|
||||
free(ctx->envv[i]);
|
||||
free(ctx->envv);
|
||||
/*for (int i=0; i<ctx->envc; ++i)
|
||||
box_free(ctx->envv[i]);
|
||||
box_free(ctx->envv);*/
|
||||
|
||||
if(ctx->atfork_sz) {
|
||||
free(ctx->atforks);
|
||||
box_free(ctx->atforks);
|
||||
ctx->atforks = NULL;
|
||||
ctx->atfork_sz = ctx->atfork_cap = 0;
|
||||
}
|
||||
@@ -274,10 +319,11 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
FreeDLPrivate(&ctx->dlprivate);
|
||||
|
||||
// free(ctx->stack); // don't free the stack, it's owned by main emu!
|
||||
// box_free(ctx->stack); // don't free the stack, it's owned by main emu!
|
||||
|
||||
free(ctx->fullpath);
|
||||
free(ctx->box86path);
|
||||
box_free(ctx->fullpath);
|
||||
box_free(ctx->box86path);
|
||||
box_free(ctx->bashpath);
|
||||
|
||||
FreeBridge(&ctx->system);
|
||||
|
||||
@@ -285,7 +331,7 @@ void FreeBox86Context(box86context_t** context)
|
||||
freeALProcWrapper(ctx);
|
||||
|
||||
if(ctx->stack_clone)
|
||||
free(ctx->stack_clone);
|
||||
box_free(ctx->stack_clone);
|
||||
|
||||
void* ptr;
|
||||
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
|
||||
@@ -295,7 +341,7 @@ void FreeBox86Context(box86context_t** context)
|
||||
pthread_key_delete(ctx->tlskey);
|
||||
|
||||
if(ctx->tlsdata)
|
||||
free(ctx->tlsdata);
|
||||
box_free(ctx->tlsdata);
|
||||
|
||||
for(int i=0; i<3; ++i) {
|
||||
if(ctx->segtls[i].present) {
|
||||
@@ -308,23 +354,24 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
if(ctx->emu_sig)
|
||||
FreeX86Emu(&ctx->emu_sig);
|
||||
FreeDefaultVersion(&ctx->defver);
|
||||
FreeDefaultVersion(&ctx->globaldefver);
|
||||
FreeDefaultVersion(&ctx->weakdefver);
|
||||
|
||||
finiAllHelpers(ctx);
|
||||
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#else
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
pthread_mutex_destroy(&ctx->mutex_bridge);
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
freeCycleLog(ctx);
|
||||
|
||||
box_free(ctx);
|
||||
}
|
||||
|
||||
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
|
||||
@@ -332,7 +379,7 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
|
||||
if(idx==ctx->elfcap) {
|
||||
// resize...
|
||||
ctx->elfcap += 16;
|
||||
ctx->elfs = (elfheader_t**)realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
|
||||
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
|
||||
}
|
||||
ctx->elfs[idx] = head;
|
||||
ctx->elfsize++;
|
||||
@@ -343,7 +390,7 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
|
||||
int AddTLSPartition(box86context_t* context, int tlssize) {
|
||||
int oldsize = context->tlssize;
|
||||
context->tlssize += tlssize;
|
||||
context->tlsdata = realloc(context->tlsdata, context->tlssize);
|
||||
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
|
||||
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
|
||||
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
|
||||
// clean GS segment for current emu
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
#define __BOX86_VERSION_H_
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 2
|
||||
#define BOX86_REVISION 6
|
||||
#define BOX86_MINOR 3
|
||||
#define BOX86_REVISION 0
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+380
-159
@@ -28,22 +28,34 @@
|
||||
#include "khash.h"
|
||||
|
||||
#define USE_MMAP
|
||||
//#define USE_MMAP_MORE
|
||||
|
||||
// init inside dynablocks.c
|
||||
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
|
||||
static dynablocklist_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
|
||||
static dynablocklist_t* dynmap[DYNAMAP_SIZE] = {0}; // 4G of memory mapped by 4K block
|
||||
static mmaplist_t *mmaplist = NULL;
|
||||
static int mmapsize = 0;
|
||||
static int mmapcap = 0;
|
||||
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
|
||||
static uintptr_t *box86_jumptable[JMPTABL_SIZE];
|
||||
static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
|
||||
// lock addresses
|
||||
KHASH_SET_INIT_INT(lockaddress)
|
||||
static kh_lockaddress_t *lockaddress = NULL;
|
||||
#endif
|
||||
#define MEMPROT_SHIFT 12
|
||||
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
|
||||
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
|
||||
#ifdef DYNAREC
|
||||
static uint8_t hotpages[MEMPROT_SIZE] = {0};
|
||||
#endif
|
||||
static int inited = 0;
|
||||
|
||||
#define PROT_LOCK() mutex_lock(&mutex_blocks)
|
||||
#define PROT_UNLOCK() mutex_unlock(&mutex_blocks)
|
||||
#define PROT_GET(A) memprot[A]
|
||||
#define PROT_SET(A, B) memprot[A] = B
|
||||
#define PROT_SET_IF_0(A, B) if(!memprot[A]) memprot[A] = B
|
||||
|
||||
typedef struct mapmem_s {
|
||||
uintptr_t begin, end;
|
||||
struct mapmem_s *next;
|
||||
@@ -53,13 +65,17 @@ static mapmem_t *mapmem = NULL;
|
||||
|
||||
typedef struct blocklist_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t maxfree;
|
||||
size_t size;
|
||||
} blocklist_t;
|
||||
|
||||
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
|
||||
|
||||
#ifndef DYNAREC
|
||||
static pthread_mutex_t mutex_blocks;
|
||||
#else
|
||||
static uint32_t mutex_blocks;
|
||||
#endif
|
||||
static int n_blocks = 0; // number of blocks for custom malloc
|
||||
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
|
||||
|
||||
@@ -79,6 +95,7 @@ typedef struct blockmark_s {
|
||||
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
|
||||
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
|
||||
|
||||
#ifdef DYNAREC
|
||||
static void printBlock(blockmark_t* b, void* start)
|
||||
{
|
||||
printf_log(LOG_INFO, "========== Block is:\n");
|
||||
@@ -88,6 +105,7 @@ static void printBlock(blockmark_t* b, void* start)
|
||||
} while(b->next.x32);
|
||||
printf_log(LOG_INFO, "===================\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
|
||||
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
|
||||
@@ -110,7 +128,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
|
||||
// get start of block
|
||||
if(start) {
|
||||
blockmark_t *m = (blockmark_t*)start;
|
||||
int maxsize = 0;
|
||||
size_t maxsize = 0;
|
||||
while(m->next.x32) { // while there is a subblock
|
||||
if(!m->next.fill && m->next.size>maxsize) {
|
||||
maxsize = m->next.size;
|
||||
@@ -120,7 +138,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
|
||||
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
|
||||
} else {
|
||||
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
|
||||
int maxsize = 0;
|
||||
size_t maxsize = 0;
|
||||
while(m->prev.x32) { // while there is a subblock
|
||||
if(!m->prev.fill && m->prev.size>maxsize) {
|
||||
maxsize = m->prev.size;
|
||||
@@ -239,7 +257,7 @@ void* customMalloc(size_t size)
|
||||
{
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if(p_blocks[i].maxfree>=size) {
|
||||
size_t rsize = 0;
|
||||
@@ -248,22 +266,23 @@ void* customMalloc(size_t size)
|
||||
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
|
||||
if(rsize==p_blocks[i].maxfree)
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add a new block
|
||||
int i = n_blocks++;
|
||||
p_blocks = (blocklist_t*)realloc(p_blocks, n_blocks*sizeof(blocklist_t));
|
||||
p_blocks = (blocklist_t*)box_realloc(p_blocks, n_blocks*sizeof(blocklist_t));
|
||||
size_t allocsize = MMAPSIZE;
|
||||
if(size+2*sizeof(blockmark_t)>allocsize)
|
||||
allocsize = size+2*sizeof(blockmark_t);
|
||||
#ifdef USE_MMAP
|
||||
#ifdef USE_MMAP_MORE
|
||||
void* p = mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
memset(p, 0, allocsize);
|
||||
setProtection((uintptr_t)p, allocsize, PROT_READ|PROT_WRITE);
|
||||
#else
|
||||
void* p = calloc(1, allocsize);
|
||||
void* p = box_calloc(1, allocsize);
|
||||
#endif
|
||||
p_blocks[i].block = p;
|
||||
p_blocks[i].size = allocsize;
|
||||
@@ -279,7 +298,7 @@ void* customMalloc(size_t size)
|
||||
// alloc 1st block
|
||||
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
return ret;
|
||||
}
|
||||
void* customCalloc(size_t n, size_t size)
|
||||
@@ -294,24 +313,24 @@ void* customRealloc(void* p, size_t size)
|
||||
if(!p)
|
||||
return customMalloc(size);
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if ((addr>(uintptr_t)p_blocks[i].block)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
if(expandBlock(p_blocks[i].block, sub, size)) {
|
||||
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
return p;
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
void* newp = customMalloc(size);
|
||||
memcpy(newp, p, sizeBlock(sub));
|
||||
customFree(p);
|
||||
return newp;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
if(n_blocks)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
|
||||
return customMalloc(size);
|
||||
@@ -321,85 +340,113 @@ void customFree(void* p)
|
||||
if(!p)
|
||||
return;
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
pthread_mutex_lock(&mutex_blocks);
|
||||
mutex_lock(&mutex_blocks);
|
||||
for(int i=0; i<n_blocks; ++i) {
|
||||
if ((addr>(uintptr_t)p_blocks[i].block)
|
||||
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
|
||||
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex_blocks);
|
||||
mutex_unlock(&mutex_blocks);
|
||||
if(n_blocks)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Free\n", (void*)addr);
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
typedef struct mmaplist_s {
|
||||
typedef struct mmapchunk_s {
|
||||
void* block;
|
||||
int maxfree;
|
||||
size_t size;
|
||||
kh_dynablocks_t* dblist;
|
||||
uint8_t* helper;
|
||||
void* first; // first free block, to speed up things
|
||||
int locked; // don't try to add stuff on locked block
|
||||
uint8_t lock; // don't try to add stuff on locked block
|
||||
} mmapchunk_t;
|
||||
#define NCHUNK 64
|
||||
typedef struct mmaplist_s {
|
||||
mmapchunk_t chunks[NCHUNK];
|
||||
mmaplist_t* next;
|
||||
} mmaplist_t;
|
||||
|
||||
mmapchunk_t* addChunk(int mmapsize) {
|
||||
if(!mmaplist)
|
||||
mmaplist = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
|
||||
mmaplist_t* head = mmaplist;
|
||||
int i = mmapsize;
|
||||
while(1) {
|
||||
if(i>=NCHUNK) {
|
||||
i-=NCHUNK;
|
||||
if(!head->next) {
|
||||
head->next = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
|
||||
}
|
||||
head=head->next;
|
||||
} else
|
||||
return &head->chunks[i];
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
|
||||
{
|
||||
// look for free space
|
||||
void* sub = NULL;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
|
||||
mmaplist[i].locked = 1;
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
|
||||
if(rsize==mmaplist[i].maxfree) {
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
mmaplist_t* head = mmaplist;
|
||||
int i = mmapsize;
|
||||
while(head) {
|
||||
const int n = (i>NCHUNK)?NCHUNK:i;
|
||||
i-=n;
|
||||
for(int i=0; i<n; ++i) {
|
||||
mmapchunk_t* chunk = &head->chunks[i];
|
||||
if(chunk->maxfree>=size+sizeof(blockmark_t) && !arm_lock_incif0b(&chunk->lock)) {
|
||||
size_t rsize = 0;
|
||||
sub = getFirstBlock(chunk->block, size, &rsize, chunk->first);
|
||||
if(sub) {
|
||||
uintptr_t ret = (uintptr_t)allocBlock(chunk->block, sub, size, &chunk->first);
|
||||
if(rsize==chunk->maxfree) {
|
||||
chunk->maxfree = getMaxFreeBlock(chunk->block, chunk->size, chunk->first);
|
||||
}
|
||||
kh_dynablocks_t *blocks = chunk->dblist;
|
||||
if(!blocks) {
|
||||
blocks = chunk->dblist = kh_init(dynablocks);
|
||||
kh_resize(dynablocks, blocks, 64);
|
||||
}
|
||||
khint_t k;
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
int size255=(size<256)?size:255;
|
||||
for(size_t j=0; j<size255; ++j)
|
||||
chunk->helper[(uintptr_t)ret-(uintptr_t)(chunk->block)+j] = j;
|
||||
if(size!=size255)
|
||||
memset(&chunk->helper[(uintptr_t)ret-(uintptr_t)(chunk->block)+256], -1, size-255);
|
||||
arm_lock_decifnot0b(&chunk->lock);
|
||||
return ret;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted %p->chunk[%d] info?\n", head, i);
|
||||
arm_lock_decifnot0b(&chunk->lock);
|
||||
if(box86_log >= LOG_DEBUG)
|
||||
printBlock(chunk->block, chunk->first);
|
||||
}
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(!blocks) {
|
||||
blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
kh_resize(dynablocks, blocks, 64);
|
||||
}
|
||||
khint_t k;
|
||||
int r;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
|
||||
kh_value(blocks, k) = db;
|
||||
int size255=(size<256)?size:255;
|
||||
for(size_t j=0; j<size255; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
|
||||
if(size!=size255)
|
||||
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
|
||||
mmaplist[i].locked = 0;
|
||||
return ret;
|
||||
} else {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted mmaplist[%d] info?\n", i);
|
||||
if(box86_log >= LOG_DEBUG)
|
||||
printBlock(mmaplist[i].block, mmaplist[i].first);
|
||||
}
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
{
|
||||
int i = mmapsize++; // yeah, useful post incrementation
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
|
||||
if(mmapsize>mmapcap) {
|
||||
mmapcap += 32;
|
||||
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
|
||||
mmapchunk_t* chunk = addChunk(mmapsize++);
|
||||
arm_lock_incb(&chunk->lock);
|
||||
#ifndef USE_MMAP
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
arm_lock_storeb(&chunk->lock, 0);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
@@ -407,18 +454,18 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
#else
|
||||
void* p = mmap(NULL, MMAPSIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if(p==(void*)-1) {
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
|
||||
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, mmapsize-1);
|
||||
arm_lock_storeb(&chunk->lock, 0);
|
||||
--mmapsize;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
mmaplist[i].locked = 1;
|
||||
mmaplist[i].block = p;
|
||||
mmaplist[i].size = MMAPSIZE;
|
||||
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
|
||||
mmaplist[i].first = p;
|
||||
chunk->block = p;
|
||||
chunk->size = MMAPSIZE;
|
||||
chunk->helper = (uint8_t*)box_calloc(1, MMAPSIZE);
|
||||
chunk->first = p;
|
||||
// setup marks
|
||||
blockmark_t* m = (blockmark_t*)p;
|
||||
m->prev.x32 = 0;
|
||||
@@ -429,17 +476,17 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
|
||||
n->prev.fill = 0;
|
||||
n->prev.size = m->next.size;
|
||||
// alloc 1st block
|
||||
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
|
||||
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
|
||||
uintptr_t sub = (uintptr_t)allocBlock(chunk->block, p, size, &chunk->first);
|
||||
chunk->maxfree = getMaxFreeBlock(chunk->block, chunk->size, chunk->first);
|
||||
kh_dynablocks_t *blocks = chunk->dblist = kh_init(dynablocks);
|
||||
kh_resize(dynablocks, blocks, 64);
|
||||
khint_t k;
|
||||
int ret;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
for(int j=0; j<size; ++j)
|
||||
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
|
||||
mmaplist[i].locked = 0;
|
||||
chunk->helper[(uintptr_t)sub-(uintptr_t)chunk->block + j] = (j<256)?j:255;
|
||||
arm_lock_decifnot0b(&chunk->lock);
|
||||
return sub;
|
||||
}
|
||||
|
||||
@@ -447,25 +494,41 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
{
|
||||
if(!addr || !size)
|
||||
return;
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
if ((addr>(uintptr_t)mmaplist[i].block)
|
||||
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
|
||||
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
|
||||
kh_dynablocks_t *blocks = mmaplist[i].dblist;
|
||||
if(blocks) {
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
|
||||
mmaplist_t* head = mmaplist;
|
||||
int i = mmapsize;
|
||||
while(head) {
|
||||
const int n = (i>NCHUNK)?NCHUNK:i;
|
||||
i-=n;
|
||||
for(int i=0; i<n; ++i) {
|
||||
mmapchunk_t* chunk = &head->chunks[i];
|
||||
if ((addr>(uintptr_t)(chunk->block))
|
||||
&& (addr<((uintptr_t)(chunk->block)+chunk->size))) {
|
||||
int loopedwait = 256;
|
||||
while (arm_lock_incif0b(&chunk->lock) && loopedwait) {
|
||||
sched_yield();
|
||||
--loopedwait;
|
||||
}
|
||||
if(!loopedwait) {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
|
||||
//arm_lock_incb(&chunk->lock);
|
||||
if(cycle_log)
|
||||
print_cycle_log(LOG_INFO);
|
||||
}
|
||||
void* sub = (void*)(addr-sizeof(blockmark_t));
|
||||
size_t newfree = freeBlock(chunk->block, sub, &chunk->first);
|
||||
if(chunk->maxfree < newfree) chunk->maxfree = newfree;
|
||||
kh_dynablocks_t *blocks = chunk->dblist;
|
||||
if(blocks) {
|
||||
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
|
||||
if(k!=kh_end(blocks))
|
||||
kh_del(dynablocks, blocks, k);
|
||||
memset(&chunk->helper[(uintptr_t)sub-(uintptr_t)chunk->block], 0, size);
|
||||
}
|
||||
arm_lock_decifnot0b(&chunk->lock);
|
||||
return;
|
||||
}
|
||||
if(mmaplist[i].locked) {
|
||||
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
|
||||
++mmaplist[i].locked;
|
||||
}
|
||||
return;
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
if(mmapsize)
|
||||
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
|
||||
@@ -474,20 +537,28 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
|
||||
dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
{
|
||||
// look in actual list
|
||||
for(int i=0; i<mmapsize; ++i) {
|
||||
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
|
||||
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) {
|
||||
if(!mmaplist[i].helper)
|
||||
return FindDynablockDynablocklist(addr, mmaplist[i].dblist);
|
||||
else {
|
||||
uintptr_t p = (uintptr_t)addr - (uintptr_t)mmaplist[i].block;
|
||||
while(mmaplist[i].helper[p]) p -= mmaplist[i].helper[p];
|
||||
khint_t k = kh_get(dynablocks, mmaplist[i].dblist, (uintptr_t)mmaplist[i].block + p);
|
||||
if(k!=kh_end(mmaplist[i].dblist))
|
||||
return kh_value(mmaplist[i].dblist, k);
|
||||
return NULL;
|
||||
mmaplist_t* head = mmaplist;
|
||||
int i = mmapsize;
|
||||
while(head) {
|
||||
const int n = (i>NCHUNK)?NCHUNK:i;
|
||||
i-=n;
|
||||
for(int i=0; i<n; ++i) {
|
||||
mmapchunk_t* chunk = &head->chunks[i];
|
||||
if ((uintptr_t)addr>=(uintptr_t)chunk->block
|
||||
&& ((uintptr_t)addr<(uintptr_t)chunk->block+chunk->size)) {
|
||||
if(!chunk->helper)
|
||||
return FindDynablockDynablocklist(addr, chunk->dblist);
|
||||
else {
|
||||
uintptr_t p = (uintptr_t)addr - (uintptr_t)chunk->block;
|
||||
while(chunk->helper[p]) p -= chunk->helper[p];
|
||||
khint_t k = kh_get(dynablocks, chunk->dblist, (uintptr_t)chunk->block + p);
|
||||
if(k!=kh_end(chunk->dblist))
|
||||
return kh_value(chunk->dblist, k);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
// look in oversized
|
||||
return FindDynablockDynablocklist(addr, dblist_oversized);
|
||||
@@ -538,7 +609,7 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
|
||||
return;
|
||||
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
|
||||
#ifndef USE_MMAP
|
||||
free((void*)addr);
|
||||
box_free((void*)addr);
|
||||
#else
|
||||
munmap((void*)addr, size);
|
||||
#endif
|
||||
@@ -568,7 +639,7 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
if(!dynmap[i]) {
|
||||
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
|
||||
if(arm_lock_storeifnull(&dynmap[i], p)!=p)
|
||||
if(arm_lock_storeifnull(&dynmap[i], p)!=NULL)
|
||||
FreeDynablockList(&p);
|
||||
}
|
||||
}
|
||||
@@ -580,11 +651,14 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
dynablocklist_t* dblist = dynmap[i];
|
||||
int need_free = (destroy && addr<=(i<<DYNAMAP_SHIFT) && end>=((i+1)>>DYNAMAP_SHIFT)-1)?1:0;
|
||||
dynablocklist_t* dblist = (need_free)?((dynablocklist_t*)arm_lock_xchg(&dynmap[i], 0)):dynmap[i];
|
||||
if(dblist) {
|
||||
if(destroy)
|
||||
if(destroy) {
|
||||
FreeRangeDynablock(dblist, addr, size);
|
||||
else
|
||||
if(need_free)
|
||||
FreeDynablockList(&dblist);
|
||||
} else
|
||||
MarkRangeDynablock(dblist, addr, size);
|
||||
}
|
||||
}
|
||||
@@ -598,11 +672,11 @@ void addJumpTableIfDefault(void* addr, void* jmp)
|
||||
{
|
||||
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
|
||||
if(box86_jumptable[idx] == box86_jmptbl_default) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm_next;
|
||||
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
|
||||
free(tbl);
|
||||
box_free(tbl);
|
||||
}
|
||||
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
|
||||
arm_lock_storeifref(&box86_jumptable[idx][off], jmp, arm_next);
|
||||
@@ -634,11 +708,11 @@ uintptr_t getJumpTableAddress(uintptr_t addr)
|
||||
{
|
||||
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
|
||||
if(box86_jumptable[idx] == box86_jmptbl_default) {
|
||||
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
|
||||
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
|
||||
tbl[i] = (uintptr_t)arm_next;
|
||||
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
|
||||
free(tbl);
|
||||
box_free(tbl);
|
||||
}
|
||||
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
|
||||
return (uintptr_t)&box86_jumptable[idx][off];
|
||||
@@ -651,32 +725,60 @@ void protectDB(uintptr_t addr, uintptr_t size)
|
||||
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
PROT_LOCK();
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
if(!(prot&PROT_DYNAREC)) {
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
|
||||
memprot[i] = prot|PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
}
|
||||
uint32_t prot = PROT_GET(i);
|
||||
uint32_t dyn = prot&PROT_CUSTOM;
|
||||
prot&=~PROT_CUSTOM;
|
||||
if(!prot)
|
||||
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
|
||||
if(prot&PROT_WRITE) {
|
||||
PROT_SET(i, prot|PROT_DYNAREC);
|
||||
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
} else
|
||||
PROT_SET(i, prot|PROT_DYNAREC_R);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
// Add the Write flag from an adress range, and mark all block as dirty
|
||||
// no log, as it can be executed inside a signal handler
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size)
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p (mark=%d)\n", (void*)addr, (void*)(addr+size-1), mark);
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
PROT_LOCK();
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = memprot[i];
|
||||
uint32_t prot = PROT_GET(i);
|
||||
if(prot&PROT_DYNAREC) {
|
||||
memprot[i] = prot&~PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
PROT_SET(i, prot&~PROT_CUSTOM);
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
if(mark)
|
||||
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
|
||||
} else if(prot&PROT_DYNAREC_R)
|
||||
PROT_SET(i, prot&~PROT_CUSTOM);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
int isprotectedDB(uintptr_t addr, size_t size)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
PROT_LOCK();
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t prot = PROT_GET(i);
|
||||
if(!(prot&(PROT_DYNAREC|PROT_DYNAREC_R))) {
|
||||
dynarec_log(LOG_DEBUG, "0\n");
|
||||
PROT_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "1\n");
|
||||
PROT_UNLOCK();
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -685,13 +787,15 @@ void printMapMem()
|
||||
{
|
||||
mapmem_t* m = mapmem;
|
||||
while(m) {
|
||||
printf_log(LOG_INFO, " %p-%p\n", (void*)m->begin, (void*)m->end);
|
||||
printf_log(LOG_NONE, " %p-%p\n", (void*)m->begin, (void*)m->end);
|
||||
m = m->next;
|
||||
}
|
||||
}
|
||||
|
||||
void addMapMem(uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
begin &=~0xfff;
|
||||
end = (end&~0xfff)+0xfff; // full page
|
||||
// sanitize values
|
||||
@@ -711,7 +815,7 @@ void addMapMem(uintptr_t begin, uintptr_t end)
|
||||
newm = m;
|
||||
} else {
|
||||
// create a new block
|
||||
newm = (mapmem_t*)calloc(1, sizeof(mapmem_t));
|
||||
newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
newm->next = m->next;
|
||||
newm->begin = begin;
|
||||
newm->end = end;
|
||||
@@ -723,12 +827,14 @@ void addMapMem(uintptr_t begin, uintptr_t end)
|
||||
newm->end = newm->next->end;
|
||||
mapmem_t* tmp = newm->next;
|
||||
newm->next = tmp->next;
|
||||
free(tmp);
|
||||
box_free(tmp);
|
||||
}
|
||||
// all done!
|
||||
}
|
||||
void removeMapMem(uintptr_t begin, uintptr_t end)
|
||||
{
|
||||
if(!mapmem)
|
||||
return;
|
||||
begin &=~0xfff;
|
||||
end = (end&~0xfff)+0xfff; // full page
|
||||
// sanitize values
|
||||
@@ -751,9 +857,9 @@ void removeMapMem(uintptr_t begin, uintptr_t end)
|
||||
m = mapmem;
|
||||
prev = NULL;
|
||||
}
|
||||
free(tmp);
|
||||
box_free(tmp);
|
||||
} else if(begin>m->begin && end<m->end) { // the zone is totaly inside the block => split it!
|
||||
mapmem_t* newm = (mapmem_t*)calloc(1, sizeof(mapmem_t)); // create a new "next"
|
||||
mapmem_t* newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t)); // create a new "next"
|
||||
newm->end = m->end;
|
||||
m->end = begin - 1;
|
||||
newm->begin = end + 1;
|
||||
@@ -773,64 +879,82 @@ void removeMapMem(uintptr_t begin, uintptr_t end)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
PROT_LOCK();
|
||||
addMapMem(addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
uint32_t dyn=(memprot[i]&PROT_DYNAREC);
|
||||
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
|
||||
uint32_t dyn=(PROT_GET(i)&(PROT_DYNAREC|PROT_DYNAREC_R));
|
||||
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
|
||||
dyn = PROT_DYNAREC;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
|
||||
memprot[i] = prot|dyn;
|
||||
} else if(dyn && !(prot&PROT_WRITE)) {
|
||||
dyn = PROT_DYNAREC_R;
|
||||
}
|
||||
PROT_SET(i, prot|dyn);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "forceProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
PROT_LOCK();
|
||||
addMapMem(addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
|
||||
memprot[i] = prot;
|
||||
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
|
||||
PROT_SET(i, prot);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
|
||||
PROT_LOCK();
|
||||
addMapMem(addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
memprot[i] = prot;
|
||||
PROT_SET(i, prot);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
void freeProtection(uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
PROT_LOCK();
|
||||
removeMapMem(addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
memprot[i] = 0;
|
||||
PROT_SET(i, 0);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
uint32_t getProtection(uintptr_t addr)
|
||||
{
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
uint32_t ret = memprot[idx];
|
||||
PROT_LOCK();
|
||||
uint32_t ret = PROT_GET(idx);
|
||||
PROT_UNLOCK();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void allocProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
|
||||
{
|
||||
PROT_LOCK();
|
||||
addMapMem(addr, addr+size-1);
|
||||
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
|
||||
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
if(!memprot[i])
|
||||
memprot[i] = prot;
|
||||
PROT_SET_IF_0(i, prot);
|
||||
}
|
||||
PROT_UNLOCK();
|
||||
}
|
||||
|
||||
void loadProtectionFromMap()
|
||||
@@ -840,6 +964,7 @@ void loadProtectionFromMap()
|
||||
char buf[500];
|
||||
FILE *f = fopen("/proc/self/maps", "r");
|
||||
uintptr_t current = 0x0;
|
||||
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "Refresh mmap allocated block start =============\n");}
|
||||
if(!f)
|
||||
return;
|
||||
while(!feof(f)) {
|
||||
@@ -847,7 +972,8 @@ void loadProtectionFromMap()
|
||||
(void)ret;
|
||||
char r, w, x;
|
||||
uintptr_t s, e;
|
||||
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
|
||||
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "\t%s", buf);}
|
||||
if(sscanf(buf, "%x-%x %c%c%c", &s, &e, &r, &w, &x)==5) {
|
||||
if(current<s) {
|
||||
removeMapMem(current, s-1);
|
||||
current = e;
|
||||
@@ -857,11 +983,16 @@ void loadProtectionFromMap()
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {
|
||||
printf_log(LOG_NONE, "Refresh mmap allocated block done =============\n");
|
||||
printMapMem();
|
||||
}
|
||||
box86_mapclean = 1;
|
||||
}
|
||||
|
||||
#define LOWEST (void*)0x10000
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
#define MEDIAN (void*)0x40000000
|
||||
static void* findBlockHinted(void* hint, size_t size)
|
||||
{
|
||||
mapmem_t* m = mapmem;
|
||||
uintptr_t h = (uintptr_t)hint;
|
||||
@@ -874,24 +1005,80 @@ void* findBlockNearHint(void* hint, size_t size)
|
||||
return hint;
|
||||
if(addr>=h && end-addr+1>=size)
|
||||
return (void*)addr;
|
||||
if(end>=0xc0000000 && h<0xc0000000)
|
||||
return NULL;
|
||||
m = m->next;
|
||||
}
|
||||
return hint;
|
||||
return NULL;
|
||||
}
|
||||
void* findBlockNearHint(void* hint, size_t size)
|
||||
{ void* ret = findBlockHinted(hint, size);
|
||||
return ret?ret:hint;
|
||||
}
|
||||
void* find32bitBlock(size_t size)
|
||||
{
|
||||
return findBlockNearHint(LOWEST, size);
|
||||
void* ret = findBlockHinted(MEDIAN, size);
|
||||
if(!ret) ret = findBlockHinted(LOWEST, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
int IsInHotPage(uintptr_t addr) {
|
||||
if(addr<=(1LL<<48))
|
||||
return 0;
|
||||
int idx = (addr>>MEMPROT_SHIFT);
|
||||
if(!hotpages[idx])
|
||||
return 0;
|
||||
// decrement hot
|
||||
arm_lock_decifnot0b(&hotpages[idx]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int AreaInHotPage(uintptr_t start, uintptr_t end_) {
|
||||
uintptr_t idx = (start>>MEMPROT_SHIFT);
|
||||
uintptr_t end = (end_>>MEMPROT_SHIFT);
|
||||
if(end<idx) { // memory addresses higher than 48bits are not tracked
|
||||
return 0;
|
||||
}
|
||||
int ret = 0;
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
if(hotpages[idx]) {
|
||||
// decrement hot
|
||||
arm_lock_decifnot0b(&hotpages[idx]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
if(ret && box86_dynarec_log>LOG_INFO)
|
||||
dynarec_log(LOG_DEBUG, "BOX86: AreaInHotPage %p-%p\n", (void*)start, (void*)end_);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void AddHotPage(uintptr_t addr) {
|
||||
int idx = (addr>>MEMPROT_SHIFT);
|
||||
arm_lock_storeb(&hotpages[idx], box86_dynarec_hotpage);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int unlockCustommemMutex()
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
#ifdef DYNAREC
|
||||
void* tid = (void*)GetTID();
|
||||
#define GO(A, B) \
|
||||
i = (arm_lock_storeifref2(&A, NULL, (void*)tid)==tid); \
|
||||
if(i) { \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
#else
|
||||
#define GO(A, B) \
|
||||
i = checkUnlockMutex(&A); \
|
||||
if(i) { \
|
||||
ret|=(1<<B); \
|
||||
}
|
||||
#endif
|
||||
GO(mutex_blocks, 0)
|
||||
#undef GO
|
||||
return ret;
|
||||
@@ -901,7 +1088,7 @@ void relockCustommemMutex(int locks)
|
||||
{
|
||||
#define GO(A, B) \
|
||||
if(locks&(1<<B)) \
|
||||
pthread_mutex_lock(&A); \
|
||||
mutex_lock(&A); \
|
||||
|
||||
GO(mutex_blocks, 0)
|
||||
#undef GO
|
||||
@@ -909,12 +1096,16 @@ void relockCustommemMutex(int locks)
|
||||
|
||||
static void init_mutexes(void)
|
||||
{
|
||||
#ifdef DYNAREC
|
||||
arm_lock_stored(&mutex_blocks, 0);
|
||||
#else
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&mutex_blocks, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void atfork_child_custommem(void)
|
||||
@@ -925,6 +1116,7 @@ static void atfork_child_custommem(void)
|
||||
|
||||
void init_custommem_helper(box86context_t* ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(inited) // already initialized
|
||||
return;
|
||||
inited = 1;
|
||||
@@ -938,10 +1130,11 @@ void init_custommem_helper(box86context_t* ctx)
|
||||
#else
|
||||
#error Unsupported architecture!
|
||||
#endif
|
||||
lockaddress = kh_init(lockaddress);
|
||||
#endif
|
||||
pthread_atfork(NULL, NULL, atfork_child_custommem);
|
||||
// init mapmem list
|
||||
mapmem = (mapmem_t*)calloc(1, sizeof(mapmem_t));
|
||||
mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
|
||||
mapmem->begin = 0x0;
|
||||
mapmem->end = (uintptr_t)LOWEST - 1;
|
||||
loadProtectionFromMap();
|
||||
@@ -949,57 +1142,85 @@ void init_custommem_helper(box86context_t* ctx)
|
||||
|
||||
void fini_custommem_helper(box86context_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
if(!inited)
|
||||
return;
|
||||
inited = 0;
|
||||
#ifdef DYNAREC
|
||||
if(box86_dynarec) {
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
for (int i=0; i<mmapsize; ++i) {
|
||||
if(mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(mmaplist[i].block, mmaplist[i].size);
|
||||
#else
|
||||
free(mmaplist[i].block);
|
||||
#endif
|
||||
if(mmaplist[i].dblist) {
|
||||
kh_destroy(dynablocks, mmaplist[i].dblist);
|
||||
mmaplist[i].dblist = NULL;
|
||||
}
|
||||
if(mmaplist[i].helper) {
|
||||
free(mmaplist[i].helper);
|
||||
mmaplist[i].helper = NULL;
|
||||
mmaplist_t* head = mmaplist;
|
||||
mmaplist = NULL;
|
||||
while(head) {
|
||||
for (int i=0; i<NCHUNK; ++i) {
|
||||
if(head->chunks[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(head->chunks[i].block, head->chunks[i].size);
|
||||
#else
|
||||
box_free(head->chunks[i].block);
|
||||
#endif
|
||||
if(head->chunks[i].dblist) {
|
||||
kh_destroy(dynablocks, head->chunks[i].dblist);
|
||||
head->chunks[i].dblist = NULL;
|
||||
}
|
||||
if(head->chunks[i].helper) {
|
||||
box_free(head->chunks[i].helper);
|
||||
head->chunks[i].helper = NULL;
|
||||
}
|
||||
}
|
||||
mmaplist_t *old = head;
|
||||
head = head->next;
|
||||
free(old);
|
||||
}
|
||||
if(dblist_oversized) {
|
||||
kh_destroy(dynablocks, dblist_oversized);
|
||||
dblist_oversized = NULL;
|
||||
}
|
||||
mmapsize = 0;
|
||||
mmapcap = 0;
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
uintptr_t idx = 0;
|
||||
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i)
|
||||
if(dynmap[i])
|
||||
FreeDynablockList(&dynmap[i]);
|
||||
free(mmaplist);
|
||||
box_free(mmaplist);
|
||||
for (int i=0; i<DYNAMAP_SIZE; ++i)
|
||||
if(box86_jumptable[i]!=box86_jmptbl_default)
|
||||
free(box86_jumptable[i]);
|
||||
box_free(box86_jumptable[i]);
|
||||
}
|
||||
kh_destroy(lockaddress, lockaddress);
|
||||
lockaddress = NULL;
|
||||
#endif
|
||||
for(int i=0; i<n_blocks; ++i)
|
||||
#ifdef USE_MMAP
|
||||
#ifdef USE_MMAP_MORE
|
||||
munmap(p_blocks[i].block, p_blocks[i].size);
|
||||
#else
|
||||
free(p_blocks[i].block);
|
||||
box_free(p_blocks[i].block);
|
||||
#endif
|
||||
free(p_blocks);
|
||||
box_free(p_blocks);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&mutex_blocks);
|
||||
#endif
|
||||
while(mapmem) {
|
||||
mapmem_t *tmp = mapmem;
|
||||
mapmem = mapmem->next;
|
||||
free(tmp);
|
||||
box_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DYNAREC
|
||||
// add an address to the list of "LOCK"able
|
||||
void addLockAddress(uintptr_t addr)
|
||||
{
|
||||
int ret;
|
||||
kh_put(lockaddress, lockaddress, addr, &ret);
|
||||
}
|
||||
|
||||
// return 1 is the address is used as a LOCK, 0 else
|
||||
int isLockAddress(uintptr_t addr)
|
||||
{
|
||||
khint_t k = kh_get(lockaddress, lockaddress, addr);
|
||||
return (k==kh_end(lockaddress))?0:1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -464,7 +464,6 @@ Op is 20-27
|
||||
#define LDRH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
|
||||
#define LDRH_IMM8_COND(cond, reg, addr, imm8) EMIT(HWS_OFF(cond, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
|
||||
#define STRH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
|
||||
#define STRSH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 1, 1, abs(imm8)))
|
||||
|
||||
#define LDRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 1, addr, reg, 0, 1, rm))
|
||||
#define STRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 0, addr, reg, 0, 1, rm))
|
||||
@@ -793,6 +792,8 @@ Op is 20-27
|
||||
#define VNEG_F64_cond(cond, Dd, Dm) EMIT((cond) | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
// Neg F32 Dd = - Dm
|
||||
#define VNEG_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
// Neg F32 Dd = - Dm
|
||||
#define VNEG_F32_cond(cond, Sd, Sm) EMIT((cond) | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
|
||||
// Sqrt F64 Dd = - Dm
|
||||
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
@@ -819,6 +820,8 @@ Op is 20-27
|
||||
#define VLD1_32(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 15))
|
||||
// Load [Rn]! => Dd. Align is 4
|
||||
#define VLD1_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
|
||||
// Load [Rn]! => Dd. Align is 8
|
||||
#define VLD1_64_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
|
||||
// Load [Rn]! => Dd/Dd+1. Align is 4
|
||||
#define VLD1Q_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 13))
|
||||
// Load [Rn, Rm]! => Dd/Dd+1. If Rm==15, no writeback, Rm ignored, else writeback Rn <- Rn+Rm. Align is 4
|
||||
@@ -840,6 +843,8 @@ Op is 20-27
|
||||
|
||||
// Store [Rn]! => Dd. Align is 4
|
||||
#define VST1_32_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
|
||||
// Store [Rn]! => Dd. Align is 8
|
||||
#define VST1_64_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
|
||||
// Store [Rn] => Dd/Dd+1. Align is 4
|
||||
#define VST1Q_32(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 15))
|
||||
// Store [Rn]! => Dd/Dd+1. Align is 4
|
||||
|
||||
+101
-10
@@ -16,7 +16,14 @@
|
||||
.global arm_lock_xchg
|
||||
.global arm_lock_storeifnull
|
||||
.global arm_lock_storeifref
|
||||
|
||||
.global arm_lock_storeifref2
|
||||
.global arm_lock_decifnot0b
|
||||
.global arm_lock_incb
|
||||
.global arm_lock_incif0b
|
||||
.global arm_lock_stored
|
||||
.global arm_lock_storeb
|
||||
.global arm_lock_storeif0b
|
||||
.global arm_lock_readb
|
||||
|
||||
arm_lock_read_b:
|
||||
// address is r0, return is r0
|
||||
@@ -83,33 +90,117 @@ arm_lock_xchg:
|
||||
bx lr
|
||||
|
||||
arm_lock_storeifnull:
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return old [r0] value
|
||||
// r0 needs to be aligned
|
||||
dmb ish
|
||||
ldrex r2, [r0]
|
||||
cmp r2, #0
|
||||
bne arm_lock_storeifnull_exit
|
||||
mov r2, r1
|
||||
strex r3, r2, [r0]
|
||||
strex r3, r1, [r0]
|
||||
cmp r3, #1
|
||||
beq arm_lock_storeifnull
|
||||
arm_lock_storeifnull_exit:
|
||||
mov r0, r2
|
||||
bx lr
|
||||
|
||||
arm_lock_storeifref2:
|
||||
dmb ish
|
||||
arm_lock_storeifref2_loop:
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return old [r0] value (so r2 or old value)
|
||||
ldrex r3, [r0]
|
||||
cmp r3, r2
|
||||
movne r0, r3
|
||||
bne arm_lock_storeifref2_exit
|
||||
strex r3, r1, [r0]
|
||||
cmp r3, #1
|
||||
beq arm_lock_storeifref_loop
|
||||
mov r0, r2
|
||||
arm_lock_storeifref2_exit:
|
||||
bx lr
|
||||
|
||||
arm_lock_storeifref:
|
||||
push {r4}
|
||||
dmb ish
|
||||
arm_lock_storeifref_loop:
|
||||
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return new [r0] value (so r1 or old value)
|
||||
ldrex r3, [r0]
|
||||
cmp r3, r2
|
||||
movne r0, r3
|
||||
bne arm_lock_storeifref_exit
|
||||
mov r3, r1
|
||||
strex r4, r3, [r0]
|
||||
cmp r4, #1
|
||||
strex r3, r1, [r0]
|
||||
cmp r3, #1
|
||||
beq arm_lock_storeifref_loop
|
||||
mov r0, r1
|
||||
arm_lock_storeifref_exit:
|
||||
mov r0, r3
|
||||
pop {r4}
|
||||
bx lr
|
||||
|
||||
arm_lock_decifnot0b:
|
||||
dmb ish
|
||||
arm_lock_decifnot0b_0:
|
||||
ldrexb r1, [r0]
|
||||
cmp r1, #0
|
||||
subne r3, r1, #1
|
||||
moveq r3, r1
|
||||
strexb r2, r3, [r0]
|
||||
cmp r2, #1
|
||||
beq arm_lock_decifnot0b_0
|
||||
dmb ish
|
||||
mov r0, r1
|
||||
bx lr
|
||||
|
||||
arm_lock_incb:
|
||||
dmb ish
|
||||
arm_lock_incb_0:
|
||||
ldrexb r1, [r0]
|
||||
add r1, r1, #1
|
||||
strexb r2, r1, [r0]
|
||||
cmp r2, #1
|
||||
beq arm_lock_incb_0
|
||||
arm_lock_incb_exit:
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_incif0b:
|
||||
dmb ish
|
||||
arm_lock_incif0b_0:
|
||||
ldrexb r1, [r0]
|
||||
cmp r1, #0
|
||||
addeq r3, r1, #1
|
||||
movne r3, r1
|
||||
strexb r2, r3, [r0]
|
||||
cmp r2, #1
|
||||
beq arm_lock_incif0b_0
|
||||
dmb ish
|
||||
mov r0, r1
|
||||
bx lr
|
||||
|
||||
arm_lock_stored:
|
||||
dmb ish
|
||||
str r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeb:
|
||||
dmb ish
|
||||
strb r1, [r0]
|
||||
dmb ish
|
||||
bx lr
|
||||
|
||||
arm_lock_storeif0b:
|
||||
dmb ish
|
||||
arm_lock_storeif0b_0:
|
||||
ldrexb r2, [r0]
|
||||
cmp r2, #0
|
||||
bne arm_lock_storeif0b_exit
|
||||
strexb r3, r1, [r0]
|
||||
cmp r3, #1
|
||||
beq arm_lock_storeif0b_0
|
||||
mov r2, #0
|
||||
dmb ish
|
||||
arm_lock_storeif0b_exit:
|
||||
mov r0, r2
|
||||
bx lr
|
||||
|
||||
arm_lock_readb:
|
||||
dmb ish
|
||||
ldrb r0, [r0]
|
||||
bx lr
|
||||
@@ -25,10 +25,34 @@ extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
|
||||
// Atomically exchange value at [p] with val, return old p
|
||||
extern uintptr_t arm_lock_xchg(void* p, uintptr_t val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
|
||||
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
|
||||
extern void* arm_lock_storeifnull(void* p, void* val);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
|
||||
extern void* arm_lock_storeifref(void* p, void* val, void* ref);
|
||||
|
||||
// Atomically store value to [p] only if [p] is ref. Return old [p] value
|
||||
extern void* arm_lock_storeifref2(void* p, void* val, void* ref);
|
||||
|
||||
// decrement atomicaly the byte at [p] (but only if p not 0). Return old [p] value
|
||||
extern int arm_lock_decifnot0b(void*p);
|
||||
|
||||
// increment atomicaly the byte at [p]
|
||||
extern void arm_lock_incb(void*p);
|
||||
|
||||
// increment atomicaly the byte at [p] only if it was 0. Return the old value of [p]
|
||||
extern int arm_lock_incif0b(void*p);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm_lock_stored(void*p, uint32_t d);
|
||||
|
||||
// atomic store (with memory barrier)
|
||||
extern void arm_lock_storeb(void*p, uint8_t b);
|
||||
|
||||
// atomic store (with memory barrier) only if it was 0. Return the old value of [p]
|
||||
extern int arm_lock_storeif0b(void*p, uint8_t b);
|
||||
|
||||
// atomic load (with memory barrier)
|
||||
extern int arm_lock_readb(void*p);
|
||||
|
||||
#endif //__ARM_LOCK_HELPER__H__
|
||||
@@ -1,5 +1,5 @@
|
||||
/******************************************************************
|
||||
* File automatically generated by rebuild_printer.py (v1.2.0.05) *
|
||||
* File automatically generated by rebuild_printer.py (v1.2.0.06) *
|
||||
******************************************************************/
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
+37
-28
@@ -20,6 +20,7 @@
|
||||
#include "dynablock_private.h"
|
||||
#include "dynarec_private.h"
|
||||
#include "elfloader.h"
|
||||
#include "bridge.h"
|
||||
#ifdef ARM
|
||||
#include "dynarec_arm.h"
|
||||
#include "arm_lock_helper.h"
|
||||
@@ -46,11 +47,11 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
|
||||
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
|
||||
return NULL;
|
||||
}
|
||||
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
|
||||
dynablocklist_t* ret = (dynablocklist_t*)box_calloc(1, sizeof(dynablocklist_t));
|
||||
ret->text = text;
|
||||
ret->textsz = textsz;
|
||||
if(direct && textsz) {
|
||||
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
|
||||
ret->direct = (dynablock_t**)box_calloc(textsz, sizeof(dynablock_t*));
|
||||
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
|
||||
@@ -64,7 +65,7 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
return; // already in the process of deletion!
|
||||
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0;
|
||||
db->gone = 1;
|
||||
// remove from direct if there
|
||||
@@ -86,12 +87,12 @@ void FreeDynablock(dynablock_t* db, int need_lock)
|
||||
if(!db->father) {
|
||||
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
|
||||
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
|
||||
free(db->sons);
|
||||
free(db->instsize);
|
||||
box_free(db->sons);
|
||||
box_free(db->instsize);
|
||||
}
|
||||
free(db);
|
||||
box_free(db);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,11 +108,11 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
|
||||
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
|
||||
}
|
||||
free((*dynablocks)->direct);
|
||||
box_free((*dynablocks)->direct);
|
||||
}
|
||||
(*dynablocks)->direct = NULL;
|
||||
|
||||
free(*dynablocks);
|
||||
box_free(*dynablocks);
|
||||
*dynablocks = NULL;
|
||||
}
|
||||
|
||||
@@ -177,6 +178,7 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
return;
|
||||
|
||||
if(dynablocks->direct) {
|
||||
int need_lock = my_context?1:0;
|
||||
dynablock_t* db;
|
||||
int ret;
|
||||
khint_t k;
|
||||
@@ -206,7 +208,7 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db, 1);
|
||||
FreeDynablock(db, need_lock);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
}
|
||||
@@ -273,23 +275,21 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
|
||||
if (!*created)
|
||||
return block;
|
||||
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(!dynablocks->direct) {
|
||||
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
|
||||
free(p); // someone already create the direct array, too late...
|
||||
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
|
||||
if(arm_lock_storeifnull(&dynablocks->direct, p)!=NULL)
|
||||
box_free(p); // someone already create the direct array, too late...
|
||||
}
|
||||
|
||||
// create and add new block
|
||||
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
|
||||
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
|
||||
block->parent = dynablocks;
|
||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], block, NULL);
|
||||
if(tmp != block) {
|
||||
// a block appeard!
|
||||
free(block);
|
||||
box_free(block);
|
||||
*created = 0;
|
||||
return tmp;
|
||||
}
|
||||
@@ -311,6 +311,8 @@ void cancelFillBlock()
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
|
||||
{
|
||||
if(hasAlternate((void*)addr))
|
||||
return NULL;
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
dynablock_t* block = NULL;
|
||||
@@ -334,23 +336,26 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
return block;
|
||||
|
||||
int created = create;
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
block = AddNewDynablock(dynablocks, addr, &created);
|
||||
if(!created)
|
||||
if(!created) {
|
||||
if(need_lock)
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return block; // existing block...
|
||||
}
|
||||
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
if(need_lock)
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
|
||||
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
return NULL;
|
||||
}
|
||||
void* ret = FillBlock(block, filladdr);
|
||||
if(need_lock)
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
if(!ret) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
void* old = (void*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
|
||||
@@ -358,7 +363,7 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
|
||||
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
|
||||
// Doing nothing else, the block has not been written
|
||||
}
|
||||
free(block);
|
||||
box_free(block);
|
||||
block = NULL;
|
||||
}
|
||||
// check size
|
||||
@@ -392,7 +397,11 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_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->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
@@ -413,7 +422,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -424,7 +433,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
|
||||
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
|
||||
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
|
||||
if(mutex_trylock(&my_context->mutex_dyndump))
|
||||
return NULL;
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
@@ -442,7 +451,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
for(int i=0; i<father->sons_size; ++i)
|
||||
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
@@ -4,8 +4,8 @@
|
||||
typedef struct dynablocklist_s dynablocklist_t;
|
||||
|
||||
typedef struct instsize_s {
|
||||
unsigned int x86:4;
|
||||
unsigned int nat:4;
|
||||
unsigned char x86:4;
|
||||
unsigned char nat:4;
|
||||
} instsize_t;
|
||||
|
||||
typedef struct dynablock_s {
|
||||
|
||||
@@ -168,6 +168,7 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
}
|
||||
|
||||
int my_setcontext(x86emu_t* emu, void* ucp);
|
||||
int DynaRun(x86emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
@@ -229,6 +230,10 @@ int DynaRun(x86emu_t* emu)
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
else if(emu->quit && emu->uc_link) {
|
||||
emu->quit = 0;
|
||||
my_setcontext(emu, emu->uc_link);
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear the setjmp
|
||||
|
||||
+119
-154
@@ -29,15 +29,15 @@ void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const cha
|
||||
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
|
||||
uint32_t a = *(uint32_t*)(ip+3);
|
||||
if(a==0) {
|
||||
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
|
||||
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
|
||||
} else {
|
||||
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
|
||||
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
|
||||
}
|
||||
} else {
|
||||
if(dec) {
|
||||
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[1m":"", ip, DecodeX86Trace(dec, inst->addr));
|
||||
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[01;33m":"", ip, DecodeX86Trace(dec, inst->addr));
|
||||
} else {
|
||||
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[1m":"", ip);
|
||||
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[01;33m":"", ip);
|
||||
for(int i=0; i<inst->size; ++i) {
|
||||
dynarec_log(LOG_NONE, "%02X ", ip[i]);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
|
||||
// add slots
|
||||
if(dyn->next_sz == dyn->next_cap) {
|
||||
dyn->next_cap += 16;
|
||||
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
dyn->next = (uintptr_t*)box_realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
|
||||
}
|
||||
dyn->next[dyn->next_sz++] = addr;
|
||||
}
|
||||
@@ -100,7 +100,9 @@ int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
return 1;
|
||||
if(PK(0)==0x90)
|
||||
return is_nops(dyn, addr+1, n-1);
|
||||
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
|
||||
if(n>1 && PK(0)==0x2E) // if opcode start with 0x2E, and there is more after, than this *can* be a NOP
|
||||
return is_nops(dyn, addr+1, n-1);
|
||||
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than this *can* be a NOP
|
||||
return is_nops(dyn, addr+1, n-1);
|
||||
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
|
||||
return is_nops(dyn, addr+3, n-3);
|
||||
@@ -249,7 +251,7 @@ static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86
|
||||
toadd = 1 + arm_size/15;
|
||||
if((*size)+toadd>(*cap)) {
|
||||
*cap = (*size)+toadd;
|
||||
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
|
||||
insts = (instsize_t*)box_realloc(insts, (*cap)*sizeof(instsize_t));
|
||||
}
|
||||
while(toadd) {
|
||||
if(x86_size>15)
|
||||
@@ -270,7 +272,7 @@ static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86
|
||||
|
||||
static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
{
|
||||
int pred_sz = 0;
|
||||
int pred_sz = 1; // to be safe
|
||||
// compute total size of predecessor to alocate the array
|
||||
// first compute the jumps
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
@@ -280,13 +282,13 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
}
|
||||
}
|
||||
// second the "has_next"
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz)) {
|
||||
for(int i=0; i<dyn->size-1; ++i) {
|
||||
if(dyn->insts[i].x86.has_next) {
|
||||
++pred_sz;
|
||||
++dyn->insts[i+1].pred_sz;
|
||||
}
|
||||
}
|
||||
dyn->predecessor = (int*)malloc(pred_sz*sizeof(int));
|
||||
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
|
||||
// fill pred pointer
|
||||
int* p = dyn->predecessor;
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
@@ -294,70 +296,64 @@ static void fillPredecessors(dynarec_arm_t* dyn)
|
||||
p += dyn->insts[i].pred_sz;
|
||||
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
|
||||
}
|
||||
assert(p==dyn->predecessor+pred_sz);
|
||||
// fill pred
|
||||
for(int i=0; i<dyn->size; ++i) {
|
||||
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz))
|
||||
if((i!=dyn->size-1) && dyn->insts[i].x86.has_next)
|
||||
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
|
||||
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
|
||||
dyn->insts[dyn->insts[i].x86.jmp_insts].pred[dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz++] = i;
|
||||
if(dyn->insts[i].x86.jmp && (dyn->insts[i].x86.jmp_insts!=-1)) {
|
||||
int j = dyn->insts[i].x86.jmp_insts;
|
||||
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void updateNeed(dynarec_arm_t* dyn, int ninst, uint32_t need) {
|
||||
uint32_t old_need = dyn->insts[ninst].x86.need_flags;
|
||||
uint32_t new_need = old_need | need;
|
||||
uint32_t new_use = dyn->insts[ninst].x86.use_flags;
|
||||
uint32_t old_use = dyn->insts[ninst].x86.old_use;
|
||||
|
||||
if((new_need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET) {
|
||||
new_need &=~X_PEND;
|
||||
new_need |= X_ALL;
|
||||
}
|
||||
|
||||
uint32_t new_set = 0;
|
||||
if(dyn->insts[ninst].x86.state_flags & SF_SET)
|
||||
new_set = dyn->insts[ninst].x86.set_flags;
|
||||
if(dyn->insts[ninst].x86.state_flags & SF_PENDING)
|
||||
new_set |= X_PEND;
|
||||
if((new_need&X_PEND) && (
|
||||
dyn->insts[ninst].x86.state_flags==SF_SET || dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
|
||||
new_need &=~X_PEND;
|
||||
new_need |=X_ALL;
|
||||
}
|
||||
|
||||
dyn->insts[ninst].x86.need_flags = new_need;
|
||||
dyn->insts[ninst].x86.old_use = new_use;
|
||||
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1)
|
||||
new_need |= X_PEND;
|
||||
|
||||
// a Flag Barrier will change all need to "Pending", as it clear all flags optimisation
|
||||
if(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)
|
||||
new_need = X_PEND;
|
||||
|
||||
if((new_need == old_need) && (new_use == old_use)) // no changes, bye
|
||||
return;
|
||||
|
||||
if(!(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)) {
|
||||
new_need &=~new_set; // clean needed flag that were suplied
|
||||
new_need |= new_use; // new need
|
||||
}
|
||||
|
||||
if((new_need == (X_ALL|X_PEND)) && (dyn->insts[ninst].x86.state_flags & SF_SET))
|
||||
new_need = X_ALL;
|
||||
|
||||
//update need to new need on predecessor
|
||||
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
|
||||
updateNeed(dyn, dyn->insts[ninst].pred[i], new_need);
|
||||
}
|
||||
|
||||
static void resetNeed(dynarec_arm_t* dyn) {
|
||||
for(int i = dyn->size; i-- > 0;) {
|
||||
dyn->insts[i].x86.old_use = 0;
|
||||
dyn->insts[i].x86.need_flags = dyn->insts[i].x86.default_need;
|
||||
// updateNeed goes backward, from last intruction to top
|
||||
static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
|
||||
while (ninst>=0) {
|
||||
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
|
||||
need |= dyn->insts[ninst].x86.need_after;
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
|
||||
need &=~X_PEND;
|
||||
need |= X_ALL;
|
||||
}
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SET)) {
|
||||
need &=~X_PEND;
|
||||
need |= dyn->insts[ninst].x86.set_flags; // SF_SET will compute all flags, it's not SUBSET!
|
||||
}
|
||||
if((need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET_PENDING) {
|
||||
need |= X_ALL&~(dyn->insts[ninst].x86.set_flags);
|
||||
}
|
||||
dyn->insts[ninst].x86.gen_flags = need&dyn->insts[ninst].x86.set_flags;
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags&SF_PENDING))
|
||||
dyn->insts[ninst].x86.gen_flags |= X_PEND;
|
||||
dyn->insts[ninst].x86.need_after = need;
|
||||
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
|
||||
if(dyn->insts[ninst].x86.may_set)
|
||||
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
|
||||
// Consume X_PEND if relevant
|
||||
if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
|
||||
need &=~X_PEND;
|
||||
need |= dyn->insts[ninst].x86.use_flags;
|
||||
if(dyn->insts[ninst].x86.need_before == need)
|
||||
return ninst - 1;
|
||||
dyn->insts[ninst].x86.need_before = need;
|
||||
if(dyn->insts[ninst].x86.barrier&BARRIER_FLAGS) {
|
||||
need = need?X_PEND:0;
|
||||
}
|
||||
int ok = 0;
|
||||
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i) {
|
||||
if(dyn->insts[ninst].pred[i] == ninst-1)
|
||||
ok = 1;
|
||||
else
|
||||
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
|
||||
}
|
||||
if(!ok)
|
||||
return ninst - 1;
|
||||
--ninst;
|
||||
}
|
||||
return ninst;
|
||||
}
|
||||
|
||||
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
@@ -365,7 +361,7 @@ uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
__thread void* current_helper = NULL;
|
||||
void* current_helper = NULL;
|
||||
|
||||
void CancelBlock()
|
||||
{
|
||||
@@ -373,25 +369,42 @@ void CancelBlock()
|
||||
current_helper = NULL;
|
||||
if(!helper)
|
||||
return;
|
||||
free(helper->next);
|
||||
free(helper->insts);
|
||||
free(helper->predecessor);
|
||||
free(helper->sons_x86);
|
||||
free(helper->sons_arm);
|
||||
box_free(helper->next);
|
||||
box_free(helper->insts);
|
||||
box_free(helper->predecessor);
|
||||
if(helper->dynablock && helper->dynablock->block)
|
||||
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
|
||||
}
|
||||
|
||||
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
|
||||
block->isize = 0;
|
||||
block->done = 0;
|
||||
block->size = 0;
|
||||
block->block = NULL;
|
||||
block->need_test = 0;
|
||||
return block;
|
||||
}
|
||||
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(IsInHotPage(addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
|
||||
return NULL;
|
||||
return CreateEmptyBlock(block, addr);
|
||||
}
|
||||
if(!isJumpTableDefault((void*)addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Asked to fill a block at %p, but JumpTable is not default\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
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
|
||||
dynarec_arm_t helper = {0};
|
||||
current_helper = &helper;
|
||||
@@ -399,11 +412,11 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.start = addr;
|
||||
uintptr_t start = addr;
|
||||
helper.cap = 64; // needs epilog handling
|
||||
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
helper.insts = (instruction_arm_t*)box_calloc(helper.cap, sizeof(instruction_arm_t));
|
||||
// pass 0, addresses, x86 jump addresses, overall size of the block
|
||||
uintptr_t end = arm_pass0(&helper, addr);
|
||||
// no need for next anymore
|
||||
free(helper.next);
|
||||
box_free(helper.next);
|
||||
helper.next_sz = helper.next_cap = 0;
|
||||
helper.next = NULL;
|
||||
// basic checks
|
||||
@@ -412,20 +425,24 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
CancelBlock();
|
||||
return (void*)block;
|
||||
}
|
||||
if(!isprotectedDB(addr, 1)) {
|
||||
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
|
||||
AddHotPage(addr);
|
||||
CancelBlock();
|
||||
return NULL;
|
||||
}
|
||||
// already protect the block and compute hash signature
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
// protect the block of it goes over the 1st page
|
||||
if((addr&~box86_pagesize)!=(end&~box86_pagesize)) // need to protect some other pages too
|
||||
protectDB(addr, end-addr); //end is 1byte after actual end
|
||||
uint32_t hash = X31_hash_code((void*)addr, end-addr);
|
||||
// Compute flag_need, without with current barriers
|
||||
resetNeed(&helper);
|
||||
for(int i = helper.size; i-- > 0;)
|
||||
updateNeed(&helper, i, 0);
|
||||
// calculate barriers
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
if(helper.insts[i].x86.jmp) {
|
||||
uintptr_t j = helper.insts[i].x86.jmp;
|
||||
if(j<start || j>=end) {
|
||||
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
|
||||
helper.insts[i].x86.jmp_insts = -1;
|
||||
helper.insts[i].x86.use_flags |= X_PEND;
|
||||
helper.insts[i].x86.need_after |= X_PEND;
|
||||
} else {
|
||||
// find jump address instruction
|
||||
int k=-1;
|
||||
@@ -440,65 +457,10 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
}
|
||||
// fill predecessors with the jump address
|
||||
fillPredecessors(&helper);
|
||||
// check for the optionnal barriers now
|
||||
for(int i=helper.size-1; i>=0; --i) {
|
||||
if(helper.insts[i].barrier_maybe) {
|
||||
// out-of-block jump
|
||||
if(helper.insts[i].x86.jmp_insts == -1) {
|
||||
// nothing for now
|
||||
} else {
|
||||
// inside block jump
|
||||
int k = helper.insts[i].x86.jmp_insts;
|
||||
if(k>i) {
|
||||
// jump in the future
|
||||
if(helper.insts[k].pred_sz>1) {
|
||||
// with multiple flow, put a barrier
|
||||
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
|
||||
}
|
||||
} else {
|
||||
// jump back
|
||||
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check to remove useless barrier, in case of jump when destination doesn't needs flags
|
||||
/*for(int i=helper.size-1; i>=0; --i) {
|
||||
int k;
|
||||
if(helper.insts[i].x86.jmp
|
||||
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
|
||||
&& helper.insts[k].x86.barrier&BARRIER_FLAGS) {
|
||||
//TODO: optimize FPU barrier too
|
||||
if((!helper.insts[k].x86.need_flags)
|
||||
||(helper.insts[k].x86.set_flags==X_ALL
|
||||
&& helper.insts[k].x86.state_flags==SF_SET)
|
||||
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
|
||||
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
|
||||
helper.insts[k].x86.barrier &= ~BARRIER_FLAGS; // remove flag barrier
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
|
||||
for(int i = helper.size; i-- > 0;) {
|
||||
int k;
|
||||
if(helper.insts[i].x86.jmp
|
||||
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
|
||||
) {
|
||||
if(helper.insts[k].x86.barrier&BARRIER_FLAGS)
|
||||
// jumpto barrier
|
||||
helper.insts[i].x86.use_flags |= X_PEND;
|
||||
if(helper.insts[i].x86.barrier&BARRIER_FLAGS && (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags))
|
||||
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
|
||||
else
|
||||
helper.insts[i].x86.use_flags |= (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags);
|
||||
}
|
||||
if(helper.insts[i].x86.barrier&BARRIER_FLAGS)
|
||||
// immediate barrier
|
||||
helper.insts[i].x86.use_flags |= X_PEND;
|
||||
}
|
||||
resetNeed(&helper);
|
||||
for(int i = helper.size; i-- > 0;)
|
||||
updateNeed(&helper, i, 0);
|
||||
|
||||
int pos = helper.size;
|
||||
while (pos>=0)
|
||||
pos = updateNeed(&helper, pos, 0);
|
||||
|
||||
// pass 1, float optimisations, first pass for flags
|
||||
arm_pass1(&helper, addr);
|
||||
@@ -516,8 +478,8 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
helper.block = p;
|
||||
helper.arm_start = (uintptr_t)p;
|
||||
if(helper.sons_size) {
|
||||
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
|
||||
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
|
||||
helper.sons_x86 = (uintptr_t*)alloca(helper.sons_size*sizeof(uintptr_t));
|
||||
helper.sons_arm = (void**)alloca(helper.sons_size*sizeof(void*));
|
||||
}
|
||||
// pass 3, emit (log emit arm opcode)
|
||||
if(box86_dynarec_dump) {
|
||||
@@ -547,15 +509,15 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
|
||||
size_t size = 0;
|
||||
block->instsize = (instsize_t*)calloc(cap, sizeof(instsize_t));
|
||||
block->instsize = (instsize_t*)box_calloc(cap, sizeof(instsize_t));
|
||||
for(int i=0; i<helper.size; ++i)
|
||||
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
|
||||
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
|
||||
}
|
||||
// ok, free the helper now
|
||||
free(helper.insts);
|
||||
box_free(helper.insts);
|
||||
helper.insts = NULL;
|
||||
free(helper.next);
|
||||
box_free(helper.next);
|
||||
helper.next = NULL;
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
@@ -570,13 +532,20 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
if(block->hash != hash) {
|
||||
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
|
||||
CancelBlock();
|
||||
AddHotPage(addr);
|
||||
return NULL;
|
||||
}
|
||||
if(!isprotectedDB(addr, end-addr)) {
|
||||
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%zd, cancelling\n", block->x86_addr, block->x86_size);
|
||||
AddHotPage(addr);
|
||||
block->need_test = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
// fill sons if any
|
||||
dynablock_t** sons = NULL;
|
||||
int sons_size = 0;
|
||||
if(helper.sons_size) {
|
||||
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
|
||||
sons = (dynablock_t**)box_calloc(helper.sons_size, sizeof(dynablock_t*));
|
||||
for (int i=0; i<helper.sons_size; ++i) {
|
||||
int created = 1;
|
||||
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
|
||||
@@ -596,14 +565,10 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
|
||||
block->sons = sons;
|
||||
block->sons_size = sons_size;
|
||||
} else
|
||||
free(sons);
|
||||
box_free(sons);
|
||||
}
|
||||
free(helper.predecessor);
|
||||
box_free(helper.predecessor);
|
||||
helper.predecessor = NULL;
|
||||
free(helper.sons_x86);
|
||||
helper.sons_x86 = NULL;
|
||||
free(helper.sons_arm);
|
||||
helper.sons_arm = NULL;
|
||||
current_helper = NULL;
|
||||
block->done = 1;
|
||||
return (void*)block;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "dynarec_arm.h"
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "arm_printer.h"
|
||||
#include "custommem.h"
|
||||
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
@@ -36,12 +38,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
uint32_t u32;
|
||||
uint8_t wback, wb1, wb2;
|
||||
int fixedaddress;
|
||||
int lock;
|
||||
int cacheupd;
|
||||
|
||||
opcode = F8;
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(tmp);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(lock);
|
||||
MAYUSE(cacheupd);
|
||||
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
@@ -575,7 +581,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x57:
|
||||
INST_NAME("PUSH reg");
|
||||
gd = xEAX+(opcode&0x07);
|
||||
PUSH1(gd);
|
||||
if(gd==xESP) {
|
||||
MOV_REG(x1, gd);
|
||||
PUSH1(x1);
|
||||
} else {
|
||||
PUSH1(gd);
|
||||
}
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
@@ -587,7 +598,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x5F:
|
||||
INST_NAME("POP reg");
|
||||
gd = xEAX+(opcode&0x07);
|
||||
#ifdef RPI2
|
||||
if(gd==xESP) {
|
||||
POP1(x1);
|
||||
MOV_REG(gd, x1);
|
||||
} else {
|
||||
POP1(gd);
|
||||
}
|
||||
#else
|
||||
POP1(gd);
|
||||
#endif
|
||||
break;
|
||||
case 0x60:
|
||||
INST_NAME("PUSHAD");
|
||||
@@ -641,7 +661,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = F32S;
|
||||
if(PK(0)==0xC3) {
|
||||
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
|
||||
MOV32(x3, ip+1);
|
||||
MOV32(x3, addr-4);
|
||||
LDR_IMM9(x1, x3, 0);
|
||||
PUSH1(x1);
|
||||
} else {
|
||||
@@ -702,11 +722,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
|
||||
Bcond(NO, i32); \
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
|
||||
if(!dyn->insts[ninst].x86.barrier) \
|
||||
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
|
||||
Bcond(c__, i32); \
|
||||
} \
|
||||
@@ -991,8 +1011,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(eb1, x14, eb2*8, 8);
|
||||
} else {
|
||||
GETGB(x14);
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
LDREXB(x1, ed);
|
||||
@@ -1001,7 +1021,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
BFI(gb1, x1, gb2*8, 8);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 0x87:
|
||||
@@ -1017,8 +1037,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
} else {
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(ed, 3);
|
||||
B_MARK(cNE);
|
||||
@@ -1041,7 +1061,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(!fixedaddress) {
|
||||
MARK2;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
MOV_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
@@ -1063,8 +1083,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
eb2 = ((ed&4)>>2); // L or H
|
||||
BFI(eb1, gd, eb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
STRB_IMM9(gd, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x89:
|
||||
@@ -1074,8 +1095,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
STR_IMM9(gd, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x8A:
|
||||
@@ -1097,9 +1119,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
if(box86_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
|
||||
SMREADLOCK(lock);
|
||||
LDRB_IMM9(x14, wback, fixedaddress);
|
||||
ed = x14;
|
||||
}
|
||||
@@ -1112,11 +1135,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
if(box86_dynarec_strongmem &&
|
||||
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
|
||||
DMB_ISH();
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
SMREADLOCK(lock);
|
||||
LDR_IMM9(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1127,9 +1147,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= seg
|
||||
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
|
||||
} else { // mem <= seg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDRH_REG(x3, xEmu, x3);
|
||||
STRH_IMM8(x3, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x8D:
|
||||
@@ -1139,7 +1160,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg? that's an invalid operation
|
||||
DEFAULT;
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
|
||||
MOV_REG(gd, ed);
|
||||
}
|
||||
@@ -1151,7 +1172,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1172,7 +1193,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
POP1(xEAX+(nextop&7));
|
||||
} else {
|
||||
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
if(ed==xESP) {
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
} else {
|
||||
@@ -1257,12 +1278,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
STRB_IMM9(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA3:
|
||||
INST_NAME("MOV Od, EAX");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
STR_IMM9(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA4:
|
||||
INST_NAME("MOVSB");
|
||||
@@ -1569,7 +1592,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xC2:
|
||||
INST_NAME("RETN");
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
READFLAGS(X_PEND); // lets play safe here too
|
||||
if(box86_dynarec_safeflags) {
|
||||
READFLAGS(X_PEND); // lets play safe here too
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
i32 = F16;
|
||||
retn_to_epilog(dyn, ninst, i32);
|
||||
@@ -1580,7 +1605,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("RET");
|
||||
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
// ^^^ that hack break PlantsVsZombies and GOG Setup under wine....
|
||||
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
|
||||
if(box86_dynarec_safeflags) {
|
||||
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
ret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
@@ -1598,10 +1625,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x3, u8);
|
||||
BFI(eb1, x3, eb2*8, 8);
|
||||
} else { // mem <= u8
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, &lock);
|
||||
u8 = F8;
|
||||
MOVW(x3, u8);
|
||||
STRB_IMM9(x3, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
@@ -1612,10 +1640,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
STR_IMM9(x3, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1644,7 +1673,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if(box86_log<2) { // call the wrapper directly
|
||||
if((box86_log<2) && !cycle_log) { // call the wrapper directly
|
||||
uintptr_t ncall[2]; // to avoid BUSERROR!!!
|
||||
memcpy(ncall, (void*)addr, 2*sizeof(void*)); // the wrapper + function
|
||||
addr+=8;
|
||||
@@ -1686,6 +1715,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xCD:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
SMEND();
|
||||
if(PK(0)==0x80) {
|
||||
INST_NAME("Syscall");
|
||||
u8 = F8;
|
||||
@@ -2032,6 +2062,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xD7:
|
||||
INST_NAME("XLAT");
|
||||
UBFX(x1, xEAX, 0, 8); // x1 = AL
|
||||
SMREAD();
|
||||
LDRB_REG_LSL_IMM5(x1, xEBX, x1, 0); //x1 = byte ptr[EBX+AL]
|
||||
BFI(xEAX, x1, 0, 8);
|
||||
break;
|
||||
@@ -2068,11 +2099,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
|
||||
Bcond(NO, i32); \
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
|
||||
if(!dyn->insts[ninst].x86.barrier) \
|
||||
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
|
||||
Bcond(c__, i32); \
|
||||
} \
|
||||
@@ -2125,7 +2156,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
#if STEP < 2
|
||||
if (i32==0)
|
||||
tmp = dyn->insts[ninst].pass2choice = 1;
|
||||
else if (((u32)>0x10000) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
|
||||
else if ((getProtection(u32)&PROT_READ) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
|
||||
tmp = dyn->insts[ninst].pass2choice = 2;
|
||||
/*else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;*/
|
||||
@@ -2158,7 +2189,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
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
|
||||
x87_forget(dyn, ninst, x3, x14, 0);
|
||||
if(box86_log<2 && dyn->insts[ninst].natcall) { // call the wrapper directly
|
||||
if((box86_log<2) && !cycle_log && dyn->insts[ninst].natcall) { // call the wrapper directly
|
||||
uintptr_t ncall[2];
|
||||
memcpy(ncall, (void*)(dyn->insts[ninst].natcall+2), 2*sizeof(void*)); // the wrapper + function
|
||||
MOV32(xEIP, dyn->insts[ninst].natcall+2+4+4);
|
||||
@@ -2190,7 +2221,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
break;*/
|
||||
default:
|
||||
if(ninst && dyn->insts[ninst-1].x86.set_flags) {
|
||||
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
@@ -2228,7 +2259,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
jump_to_next(dyn, addr+i32, 0, ninst);
|
||||
} else {
|
||||
// inside the block
|
||||
fpuCacheTransform(dyn, ninst, x1, x2, x3);
|
||||
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
|
||||
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
|
||||
if(tmp==-4) {
|
||||
NOP;
|
||||
@@ -2284,7 +2315,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xAF:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3, 2);
|
||||
@@ -2343,7 +2375,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xC3:
|
||||
INST_NAME("(REPZ) RET");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
if(box86_dynarec_safeflags>1) {
|
||||
READFLAGS(X_PEND);
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
}
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
ret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
@@ -2375,7 +2411,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xA6:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,1);
|
||||
@@ -2399,7 +2436,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xA7:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ CMPSD");} else {INST_NAME("REPZ CMPSD");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,4);
|
||||
@@ -2464,7 +2502,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xAE:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,1);
|
||||
@@ -2488,7 +2527,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xAF:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3,4);
|
||||
@@ -2783,7 +2823,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
|
||||
PASS2IF((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags), 1) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
//SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
@@ -2799,7 +2839,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 4: // JMP Ed
|
||||
INST_NAME("JMP Ed");
|
||||
BARRIER(BARRIER_FULL);
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
GETEDH(xEIP);
|
||||
jump_to_next(dyn, 0, ed, ninst);
|
||||
*need_epilog = 0;
|
||||
|
||||
+151
-64
@@ -31,7 +31,8 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
|
||||
a = fpu_get_scratch_quad(dyn); \
|
||||
VLD1Q_64(a, ed); \
|
||||
}
|
||||
@@ -42,13 +43,15 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
|
||||
a = fpu_get_scratch_double(dyn); \
|
||||
VLD1_64(a, ed); \
|
||||
}
|
||||
#define PUTEM(a) \
|
||||
if((nextop&0xC0)!=0xC0) { \
|
||||
VST1_64(a, ed); \
|
||||
SMWRITE2(); \
|
||||
}
|
||||
|
||||
uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
@@ -66,6 +69,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int s0;
|
||||
int fixedaddress;
|
||||
int parity;
|
||||
int cacheupd;
|
||||
MAYUSE(s0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v2);
|
||||
@@ -75,6 +79,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(wb2);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(cacheupd);
|
||||
#if STEP == 3
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
@@ -93,7 +98,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 1:
|
||||
INST_NAME("PREFETCHW");
|
||||
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
addr = fakeed(dyn,addr, ninst, nextop);
|
||||
// should use PLDW, but it's not available on cortex-a8 for example
|
||||
break;
|
||||
@@ -110,8 +115,9 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
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, 4095-12, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
|
||||
//LDRD also have alignment requirements
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -130,7 +136,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-16, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-16, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
// cannot use STRD, this needs alignement too
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
@@ -138,6 +144,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
STR_IMM9(x2, ed, fixedaddress+8);
|
||||
STR_IMM9(x3, ed, fixedaddress+12);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -150,7 +157,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
INST_NAME("MOVLPS Gx,Ex");
|
||||
GETGX(v0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -166,14 +174,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1_32(v0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
|
||||
|
||||
SMWRITE2();
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -210,7 +219,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
INST_NAME("MOVHPS Gx,Ex");
|
||||
GETGX(v0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1_64(v0+1, ed);
|
||||
}
|
||||
break;
|
||||
@@ -224,14 +234,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1_64(v0+1, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
|
||||
|
||||
SMWRITE2();
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -246,7 +257,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
case 3:
|
||||
INST_NAME("PREFETCHh Ed");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xffff, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xffff, 0, 0, NULL);
|
||||
MOVW(x3, fixedaddress);
|
||||
if(fixedaddress<0) {
|
||||
PLDn(ed, x3);
|
||||
@@ -276,7 +287,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1Q_32(v0, ed);
|
||||
}
|
||||
break;
|
||||
@@ -289,8 +301,9 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_32(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x2A:
|
||||
@@ -301,7 +314,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_double(dyn);
|
||||
VLD1_32(v1, ed);
|
||||
}
|
||||
@@ -316,7 +330,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_32(v0, ed);
|
||||
}
|
||||
break;
|
||||
@@ -328,7 +342,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_double(dyn);
|
||||
VLD1_32(v1, ed);
|
||||
}
|
||||
@@ -342,7 +357,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_double(dyn);
|
||||
VLD1_32(v1, ed);
|
||||
}
|
||||
@@ -381,10 +397,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
s0 = d0*2;
|
||||
} else {
|
||||
SMREAD();
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -442,6 +459,34 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(d1);
|
||||
VQRDMULH_S16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("MOVBE Gd, Ed");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
REV(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(gd, ed, fixedaddress);
|
||||
REV(gd, gd);
|
||||
}
|
||||
break;
|
||||
case 0xF1:
|
||||
INST_NAME("MOVBE Ed, Gd");
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
REV(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
REV(x1, gd);
|
||||
STR_IMM9(gd, ed, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -480,7 +525,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7); \
|
||||
MOV_REG_COND(YES, gd, ed); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL); \
|
||||
LDR_IMM9_COND(YES, gd, ed, fixedaddress); \
|
||||
}
|
||||
|
||||
@@ -592,7 +638,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(gd, x3, 3, 1);
|
||||
} else {
|
||||
// EX is memory
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4096-16, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4096-16, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
UBFX(x3, x2, 31, 1);
|
||||
BFI(gd, x3, 0, 1);
|
||||
@@ -843,7 +890,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
VMOVD(q0+1, d1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1_64(q0+1, ed);
|
||||
}
|
||||
VMOVD(q0, d0);
|
||||
@@ -919,7 +966,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMOVD(v0, v1);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1_64(v0, ed);
|
||||
}
|
||||
break;
|
||||
@@ -953,7 +1000,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
ADD_IMM8(xSP, xSP, 4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
if (u8) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
@@ -977,7 +1024,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
d0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1_16(d0, ed);
|
||||
}
|
||||
@@ -990,6 +1038,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1_16(d0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -998,7 +1047,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
d0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1_16(d0, ed);
|
||||
}
|
||||
@@ -1008,6 +1058,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1_16(d0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1015,7 +1066,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
d0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1_16(d0, ed);
|
||||
}
|
||||
@@ -1028,6 +1080,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1_16(d0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1037,6 +1090,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0x72:
|
||||
nextop = F8;
|
||||
SMREAD();
|
||||
GETEM(v0);
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
@@ -1078,6 +1132,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x73:
|
||||
nextop = F8;
|
||||
GETEM(v0);
|
||||
SMREAD();
|
||||
switch((nextop>>3)&7) {
|
||||
case 2:
|
||||
INST_NAME("PSRLQ Em, Ib");
|
||||
@@ -1141,8 +1196,9 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMOVfrDx_32(ed, v0, 0);
|
||||
} else {
|
||||
VMOVfrDx_32(x2, v0, 0); // there can be some bus error is storing the VFPU reg directly
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x7F:
|
||||
@@ -1155,13 +1211,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v0, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1178,11 +1236,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
|
||||
Bcond(NO, i32); \
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
|
||||
if(!dyn->insts[ninst].x86.barrier) \
|
||||
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i32_, 0, ninst); \
|
||||
} else { \
|
||||
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
|
||||
Bcond(c__, i32); \
|
||||
} \
|
||||
@@ -1279,6 +1337,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
, cNE, cEQ, X_SF|X_OF|X_ZF)
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
#define GO(GETFLAGS, NO, YES, F) \
|
||||
READFLAGS(F); \
|
||||
GETFLAGS; \
|
||||
@@ -1291,10 +1350,10 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
eb2 = ((ed&4)>>2); \
|
||||
BFI(eb1, x3, eb2*8, 8); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);\
|
||||
STRB_IMM9(x3, ed, fixedaddress); \
|
||||
SMWRITE(); \
|
||||
}
|
||||
|
||||
case 0x90:
|
||||
INST_NAME("SETO Eb");
|
||||
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
|
||||
@@ -1415,7 +1474,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x1, ed, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x1, fixedaddress);
|
||||
@@ -1471,7 +1531,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x3, fixedaddress);
|
||||
@@ -1489,6 +1550,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ORR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
@@ -1516,15 +1578,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
// xFENCE -> DMB is approximative, but should be good enough
|
||||
if((nextop&0xF8)==0xE8) {
|
||||
INST_NAME("LFENCE");
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
} else
|
||||
if((nextop&0xF8)==0xF0) {
|
||||
INST_NAME("MFENCE");
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
} else
|
||||
if((nextop&0xF8)==0xF8) {
|
||||
INST_NAME("SFENCE");
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
} else {
|
||||
switch((nextop>>3)&7) {
|
||||
case 0:
|
||||
@@ -1535,7 +1597,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fxsave, -1, 0);
|
||||
}
|
||||
@@ -1547,7 +1609,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fxrstor, -1, 0);
|
||||
}
|
||||
@@ -1556,6 +1618,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LDMXCSR Md");
|
||||
GETED;
|
||||
STR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
if(box86_sse_flushto0) {
|
||||
VMRS(x14); // get fpscr
|
||||
MOV_REG_LSR_IMM5(x3, ed, 15); // get FZ bit
|
||||
BFI(x14, x3, 24, 1); // inject FZ bit
|
||||
VMSR(x14); // put new fpscr
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("STMXCSR Md");
|
||||
@@ -1563,7 +1631,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
LDR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
STR_IMM9(x14, ed, fixedaddress);
|
||||
}
|
||||
@@ -1646,7 +1714,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
wback = x3;
|
||||
@@ -1664,6 +1733,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1678,7 +1748,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
UXTB(gd, eb1, eb2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDRB_IMM9(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1690,7 +1761,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
UXTH(gd, ed, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1706,7 +1778,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1726,7 +1799,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1746,6 +1820,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1756,7 +1831,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1776,6 +1852,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
@@ -1786,7 +1863,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1807,6 +1885,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1824,7 +1903,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x3, fixedaddress);
|
||||
@@ -1840,6 +1920,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_REG(ed, ed, x14, x2);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
@@ -1896,7 +1977,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
SXTB(gd, eb1, eb2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRSB_IMM8(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1908,7 +1990,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
SXTH(gd, ed, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRSH_IMM8(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1928,12 +2011,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED;
|
||||
MOV_REG(x1, gd);
|
||||
if(gd!=ed) {
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
|
||||
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
|
||||
MOV_REG(gd, ed);
|
||||
}
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
emit_add32(dyn, ninst, ed, x1, x3, x14);
|
||||
WBACK;
|
||||
break;
|
||||
case 0xC2:
|
||||
@@ -1975,7 +2057,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd); // doesn't exist
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
STR_IMM9(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -1988,7 +2070,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
VMOVtoDx_16(d0, u8, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = (F8)&3;
|
||||
VLD1LANE_16(d0, wback, u8);
|
||||
}
|
||||
@@ -2002,7 +2085,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
u8 = (F8)&3;
|
||||
VMOVfrDx_U16(gd, d0, u8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0, NULL);
|
||||
u8 = (F8)&3;
|
||||
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
|
||||
}
|
||||
@@ -2015,8 +2099,9 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETGX(v0, 1);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
SMREAD();
|
||||
// from memory
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
q0 = v0;
|
||||
// Low part
|
||||
@@ -2166,7 +2251,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
INST_NAME("CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x1, wback, fixedaddress+0);
|
||||
LDR_IMM9(x2, wback, fixedaddress+4);
|
||||
CMPS_REG_LSL_IMM5(xEAX, x1, 0);
|
||||
@@ -2183,6 +2269,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x1, 0);
|
||||
MARK3;
|
||||
BFI(xFlags, x1, F_ZF, 1);
|
||||
SMWRITE();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
@@ -2404,7 +2491,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
DEFAULT;
|
||||
} else {
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1_64(v0, ed);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -29,7 +29,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint8_t wback, u8;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(j32);
|
||||
@@ -103,6 +103,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
STRH_REG(gd, x14, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -114,6 +115,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
@@ -129,6 +131,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, x1, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -140,6 +143,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
SMREAD();
|
||||
LDR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
@@ -152,6 +156,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
STR_IMM9(xEAX, x1, 0);
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
@@ -163,6 +168,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
@@ -185,8 +191,9 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
STR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -198,7 +205,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -210,9 +218,10 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP1(xEAX+(nextop&7));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -224,6 +233,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDRB_IMM9(xEAX, x1, i32);
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
SMREAD();
|
||||
LDRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
|
||||
}
|
||||
break;
|
||||
@@ -235,6 +245,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(xEAX, x1, i32);
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
SMREAD();
|
||||
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
|
||||
}
|
||||
break;
|
||||
@@ -247,6 +258,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
STRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0xA3:
|
||||
@@ -255,12 +267,23 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = F32S;
|
||||
if(i32>-4096 && i32<4096) {
|
||||
STR_IMM9(xEAX, x1, i32);
|
||||
SMWRITE2();
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA8:
|
||||
INST_NAME("TEST AL, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
UXTB(x1, xEAX, 0);
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
emit_test8(dyn, ninst, x1, x2, x3, x14);
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
INST_NAME("MOV FS:Ed, Id");
|
||||
grab_fsdata(dyn, addr, ninst, x14);
|
||||
@@ -270,10 +293,11 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
STR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -297,7 +321,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
MOV_REG(xEIP, xEAX+(nextop&7));
|
||||
} else { // mem
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
|
||||
}
|
||||
BARRIER(BARRIER_FULL);
|
||||
@@ -312,7 +336,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
@@ -97,7 +97,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_and32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
@@ -118,7 +118,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_sub32(dyn, ninst, ed, gd, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
@@ -139,7 +139,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETGD;
|
||||
GETEDO2(x14);
|
||||
emit_xor32(dyn, ninst, gd, ed, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
@@ -202,7 +202,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR GS:Eb, Ib");
|
||||
@@ -211,7 +211,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC GS:Eb, Ib");
|
||||
@@ -221,7 +221,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB GS:Eb, Ib");
|
||||
@@ -231,7 +231,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND GS:Eb, Ib");
|
||||
@@ -240,7 +240,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB GS:Eb, Ib");
|
||||
@@ -249,7 +249,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR GS:Eb, Ib");
|
||||
@@ -258,7 +258,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x14);
|
||||
EBBACK;
|
||||
EBBACK2;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP GS:Eb, Ib");
|
||||
@@ -290,7 +290,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_add32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
|
||||
@@ -299,7 +299,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_or32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
|
||||
@@ -309,7 +309,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
|
||||
@@ -319,7 +319,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
|
||||
@@ -328,7 +328,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_and32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
|
||||
@@ -337,7 +337,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
|
||||
@@ -346,7 +346,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
|
||||
@@ -372,8 +372,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(xEAX+(nextop&7), gd);
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
STR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -385,7 +386,8 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
|
||||
}
|
||||
break;
|
||||
@@ -397,9 +399,10 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP1((xEAX+(nextop&7)));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -407,6 +410,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV EAX, GS:Id");
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
i32 = F32S;
|
||||
SMREAD();
|
||||
if(i32>-4096 && i32<4096) {
|
||||
LDR_IMM9(xEAX, x1, i32);
|
||||
} else {
|
||||
@@ -416,6 +420,16 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA2:
|
||||
INST_NAME("MOV GS:Od, AL");
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
|
||||
STRB_IMM9(xEAX, x2, 0);
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV GS:Od, EAX");
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
@@ -423,6 +437,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
|
||||
STR_IMM9(xEAX, x2, 0);
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0xC6:
|
||||
@@ -437,10 +452,11 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x3, u8);
|
||||
BFI(eb1, x3, eb2*8, 8);
|
||||
} else { // mem <= u8
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
MOVW(x3, u8);
|
||||
STRB_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0xC7:
|
||||
@@ -452,10 +468,11 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(ed, i32);
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
STR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -468,14 +485,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEDO2(x14);
|
||||
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 1:
|
||||
INST_NAME("ROR Ed, 1");
|
||||
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
|
||||
GETEDO2(x14);
|
||||
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 2:
|
||||
INST_NAME("RCL Ed, 1");
|
||||
@@ -484,10 +501,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOVW(x2, 1);
|
||||
GETEDO2(x14);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
CALL_(rcl32, ed, (1<<x2));
|
||||
WBACK2;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, 1");
|
||||
@@ -495,10 +511,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
MOVW(x2, 1);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
CALL_(rcr32, ed, (1<<x2));
|
||||
WBACK2;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
@@ -506,21 +521,21 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_shl32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_shr32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, 1");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
|
||||
GETEDO2(x14);
|
||||
emit_sar32c(dyn, ninst, ed, 1, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -537,7 +552,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
RSB_IMM8(x3, x3, 0x20);
|
||||
GETEDO2(x14);
|
||||
MOV_REG_ROR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x3, 31);
|
||||
B_MARK(cNE);
|
||||
@@ -558,7 +573,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARK2(cEQ);
|
||||
GETEDO2(x14);
|
||||
MOV_REG_ROR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
UFLAG_IF { // calculate flags directly
|
||||
CMPS_IMM8(x3, 1);
|
||||
B_MARK(cNE);
|
||||
@@ -578,10 +593,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcl32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
CALL_(rcl32, ed, (1<<x2));
|
||||
WBACK2;
|
||||
break;
|
||||
case 3:
|
||||
INST_NAME("RCR Ed, CL");
|
||||
@@ -589,10 +603,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_OF|X_CF, SF_SET);
|
||||
AND_IMM8(x2, xECX, 0x1f);
|
||||
wb = ed;
|
||||
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
|
||||
CALL_(rcr32, ed, (1<<x14));
|
||||
SBACK(wb);
|
||||
WBACK2;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
@@ -601,7 +614,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETEDO2(x14);
|
||||
emit_shl32(dyn, ninst, ed, x3, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("SHR Ed, CL");
|
||||
@@ -609,7 +622,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
AND_IMM8(x3, xECX, 0x1f);
|
||||
GETEDO2(x14);
|
||||
emit_shr32(dyn, ninst, ed, x3, x3, x14);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("SAR Ed, CL");
|
||||
@@ -618,7 +631,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEDO2(x14);
|
||||
UFLAG_OP12(ed, x3);
|
||||
MOV_REG_ASR_REG(ed, ed, x3);
|
||||
WBACK;
|
||||
WBACK2;
|
||||
UFLAG_RES(ed);
|
||||
UFLAG_DF(x3, d_sar32);
|
||||
break;
|
||||
@@ -640,7 +653,8 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
}
|
||||
|
||||
@@ -33,12 +33,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
uint16_t u16;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
int lock;
|
||||
int fixedaddress;
|
||||
MAYUSE(u16);
|
||||
MAYUSE(u8);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(lock);
|
||||
while(opcode==0x66) opcode = F8; // "unlimited" 0x66 as prefix for variable sized NOP
|
||||
if(opcode==0x2E) opcode = F8; // cs: is ignored
|
||||
if((opcode==0x26) || (opcode==0x2E) || (opcode==0x36) || (opcode==0x3E)) opcode = F8; // segment prefix are ignored
|
||||
switch(opcode) {
|
||||
|
||||
case 0x01:
|
||||
@@ -503,7 +505,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
INST_NAME("XCHG Ew, Gw");
|
||||
INST_NAME("(LOCK) XCHG Ew, Gw");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GETGD;
|
||||
@@ -516,7 +518,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
GETGD;
|
||||
UXTH(x14, gd, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
#if 0
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
@@ -529,6 +532,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
STRH_IMM8(x14, ed, fixedaddress);
|
||||
#endif
|
||||
SMDMB();
|
||||
BFI(gd, x1, 0, 16);
|
||||
}
|
||||
break;
|
||||
@@ -543,8 +547,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(ed, gd, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
|
||||
STRH_IMM8(gd, ed, fixedaddress);
|
||||
SMWRITELOCK(lock);
|
||||
}
|
||||
break;
|
||||
case 0x8B:
|
||||
@@ -557,7 +562,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(gd, ed, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
|
||||
SMREADLOCK(lock);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
BFI(gd, x1, 0, 16);
|
||||
}
|
||||
@@ -571,8 +577,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
BFI(ed, x1, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
STRH_IMM8(x1, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -584,7 +591,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(ed, xEmu, x2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(x1, xEmu, x2);
|
||||
@@ -641,6 +649,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOV, AX, Od");
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
SMREAD();
|
||||
LDRH_IMM8(x2, x2, 0);
|
||||
BFI(xEAX, x2, 0, 16);
|
||||
break;
|
||||
@@ -649,6 +658,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
STRH_IMM8(xEAX, x2, 0);
|
||||
SMWRITE();
|
||||
break;
|
||||
case 0xA5:
|
||||
INST_NAME("MOVSW");
|
||||
@@ -798,7 +808,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x1, u16);
|
||||
BFI(ed, x1, 0, 16);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
u16 = F16;
|
||||
MOVW(x1, u16);
|
||||
STRH_IMM8(x1, ed, fixedaddress);
|
||||
@@ -939,7 +949,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xA7:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3, 2);
|
||||
@@ -975,7 +986,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xAF:
|
||||
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
|
||||
SETFLAGS(X_ALL, SF_MAYSET);
|
||||
MAYSETFLAGS();
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
|
||||
B_NEXT(cEQ); // end of loop
|
||||
GETDIR(x3, 2);
|
||||
|
||||
+186
-105
@@ -27,9 +27,10 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
|
||||
a = fpu_get_scratch_quad(dyn); \
|
||||
VLD1Q_8(a, ed); \
|
||||
VLD1Q_8(a, ed); \
|
||||
}
|
||||
#define GETGX(a, w) \
|
||||
gd = (nextop&0x38)>>3; \
|
||||
@@ -70,8 +71,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
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, 4095-12, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -89,13 +91,14 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
STR_IMM9(x2, ed, fixedaddress+8);
|
||||
STR_IMM9(x3, ed, fixedaddress+12);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -108,11 +111,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
return addr;
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -129,14 +133,15 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v0, ed, fixedaddress);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
SMWRITE2();
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("UNPCKLPD Gx, Ex");
|
||||
@@ -146,7 +151,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0+1, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -159,7 +165,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1+1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0, NULL);
|
||||
VLDR_64(v0+1, ed, fixedaddress+4);
|
||||
}
|
||||
break;
|
||||
@@ -173,11 +180,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
return addr;
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0+1, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0+1,x2, x3);
|
||||
@@ -194,14 +202,15 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v0+1, ed, fixedaddress);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
@@ -220,8 +229,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1Q_32(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x29:
|
||||
@@ -233,8 +243,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_32(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -262,7 +273,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1Q_64(q1, ed);
|
||||
v0 = q1;
|
||||
}
|
||||
@@ -469,7 +481,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
ed = xEAX+(nextop&7); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);\
|
||||
LDRH_IMM8_COND(YES, x1, ed, fixedaddress); \
|
||||
ed = x1; \
|
||||
} \
|
||||
@@ -622,24 +635,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q1, 1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VADD_F64(q1, q1, q0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1, q1);
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VADD_F64(q1+1, q1+1, q0+1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1+1, q1+1);
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -649,24 +662,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q1, 1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VMUL_F64(q1, q1, q0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1, q1);
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VMUL_F64(q1+1, q1+1, q0+1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1+1, q1+1);
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -687,8 +700,26 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0);
|
||||
// need rounding?
|
||||
VCVTQ_S32_F32(v0, v1);
|
||||
if(v0>15)
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
q0 = v0;
|
||||
if(v1>15) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else
|
||||
q1 = v1;
|
||||
// need rounding!
|
||||
//VCVTQ_S32_F32(v0, v1);
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
VCVTR_S32_F32(q0*2+0, q1*2+0);
|
||||
VCVTR_S32_F32(q0*2+1, q1*2+1);
|
||||
VCVTR_S32_F32(q0*2+2, q1*2+2);
|
||||
VCVTR_S32_F32(q0*2+3, q1*2+3);
|
||||
if(q0!=v0) {
|
||||
VMOVQ(v0, q0);
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
case 0x5C:
|
||||
INST_NAME("SUBPD Gx, Ex");
|
||||
@@ -697,24 +728,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q1, 1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VSUB_F64(q1, q1, q0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1, q1);
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VSUB_F64(q1+1, q1+1, q0+1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1+1, q1+1);
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -737,24 +768,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q1, 1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VDIV_F64(q1, q1, q0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1, q1);
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VDIV_F64(q1+1, q1+1, q0+1);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, q1+1, q1+1);
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -893,7 +924,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0+1, v1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0+1, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
@@ -906,7 +938,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(q0+1, q1+1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0, NULL);
|
||||
VLDR_64(q0+1, ed, fixedaddress+8);
|
||||
}
|
||||
break;
|
||||
@@ -928,8 +961,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
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, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1Q_64(v0, ed);
|
||||
}
|
||||
break;
|
||||
@@ -952,6 +986,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVD(v0+1, v1+1);
|
||||
} else if (u8==0b10110001) {
|
||||
VREV64Q_32(v0, v1);
|
||||
} else if (u8==0b01010001) {
|
||||
VDUP_32(v0+1, v1, 1);
|
||||
VREV64Q_32(v0, v1);
|
||||
} else if (u8==0b00011011) {
|
||||
VREV64Q_32(v0, v1);
|
||||
VSWP(v0, v0+1);
|
||||
@@ -1040,8 +1077,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVQ(v0, q0);
|
||||
}
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = F8;
|
||||
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
|
||||
if(u8&3) {
|
||||
@@ -1068,7 +1106,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_16(q0, ed);
|
||||
}
|
||||
@@ -1081,6 +1120,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_16(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1089,7 +1129,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_16(q0, ed);
|
||||
}
|
||||
@@ -1099,6 +1140,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_16(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1106,7 +1148,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_16(q0, ed);
|
||||
}
|
||||
@@ -1119,6 +1162,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_16(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1135,7 +1179,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_32(q0, ed);
|
||||
}
|
||||
@@ -1148,6 +1193,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_32(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1156,7 +1202,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_32(q0, ed);
|
||||
}
|
||||
@@ -1166,6 +1213,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_32(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -1173,7 +1221,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_32(q0, ed);
|
||||
}
|
||||
@@ -1186,6 +1235,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_32(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1201,7 +1251,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q0, ed);
|
||||
}
|
||||
@@ -1214,6 +1265,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_64(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1222,7 +1274,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q0, ed);
|
||||
}
|
||||
@@ -1237,6 +1290,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_64(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1245,7 +1299,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q0, ed);
|
||||
}
|
||||
@@ -1258,6 +1313,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_64(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1266,7 +1322,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q0, ed);
|
||||
}
|
||||
@@ -1281,6 +1338,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
if((nextop&0xC0)!=0xC0) {
|
||||
VST1Q_64(q0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1320,8 +1378,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVfrDx_32(ed, v0, 0);
|
||||
} else {
|
||||
VMOVfrDx_32(x2, v0, 0); // to avoid Bus Error, using regular store
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x7F:
|
||||
@@ -1332,8 +1391,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_32(v0, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1346,7 +1406,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7); // no need for extract
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
SBFX(x1, gd, 4, 12); // r1 = (gw>>4);
|
||||
ADD_REG_LSL_IMM5(x1, ed, x1, 1); //(&ed)+=r1*2;
|
||||
LDRH_IMM8(x1, x1, fixedaddress);
|
||||
@@ -1388,7 +1449,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
|
||||
LDRH_IMM8(x14, x3, fixedaddress);
|
||||
@@ -1404,6 +1466,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ORR_REG_LSL_REG(ed, ed, x1, x2);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xAC:
|
||||
@@ -1436,7 +1499,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1456,7 +1519,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
|
||||
LDRH_IMM8(x14, x3, fixedaddress);
|
||||
@@ -1472,6 +1536,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
XOR_REG_LSL_REG(ed, ed, x1, x2);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1485,7 +1550,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
UXTB(x1, eb1, eb2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDRB_IMM9(x1, ed, fixedaddress);
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
@@ -1498,7 +1564,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX + (nextop&7);
|
||||
UXTH(x1, ed, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
@@ -1514,7 +1581,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1534,7 +1602,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1552,6 +1621,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1563,7 +1633,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1581,6 +1652,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1592,7 +1664,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRH_IMM8(x1, wback, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -1609,6 +1682,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
@@ -1626,7 +1700,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0; // no need for extract
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
|
||||
LDRH_IMM8(x14, x3, fixedaddress);
|
||||
@@ -1640,6 +1715,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
XOR_REG_LSL_REG(ed, ed, x1, x2);
|
||||
if(wback) {
|
||||
STRH_IMM8(ed, wback, fixedaddress);
|
||||
SMWRITE();
|
||||
}
|
||||
break;
|
||||
case 0xBC:
|
||||
@@ -1685,7 +1761,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
eb2 = (ed&4)>>2; // L or H
|
||||
SXTB(x1, eb1, eb2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRSB_IMM8(x1, ed, fixedaddress);
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
@@ -1756,7 +1833,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
ed = xEAX+(nextop&7);
|
||||
VMOVtoDx_16(v0+(u8/4), u8&3, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
|
||||
u8 = (F8)&7;
|
||||
VLD1LANE_16(v0+(u8/4), wback, u8&3);
|
||||
}
|
||||
@@ -1770,7 +1848,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
u8 = (F8)&7;
|
||||
VMOVfrDx_U16(gd, v0+(u8/4), (u8&3));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0, NULL);
|
||||
u8 = (F8)&7;
|
||||
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
|
||||
}
|
||||
@@ -1827,8 +1906,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VDUPQ_16(v0, q1, 0);
|
||||
VNEGNQ_16(v0, v0); // because we want SHR and not SHL
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
|
||||
VSHLQ_U16(q0, q0, v0);
|
||||
break;
|
||||
case 0xD2:
|
||||
@@ -1837,11 +1919,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VNEGN_32(v0, v0); // because we want SHR and not SHL
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
|
||||
VSHLQ_U32(q0, q0, v0);
|
||||
break;
|
||||
case 0xD3:
|
||||
@@ -1850,11 +1932,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VNEGN_32(v0, v0); // because we want SHR and not SHL
|
||||
VMOVL_S32(v0, v0); // 2*q1 in 64 bits now
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
|
||||
VSHLQ_U64(q0, q0, v0);
|
||||
break;
|
||||
case 0xD4:
|
||||
@@ -1883,14 +1965,15 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
// can be unaligned sometimes
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(q0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, q0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0xD7:
|
||||
@@ -1996,13 +2079,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
|
||||
VNEGN_16(v0, v0); // because we want SHR and not SHL
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
|
||||
VSHLQ_S16(q0, q0, v0);
|
||||
break;
|
||||
case 0xE2:
|
||||
@@ -2011,11 +2092,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VNEGN_32(v0, v0); // because we want SHR and not SHL
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
|
||||
VSHLQ_S32(q0, q0, v0);
|
||||
break;
|
||||
case 0xE3:
|
||||
@@ -2072,7 +2153,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VST1Q_64(v0, ed);
|
||||
}
|
||||
break;
|
||||
@@ -2145,12 +2226,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VSHLQ_U16(q0, q0, v0);
|
||||
break;
|
||||
case 0xF2:
|
||||
@@ -2159,10 +2238,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
|
||||
VMOVD(v0+1, v0);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VSHLQ_U32(q0, q0, v0);
|
||||
break;
|
||||
case 0xF3:
|
||||
@@ -2171,8 +2250,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VQMOVN_S64(v0, q1);
|
||||
VQMOVN_S32(v0, v0);
|
||||
VQMOVN_S16(v0, v0);
|
||||
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
|
||||
VSHLQ_U64(q0, q0, v0);
|
||||
break;
|
||||
case 0xF4:
|
||||
|
||||
@@ -30,6 +30,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
uint8_t ed, gd, u8;
|
||||
int fixedaddress;
|
||||
int32_t i32, j32;
|
||||
int16_t i16;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(gb1);
|
||||
@@ -37,10 +38,64 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
switch(opcode) {
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
INST_NAME("LOCK ADD Ew, Iw");
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ew, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add16c(dyn, ninst, ed, i16, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 0x1);
|
||||
B_MARK(cNE);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
|
||||
MARKLOCK;
|
||||
LDREXH(x1, wback);
|
||||
emit_add16c(dyn, ninst, x1, i16, x3, x14);
|
||||
STREXH(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
|
||||
MARK; // unaligned! also, not enough
|
||||
LDRH_IMM8(x1, wback, 0);
|
||||
LDREXB(x14, wback);
|
||||
BFI(x1, x14, 0, 8); // re-inject
|
||||
emit_add16c(dyn, ninst, x1, i16, x3, x14);
|
||||
STREXB(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STRH_IMM8(x1, wback, 0); // put the whole value
|
||||
}
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
SMDMB();
|
||||
break;
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Ew
|
||||
@@ -51,7 +106,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
emit_inc16(dyn, ninst, ed, x3, x14);
|
||||
EWBACK(x1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 1);
|
||||
B_MARK(cNE); // unaligned
|
||||
@@ -65,7 +120,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
|
||||
@@ -89,7 +144,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
emit_dec32(dyn, ninst, ed, x3, x14);
|
||||
EWBACK(x1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 1);
|
||||
B_MARK(cNE); // unaligned
|
||||
@@ -103,7 +158,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -123,7 +178,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
// default to NO LOCK
|
||||
addr-=2;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -30,9 +30,11 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
int cacheupd;
|
||||
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(cacheupd);
|
||||
|
||||
nextop = F8;
|
||||
|
||||
@@ -56,6 +58,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
STRH_REG(gd, x14, ed);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -70,6 +73,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(gd, ed, 0, 16);
|
||||
}
|
||||
} else { // mem <= reg
|
||||
SMREAD();
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, x14, ed, 0);
|
||||
}
|
||||
@@ -85,6 +89,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
POP1(x2);
|
||||
STR_REG_LSL_IMM5(x2, x14, ed, 0);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -96,6 +101,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
SMREAD();
|
||||
LDR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
@@ -108,6 +114,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
STR_IMM9(xEAX, x1, 0);
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
@@ -119,6 +126,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
SMREAD();
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
|
||||
PUSH1(x3);
|
||||
@@ -142,11 +150,11 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
|
||||
Bcond(NO, i32); \
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
|
||||
if(!dyn->insts[ninst].x86.barrier) \
|
||||
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
|
||||
jump_to_next(dyn, addr+i8, 0, ninst); \
|
||||
} else { \
|
||||
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
|
||||
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
|
||||
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
|
||||
Bcond(c__, i32); \
|
||||
} \
|
||||
|
||||
@@ -190,7 +190,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -210,7 +210,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -230,7 +230,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -251,7 +251,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -273,7 +273,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -293,7 +293,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -313,7 +313,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -333,7 +333,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
|
||||
@@ -575,10 +575,10 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
@@ -598,10 +598,10 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VSTR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
VMOVfrV(x2, s0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
@@ -617,10 +617,10 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VSTR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
VMOVfrV(x2, s0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
@@ -630,7 +630,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FLDENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
@@ -641,14 +641,12 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FLDCW Ew");
|
||||
GETEW(x1);
|
||||
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
|
||||
UBFX(x1, x1, 10, 2); // extract round
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
@@ -657,7 +655,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTCW Ew");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
wb1 = 1;
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw));
|
||||
|
||||
+115
-95
@@ -187,7 +187,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -202,13 +202,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
VMRS(x14); // Get FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVT_S32_F64(s0, v1);
|
||||
@@ -223,20 +223,16 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
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, x14); // x1 have the modified RPSCR reg
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
ed = x1; // will not be writen immediatly, so x1 is safe for now
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
// x1 already have FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
VMOVfrV(ed, s0);
|
||||
@@ -248,20 +244,16 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
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, x14); // x1 have the modified RPSCR reg
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
|
||||
ed = x1;
|
||||
}
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
// The FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVTR_S32_F64(s0, v1);
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (denormal and overflow only)
|
||||
VMOVfrV(ed, s0);
|
||||
@@ -273,7 +265,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("FLD tbyte");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
|
||||
// the FLD is immediatly followed by an FSTP
|
||||
LDR_IMM9(x2, ed, 0);
|
||||
@@ -283,21 +275,93 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
|
||||
nextop = F8; //0xDB
|
||||
nextop = F8; //modrm
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
STRH_IMM8(x14, ed, 8);
|
||||
} else {
|
||||
if(box86_x87_no80bits) {
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress + 4);
|
||||
VMOVtoV_D(v1, x2, x3);
|
||||
}
|
||||
} else {
|
||||
#if 0
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
CALL(arm_fld, -1, 0);
|
||||
#else
|
||||
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
|
||||
// copy 10bytes of *ED to STld(0)
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
|
||||
int a = -dyn->n.x87stack;
|
||||
if(a) {
|
||||
if(a<0) {
|
||||
SUB_IMM8(x3, x3, -a);
|
||||
} else {
|
||||
ADD_IMM8(x3, x3, a);
|
||||
}
|
||||
AND_IMM8(x3, x3, 7);
|
||||
}
|
||||
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
|
||||
MOVW(x14, sizeof(fpu_ld_t));
|
||||
MLA(x2, x3, x14, x2);
|
||||
LDR_IMM9(x14, ed, 0);
|
||||
STR_IMM9(x14, x2, 0);
|
||||
LDR_IMM9(x14, ed, 4);
|
||||
STR_IMM9(x14, x2, 4);
|
||||
LDRH_IMM8(x14, ed, 8);
|
||||
STRH_IMM8(x14, x2, 8);
|
||||
// convert 10bytes -> double
|
||||
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
|
||||
// store ref to STld(0).uref, but can be unaligned...
|
||||
VMOVfrV_D(x3, x14, 0);
|
||||
// also, store result to ST0
|
||||
VMOVD(v1, 0);
|
||||
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
|
||||
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
if(box86_x87_no80bits) {
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
} else {
|
||||
#if 0
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
x87_do_push_empty(dyn, ninst, x3);
|
||||
CALL(arm_fld, -1, 0);
|
||||
CALL(arm_fstp, -1, 0);
|
||||
#else
|
||||
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
|
||||
// copy 10bytes of *ED to STld(0)
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
// get top in x3
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
|
||||
int a = -dyn->n.x87stack;
|
||||
if(a) {
|
||||
@@ -308,85 +372,41 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
AND_IMM8(x3, x3, 7);
|
||||
}
|
||||
// get STld(0)
|
||||
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
|
||||
MOVW(x14, sizeof(fpu_ld_t));
|
||||
MLA(x2, x3, x14, x2);
|
||||
LDR_IMM9(x14, ed, 0);
|
||||
STR_IMM9(x14, x2, 0);
|
||||
LDR_IMM9(x14, ed, 4);
|
||||
STR_IMM9(x14, x2, 4);
|
||||
LDRH_IMM8(x14, ed, 8);
|
||||
STRH_IMM8(x14, x2, 8);
|
||||
// convert 10bytes -> double
|
||||
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
|
||||
// store ref to STld(0).uref, but can be unaligned...
|
||||
VMOVfrV_D(x3, x14, 0);
|
||||
// also, store result to ST0
|
||||
VMOVD(v1, 0);
|
||||
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
|
||||
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
|
||||
// compare uref with actual value, top is not used anymore, so x3 is free
|
||||
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
|
||||
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
|
||||
VMOVtoV_D(v2, x14, x3);
|
||||
VCEQ_32(v2, v2, v1); // same?
|
||||
VMOVfrV_D(x14, x3, v2);
|
||||
TSTS_REG_LSL_IMM5(x14, x3, 0);
|
||||
B_MARK(cEQ); // different, do the conversion
|
||||
// same... copy STld(0).ld
|
||||
LDR_IMM9(x14, x2, 0);
|
||||
LDR_IMM9(x3, x2, 4);
|
||||
STR_IMM9(x14, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
LDRH_IMM8(x14, x2, 8);
|
||||
STRH_IMM8(x14, ed, 8);
|
||||
B_MARK2(c__);
|
||||
MARK;
|
||||
// different, call D2LD
|
||||
SUB_IMM8(xSP, xSP, 8);
|
||||
VSTR_64(v1, xSP, 0);
|
||||
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
|
||||
ADD_IMM8(0, xSP, 8); //1st arg is &d
|
||||
if(ed!=x1) {
|
||||
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
|
||||
}
|
||||
CALL_S(D2LD, -2, 0);
|
||||
POP(xSP, (1<<xEmu)|(1<<xFlags));
|
||||
ADD_IMM8(xSP, xSP, 8);
|
||||
MARK2;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FSTP tbyte");
|
||||
#if 0
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
CALL(arm_fstp, -1, 0);
|
||||
#else
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
// get top in x3
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
|
||||
int a = -dyn->n.x87stack;
|
||||
if(a) {
|
||||
if(a<0) {
|
||||
SUB_IMM8(x3, x3, -a);
|
||||
} else {
|
||||
ADD_IMM8(x3, x3, a);
|
||||
}
|
||||
AND_IMM8(x3, x3, 7);
|
||||
}
|
||||
// get STld(0)
|
||||
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
|
||||
MOVW(x14, sizeof(fpu_ld_t));
|
||||
MLA(x2, x3, x14, x2);
|
||||
// compare uref with actual value, top is not used anymore, so x3 is free
|
||||
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
|
||||
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
|
||||
VMOVtoV_D(v2, x14, x3);
|
||||
VCEQ_32(v2, v2, v1); // same?
|
||||
VMOVfrV_D(x14, x3, v2);
|
||||
TSTS_REG_LSL_IMM5(x14, x3, 0);
|
||||
B_MARK(cEQ); // different, do the conversion
|
||||
// same... copy STld(0).ld
|
||||
LDR_IMM9(x14, x2, 0);
|
||||
LDR_IMM9(x3, x2, 4);
|
||||
STR_IMM9(x14, ed, 0);
|
||||
STR_IMM9(x3, ed, 4);
|
||||
LDRH_IMM8(x14, x2, 8);
|
||||
STRH_IMM8(x14, ed, 8);
|
||||
B_MARK2(c__);
|
||||
MARK;
|
||||
// different, call D2LD
|
||||
SUB_IMM8(xSP, xSP, 8);
|
||||
VSTR_64(v1, xSP, 0);
|
||||
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
|
||||
ADD_IMM8(0, xSP, 8); //1st arg is &d
|
||||
if(ed!=x1) {
|
||||
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
|
||||
}
|
||||
CALL_S(D2LD, -2, 0);
|
||||
POP(xSP, (1<<xEmu)|(1<<xFlags));
|
||||
ADD_IMM8(xSP, xSP, 8);
|
||||
MARK2;
|
||||
#endif
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -184,10 +184,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -200,10 +200,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -216,10 +216,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -233,10 +233,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -251,10 +251,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -267,10 +267,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -283,10 +283,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
@@ -299,10 +299,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(d1, wback, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, wback, fixedaddress);
|
||||
LDR_IMM9(x3, wback, fixedaddress+4);
|
||||
VMOVtoV_D(d1, x2, x3);
|
||||
|
||||
@@ -156,10 +156,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress + 4);
|
||||
VMOVtoV_D(v1, x2, x3);
|
||||
@@ -168,7 +168,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
INST_NAME("FISTTP i64, ST0");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fistt64, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
@@ -178,10 +178,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -192,10 +192,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VSTR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v1);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -205,20 +205,20 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 4:
|
||||
INST_NAME("FRSTOR m108byte");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_frstor, -1, 0);
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FSAVE m108byte");
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fsave, -1, 0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0, NULL);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
|
||||
if(dyn->n.x87stack) {
|
||||
|
||||
@@ -166,11 +166,27 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FDIVP STx, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
if(ST_IS_F(0)) {
|
||||
VDIV_F32(v2, v2, v1);
|
||||
} else {
|
||||
VDIV_F64(v2, v2, v1);
|
||||
}
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
if(ST_IS_F(0)) {
|
||||
VNEG_F32_cond(cNE, v2, v2);
|
||||
} else {
|
||||
VNEG_F64_cond(cNE, v2, v2);
|
||||
}
|
||||
VMSR(x14); // restore fpscr
|
||||
}
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0:
|
||||
INST_NAME("FILD ST0, Ew");
|
||||
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
|
||||
LDRSH_IMM8(x1, wback, fixedaddress);
|
||||
if(ST_IS_F(0)) {
|
||||
VMOVtoV(v1, x1);
|
||||
@@ -176,13 +176,13 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
INST_NAME("FISTTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
VMRS(x14); // get fpscr
|
||||
// x1 already have FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
if(ST_IS_F(0)) {
|
||||
@@ -203,15 +203,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 2:
|
||||
INST_NAME("FIST Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
// x1 already have FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
if(ST_IS_F(0)) {
|
||||
VCVTR_S32_F32(s0, v1);
|
||||
} else {
|
||||
@@ -229,15 +225,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 3:
|
||||
INST_NAME("FISTP Ew, ST0");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
|
||||
u8 = x87_setround(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
|
||||
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
|
||||
ed = x1;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
MSR_nzcvq_0();
|
||||
// x1 already have FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
if(ST_IS_F(0)) {
|
||||
VCVTR_S32_F32(s0, v1);
|
||||
} else {
|
||||
@@ -257,7 +249,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FBLD ST0, tbytes");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_do_push_empty(dyn, ninst, x1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fbld, -1, 0);
|
||||
break;
|
||||
@@ -267,7 +259,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(parity) {
|
||||
LDRD_IMM8(x2, wback, 0); // x2/x3 is 64bits
|
||||
} else {
|
||||
@@ -320,7 +312,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("FBSTP tbytes, ST0");
|
||||
MESSAGE(LOG_DUMP, "Need Optimization\n");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(fpu_fbst, -1, 0);
|
||||
x87_do_pop(dyn, ninst, x3);
|
||||
@@ -328,7 +320,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 7: // could be inlined for most thing, but is it usefull?
|
||||
INST_NAME("FISTP i64, ST0");
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
if(ninst
|
||||
&& dyn->insts[ninst-1].x86.addr
|
||||
&& *(uint8_t*)dyn->insts[ninst-1].x86.addr==0xDF
|
||||
@@ -343,7 +335,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
#if 1
|
||||
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
|
||||
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
fpu_get_scratch_double(dyn); // to alocate v0
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
#if 1
|
||||
@@ -413,7 +405,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VDIV_F64(v2, v1, v0); // v2 = abs(ST0)/(1<<32) : so 32 bits high part
|
||||
MSR_nzcvq_0();
|
||||
VMRS(x2); // get fpscr
|
||||
ORR_IMM8(x3, x2, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x2, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
VCVT_U32_F64(s0, v2); // convert high part to U32
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_or32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -63,9 +61,6 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_or32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -77,7 +72,7 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
ORR_IMM8(s1, s1, c, 0);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOV32(s3, c);}
|
||||
MOV32(s3, c);
|
||||
IFX(X_ALL) {
|
||||
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -109,8 +104,6 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_xor32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -145,9 +138,6 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_xor32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -159,7 +149,7 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
XOR_IMM8(s1, s1, c);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOV32(s3, c);}
|
||||
MOV32(s3, c);
|
||||
IFX(X_ALL) {
|
||||
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -191,8 +181,6 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_and32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -227,9 +215,6 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_and32);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -248,7 +233,7 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
BIC_IMM8(s1, s1, ~c, 0);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOV32(s3, c);}
|
||||
MOV32(s3, c);
|
||||
IFX(X_ALL) {
|
||||
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -281,8 +266,6 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_or8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -317,9 +300,6 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_or8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -354,8 +334,6 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_xor8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -390,9 +368,6 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_xor8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -427,8 +402,6 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_and8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -463,9 +436,6 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_and8);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -501,8 +471,6 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_or16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -537,9 +505,6 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_or16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -551,7 +516,7 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
ORR_IMM8(s1, s1, c, 0);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
MOVW(s3, c);
|
||||
IFX(X_ALL) {
|
||||
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -583,8 +548,6 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
|
||||
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_xor16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -619,9 +582,6 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_xor16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -633,7 +593,7 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
XOR_IMM8(s1, s1, c);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
MOVW(s3, c);
|
||||
IFX(X_ALL) {
|
||||
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -665,8 +625,6 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s3, d_and16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s3);
|
||||
@@ -701,9 +659,6 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
SET_DF(s4, d_and16);
|
||||
} else IFX(X_ALL) {
|
||||
SET_DFNONE(s4);
|
||||
@@ -715,7 +670,7 @@ void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
AND_IMM8(s1, s1, c);
|
||||
}
|
||||
} else {
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
MOVW(s3, c);
|
||||
IFX(X_ALL) {
|
||||
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
|
||||
@@ -76,7 +76,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.gen_flags==X_PEND || dyn->insts[ninst].x86.gen_flags==X_ALL)))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
if(c>=0 && c<256) {
|
||||
@@ -210,7 +210,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
|
||||
void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
|
||||
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.gen_flags==X_PEND || dyn->insts[ninst].x86.gen_flags==X_ALL)))
|
||||
{
|
||||
// special case when doing math on ESP and only PEND is needed: ignoring it!
|
||||
if(c>=0 && c<256) {
|
||||
|
||||
+158
-140
@@ -42,7 +42,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -51,7 +51,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_add8(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_add8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
|
||||
@@ -59,19 +59,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
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 = xEAX+(nextop&7);
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_add32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -79,13 +79,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x08:
|
||||
INST_NAME("LOCK OR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
@@ -95,7 +95,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_or8(dyn, ninst, x1, x2, x14, x3);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
GETGB(x2);
|
||||
LDREXB(x1, wback);
|
||||
@@ -104,19 +104,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
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((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_or32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -124,7 +124,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x10:
|
||||
INST_NAME("LOCK ADC Eb, Gb");
|
||||
@@ -132,7 +132,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -141,7 +141,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_adc8(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_adc8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
|
||||
@@ -149,7 +149,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ed, Gd");
|
||||
@@ -157,12 +157,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_adc32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -170,7 +170,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x18:
|
||||
INST_NAME("LOCK SBB Eb, Gb");
|
||||
@@ -178,7 +178,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -187,7 +187,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_sbb8(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_sbb8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
|
||||
@@ -195,7 +195,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x19:
|
||||
INST_NAME("LOCK SBB Ed, Gd");
|
||||
@@ -203,12 +203,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sbb32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -216,13 +216,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x20:
|
||||
INST_NAME("LOCK AND Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
@@ -232,7 +232,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_and8(dyn, ninst, x1, x2, x14, x3);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
GETGB(x2);
|
||||
LDREXB(x1, wback);
|
||||
@@ -241,19 +241,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("LOCK AND Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_and32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -261,14 +261,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x28:
|
||||
INST_NAME("LOCK SUB Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
@@ -277,7 +277,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_sub8(dyn, ninst, x1, x2, x14, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_sub8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
|
||||
@@ -285,19 +285,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x29:
|
||||
INST_NAME("LOCK SUB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sub32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -305,13 +305,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x38:
|
||||
INST_NAME("LOCK XOR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GETGB(x2);
|
||||
wback = (nextop&7);
|
||||
@@ -321,7 +321,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_xor8(dyn, ninst, x1, x2, x14, x3);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
GETGB(x2);
|
||||
LDREXB(x1, wback);
|
||||
@@ -330,19 +330,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0x39:
|
||||
INST_NAME("LOCK XOR Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_xor32(dyn, ninst, x1, gd, x3, x14);
|
||||
@@ -350,7 +350,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0x66:
|
||||
@@ -368,13 +368,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("LOCK ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 0x3);
|
||||
@@ -389,7 +389,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -403,19 +403,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0); // put the whole value
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 1: //OR
|
||||
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
@@ -424,19 +424,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 2: //ADC
|
||||
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
@@ -445,19 +445,19 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 3: //SBB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
@@ -466,18 +466,18 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 4: //AND
|
||||
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
@@ -486,7 +486,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
|
||||
@@ -496,8 +496,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 0x3);
|
||||
@@ -512,7 +512,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -526,7 +526,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0); // put the whole value
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 6: //XOR
|
||||
@@ -537,8 +537,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
|
||||
} else {
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
@@ -546,13 +546,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
}
|
||||
break;
|
||||
case 7: //CMP
|
||||
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETEDH(x1);
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
@@ -582,7 +582,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
#undef GO
|
||||
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
|
||||
case 0x87:
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
--addr;
|
||||
break;
|
||||
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
|
||||
@@ -593,7 +593,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
--addr;
|
||||
break;
|
||||
|
||||
@@ -603,7 +603,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xB0:
|
||||
INST_NAME("LOCK CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
@@ -613,7 +613,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = x2;
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x2, wback);
|
||||
ed = x2;
|
||||
@@ -640,7 +640,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
// AL != Eb
|
||||
BFI(xEAX, ed, 0, 8);
|
||||
MARK3;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
// done, do the cmp now
|
||||
UFLAG_IF {emit_cmp8(dyn, ninst, x1, x2, x3, x14);}
|
||||
break;
|
||||
@@ -649,53 +649,71 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
MARKLOCK;
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
TSTS_IMM8(wback, 3); // can be unaligned it seems
|
||||
LDREX_COND(cEQ, x1, wback);
|
||||
LDR_IMM9_COND(cNE, x1, wback, 0);
|
||||
LDREXB_COND(cNE, x3, wback); // dummy read, to arm the write...
|
||||
} else {
|
||||
LDREX(x1, wback);
|
||||
}
|
||||
ed = x1;
|
||||
}
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
if(wback) {
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
TSTS_IMM8(wback, 3);
|
||||
STREX_COND(cEQ, x14, gd, wback);
|
||||
STREXB_COND(cNE, x14, gd, wback);
|
||||
} else {
|
||||
STREX(x14, gd, wback);
|
||||
}
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
TSTS_IMM8(wback, 3); // anoying, all those test
|
||||
STR_IMM9_COND(cNE, gd, wback, 0);
|
||||
}
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);}
|
||||
} else {
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);}
|
||||
// same as no lock, all in regs...
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
MOV_REG(x3, ed);
|
||||
MOV_REG(ed, gd);
|
||||
emit_cmp32(dyn, ninst, xEAX, x3, x1, x14);
|
||||
B_NEXT(c__);
|
||||
MARK;
|
||||
// EAX != Ed
|
||||
emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);
|
||||
MOV_REG(xEAX, ed);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
ed = x1;
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
if(!fixedaddress) {
|
||||
// alignment is undetermined
|
||||
TSTS_IMM8(wback, 3);
|
||||
B_MARK2(cNE);
|
||||
MARKLOCK;
|
||||
// aligned
|
||||
LDREX(ed, wback);
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STREX(x14, gd, wback);
|
||||
SMDMB();
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
B_MARK(c__);
|
||||
}
|
||||
// unaligned
|
||||
MARK2;
|
||||
LDR_IMM9(x1, wback, 0);
|
||||
LDREXB( x3, wback); // dummy read, to arm the write...
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STREXB(x14, gd, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARK2(cNE);
|
||||
STR_IMM9(gd, wback, 0);
|
||||
SMDMB();
|
||||
} else {
|
||||
MARKLOCK;
|
||||
// alignment is good
|
||||
LDREX(ed, wback);
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
STREX(x14, gd, wback);
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
SMDMB();
|
||||
}
|
||||
// end of EAX == Ed or EAX != Ed
|
||||
MARK;
|
||||
UFLAG_IF { MOV_REG(x2, xEAX); }
|
||||
MOV_REG(xEAX, ed);
|
||||
UFLAG_IF { emit_cmp32(dyn, ninst, x2, ed, x3, x14); }
|
||||
}
|
||||
// done
|
||||
B_MARK3(c__); // not next, in case its called with a LOCK prefix
|
||||
MARK;
|
||||
// EAX != Ed
|
||||
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);}
|
||||
MOV_REG(xEAX, ed);
|
||||
MARK3
|
||||
DMB_ISH();
|
||||
break;
|
||||
case 0xB3:
|
||||
INST_NAME("LOCK BTR Ed, Gd");
|
||||
@@ -703,12 +721,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
wback = x3;
|
||||
@@ -729,12 +747,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
MARK3;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7) {
|
||||
case 4:
|
||||
INST_NAME("(LOCK) BT Ed, Ib");
|
||||
@@ -744,7 +762,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0, LOCK_LOCK);
|
||||
LDR_IMM9(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
@@ -767,7 +785,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(gd, u8&0x1f);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
u8 = F8;
|
||||
ed = x1;
|
||||
MOVW(gd, u8&0x1f);
|
||||
@@ -798,7 +816,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(gd, u8&0x1f);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
u8 = F8;
|
||||
ed = x1;
|
||||
MOVW(gd, u8&0x1f);
|
||||
@@ -821,7 +839,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0xBB:
|
||||
INST_NAME("LOCK BTC Ed, Gd");
|
||||
@@ -829,12 +847,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
SET_DFNONE(x1);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
MARKLOCK;
|
||||
@@ -852,14 +870,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
CMPS_IMM8(x14, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
INST_NAME("LOCK XADD Gb, Eb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
GETGB(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
@@ -869,7 +887,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
wb1 = 0;
|
||||
ed = x2;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
LDREXB(x2, wback);
|
||||
wb1 = 1;
|
||||
@@ -884,14 +902,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
case 0xC1:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(gd!=ed) {
|
||||
@@ -901,7 +919,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 3);
|
||||
B_MARK(cNE); // unaligned
|
||||
@@ -937,7 +955,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
MOV_REG(gd, x1);
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
@@ -946,8 +964,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 1:
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
DMB_ISH();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1);
|
||||
SMDMB();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
MARKLOCK;
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
|
||||
TSTS_IMM8(wback, 7);
|
||||
@@ -983,7 +1001,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV_REG(xEDX, x3);
|
||||
MOVW(x1, 0);
|
||||
MARK3;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
BFI(xFlags, x1, F_ZF, 1);
|
||||
break;
|
||||
default:
|
||||
@@ -999,7 +1017,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0: // INC Ed
|
||||
@@ -1009,7 +1027,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_inc32(dyn, ninst, ed, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 3);
|
||||
B_MARK(cNE); // unaligned
|
||||
@@ -1023,7 +1041,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -1046,7 +1064,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_dec32(dyn, ninst, ed, x3, x14);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
|
||||
if(!fixedaddress) {
|
||||
TSTS_IMM8(wback, 3);
|
||||
B_MARK(cNE); // unaligned
|
||||
@@ -1060,7 +1078,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
if(!fixedaddress) {
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
B_NEXT(c__);
|
||||
}
|
||||
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
|
||||
@@ -1080,7 +1098,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
// default to NO LOCK
|
||||
addr-=2;
|
||||
}
|
||||
DMB_ISH();
|
||||
SMDMB();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -29,11 +29,12 @@
|
||||
} else { \
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3); \
|
||||
a = fpu_get_scratch_double(dyn); \
|
||||
SMREAD(); \
|
||||
if(parity) { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL); \
|
||||
VLDR_64(a, ed, fixedaddress); \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);\
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);\
|
||||
LDR_IMM9(x2, ed, fixedaddress+0); \
|
||||
LDR_IMM9(x3, ed, fixedaddress+4); \
|
||||
VMOVtoV_D(a, x2, x3); \
|
||||
@@ -72,8 +73,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
VMOVD(v0, d0);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -90,9 +92,10 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVD(d0, v0);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -104,8 +107,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, d0);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -132,28 +136,50 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VLDR_64(d0, ed, fixedaddress);
|
||||
}
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x14); // Get FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VCVT_S32_F64(s0, d0);
|
||||
VMOVfrV(gd, s0);
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
|
||||
VMSR(x14); // put back values
|
||||
}
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("CVTSD2SI Gd, Ex");
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
else
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VLDR_64(d0, ed, fixedaddress);
|
||||
}
|
||||
VCVTR_S32_F64(s0, d0);
|
||||
VMOVfrV(gd, s0);
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
|
||||
@@ -165,7 +191,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(d0, 0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
@@ -174,6 +200,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, v0, v0);
|
||||
VMSR(x14); // restore FPSCR
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -185,7 +212,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(d0, 0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
@@ -194,6 +221,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, v0, v0);
|
||||
VMSR(x14); // restore FPSCR
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -204,7 +232,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(d0, 0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
@@ -213,6 +241,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, v0, v0);
|
||||
VMSR(x14); // restore FPSCR
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -239,7 +268,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(d0, 0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
@@ -248,6 +277,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, v0, v0);
|
||||
VMSR(x14); // restore FPSCR
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -269,7 +299,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(d0, 0);
|
||||
if(!box86_dynarec_fastnan) {
|
||||
VMRS(x14); // get fpscr
|
||||
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
@@ -278,6 +308,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
VNEG_F64_cond(cNE, v0, v0);
|
||||
VMSR(x14); // restore FPSCR
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -300,7 +331,8 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -335,7 +367,8 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -347,6 +380,24 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
case 0x82:
|
||||
case 0x83:
|
||||
case 0x84:
|
||||
case 0x85:
|
||||
case 0x86:
|
||||
case 0x87:
|
||||
case 0x88:
|
||||
case 0x89:
|
||||
case 0x8A:
|
||||
case 0x8B:
|
||||
case 0x8C:
|
||||
case 0x8D:
|
||||
case 0x8E:
|
||||
case 0x8F:
|
||||
return dynarec0F(dyn, addr-1, ip, ninst, ok, need_epilog);
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPSD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -378,6 +429,33 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOV_64(v0, v1);
|
||||
break;
|
||||
|
||||
case 0xE6:
|
||||
INST_NAME("CVTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_8(v1, ed);
|
||||
}
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
if(v0<16) {
|
||||
VCVTR_S32_F64(v0*2, v1);
|
||||
VCVTR_S32_F64(v0*2+1, v1+1);
|
||||
} else {
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VCVTR_S32_F64(d0*2, v1);
|
||||
VCVTR_S32_F64(d0*2+1, v1+1);
|
||||
VMOVD(v0, d0);
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
VEOR(v0+1, v0+1, v0+1);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("LDDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -387,8 +465,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
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, 4095-12, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
|
||||
@@ -37,8 +37,9 @@
|
||||
b = fpu_get_scratch_double(dyn); \
|
||||
a = b*2; \
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2); \
|
||||
SMREAD(); \
|
||||
if(parity) { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL); \
|
||||
VLDR_32(a, ed, fixedaddress); \
|
||||
} else { \
|
||||
GETED; \
|
||||
@@ -102,12 +103,13 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
SMREAD();
|
||||
if(parity && (v0<16)) {
|
||||
VEORQ(v0, v0, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VLDR_32(v0*2, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
|
||||
VEORQ(v0, v0, v0);
|
||||
VMOVtoDx_32(v0, 0, x2);
|
||||
@@ -140,13 +142,14 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity && (v0<16)) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
|
||||
VSTR_32(v0*2, ed, fixedaddress);
|
||||
} else {
|
||||
VMOVfrDx_32(x2, v0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
@@ -156,7 +159,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
@@ -172,7 +176,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
@@ -229,21 +234,37 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOV_32(s0, d0*2);
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
}
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x14); // Get FPCSR reg to clear exceptions flags
|
||||
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(x3, x3, 0b10011111, 0);
|
||||
VMSR(x3);
|
||||
}
|
||||
VCVT_S32_F32(s0, s0);
|
||||
VMOVfrV(gd, s0);
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
|
||||
VMSR(x14); // put back values
|
||||
}
|
||||
break;
|
||||
case 0x2D:
|
||||
INST_NAME("CVTSS2SI Gd, Ex");
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
if(!box86_dynarec_fastround)
|
||||
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
|
||||
else
|
||||
u8 = sse_setround(dyn, ninst, x1, x2, x14);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
s0 = fpu_get_scratch_single(dyn);
|
||||
@@ -258,17 +279,23 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOV_32(s0, d0*2);
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
}
|
||||
VCVTR_S32_F32(s0, s0);
|
||||
VMOVfrV(gd, s0);
|
||||
if(!box86_dynarec_fastround) {
|
||||
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
|
||||
TSTS_IMM8_ROR(x3, 0b00000001, 0);
|
||||
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
|
||||
}
|
||||
x87_restoreround(dyn, ninst, u8);
|
||||
break;
|
||||
|
||||
@@ -396,7 +423,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
@@ -500,8 +528,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
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, 4095-12, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -514,14 +543,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("PSHUFHW Gx, Ex, Ib");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(v1, ed);
|
||||
}
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
u8 = F8;
|
||||
// only high part need to be shuffled. VTBL only handle 8bits value, so the 16bits shuffles need to be changed in 8bits
|
||||
u32 = 0;
|
||||
@@ -554,8 +584,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, v1);
|
||||
} else {
|
||||
SMREAD();
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
|
||||
VLD1_64(v0, ed);
|
||||
}
|
||||
VEOR(v0+1, v0+1, v0+1);
|
||||
@@ -569,13 +600,14 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
STR_IMM9(x2, ed, fixedaddress+8);
|
||||
STR_IMM9(x3, ed, fixedaddress+12);
|
||||
SMWRITE2();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -640,11 +672,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOV_64(v0, v1);
|
||||
} else {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
@@ -666,11 +699,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
} else {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
SMREAD();
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
|
||||
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
|
||||
@@ -491,7 +491,7 @@ int getNominalPred(dynarec_arm_t* dyn, int ninst) {
|
||||
return dyn->insts[ninst].pred[0];
|
||||
}
|
||||
|
||||
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
int i2 = dyn->insts[ninst].x86.jmp_insts;
|
||||
if(i2<0)
|
||||
return 1;
|
||||
@@ -754,3 +754,45 @@ int isInstClean(dynarec_arm_t* dyn, int ninst)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
int jmp = dyn->insts[ninst].x86.jmp_insts;
|
||||
if(jmp<0)
|
||||
return 0;
|
||||
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
|
||||
return 0;
|
||||
/* if((dyn->f.pending!=SF_SET)
|
||||
&& (dyn->f.pending!=SF_SET_PENDING)) {
|
||||
if(dyn->f.pending!=SF_PENDING) {*/
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: return 0;
|
||||
case SF_SET:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
case SF_SET_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
case SF_PENDING:
|
||||
if(dyn->insts[ninst].f_exit.pending!=SF_SET
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
|
||||
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
|
||||
return 1;
|
||||
else
|
||||
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
|
||||
int ret = 0;
|
||||
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
|
||||
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
|
||||
return ret;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
|
||||
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
|
||||
|
||||
// FPU Cache transformation (for loops)
|
||||
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int i1);
|
||||
int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
|
||||
|
||||
// Undo the changes of a neoncache to get the status before the instruction
|
||||
void neoncacheUnwind(neoncache_t* cache);
|
||||
|
||||
@@ -27,8 +27,11 @@
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask, int getfixonly)
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask, int getfixonly, int* l)
|
||||
{
|
||||
int lock = l?((l==LOCK_LOCK)?1:2):0;
|
||||
if(lock==2)
|
||||
*l = (box86_dynarec_strongmem==2)?1:0;
|
||||
uint8_t ret = 2;
|
||||
uint8_t scratch = 2;
|
||||
*fixaddress = 0;
|
||||
@@ -51,6 +54,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
*fixaddress = tmp;
|
||||
}
|
||||
} else {
|
||||
switch(lock) {
|
||||
case 1: addLockAddress(tmp); break;
|
||||
case 2: if(isLockAddress(tmp)) *l=1; break;
|
||||
}
|
||||
MOV32(ret, tmp);
|
||||
}
|
||||
} else {
|
||||
@@ -244,6 +251,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
}
|
||||
PASS3(void* epilog = arm_epilog);
|
||||
MOV32_(2, (uintptr_t)epilog);
|
||||
SMEND();
|
||||
BX(2);
|
||||
}
|
||||
|
||||
@@ -270,6 +278,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
SMEND();
|
||||
BX(x3);
|
||||
}
|
||||
|
||||
@@ -286,6 +295,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
SMEND();
|
||||
BX(x3);
|
||||
}
|
||||
|
||||
@@ -308,6 +318,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
#ifdef HAVE_TRACE
|
||||
MOV_REG(x2, 15); // move current PC to x2, for tracing
|
||||
#endif
|
||||
SMEND();
|
||||
BX(x3);
|
||||
}
|
||||
|
||||
@@ -330,6 +341,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
SET_DFNONE(x1);
|
||||
// Ret....
|
||||
MOV32_(x2, (uintptr_t)arm_epilog); // epilog on purpose, CS might have changed!
|
||||
SMEND();
|
||||
BX(x2);
|
||||
}
|
||||
|
||||
@@ -471,7 +483,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
|
||||
if(s1!=xFlags) mask=1<<xFlags; else mask=1<<x3;
|
||||
}
|
||||
PUSH(xSP, (1<<xEmu) | mask);
|
||||
fpu_pushcache(dyn, ninst, reg);
|
||||
fpu_pushcache(dyn, ninst, s1);
|
||||
if(saveflags) {
|
||||
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
}
|
||||
@@ -483,7 +495,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
|
||||
#ifdef ARM_SOFTFP
|
||||
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
|
||||
#endif
|
||||
fpu_popcache(dyn, ninst, reg);
|
||||
fpu_popcache(dyn, ninst, s1);
|
||||
POP(xSP, (1<<xEmu) | mask);
|
||||
if(saveflags) {
|
||||
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
|
||||
@@ -1059,15 +1071,13 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|
||||
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
|
||||
}
|
||||
|
||||
static int round_map[] = {0, 2, 1, 3}; // map x86 -> arm round flag
|
||||
|
||||
// Set rounding according to cw flags, return reg to restore flags
|
||||
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
|
||||
UBFX(s2, s1, 10, 2); // extract round...
|
||||
MOV32(s1, round_map);
|
||||
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
|
||||
UBFX(s1, s1, 10, 2); // extract round...
|
||||
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
|
||||
BFI(s2, s1, 1, 1);
|
||||
VMRS(s1); // get fpscr
|
||||
MOV_REG(s3, s1);
|
||||
BFI(s1, s2, 22, 2); // inject new round
|
||||
@@ -1075,6 +1085,21 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
return s3;
|
||||
}
|
||||
|
||||
// Set rounding according to cw flags, also enable exception and reset counter, return reg to restore flags
|
||||
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
|
||||
UBFX(s1, s1, 10, 2); // extract round...
|
||||
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
|
||||
BFI(s2, s1, 1, 1);
|
||||
VMRS(s3); // get fpscr
|
||||
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
|
||||
BFI(s1, s2, 22, 2); // inject new round
|
||||
VMSR(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
|
||||
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
|
||||
{
|
||||
int i1, i2, i3;
|
||||
@@ -1098,10 +1123,10 @@ void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags
|
||||
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
UBFX(s2, s1, 13, 2); // extract round...
|
||||
MOV32(s1, round_map);
|
||||
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
UBFX(s1, s1, 13, 2); // extract round...
|
||||
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
|
||||
BFI(s2, s1, 1, 1);
|
||||
VMRS(s1); // get fpscr
|
||||
MOV_REG(s3, s1);
|
||||
BFI(s1, s2, 22, 2); // inject new round
|
||||
@@ -1109,6 +1134,21 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
return s3;
|
||||
}
|
||||
|
||||
// Set rounding according to mxcsr flags, also enable exception and reset counter, return reg to restore flags
|
||||
int sse_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
|
||||
UBFX(s1, s1, 13, 2); // extract round...
|
||||
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
|
||||
BFI(s2, s1, 1, 1);
|
||||
VMRS(s3); // get fpscr
|
||||
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
|
||||
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
|
||||
BFI(s1, s2, 22, 2); // inject new round
|
||||
VMSR(s1); // put new fpscr
|
||||
return s3;
|
||||
}
|
||||
|
||||
// Restore round flag
|
||||
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
@@ -1326,7 +1366,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
MOV_REG(s1, xSP);
|
||||
for (int i=16; i<32; ++i) { // should use VSTM?
|
||||
if(dyn->n.fpuused[i-8]) {
|
||||
VST1_32_W(i, s1);
|
||||
VST1_64_W(i, s1);
|
||||
}
|
||||
}
|
||||
MESSAGE(LOG_DUMP, "\t------- Push FPU Cache (%d)\n", n);
|
||||
@@ -1345,7 +1385,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
MOV_REG(s1, xSP);
|
||||
for (int i=16; i<32; ++i) {
|
||||
if(dyn->n.fpuused[i-8]) {
|
||||
VLD1_32_W(i, s1);
|
||||
VLD1_64_W(i, s1);
|
||||
}
|
||||
}
|
||||
if(n>=8) {
|
||||
@@ -1589,7 +1629,7 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
|
||||
cache->neoncache[i].v = 0;
|
||||
}
|
||||
|
||||
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
#if STEP > 1
|
||||
int i2 = dyn->insts[ninst].x86.jmp_insts;
|
||||
@@ -1747,6 +1787,59 @@ void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
|
||||
#endif
|
||||
}
|
||||
static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
{
|
||||
#if STEP > 1
|
||||
int j32;
|
||||
int jmp = dyn->insts[ninst].x86.jmp_insts;
|
||||
if(jmp<0)
|
||||
return;
|
||||
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
|
||||
return;
|
||||
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
|
||||
int go = 0;
|
||||
switch (dyn->insts[jmp].f_entry.pending) {
|
||||
case SF_UNKNOWN: break;
|
||||
case SF_SET:
|
||||
if(dyn->f.pending!=SF_SET && dyn->f.pending!=SF_SET_PENDING)
|
||||
go = 1;
|
||||
break;
|
||||
case SF_SET_PENDING:
|
||||
if(dyn->f.pending!=SF_SET
|
||||
&& dyn->f.pending!=SF_SET_PENDING
|
||||
&& dyn->f.pending!=SF_PENDING)
|
||||
go = 1;
|
||||
break;
|
||||
case SF_PENDING:
|
||||
if(dyn->f.pending!=SF_SET
|
||||
&& dyn->f.pending!=SF_SET_PENDING
|
||||
&& dyn->f.pending!=SF_PENDING)
|
||||
go = 1;
|
||||
else
|
||||
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
|
||||
break;
|
||||
}
|
||||
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
|
||||
go = 1;
|
||||
if(go) {
|
||||
if(dyn->f.pending!=SF_PENDING) {
|
||||
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
j32 = (GETMARK3)-(dyn->arm_size+8);
|
||||
Bcond(cEQ, j32);
|
||||
}
|
||||
CALL_(UpdateFlags, -1, 0);
|
||||
MARK3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) {
|
||||
if(cacheupd&1)
|
||||
fpuCacheTransform(dyn, ninst, s1, s2, s3);
|
||||
if(cacheupd&2)
|
||||
flagsCacheTransform(dyn, ninst, s1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
|
||||
@@ -27,6 +27,33 @@
|
||||
#define PKip(a) *(uint8_t*)(ip+a)
|
||||
#define PKa(a) *(uint8_t*)(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 && box86_dynarec_strongmem>1) {SMDMB();}
|
||||
// Opcode will read with option forced lock
|
||||
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box86_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(box86_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 && box86_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
|
||||
|
||||
// GETGD get x86 register in gd
|
||||
#define GETGD gd = xEAX+((nextop&0x38)>>3)
|
||||
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
@@ -34,7 +61,8 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL); \
|
||||
LDR_IMM9(x1, wback, fixedaddress); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -43,7 +71,8 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0, NULL); \
|
||||
LDR_IMM9(hint, wback, fixedaddress); \
|
||||
ed = hint; \
|
||||
}
|
||||
@@ -53,20 +82,22 @@
|
||||
MOV_REG(ret, ed); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0, NULL); \
|
||||
ed = ret; \
|
||||
LDR_IMM9(ed, wback, fixedaddress); \
|
||||
}
|
||||
// Write back ed in wback (if wback not 0)
|
||||
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress);}
|
||||
// Send back wb to either ed or wback
|
||||
#define SBACK(wb) if(wback) {STR_IMM9(wb, wback, fixedaddress);} else {MOV_REG(ed, wb);}
|
||||
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE();}
|
||||
// Write back ed in wback (if wback not 0) (SMWRITE2 version)
|
||||
#define WBACK2 if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE2();}
|
||||
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
|
||||
#define GETEDO(O) if((nextop&0xC0)==0xC0) { \
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
|
||||
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
|
||||
ed = x1; \
|
||||
}
|
||||
@@ -75,13 +106,14 @@
|
||||
ed = xEAX+(nextop&7); \
|
||||
wback = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
|
||||
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
|
||||
if(wback != x2) wback = x2; \
|
||||
LDR_IMM9(x1, wback, 0); \
|
||||
ed = x1; \
|
||||
}
|
||||
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0);}
|
||||
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0); SMWRITE();}
|
||||
//FAKEELike GETED, but doesn't get anything
|
||||
#define FAKEED if((nextop&0xC0)!=0xC0) { \
|
||||
addr = fakeed(dyn, addr, ninst, nextop); \
|
||||
@@ -95,7 +127,8 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0, NULL); \
|
||||
LDRH_IMM8(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
@@ -107,7 +140,8 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
|
||||
LDRH_IMM8(i, wback, fixedaddress); \
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
@@ -119,15 +153,16 @@
|
||||
ed = i; \
|
||||
wb1 = 0; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
|
||||
LDRSH_IMM8(i, wback, fixedaddress);\
|
||||
ed = i; \
|
||||
wb1 = 1; \
|
||||
}
|
||||
// Write ed back to original register / memory
|
||||
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress);} else {BFI(wback, ed, 0, 16);}
|
||||
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, 0, 16);}
|
||||
// Write w back to original register / memory
|
||||
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress);} else {BFI(wback, w, 0, 16);}
|
||||
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress); SMWRITE();} else {BFI(wback, w, 0, 16);}
|
||||
// Write back gd in correct register
|
||||
#define GWBACK BFI((xEAX+((nextop&0x38)>>3)), gd, 0, 16);
|
||||
//GETEB will use i for ed, and can use r3 for wback.
|
||||
@@ -139,7 +174,8 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
@@ -153,7 +189,8 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL); \
|
||||
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
|
||||
if(wback!=x3) wback = x3; \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
@@ -169,13 +206,16 @@
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
|
||||
SMREAD(); \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
|
||||
LDRSB_IMM8(i, wback, fixedaddress);\
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
// Write eb (ed) back to original register / memory
|
||||
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress);} else {BFI(wback, ed, wb2*8, 8);}
|
||||
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, wb2*8, 8);}
|
||||
// Write eb (ed) back to original register / memory (SMWRITE2 version)
|
||||
#define EBBACK2 if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE2();} else {BFI(wback, ed, wb2*8, 8);}
|
||||
//GETGB will use i for gd
|
||||
#define GETGB(i) gd = (nextop&0x38)>>3; \
|
||||
gb2 = ((gd&4)>>2); \
|
||||
@@ -258,11 +298,11 @@
|
||||
j32 = GETMARKLOCK-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
|
||||
#define IFX(A) if((dyn->insts[ninst].x86.need_flags&(A)))
|
||||
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
|
||||
#define IFXX(A) if((dyn->insts[ninst].x86.need_flags==(A)))
|
||||
#define IFX2X(A, B) if((dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if((dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
|
||||
#define IFX(A) if((dyn->insts[ninst].x86.gen_flags&(A)))
|
||||
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.gen_flags&(X_PEND) || !dyn->insts[ninst].x86.gen_flags))
|
||||
#define IFXX(A) if((dyn->insts[ninst].x86.gen_flags==(A)))
|
||||
#define IFX2X(A, B) if((dyn->insts[ninst].x86.gen_flags==(A) || dyn->insts[ninst].x86.gen_flags==(B) || dyn->insts[ninst].x86.gen_flags==((A)|(B))))
|
||||
#define IFXN(A, B) if((dyn->insts[ninst].x86.gen_flags&(A) && !(dyn->insts[ninst].x86.gen_flags&(B))))
|
||||
|
||||
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOM(s1, s2) \
|
||||
@@ -297,9 +337,13 @@
|
||||
#define SET_NODF() dyn->f.dfnone = 0
|
||||
#define SET_DFOK() dyn->f.dfnone = 1
|
||||
|
||||
#ifndef MAYSETFLAGS
|
||||
#define MAYSETFLAGS()
|
||||
#endif
|
||||
|
||||
#ifndef READFLAGS
|
||||
#define READFLAGS(A) \
|
||||
if((dyn->f.pending!=SF_SET) \
|
||||
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
|
||||
&& (dyn->f.pending!=SF_SET_PENDING)) { \
|
||||
if(dyn->f.pending!=SF_PENDING) { \
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
|
||||
@@ -313,23 +357,21 @@
|
||||
SET_DFOK(); \
|
||||
}
|
||||
#endif
|
||||
// SF_MAYSET doesn't change the flags status cache
|
||||
// it also doesn't consume any needed flags
|
||||
|
||||
#ifndef SETFLAGS
|
||||
#define SETFLAGS(A, B) \
|
||||
if(dyn->f.pending!=SF_SET \
|
||||
&& (B==SF_SUBSET || B==SF_SUBSET_PENDING) \
|
||||
&& (dyn->insts[ninst].x86.need_flags&(~((A)|((B==SF_SUBSET_PENDING)?X_PEND:0))))) \
|
||||
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
|
||||
if(dyn->insts[ninst].x86.need_flags) switch(B) { \
|
||||
&& ((B)&SF_SUB) \
|
||||
&& (dyn->insts[ninst].x86.gen_flags&(~(A)))) \
|
||||
READFLAGS(((dyn->insts[ninst].x86.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x86.gen_flags)&(~(A)));\
|
||||
if(dyn->insts[ninst].x86.gen_flags) switch(B) { \
|
||||
case SF_SUBSET: \
|
||||
case SF_SET: dyn->f.pending = SF_SET; break; \
|
||||
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
|
||||
case SF_SUBSET_PENDING: \
|
||||
case SF_SET_PENDING: \
|
||||
dyn->f.pending = (dyn->insts[ninst].x86.need_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
|
||||
dyn->f.pending = (dyn->insts[ninst].x86.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
|
||||
break; \
|
||||
case SF_MAYSET: break; \
|
||||
} else dyn->f.pending = SF_SET
|
||||
#endif
|
||||
#ifndef JUMP
|
||||
@@ -341,12 +383,12 @@
|
||||
#ifndef BARRIER_NEXT
|
||||
#define BARRIER_NEXT(A)
|
||||
#endif
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts[ninst].x86.need_flags)
|
||||
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
|
||||
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
|
||||
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
|
||||
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.gen_flags) {SET_DF(r, A)}
|
||||
#define UFLAG_IF if(dyn->insts[ninst].x86.gen_flags)
|
||||
#ifndef DEFAULT
|
||||
#define DEFAULT *ok = -1; BARRIER(BARRIER_NOFLAGS)
|
||||
#endif
|
||||
@@ -492,9 +534,11 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
#define x87_reget_st STEPNAME(x87_reget_st)
|
||||
#define x87_stackcount STEPNAME(x87_stackcount)
|
||||
#define x87_setround STEPNAME(x87_setround)
|
||||
#define x87_setround_reset STEPNAME(x87_setround_reset)
|
||||
#define x87_restoreround STEPNAME(x87_restoreround)
|
||||
#define x87_swapreg STEPNAME(x87_swapreg)
|
||||
#define sse_setround STEPNAME(sse_setround)
|
||||
#define sse_setround_reset STEPNAME(sse_setround_reset)
|
||||
#define mmx_get_reg STEPNAME(mmx_get_reg)
|
||||
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
|
||||
#define sse_get_reg STEPNAME(sse_get_reg)
|
||||
@@ -515,10 +559,10 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
|
||||
// put back (if needed) the single reg in place
|
||||
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
|
||||
|
||||
#define fpuCacheTransform STEPNAME(fpuCacheTransform)
|
||||
#define CacheTransform STEPNAME(CacheTransform)
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly);
|
||||
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly, int* l);
|
||||
|
||||
/* setup r2 to address pointed by */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
|
||||
@@ -639,19 +683,23 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
|
||||
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
|
||||
// Set rounding according to cw flags, return reg to restore flags
|
||||
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// Set rounding according to cw flags, return reg to restore flags, also enable exceptions and reset counters
|
||||
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// Restore round flag
|
||||
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
|
||||
// swap 2 x87 regs
|
||||
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b);
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags
|
||||
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// Set rounding according to mxcsr flags, return reg to restore flags, also enable exceptions and reset counters
|
||||
int sse_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
|
||||
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
|
||||
|
||||
#if STEP < 2
|
||||
#define CHECK_CACHE() 0
|
||||
#else
|
||||
#define CHECK_CACHE() fpuCacheNeedsTransform(dyn, ninst)
|
||||
#define CHECK_CACHE() (cacheupd = CacheNeedsTransform(dyn, ninst))
|
||||
#endif
|
||||
|
||||
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
#include "custommem.h"
|
||||
#include "elfloader.h"
|
||||
|
||||
#ifndef STEP
|
||||
#error No STEP defined
|
||||
@@ -30,6 +31,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
{
|
||||
int ok = 1;
|
||||
int ninst = 0;
|
||||
int j32;
|
||||
uintptr_t ip = addr;
|
||||
uintptr_t init_addr = addr;
|
||||
MAYUSE(init_addr);
|
||||
@@ -38,9 +40,13 @@ uintptr_t arm_pass(dynarec_arm_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;
|
||||
// ok, go now
|
||||
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3 // ok, go now
|
||||
INIT;
|
||||
while(ok) {
|
||||
ip = addr;
|
||||
@@ -118,7 +124,11 @@ uintptr_t arm_pass(dynarec_arm_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].x86.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
|
||||
READFLAGS(dyn->insts[ninst].x86.need_before&~X_PEND);
|
||||
}
|
||||
#ifdef HAVE_TRACE
|
||||
if(my_context->dec && box86_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
@@ -170,12 +180,36 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM)
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 1
|
||||
#endif
|
||||
if(dyn->forward) {
|
||||
if(dyn->forward_to == addr) {
|
||||
// we made it!
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
|
||||
dyn->forward = 0;
|
||||
dyn->forward_to = 0;
|
||||
dyn->forward_size = 0;
|
||||
dyn->forward_ninst = 0;
|
||||
} else if ((dyn->forward_to < addr) || !ok) {
|
||||
// something when wrong! rollback
|
||||
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block %p -> %p\n", (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 && box86_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 && (
|
||||
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
|
||||
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
|
||||
/*&& box86_dynarec_bigblock*/))
|
||||
{
|
||||
ok = 1;
|
||||
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
|
||||
@@ -186,16 +220,23 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
ii=ninst;
|
||||
}
|
||||
if(box86_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(box86_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<box86_dynarec_forward)
|
||||
&& (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=forwardblock*/) {
|
||||
dyn->forward = addr;
|
||||
dyn->forward_to = next;
|
||||
dyn->forward_size = dyn->size;
|
||||
dyn->forward_ninst = ninst;
|
||||
reset_n = -2;
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(ok<0) {ok = 0; need_epilog=1;}
|
||||
++ninst;
|
||||
#if STEP == 0
|
||||
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
|
||||
(ok && dyn->size >= 2000))
|
||||
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|
||||
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
|
||||
/*|| (dyn->size >= 2000)*/)) // is this still needed? maybe it should be a parameter?
|
||||
#else
|
||||
if(ok && (ninst==dyn->size))
|
||||
#endif
|
||||
@@ -208,10 +249,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
}
|
||||
#if STEP == 0
|
||||
if(dyn->insts[ninst].x86.set_flags)
|
||||
dyn->insts[ninst].x86.default_need |= X_PEND;
|
||||
else
|
||||
dyn->insts[ninst].x86.use_flags |= X_PEND;
|
||||
dyn->insts[ninst].x86.need_after |= X_PEND;
|
||||
#endif
|
||||
++ninst;
|
||||
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
dyn->insts[ninst].x86.addr = addr;\
|
||||
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
|
||||
#define MESSAGE(A, ...)
|
||||
#define MAYSETFLAGS() dyn->insts[ninst].x86.may_set = 1
|
||||
#define READFLAGS(A) \
|
||||
dyn->insts[ninst].x86.use_flags = A; dyn->f.dfnone = 1;\
|
||||
dyn->f.pending=SF_SET
|
||||
#define SETFLAGS(A,B) \
|
||||
dyn->insts[ninst].x86.set_flags = A; \
|
||||
if(B!=SF_MAYSET) { \
|
||||
dyn->insts[ninst].x86.state_flags = B; \
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0; \
|
||||
}
|
||||
dyn->insts[ninst].x86.set_flags = A; \
|
||||
dyn->insts[ninst].x86.state_flags = B; \
|
||||
dyn->f.pending=(B)&SF_SET_PENDING; \
|
||||
dyn->f.dfnone=((B)&SF_SET)?1:0;
|
||||
#define EMIT(A)
|
||||
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)(A)); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
|
||||
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
|
||||
@@ -22,7 +21,7 @@
|
||||
#define NEW_INST \
|
||||
++dyn->size; \
|
||||
if(dyn->size+3>=dyn->cap) { \
|
||||
dyn->insts = (instruction_arm_t*)realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
|
||||
dyn->insts = (instruction_arm_t*)box_realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
|
||||
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
|
||||
dyn->cap *= 2; \
|
||||
} \
|
||||
@@ -35,14 +34,14 @@
|
||||
#define INST_EPILOG \
|
||||
dyn->insts[ninst].f_exit = dyn->f; \
|
||||
dyn->insts[ninst].n = dyn->n; \
|
||||
dyn->insts[ninst].x86.has_next = ok;
|
||||
dyn->insts[ninst].x86.has_next = (ok>0)?1:0;
|
||||
#define INST_NAME(name)
|
||||
#define DEFAULT \
|
||||
--dyn->size; \
|
||||
*ok = -1; \
|
||||
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
|
||||
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
|
||||
(void*)ip, PKip(0), \
|
||||
dynarec_log(LOG_NONE, "%p: Dynarec stopped @ %s (%s:%u) because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
|
||||
(void*)ip, __FUNCTION__, __FILE__, __LINE__, PKip(0), \
|
||||
PKip(1), PKip(2), PKip(3), \
|
||||
PKip(4), PKip(5), PKip(6), \
|
||||
PKip(7), PKip(8), PKip(9), \
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define INST_NAME(name) \
|
||||
if(box86_dynarec_dump) {\
|
||||
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
|
||||
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), set=%X, use=%X, need=%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", \
|
||||
(box86_dynarec_dump>1)?"\e[32m":"", \
|
||||
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
|
||||
dyn->insts[ninst].size/4, \
|
||||
@@ -28,9 +28,13 @@
|
||||
dyn->insts[ninst].x86.state_flags, \
|
||||
dyn->f.pending, \
|
||||
dyn->f.dfnone, \
|
||||
dyn->insts[ninst].x86.may_set?"may":"set", \
|
||||
dyn->insts[ninst].x86.set_flags, \
|
||||
dyn->insts[ninst].x86.gen_flags, \
|
||||
dyn->insts[ninst].x86.use_flags, \
|
||||
dyn->insts[ninst].x86.need_flags); \
|
||||
dyn->insts[ninst].x86.need_before, \
|
||||
dyn->insts[ninst].x86.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)\
|
||||
|
||||
@@ -18,12 +18,12 @@ typedef struct dynablock_s dynablock_t;
|
||||
typedef union neon_cache_s {
|
||||
int8_t v;
|
||||
struct {
|
||||
unsigned int t:4; // reg type
|
||||
unsigned int n:4; // reg number
|
||||
uint8_t t:4; // reg type
|
||||
uint8_t n:4; // reg number
|
||||
};
|
||||
} neon_cache_t;
|
||||
typedef union sse_cache_s {
|
||||
int v;
|
||||
int8_t v;
|
||||
struct {
|
||||
uint8_t reg;
|
||||
uint8_t write;
|
||||
@@ -100,6 +100,12 @@ typedef struct dynarec_arm_s {
|
||||
int sons_size; // number of potential dynablock sons
|
||||
int* predecessor;// single array of all predecessor
|
||||
dynablock_t* dynablock;
|
||||
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);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#define SF_SUB 4
|
||||
#define SF_SUBSET (SF_SUB|SF_SET)
|
||||
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
|
||||
#define SF_MAYSET 8
|
||||
|
||||
typedef struct instruction_x86_s {
|
||||
uintptr_t addr; //address of the instruction
|
||||
@@ -37,9 +36,10 @@ typedef struct instruction_x86_s {
|
||||
uint8_t state_flags;// One of SF_XXX state
|
||||
uint8_t use_flags; // 0 or combination of X_?F
|
||||
uint8_t set_flags; // 0 or combination of X_?F
|
||||
uint8_t default_need;// 0 or X_PEND basically
|
||||
uint8_t need_flags; // calculated
|
||||
uint8_t old_use; // calculated
|
||||
uint8_t may_set; // 1 if the flags may not be set
|
||||
uint8_t gen_flags; // calculated
|
||||
uint8_t need_before; // calculated
|
||||
uint8_t need_after; // calculated
|
||||
} instruction_x86_t;
|
||||
|
||||
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
|
||||
|
||||
@@ -235,12 +235,12 @@ void DumpMainHeader(Elf32_Ehdr *header, elfheader_t *h)
|
||||
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
|
||||
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numPHEntries; ++i)
|
||||
for (uint16_t i=0; i<h->numPHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
|
||||
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries);
|
||||
for (int i=0; i<h->numSHEntries; ++i)
|
||||
for (uint16_t i=0; i<h->numSHEntries; ++i)
|
||||
printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
|
||||
}
|
||||
@@ -251,7 +251,7 @@ void DumpSymTab(elfheader_t *h)
|
||||
if(box86_dump && h->SymTab) {
|
||||
const char* name = ElfName(h);
|
||||
printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab);
|
||||
for (int i=0; i<h->numSymTab; ++i)
|
||||
for (uint32_t i=0; i<h->numSymTab; ++i)
|
||||
printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
|
||||
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
|
||||
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
|
||||
@@ -263,7 +263,7 @@ void DumpDynamicSections(elfheader_t *h)
|
||||
{
|
||||
if(box86_dump && h->Dynamic) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i)
|
||||
printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
|
||||
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
|
||||
}
|
||||
@@ -274,7 +274,7 @@ void DumpDynSym(elfheader_t *h)
|
||||
if(box86_dump && h->DynSym) {
|
||||
const char* name = ElfName(h);
|
||||
printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym);
|
||||
for (int i=0; i<h->numDynSym; ++i) {
|
||||
for (uint32_t i=0; i<h->numDynSym; ++i) {
|
||||
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
|
||||
printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
|
||||
}
|
||||
@@ -286,7 +286,7 @@ void DumpDynamicNeeded(elfheader_t *h)
|
||||
{
|
||||
if(box86_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i)
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i)
|
||||
if(h->Dynamic[i].d_tag==DT_NEEDED) {
|
||||
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
@@ -298,7 +298,7 @@ void DumpDynamicRPath(elfheader_t *h)
|
||||
{
|
||||
if(box86_dump && h->DynStrTab) {
|
||||
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i) {
|
||||
if(h->Dynamic[i].d_tag==DT_RPATH) {
|
||||
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
|
||||
}
|
||||
|
||||
+299
-182
File diff suppressed because it is too large.
Load diff
@@ -7,27 +7,29 @@ typedef struct dynablocklist_s dynablocklist_t;
|
||||
|
||||
typedef struct library_s library_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
|
||||
#include <pthread.h>
|
||||
#include <elf.h>
|
||||
#include "elfloader.h"
|
||||
|
||||
struct elfheader_s {
|
||||
char* name;
|
||||
char* path; // Resolved path to file
|
||||
int numPHEntries;
|
||||
uint16_t numPHEntries;
|
||||
Elf32_Phdr *PHEntries;
|
||||
int numSHEntries;
|
||||
uint16_t numSHEntries;
|
||||
Elf32_Shdr *SHEntries;
|
||||
int SHIdx;
|
||||
int numSST;
|
||||
char* SHStrTab;
|
||||
char* StrTab;
|
||||
Elf32_Sym* SymTab;
|
||||
int numSymTab;
|
||||
uint32_t numSymTab;
|
||||
char* DynStr;
|
||||
Elf32_Sym* DynSym;
|
||||
int numDynSym;
|
||||
uint32_t numDynSym;
|
||||
Elf32_Dyn* Dynamic;
|
||||
int numDynamic;
|
||||
uint32_t numDynamic;
|
||||
char* DynStrTab;
|
||||
int szDynStrTab;
|
||||
Elf32_Half* VerSym;
|
||||
@@ -66,17 +68,20 @@ struct elfheader_s {
|
||||
uintptr_t plt_end;
|
||||
uintptr_t text;
|
||||
int textsz;
|
||||
uintptr_t bss;
|
||||
int bsssz;
|
||||
|
||||
uintptr_t paddr;
|
||||
uintptr_t vaddr;
|
||||
int align;
|
||||
uint32_t align;
|
||||
uint32_t memsz;
|
||||
uint32_t reserve;
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
uint32_t stackalign;
|
||||
uintptr_t tlsaddr;
|
||||
uint32_t tlssize;
|
||||
uint32_t tlsfilesize;
|
||||
int tlsalign;
|
||||
uint32_t tlsalign;
|
||||
|
||||
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
|
||||
|
||||
@@ -91,6 +96,10 @@ struct elfheader_s {
|
||||
|
||||
library_t *lib;
|
||||
needed_libs_t *neededlibs;
|
||||
|
||||
kh_mapsymbols_t *mapsymbols;
|
||||
kh_mapsymbols_t *weaksymbols;
|
||||
kh_mapsymbols_t *localsymbols;
|
||||
};
|
||||
|
||||
#define R_386_NONE 0
|
||||
@@ -107,4 +116,4 @@ struct elfheader_s {
|
||||
|
||||
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
|
||||
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
#endif //__ELFLOADER_PRIVATE_H_
|
||||
+76
-67
@@ -17,16 +17,16 @@
|
||||
int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type)
|
||||
{
|
||||
if(type && (s->sh_type != type)) {
|
||||
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
|
||||
printf_dump(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
|
||||
return -1;
|
||||
}
|
||||
if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf32_Sym)) {
|
||||
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
|
||||
printf_dump(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
|
||||
}
|
||||
*SH = calloc(1, s->sh_size);
|
||||
*SH = box_calloc(1, s->sh_size);
|
||||
fseeko64(f, s->sh_offset ,SEEK_SET);
|
||||
if(fread(*SH, s->sh_size, 1, f)!=1) {
|
||||
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
|
||||
printf_dump(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
|
||||
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, uint32_t* num)
|
||||
{
|
||||
int n = FindSection(s, size, SHStrTab, name);
|
||||
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
|
||||
printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
|
||||
if(n)
|
||||
LoadSH(f, s+n, what, name, type);
|
||||
if(type==SHT_SYMTAB || type==SHT_DYNSYM) {
|
||||
@@ -63,59 +63,59 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
Elf32_Ehdr header;
|
||||
int level = (exec)?LOG_INFO:LOG_DEBUG;
|
||||
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
|
||||
printf_log(level, "Cannot read ELF Header\n");
|
||||
printf_dump(level, "Cannot read ELF Header\n");
|
||||
return NULL;
|
||||
}
|
||||
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
|
||||
printf_log(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
|
||||
printf_dump(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_CLASS]!=ELFCLASS32) {
|
||||
if(header.e_ident[EI_CLASS]==ELFCLASS64) {
|
||||
printf_log(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
|
||||
printf_dump(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
|
||||
printf_dump(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_DATA]!=ELFDATA2LSB) {
|
||||
printf_log(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
|
||||
printf_dump(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_VERSION]!=EV_CURRENT) {
|
||||
printf_log(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
|
||||
printf_dump(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_ident[EI_OSABI]!=ELFOSABI_LINUX && header.e_ident[EI_OSABI]!=ELFOSABI_NONE && header.e_ident[EI_OSABI]!=ELFOSABI_SYSV) {
|
||||
printf_log(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
|
||||
printf_dump(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(header.e_type != ET_EXEC && header.e_type != ET_DYN) {
|
||||
printf_log(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
|
||||
printf_dump(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(header.e_machine != EM_386) {
|
||||
printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine);
|
||||
printf_dump(level, "Not an i386 ELF (%d)\n", header.e_machine);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(header.e_entry == 0 && exec) {
|
||||
printf_log(LOG_INFO, "No entry point in ELF\n");
|
||||
printf_dump(LOG_INFO, "No entry point in ELF\n");
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_phentsize != sizeof(Elf32_Phdr)) {
|
||||
printf_log(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
|
||||
printf_dump(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
|
||||
return NULL;
|
||||
}
|
||||
if(header.e_shentsize != sizeof(Elf32_Shdr) && header.e_shentsize != 0) {
|
||||
printf_log(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
|
||||
printf_dump(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elfheader_t *h = calloc(1, sizeof(elfheader_t));
|
||||
h->name = strdup(name);
|
||||
elfheader_t *h = box_calloc(1, sizeof(elfheader_t));
|
||||
h->name = box_strdup(name);
|
||||
h->entrypoint = header.e_entry;
|
||||
h->numPHEntries = header.e_phnum;
|
||||
h->numSHEntries = header.e_shnum;
|
||||
@@ -124,55 +124,55 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
if(header.e_shentsize && header.e_shnum) {
|
||||
// special cases for nums
|
||||
if(h->numSHEntries == 0) {
|
||||
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
|
||||
printf_dump(LOG_DEBUG, "Read number of Sections in 1st Section\n");
|
||||
// read 1st section header and grab actual number from here
|
||||
fseeko64(f, header.e_shoff, SEEK_SET);
|
||||
Elf32_Shdr section;
|
||||
if(fread(§ion, sizeof(Elf32_Shdr), 1, f)!=1) {
|
||||
free(h);
|
||||
printf_log(LOG_INFO, "Cannot read Initial Section Header\n");
|
||||
box_free(h);
|
||||
printf_dump(LOG_INFO, "Cannot read Initial Section Header\n");
|
||||
return NULL;
|
||||
}
|
||||
h->numSHEntries = section.sh_size;
|
||||
}
|
||||
// now read all section headers
|
||||
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
|
||||
h->SHEntries = (Elf32_Shdr*)calloc(h->numSHEntries, sizeof(Elf32_Shdr));
|
||||
printf_dump(LOG_DEBUG, "Read %u Section header\n", h->numSHEntries);
|
||||
h->SHEntries = (Elf32_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf32_Shdr));
|
||||
fseeko64(f, header.e_shoff ,SEEK_SET);
|
||||
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
|
||||
FreeElfHeader(&h);
|
||||
printf_log(LOG_INFO, "Cannot read all Section Header\n");
|
||||
printf_dump(LOG_INFO, "Cannot read all Section Header\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(h->numPHEntries == PN_XNUM) {
|
||||
printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
|
||||
printf_dump(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
|
||||
// read 1st section header and grab actual number from here
|
||||
h->numPHEntries = h->SHEntries[0].sh_info;
|
||||
}
|
||||
}
|
||||
|
||||
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
|
||||
h->PHEntries = (Elf32_Phdr*)calloc(h->numPHEntries, sizeof(Elf32_Phdr));
|
||||
printf_dump(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
|
||||
h->PHEntries = (Elf32_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf32_Phdr));
|
||||
fseeko64(f, header.e_phoff ,SEEK_SET);
|
||||
if(fread(h->PHEntries, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
|
||||
FreeElfHeader(&h);
|
||||
printf_log(LOG_INFO, "Cannot read all Program Header\n");
|
||||
printf_dump(LOG_INFO, "Cannot read all Program Header\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(header.e_shentsize && header.e_shnum) {
|
||||
if(h->SHIdx == SHN_XINDEX) {
|
||||
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
|
||||
printf_dump(LOG_DEBUG, "Read number of String Table in 1st Section\n");
|
||||
h->SHIdx = h->SHEntries[0].sh_link;
|
||||
}
|
||||
if(h->SHIdx > h->numSHEntries) {
|
||||
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
|
||||
printf_dump(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
// load Section table
|
||||
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
|
||||
printf_dump(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
|
||||
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
@@ -188,7 +188,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
// grab DT_REL & DT_RELA stuffs
|
||||
// also grab the DT_STRTAB string table
|
||||
{
|
||||
for (int i=0; i<h->numDynamic; ++i) {
|
||||
for (uint32_t i=0; i<h->numDynamic; ++i) {
|
||||
Elf32_Dyn d = h->Dynamic[i];
|
||||
Elf32_Word val = d.d_un.d_val;
|
||||
Elf32_Addr ptr = d.d_un.d_ptr;
|
||||
@@ -231,65 +231,65 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
break;
|
||||
case DT_INIT: // Entry point
|
||||
h->initentry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
|
||||
printf_dump(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
|
||||
break;
|
||||
case DT_INIT_ARRAY:
|
||||
h->initarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
|
||||
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
|
||||
break;
|
||||
case DT_INIT_ARRAYSZ:
|
||||
h->initarray_sz = val / sizeof(Elf32_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
|
||||
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
|
||||
break;
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
if(val)
|
||||
printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
|
||||
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
|
||||
break;
|
||||
case DT_FINI: // Exit hook
|
||||
h->finientry = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
|
||||
printf_dump(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
|
||||
break;
|
||||
case DT_FINI_ARRAY:
|
||||
h->finiarray = ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
|
||||
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
|
||||
break;
|
||||
case DT_FINI_ARRAYSZ:
|
||||
h->finiarray_sz = val / sizeof(Elf32_Addr);
|
||||
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
|
||||
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
|
||||
break;
|
||||
case DT_VERNEEDNUM:
|
||||
h->szVerNeed = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
|
||||
printf_dump(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
|
||||
break;
|
||||
case DT_VERNEED:
|
||||
h->VerNeed = (Elf32_Verneed*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
|
||||
printf_dump(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
|
||||
break;
|
||||
case DT_VERDEFNUM:
|
||||
h->szVerDef = val;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
|
||||
printf_dump(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
|
||||
break;
|
||||
case DT_VERDEF:
|
||||
h->VerDef = (Elf32_Verdef*)ptr;
|
||||
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(h->rel) {
|
||||
if(h->relent != sizeof(Elf32_Rel)) {
|
||||
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_Rel));
|
||||
printf_dump(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_Rel));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
printf_dump(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
|
||||
}
|
||||
if(h->rela) {
|
||||
if(h->relaent != sizeof(Elf32_Rela)) {
|
||||
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_Rela));
|
||||
printf_dump(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_Rela));
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
printf_dump(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
|
||||
}
|
||||
if(h->jmprel) {
|
||||
if(h->pltrel == DT_REL) {
|
||||
@@ -297,16 +297,16 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
} else if(h->pltrel == DT_RELA) {
|
||||
h->pltent = sizeof(Elf32_Rela);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel);
|
||||
printf_dump(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
|
||||
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
printf_dump(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel);
|
||||
FreeElfHeader(&h);
|
||||
return NULL;
|
||||
}
|
||||
printf_log(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
printf_dump(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
|
||||
}
|
||||
if(h->DynStrTab && h->szDynStrTab) {
|
||||
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
|
||||
@@ -317,32 +317,39 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
if(ii) {
|
||||
h->gotplt = h->SHEntries[ii].sh_addr;
|
||||
h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
|
||||
printf_dump(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
|
||||
}
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
|
||||
if(ii) {
|
||||
h->got = h->SHEntries[ii].sh_addr;
|
||||
h->got_end = h->got + h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
|
||||
printf_dump(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
|
||||
}
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt");
|
||||
if(ii) {
|
||||
h->plt = h->SHEntries[ii].sh_addr;
|
||||
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
|
||||
printf_dump(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
|
||||
}
|
||||
// grab version of symbols
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
|
||||
if(ii) {
|
||||
h->VerSym = (Elf32_Half*)(h->SHEntries[ii].sh_addr);
|
||||
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
|
||||
printf_dump(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
|
||||
}
|
||||
// grab .text for main code
|
||||
// grab .bss for main code
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
|
||||
if(ii) {
|
||||
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
h->textsz = h->SHEntries[ii].sh_size;
|
||||
printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
|
||||
printf_dump(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
|
||||
}
|
||||
// grab .bss to find brk
|
||||
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".bss");
|
||||
if(ii) {
|
||||
h->bss = (uintptr_t)(h->SHEntries[ii].sh_addr);
|
||||
h->bsssz = h->SHEntries[ii].sh_size;
|
||||
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
|
||||
}
|
||||
|
||||
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
|
||||
@@ -355,19 +362,21 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
const char* GetSymbolVersion(elfheader_t* h, int version)
|
||||
{
|
||||
version&=0x7fff; // remove bit15 that switch between hidden/public
|
||||
if(!h->VerNeed || (version<2))
|
||||
if(version<2)
|
||||
return NULL;
|
||||
/*if(version==1)
|
||||
return "*";*/
|
||||
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(aux->vna_other==version)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
if(h->VerNeed) {
|
||||
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
|
||||
while(ver) {
|
||||
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
|
||||
for(int j=0; j<ver->vn_cnt; ++j) {
|
||||
if(aux->vna_other==version)
|
||||
return h->DynStr+aux->vna_name;
|
||||
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
|
||||
}
|
||||
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
|
||||
}
|
||||
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
|
||||
}
|
||||
|
||||
+53
-30
@@ -71,6 +71,14 @@
|
||||
goto _default;
|
||||
}
|
||||
NEXT;
|
||||
_0f_0x0E: /* FEMMS */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-2;
|
||||
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP;
|
||||
NEXT;
|
||||
|
||||
_0f_0x10: /* MOVUPS Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -136,16 +144,12 @@
|
||||
break;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0x19: /* HINT_NOP (multi-byte) */
|
||||
_0f_0x1A: /* NOP (multi-byte) / ignored BNDLDX */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
NEXT;
|
||||
_0f_0x1B: /* NOP (multi-byte) / ignored BNDSTX */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
NEXT;
|
||||
|
||||
_0f_0x1C: /* HINT_NOP (multi-byte) */
|
||||
_0f_0x1D: /* HINT_NOP (multi-byte) */
|
||||
_0f_0x1E: /* HINT_NOP (multi-byte) */
|
||||
_0f_0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -178,31 +182,37 @@
|
||||
_0f_0x2C: /* CVTTPS2PI Gm, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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];
|
||||
NEXT;
|
||||
_0f_0x2D: /* CVTPS2PI Gm, Ex */
|
||||
// rounding should be done; and indefinite integer should also be assigned if overflow or NaN/Inf
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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;
|
||||
}
|
||||
NEXT;
|
||||
_0f_0x2E: /* UCOMISS Gx, Ex */
|
||||
// same for now
|
||||
@@ -292,6 +302,17 @@
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF0: /* MOVBE Gd, Ed*/
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
GD.dword[0] = __builtin_bswap32(ED->dword[0]);
|
||||
break;
|
||||
case 0xF1: /* MOVBE Ed, Gd*/
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
ED->dword[0] = __builtin_bswap32(GD.dword[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
@@ -881,10 +902,12 @@
|
||||
fpu_fxrstor(emu, ED);
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr = ED->dword[0];
|
||||
emu->mxcsr.x32 = ED->dword[0];
|
||||
break;
|
||||
case 3: /* STMXCSR Md */
|
||||
ED->dword[0] = emu->mxcsr;
|
||||
ED->dword[0] = emu->mxcsr.x32;
|
||||
if(box86_sse_flushto0)
|
||||
applyFlushTo0(emu);
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
|
||||
@@ -89,6 +89,10 @@
|
||||
_66_0x3D:
|
||||
cmp16(emu, R_AX, F16);
|
||||
NEXT;
|
||||
_66_0x3E: /* DS: */
|
||||
// ignored
|
||||
opcode = F8;
|
||||
goto *opcodes66[opcode];
|
||||
|
||||
_66_0x40:
|
||||
_66_0x41:
|
||||
|
||||
+2
-3
@@ -245,9 +245,8 @@
|
||||
break;
|
||||
case 5: /* FLDCW Ew */
|
||||
GET_EW;
|
||||
emu->cw = EW->word[0];
|
||||
emu->cw.x16 = EW->word[0];
|
||||
// do something with cw?
|
||||
emu->round = (fpu_round_t)((emu->cw >> 10) & 3);
|
||||
break;
|
||||
case 6: /* FNSTENV m */
|
||||
// warning, incomplete
|
||||
@@ -259,7 +258,7 @@
|
||||
break;
|
||||
case 7: /* FNSTCW Ew */
|
||||
GET_EW;
|
||||
EW->word[0] = emu->cw;
|
||||
EW->word[0] = emu->cw.x16;
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
|
||||
+53
-34
@@ -30,25 +30,31 @@
|
||||
case 0x2C: /* CVTTSD2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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];
|
||||
break;
|
||||
case 0x2D: /* CVTSD2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case 0x51: /* SQRTSD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -119,7 +125,7 @@
|
||||
case 0x5F: /* MAXSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreater(EX->d[0], GX.d[0]))
|
||||
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(EX->d[0], GX.d[0]))
|
||||
GX.d[0] = EX->d[0];
|
||||
break;
|
||||
|
||||
@@ -151,6 +157,19 @@
|
||||
GX.f[3] = EX->f[2] + EX->f[3];
|
||||
}
|
||||
break;
|
||||
case 0x7D: /* HSUBPS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.f[0] -= GX.f[1];
|
||||
GX.f[1] = GX.f[2] - GX.f[3];
|
||||
if(EX==&GX) {
|
||||
GX.f[2] = GX.f[0];
|
||||
GX.f[3] = GX.f[1];
|
||||
} else {
|
||||
GX.f[2] = EX->f[0] - EX->f[1];
|
||||
GX.f[3] = EX->f[2] - EX->f[3];
|
||||
}
|
||||
break;
|
||||
|
||||
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
|
||||
case BASE+0: \
|
||||
@@ -275,24 +294,24 @@
|
||||
case 0xE6: /* CVTPD2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GX.sd[0] = floor(EX->d[0]+0.5);
|
||||
GX.sd[1] = floor(EX->d[1]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.sd[0] = floor(EX->d[0]);
|
||||
GX.sd[1] = floor(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.sd[0] = ceil(EX->d[0]);
|
||||
GX.sd[1] = ceil(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.sd[0] = EX->d[0];
|
||||
GX.sd[1] = EX->d[1];
|
||||
break;
|
||||
}
|
||||
for(int i=0; i<2; ++i)
|
||||
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
|
||||
GX.ud[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GX.sd[i] = nearbyint(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.sd[i] = floor(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.sd[i] = ceil(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.sd[i] = EX->d[i];
|
||||
break;
|
||||
}
|
||||
GX.q[1] = 0;
|
||||
break;
|
||||
|
||||
|
||||
+28
-21
@@ -47,25 +47,31 @@
|
||||
case 0x2C: /* CVTTSS2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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];
|
||||
break;
|
||||
case 0x2D: /* CVTSS2SI Gd, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GD.sdword[0] = floor(EX->f[0]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GD.sdword[0] = floor(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GD.sdword[0] = ceil(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;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x51: /* SQRTSS Gx, Ex */
|
||||
@@ -102,10 +108,11 @@
|
||||
case 0x5B: /* CVTTPS2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.sd[0] = EX->f[0];
|
||||
GX.sd[1] = EX->f[1];
|
||||
GX.sd[2] = EX->f[2];
|
||||
GX.sd[3] = EX->f[3];
|
||||
for(int i=0; i<4; ++i)
|
||||
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
|
||||
GX.ud[i] = 0x80000000;
|
||||
else
|
||||
GX.sd[i] = EX->f[i];
|
||||
break;
|
||||
|
||||
case 0x5C: /* SUBSS Gx, Ex */
|
||||
@@ -116,7 +123,7 @@
|
||||
case 0x5D: /* MINSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(isnan(GX.f[0]) || isnan(EX->f[0]) || isless(EX->f[0], GX.f[0]))
|
||||
if(isnan(GX.f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
|
||||
GX.f[0] = EX->f[0];
|
||||
break;
|
||||
case 0x5E: /* DIVSS Gx, Ex */
|
||||
@@ -127,7 +134,7 @@
|
||||
case 0x5F: /* MAXSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreater(EX->f[0], GX.f[0]))
|
||||
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
|
||||
GX.f[0] = EX->f[0];
|
||||
break;
|
||||
|
||||
|
||||
+34
-10
@@ -23,6 +23,13 @@
|
||||
#ifdef DYNAREC
|
||||
#include "custommem.h"
|
||||
#endif
|
||||
// for the applyFlushTo0
|
||||
#ifdef __i386__
|
||||
#include <immintrin.h>
|
||||
#elif defined(__arm__)
|
||||
#else
|
||||
#warning Architecture cannot follow SSE Flush to 0 flag
|
||||
#endif
|
||||
|
||||
typedef struct cleanup_s {
|
||||
void* f;
|
||||
@@ -81,15 +88,15 @@ static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t s
|
||||
emu->segs[_GS] = 0x33;
|
||||
// setup fpu regs
|
||||
reset_fpu(emu);
|
||||
emu->mxcsr = 0x1f80;
|
||||
emu->mxcsr.x32 = 0x1f80;
|
||||
}
|
||||
|
||||
EXPORTDYN
|
||||
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
|
||||
printf_log(LOG_DEBUG, "%04d|Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
|
||||
|
||||
x86emu_t *emu = (x86emu_t*)calloc(1, sizeof(x86emu_t));
|
||||
x86emu_t *emu = (x86emu_t*)box_calloc(1, sizeof(x86emu_t));
|
||||
|
||||
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
|
||||
|
||||
@@ -98,7 +105,7 @@ x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, i
|
||||
|
||||
x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
|
||||
{
|
||||
printf_log(LOG_DEBUG, "New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
|
||||
printf_log(LOG_DEBUG, "%04d|New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
|
||||
|
||||
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
|
||||
|
||||
@@ -108,6 +115,7 @@ x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t s
|
||||
EXPORTDYN
|
||||
void SetupX86Emu(x86emu_t *emu)
|
||||
{
|
||||
(void)emu;
|
||||
printf_log(LOG_DEBUG, "Setup X86 Emu\n");
|
||||
}
|
||||
|
||||
@@ -128,9 +136,10 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
|
||||
|
||||
void AddCleanup(x86emu_t *emu, void *p)
|
||||
{
|
||||
(void)emu;
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
}
|
||||
my_context->cleanups[my_context->clean_sz].arg = 0;
|
||||
my_context->cleanups[my_context->clean_sz].a = NULL;
|
||||
@@ -139,9 +148,10 @@ void AddCleanup(x86emu_t *emu, void *p)
|
||||
|
||||
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
|
||||
{
|
||||
(void)emu;
|
||||
if(my_context->clean_sz == my_context->clean_cap) {
|
||||
my_context->clean_cap += 4;
|
||||
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
|
||||
}
|
||||
my_context->cleanups[my_context->clean_sz].arg = 1;
|
||||
my_context->cleanups[my_context->clean_sz].a = a;
|
||||
@@ -171,7 +181,7 @@ void CallAllCleanup(x86emu_t *emu)
|
||||
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;
|
||||
free(my_context->cleanups);
|
||||
box_free(my_context->cleanups);
|
||||
my_context->cleanups = NULL;
|
||||
}
|
||||
|
||||
@@ -190,7 +200,7 @@ void FreeX86Emu(x86emu_t **emu)
|
||||
|
||||
internalFreeX86(*emu);
|
||||
|
||||
free(*emu);
|
||||
box_free(*emu);
|
||||
*emu = NULL;
|
||||
}
|
||||
|
||||
@@ -217,10 +227,9 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
|
||||
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
|
||||
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
|
||||
newemu->cw = emu->cw;
|
||||
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
|
||||
newemu->sw = emu->sw;
|
||||
newemu->top = emu->top;
|
||||
newemu->fpu_stack = emu->fpu_stack;
|
||||
memcpy(&newemu->round, &emu->round, sizeof(emu->round));
|
||||
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
|
||||
newemu->mxcsr = emu->mxcsr;
|
||||
newemu->quit = emu->quit;
|
||||
@@ -459,6 +468,7 @@ static inline void init_perfcounters (int32_t do_reset, int32_t enable_divider)
|
||||
|
||||
uint64_t ReadTSC(x86emu_t* emu)
|
||||
{
|
||||
(void)emu;
|
||||
// Read the TimeStamp Counter as 64bits.
|
||||
// this is supposed to be the number of instructions executed since last reset
|
||||
#if defined(__i386__)
|
||||
@@ -498,3 +508,17 @@ void ResetSegmentsCache(x86emu_t *emu)
|
||||
return;
|
||||
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
|
||||
}
|
||||
|
||||
void applyFlushTo0(x86emu_t* emu)
|
||||
{
|
||||
#ifdef __i386__
|
||||
_mm_setcsr(_mm_getcsr() | (emu->mxcsr.x32&0x8040));
|
||||
#elif defined(__arm__)
|
||||
uint64_t fpscr = __builtin_arm_get_fpscr();
|
||||
fpscr &= ~(1<<24); // clear bit FZ (24)
|
||||
fpscr |= (emu->mxcsr.f.MXCSR_FZ)<<24; // set FZ as mxcsr FZ
|
||||
__builtin_arm_set_fpscr(fpscr);
|
||||
#else
|
||||
(void)emu;
|
||||
#endif
|
||||
}
|
||||
@@ -29,19 +29,18 @@ typedef struct x86emu_s {
|
||||
x86flags_t eflags;
|
||||
reg32_t ip;
|
||||
// fpu / mmx
|
||||
x87control_t cw;
|
||||
x87flags_t sw;
|
||||
mmx87_regs_t x87[8];
|
||||
mmx87_regs_t mmx[8];
|
||||
uint16_t cw;
|
||||
x87flags_t sw;
|
||||
uint32_t top; // top is part of sw, but it's faster to have it separatly
|
||||
int fpu_stack;
|
||||
fpu_round_t round;
|
||||
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
|
||||
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
|
||||
fpu_p_reg_t p_regs[8];
|
||||
// sse
|
||||
sse_regs_t xmm[8];
|
||||
uint32_t mxcsr;
|
||||
mmxcontrol_t mxcsr;
|
||||
uintptr_t old_ip;
|
||||
// defered flags
|
||||
defered_flags_t df;
|
||||
@@ -89,4 +88,6 @@ typedef struct x86emu_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(x86emu_t* emu);
|
||||
|
||||
#endif //__X86EMU_PRIVATE_H_
|
||||
+113
-78
@@ -10,6 +10,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <wait.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
@@ -53,7 +54,10 @@ x86emu_t* x86emu_fork(x86emu_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) {
|
||||
// execute atforks child functions
|
||||
for (int i=0; i<my_context->atfork_sz; --i)
|
||||
@@ -85,217 +89,231 @@ void x86Int3(x86emu_t* emu)
|
||||
elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
|
||||
int have_trace = 0;
|
||||
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
|
||||
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
|
||||
if(box86_log>=LOG_DEBUG || cycle_log) {
|
||||
int tid = GetTID();
|
||||
char buff[256] = "\0";
|
||||
const char *s = NULL;
|
||||
s = GetNativeName((void*)addr);
|
||||
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)
|
||||
my_context->current_line = (my_context->current_line+1)%cycle_log;
|
||||
char *tmp;
|
||||
int post = 0;
|
||||
int perr = 0;
|
||||
uint32_t *pu32 = NULL;
|
||||
const char *s = NULL;
|
||||
s = GetNativeName((void*)addr);
|
||||
if(addr==(uintptr_t)PltResolver) {
|
||||
snprintf(buff, 256, "%s", " ... ");
|
||||
snprintf(buff, 256, "%s", cycle_log?"PltResolver ":" ... ");
|
||||
} else
|
||||
if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "glColor4f")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
|
||||
} else if(strstr(s, "glTexCoord2f")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
} else if(strstr(s, "glVertex2f")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
} else if(strstr(s, "glVertex3f")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
|
||||
} else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "opendir")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "my_open64")) {
|
||||
tmp = *(char**)(R_ESP+4);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "shm_open")) {
|
||||
tmp = *(char**)(R_ESP+4);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strcmp(s, "mkdir")==0) {
|
||||
tmp = *(char**)(R_ESP+4);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "fopen")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
perr = 2;
|
||||
} else if(!strcmp(s, "freopen")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
perr = 2;
|
||||
} else if(!strcmp(s, "fopen64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
perr = 2;
|
||||
} else if(!strcmp(s, "chdir")) {
|
||||
pu32=*(uint32_t**)(R_ESP+4);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
|
||||
} else if(strstr(s, "getenv")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
post = 2;
|
||||
} else if(strstr(s, "putenv")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
} else if(strstr(s, "pread")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "read")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "ioctl")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "statvfs64")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
} else if(strstr(s, "index")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
|
||||
} else if(strstr(s, "rindex")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
|
||||
} else if(strstr(s, "__xstat64")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strcmp(s, "__xstat")==0) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "__lxstat64")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "sem_timedwait")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
|
||||
perr = 1;
|
||||
} else if(strstr(s, "waitpid")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
post = 1;
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
} else if(strstr(s, "semop")==s) {
|
||||
int16_t* p16 = *(int16_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
|
||||
perr = 1;
|
||||
} else if(!strcmp(s, "mmap64")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
|
||||
perr = 3;
|
||||
} else if(!strcmp(s, "mmap")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
|
||||
perr = 3;
|
||||
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "gtk_signal_connect_full")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
|
||||
} else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "strstr")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "strlen")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
|
||||
} else if(strstr(s, "vsnprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %u, %p(\"%s\")...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(void**)(R_ESP+12), *(char**)(R_ESP+12));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "vsprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "__vsprintf_chk")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "__snprintf_chk")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "snprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "sprintf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 3;
|
||||
} else if(strstr(s, "printf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a _chk function
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
|
||||
} else if(strstr(s, "wprintf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a _chk function
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
|
||||
} else if(strstr(s, "__vswprintf")==s) {
|
||||
if(*(size_t*)(R_ESP+12)<2) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
|
||||
} else {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
post = 6;
|
||||
}
|
||||
} else if(strstr(s, "puts")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
} else if(strstr(s, "fputs")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
|
||||
} else if(strstr(s, "fprintf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
|
||||
pu32 = *(uint32_t**)(R_ESP+12);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
|
||||
} else if(strstr(s, "vfprintf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a _chk function
|
||||
pu32 = *(uint32_t**)(R_ESP+12);
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
|
||||
} else if(strstr(s, "vkGetInstanceProcAddr")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "vkGetDeviceProcAddr")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "glXGetProcAddress")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
} else if(strstr(s, "sscanf")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(!strcmp(s, "vsscanf")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "XCreateWindow")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
|
||||
} else if(strstr(s, "XLoadQueryFont")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "pthread_mutex_lock")==s) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
|
||||
} else if(!strcmp(s, "fmodf")) {
|
||||
post = 4;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
|
||||
} else if(!strcmp(s, "fmod")) {
|
||||
post = 4;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
|
||||
} else if(strstr(s, "SDL_GetWindowSurface")==s) {
|
||||
post = 5;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
|
||||
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
|
||||
post = 5;
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(!strcmp(s, "syscall")) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
|
||||
perr = 1;
|
||||
} else if(strstr(s, "___tls_get_addr")) {
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, (void*)(R_EAX), ((int*)(R_EAX))[0], ((int*)(R_EAX))[1]);
|
||||
} else if(strstr(s, "__tls_get_addr")) {
|
||||
pu32 = *(uint32_t**)(R_ESP+4);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, pu32, pu32[0], pu32[1]);
|
||||
} else if (!strcmp(s, "XDrawImageString")) {
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %p, %i, %i, %p\"%s\", %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(char**)(R_ESP+24), *(char**)(R_ESP+24), *(int*)(R_ESP+28));
|
||||
} else {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
|
||||
}
|
||||
if(!cycle_log) {
|
||||
mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, "%s =>", buff);
|
||||
mutex_unlock(&emu->context->mutex_trace);
|
||||
}
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, "%s =>", buff);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
w(emu, addr); // some function never come back, so unlock the mutex first!
|
||||
if(post)
|
||||
switch(post) {
|
||||
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
|
||||
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
|
||||
break;
|
||||
case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)R_EAX):"nil");
|
||||
break;
|
||||
@@ -320,9 +338,13 @@ void x86Int3(x86emu_t* emu)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
else if(perr==3 && ((int)R_EAX)==-1)
|
||||
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
|
||||
pthread_mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
|
||||
pthread_mutex_unlock(&emu->context->mutex_trace);
|
||||
if(cycle_log)
|
||||
snprintf(buffret, 127, "0x%X%s%s", R_EAX, buff2, buff3);
|
||||
else {
|
||||
mutex_lock(&emu->context->mutex_trace);
|
||||
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
|
||||
mutex_unlock(&emu->context->mutex_trace);
|
||||
}
|
||||
} else
|
||||
w(emu, addr);
|
||||
}
|
||||
@@ -338,4 +360,17 @@ void x86Int3(x86emu_t* emu)
|
||||
int GetTID()
|
||||
{
|
||||
return syscall(SYS_gettid);
|
||||
}
|
||||
}
|
||||
|
||||
void print_cycle_log(int loglevel) {
|
||||
if(cycle_log) {
|
||||
printf_log(LOG_INFO, "Last calls\n");
|
||||
int j = (my_context->current_line+1)%cycle_log;
|
||||
for (int i=0; i<cycle_log; ++i) {
|
||||
int k = (i+j)%cycle_log;
|
||||
if(my_context->log_call[k][0]) {
|
||||
printf_log(loglevel, "%s => return %s\n", my_context->log_call[k], my_context->log_ret[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -1044,14 +1044,14 @@ Implements the SBB instruction and side effects.
|
||||
****************************************************************************/
|
||||
uint16_t sbb16(x86emu_t *emu, uint16_t d, uint16_t s)
|
||||
{
|
||||
uint32_t res; /* all operands in native machine order */
|
||||
uint32_t bc;
|
||||
uint32_t res; /* all operands in native machine order */
|
||||
uint32_t bc;
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
if (ACCESS_FLAG(F_CF))
|
||||
res = d - s - 1;
|
||||
else
|
||||
res = d - s;
|
||||
res = d - s - 1;
|
||||
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);
|
||||
@@ -1075,9 +1075,9 @@ uint32_t sbb32(x86emu_t *emu, uint32_t d, uint32_t s)
|
||||
CHECK_FLAGS(emu);
|
||||
|
||||
if (ACCESS_FLAG(F_CF))
|
||||
res = d - s - 1;
|
||||
else
|
||||
res = d - s;
|
||||
res = d - s - 1;
|
||||
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);
|
||||
|
||||
+3
-8
@@ -165,14 +165,6 @@ Implements the INC instruction and side effects.
|
||||
static inline uint32_t inc32(x86emu_t *emu, uint32_t d)
|
||||
{
|
||||
CHECK_FLAGS(emu);
|
||||
if(emu->df == d_shr32) {
|
||||
// workaround for some wine trickery
|
||||
uint32_t cnt = emu->op2;
|
||||
if (cnt > 0) {
|
||||
uint32_t cc = emu->op1 & (1 << (cnt - 1));
|
||||
CONDITIONAL_SET_FLAG(cc, F_CF);
|
||||
}
|
||||
}
|
||||
emu->res = d + 1;
|
||||
emu->op1 = d;
|
||||
emu->df = d_inc32;
|
||||
@@ -255,6 +247,7 @@ Implements the NOT instruction
|
||||
****************************************************************************/
|
||||
static inline uint8_t not8(x86emu_t *emu, uint8_t s)
|
||||
{
|
||||
(void)emu;
|
||||
return ~s;
|
||||
}
|
||||
|
||||
@@ -264,6 +257,7 @@ Implements the NOT instruction
|
||||
****************************************************************************/
|
||||
static inline uint16_t not16(x86emu_t *emu, uint16_t s)
|
||||
{
|
||||
(void)emu;
|
||||
return ~s;
|
||||
}
|
||||
|
||||
@@ -273,6 +267,7 @@ Implements the NOT instruction
|
||||
****************************************************************************/
|
||||
static inline uint32_t not32(x86emu_t *emu, uint32_t s)
|
||||
{
|
||||
(void)emu;
|
||||
return ~s;
|
||||
}
|
||||
|
||||
|
||||
+21
-5
@@ -93,7 +93,7 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7,
|
||||
&&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF,
|
||||
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7,
|
||||
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF
|
||||
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_0xCE, &&_0xCF, //0xC8-0xCF
|
||||
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7,
|
||||
&&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF,
|
||||
&&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7,
|
||||
@@ -104,9 +104,9 @@ int Run(x86emu_t *emu, int step)
|
||||
|
||||
static const void* opcodes0f[256] = {
|
||||
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
|
||||
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_0f_0x0D, &&_default, &&_default, //0x08-0x0F
|
||||
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_0f_0x0D, &&_0f_0x0E, &&_default, //0x08-0x0F
|
||||
&&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17
|
||||
&&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
|
||||
&&_0f_0x18, &&_0f_0x19, &&_0f_0x1A, &&_0f_0x1B, &&_0f_0x1C ,&&_0f_0x1D, &&_0f_0x1E, &&_0f_0x1F, //0x18-0x1F
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
|
||||
&&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F,
|
||||
&&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
|
||||
@@ -145,7 +145,7 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_66_0x20_0, &&_66_0x20_1, &&_66_0x20_2, &&_66_0x20_3, &&_66_0x20_4 ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27
|
||||
&&_66_0x28_0, &&_66_0x28_1, &&_66_0x28_2, &&_66_0x28_3, &&_66_0x28_4 ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F
|
||||
&&_66_0x30_0, &&_66_0x30_1, &&_66_0x30_2, &&_66_0x30_3, &&_66_0x30_4 ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37
|
||||
&&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_default, &&_default, //0x38-0x3F
|
||||
&&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_66_0x3E, &&_default, //0x38-0x3F
|
||||
&&_66_0x40, &&_66_0x41, &&_66_0x42, &&_66_0x43, &&_66_0x44, &&_66_0x45, &&_66_0x46, &&_66_0x47,
|
||||
&&_66_0x48, &&_66_0x49, &&_66_0x4A, &&_66_0x4B, &&_66_0x4C, &&_66_0x4D, &&_66_0x4E, &&_66_0x4F,
|
||||
&&_66_0x50, &&_66_0x51, &&_66_0x52, &&_66_0x53, &&_66_0x54, &&_66_0x55, &&_66_0x56, &&_66_0x57, //0x50-0x57
|
||||
@@ -979,7 +979,14 @@ _trace:
|
||||
goto fini;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0xCE: /* INTO */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
emit_signal(emu, SIGFPE, (void*)R_EIP, FPE_INTOVF);
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
STEP;
|
||||
NEXT;
|
||||
_0xCF: /* IRET */
|
||||
ip = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu)&0xffff;
|
||||
@@ -1306,6 +1313,15 @@ _trace:
|
||||
NEXT;
|
||||
case 0x90: /* PAUSE */
|
||||
NEXT;
|
||||
case 0x64: {
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xF1: /* INT1 */
|
||||
NEXT;
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
}
|
||||
case 0xA4: /* REP MOVSB */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
|
||||
+127
-1
@@ -1209,6 +1209,7 @@ void RunFS(x86emu_t *emu)
|
||||
{
|
||||
uintptr_t ip = R_EIP+1;
|
||||
uint8_t opcode = F8;
|
||||
int8_t tmp8s;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
@@ -1232,6 +1233,7 @@ void RunFS(x86emu_t *emu)
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x2B: /* SUB Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
@@ -1338,6 +1340,93 @@ void RunFS(x86emu_t *emu)
|
||||
tmp32u = F32;
|
||||
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
|
||||
break;
|
||||
|
||||
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
|
||||
case BASE+0x0: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x1: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x2: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_CF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x3: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_CF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x4: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_ZF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x5: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_ZF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x6: \
|
||||
PREFIX \
|
||||
if((ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x7: \
|
||||
PREFIX \
|
||||
if(!(ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x8: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_SF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0x9: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_SF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xA: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_PF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xB: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_PF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xC: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xD: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xE: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_ZF) || (ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF))) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+0xF: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_ZF) && (ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF))) \
|
||||
CONDITIONAL \
|
||||
break;
|
||||
GOCOND(0x70
|
||||
, tmp8s = F8S; CHECK_FLAGS(emu);
|
||||
, ip += tmp8s;
|
||||
) /* Jxx Ib */
|
||||
#undef GOCOND
|
||||
case 0x80: /* GRP Eb,Ib */
|
||||
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
|
||||
nextop = F8;
|
||||
@@ -1374,6 +1463,39 @@ void RunFS(x86emu_t *emu)
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x87:
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
} else {
|
||||
if(((uintptr_t)ED)&3)
|
||||
{
|
||||
// not aligned, dont't try to "LOCK"
|
||||
tmp32u = ED->dword[0];
|
||||
ED->dword[0] = GD.dword[0];
|
||||
GD.dword[0] = tmp32u;
|
||||
} else {
|
||||
// XCHG is supposed to automaticaly LOCK memory bus
|
||||
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
GET_ED_OFFS(tlsdata);
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -1424,6 +1546,10 @@ void RunFS(x86emu_t *emu)
|
||||
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
|
||||
break;
|
||||
|
||||
case 0xA8: /* TEST AL, Ib */
|
||||
test8(emu, R_AL, F8);
|
||||
break;
|
||||
|
||||
case 0xC0: /* GRP2 Eb,Ib */
|
||||
nextop = F8;
|
||||
GET_EB_OFFS(tlsdata);
|
||||
@@ -1562,4 +1688,4 @@ void RunGS0F(x86emu_t *emu, uintptr_t tlsdata)
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
R_EIP = ip;
|
||||
}
|
||||
}
|
||||
+189
-49
@@ -224,30 +224,36 @@ void Run660F(x86emu_t *emu)
|
||||
case 0x2C: /* CVTTPD2PI Gm, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GM.sd[0] = EX->d[0];
|
||||
GM.sd[1] = EX->d[1];
|
||||
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
|
||||
GM.ud[0] = 0x80000000;
|
||||
else
|
||||
GM.sd[0] = EX->d[0];
|
||||
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
|
||||
GM.ud[1] = 0x80000000;
|
||||
else
|
||||
GM.sd[1] = EX->d[1];
|
||||
break;
|
||||
case 0x2D: /* CVTPD2PI Gm, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
switch((emu->mxcsr>>13)&3) {
|
||||
case ROUND_Nearest:
|
||||
GM.sd[0] = floor(EX->d[0]+0.5);
|
||||
GM.sd[1] = floor(EX->d[1]+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GM.sd[0] = floor(EX->d[0]);
|
||||
GM.sd[1] = floor(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GM.sd[0] = ceil(EX->d[0]);
|
||||
GM.sd[1] = ceil(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GM.sd[0] = EX->d[0];
|
||||
GM.sd[1] = EX->d[1];
|
||||
break;
|
||||
}
|
||||
for(int i=0; i<2; ++i)
|
||||
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
|
||||
GM.ud[i] = 0x80000000;
|
||||
else
|
||||
switch(emu->mxcsr.f.MXCSR_RC) {
|
||||
case ROUND_Nearest:
|
||||
GM.sd[i] = nearbyint(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GM.sd[i] = floor(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GM.sd[i] = ceil(EX->d[i]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GM.sd[i] = EX->d[i];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2E: /* UCOMISD Gx, Ex */
|
||||
// no special check...
|
||||
@@ -498,6 +504,14 @@ void Run660F(x86emu_t *emu)
|
||||
GX.sd[i] = EX->sd[i];
|
||||
break;
|
||||
|
||||
case 0x40: /* PMULLD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
GX.sd[i] *= EX->sd[i];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ip = R_EIP;
|
||||
UnimpOpcode(emu);
|
||||
@@ -507,6 +521,103 @@ void Run660F(x86emu_t *emu)
|
||||
case 0x3A: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x08: // roundps GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.f[0] = nearbyint(EX->f[0]);
|
||||
GX.f[1] = nearbyint(EX->f[1]);
|
||||
GX.f[2] = nearbyint(EX->f[2]);
|
||||
GX.f[3] = nearbyint(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.f[0] = floor(EX->f[0]);
|
||||
GX.f[1] = floor(EX->f[1]);
|
||||
GX.f[2] = floor(EX->f[2]);
|
||||
GX.f[3] = floor(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.f[0] = ceil(EX->f[0]);
|
||||
GX.f[1] = ceil(EX->f[1]);
|
||||
GX.f[2] = ceil(EX->f[2]);
|
||||
GX.f[3] = ceil(EX->f[3]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.f[0] = trunc(EX->f[0]);
|
||||
GX.f[1] = trunc(EX->f[1]);
|
||||
GX.f[2] = trunc(EX->f[2]);
|
||||
GX.f[3] = trunc(EX->f[3]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x09: // roundpd GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.d[0] = nearbyint(EX->d[0]);
|
||||
GX.d[1] = nearbyint(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.d[0] = floor(EX->d[0]);
|
||||
GX.d[1] = floor(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.d[0] = ceil(EX->d[0]);
|
||||
GX.d[1] = ceil(EX->d[1]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.d[0] = trunc(EX->d[0]);
|
||||
GX.d[1] = trunc(EX->d[1]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0A: // roundss GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.f[0] = nearbyint(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.f[0] = floor(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.f[0] = ceil(EX->f[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.f[0] = trunc(EX->f[0]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0B: // roundsd GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
|
||||
{
|
||||
case ROUND_Nearest:
|
||||
GX.d[0] = nearbyint(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
GX.d[0] = floor(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
GX.d[0] = ceil(EX->d[0]);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
GX.d[0] = trunc(EX->d[0]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0E: /* PBLENDW Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -561,6 +672,12 @@ void Run660F(x86emu_t *emu)
|
||||
ED->dword[0] = GX.ud[tmp8u&3];
|
||||
break;
|
||||
|
||||
case 0x20: // PINSRB GX, Ed, Ib
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp8u = F8;
|
||||
GX.ub[tmp8u&0xF] = ED->byte[0]; // only low 8bits
|
||||
break;
|
||||
case 0x21: // INSERTPS GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -664,32 +781,24 @@ void Run660F(x86emu_t *emu)
|
||||
case 0x5B: /* CVTPS2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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)
|
||||
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;
|
||||
@@ -1035,6 +1144,31 @@ void Run660F(x86emu_t *emu)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7D: /* HSUBPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
#ifndef NOALIGN
|
||||
is_nan = isnan(GX.d[0]) || isnan(GX.d[1]);
|
||||
#endif
|
||||
GX.d[0] -= GX.d[1];
|
||||
#ifndef NOALIGN
|
||||
if(!is_nan && isnan(GX.d[0]))
|
||||
GX.d[0] = -NAN;
|
||||
#endif
|
||||
if(EX==&GX) {
|
||||
GX.d[1] = GX.d[0];
|
||||
} else {
|
||||
#ifndef NOALIGN
|
||||
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
|
||||
#endif
|
||||
GX.d[1] = EX->d[0] - EX->d[1];
|
||||
#ifndef NOALIGN
|
||||
if(!is_nan && isnan(GX.d[1]))
|
||||
GX.d[1] = -NAN;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7E: /* MOVD Ed, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -1454,7 +1588,7 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xE2: /* PSRAD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
|
||||
tmp8u=(EX->q[0]>31)?31:EX->ub[0];
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sd[i] >>= tmp8u;
|
||||
break;
|
||||
@@ -1483,8 +1617,14 @@ void Run660F(x86emu_t *emu)
|
||||
case 0xE6: /* CVTTPD2DQ Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
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 */
|
||||
|
||||
@@ -50,6 +50,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
|
||||
#else
|
||||
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
|
||||
{
|
||||
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
|
||||
// let's cheat and set all args...
|
||||
Push(emu, (uint32_t)my_context->envv);
|
||||
Push(emu, (uint32_t)my_context->argv);
|
||||
@@ -63,6 +64,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
|
||||
return 0;
|
||||
emu->quit = 0;
|
||||
}
|
||||
MarkElfInitDone(my_context->elfs[0]);
|
||||
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
|
||||
// call main and finish
|
||||
PushExit(emu);
|
||||
@@ -71,7 +73,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
|
||||
DynaRun(emu);
|
||||
|
||||
emu->quit = 1; // finished!
|
||||
return 0;
|
||||
return (int)R_EAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -804,11 +806,46 @@ void printFunctionAddr(uintptr_t nextaddr, const char* text)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
extern uint64_t start_cnt;
|
||||
#define PK(a) (*(uint8_t*)(ip+a))
|
||||
#define PK32(a) (*(int32_t*)((uint8_t*)(ip+a)))
|
||||
|
||||
uintptr_t evalED(x86emu_t* emu, uintptr_t ip) {
|
||||
uint8_t nextop = PK(0);
|
||||
if((nextop&0xC0)==0xC0)
|
||||
return emu->regs[(nextop&7)].dword[0];
|
||||
else {
|
||||
++ip;
|
||||
if(!(nextop&0xC0)) {
|
||||
if((nextop&7)==4) {
|
||||
uint8_t sib = PK(0);
|
||||
++ip;
|
||||
uintptr_t base = ((sib&0x7)==5)?(uint32_t)(PK32(0)):(emu->regs[(sib&0x7)].dword[0]);
|
||||
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
|
||||
return *(uintptr_t*)base;
|
||||
} else if((nextop&7)==5) {
|
||||
return *(uintptr_t*)PK32(0);
|
||||
} else {
|
||||
return *(uintptr_t*)emu->regs[nextop&7].dword[0];
|
||||
}
|
||||
} else {
|
||||
uintptr_t base;
|
||||
if((nextop&7)==4) {
|
||||
uint8_t sib = PK(0);
|
||||
++ip;
|
||||
base = emu->regs[(sib&0x7)].dword[0];
|
||||
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
|
||||
} else {
|
||||
base = emu->regs[(nextop&0x7)].dword[0];
|
||||
} \
|
||||
base+=(nextop&0x80)?(*(int32_t*)ip):(*(int8_t*)ip);
|
||||
return *(uintptr_t*)base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRACE
|
||||
extern uint64_t start_cnt;
|
||||
|
||||
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
{
|
||||
if(start_cnt) --start_cnt;
|
||||
@@ -816,7 +853,7 @@ void PrintTrace(x86emu_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");
|
||||
@@ -839,7 +876,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_NONE, "%s", DecodeX86Trace(my_context->dec, ip));
|
||||
uint8_t peek = PK(0);
|
||||
const uint8_t peek = PK(0);
|
||||
if(peek==0xC3 || peek==0xC2) {
|
||||
printf_log(LOG_NONE, " => %p", *(void**)(R_ESP));
|
||||
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
|
||||
@@ -850,14 +887,16 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
uintptr_t nextaddr = ip + 5 + PK32(1);
|
||||
printFunctionAddr(nextaddr, "=> ");
|
||||
} else if(peek==0xFF) {
|
||||
if(PK(1)==0x25) {
|
||||
uintptr_t nextaddr = ip + 6 + PK32(2);
|
||||
printFunctionAddr(nextaddr, "=> ");
|
||||
const uint8_t pk1 = PK(1);
|
||||
if(((pk1>>3)&7)==2 || ((pk1>>3)&7)==4) { // jmp/call near
|
||||
uintptr_t nextaddr = (uintptr_t)getAlternate((void*)evalED(emu, ip+1));
|
||||
printf_log(LOG_NONE, " => %p", nextaddr);
|
||||
printFunctionAddr(nextaddr, " / ");
|
||||
}
|
||||
}
|
||||
printf_log(LOG_NONE, "\n");
|
||||
}
|
||||
pthread_mutex_unlock(&my_context->mutex_trace);
|
||||
mutex_unlock(&my_context->mutex_trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+182
-60
@@ -72,17 +72,18 @@ void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot, int fla
|
||||
void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
|
||||
int my_munmap(x86emu_t* emu, void* addr, unsigned long length);
|
||||
int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot);
|
||||
void* ElfSetBrk(void* newbrk);
|
||||
int my_vfork(x86emu_t* emu);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 04000
|
||||
#endif
|
||||
#undef fcntl
|
||||
int fcntl(int fd, int cmd, ... /* arg */ );
|
||||
int my_fcntl(x86emu_t* emu, int fd, int cmd, ... /* arg */ );
|
||||
|
||||
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
|
||||
typedef struct scwrap_s {
|
||||
int x86s;
|
||||
uint32_t x86s;
|
||||
int nats;
|
||||
int nbpars;
|
||||
} scwrap_t;
|
||||
@@ -112,7 +113,7 @@ scwrap_t syscallwrap[] = {
|
||||
{ 40, __NR_rmdir, 1 },
|
||||
{ 41, __NR_dup, 1 },
|
||||
{ 42, __NR_pipe, 1 },
|
||||
{ 45, __NR_brk, 1 },
|
||||
//{ 45, __NR_brk, 1 },
|
||||
{ 47, __NR_getgid, 0 },
|
||||
{ 49, __NR_geteuid, 0 },
|
||||
{ 50, __NR_getegid, 0 },
|
||||
@@ -192,6 +193,8 @@ scwrap_t syscallwrap[] = {
|
||||
{ 175, __NR_rt_sigprocmask, 4 },
|
||||
{ 179, __NR_rt_sigsuspend, 2 },
|
||||
{ 183, __NR_getcwd, 2 },
|
||||
{ 184, __NR_capget, 2},
|
||||
{ 185, __NR_capset, 2},
|
||||
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
|
||||
{ 191, __NR_ugetrlimit, 2 },
|
||||
// { 192, __NR_mmap2, 6},
|
||||
@@ -204,6 +207,9 @@ scwrap_t syscallwrap[] = {
|
||||
{ 201, __NR_geteuid32, 0 },
|
||||
{ 202, __NR_getegid32, 0 },
|
||||
{ 208, __NR_setresuid32, 3 },
|
||||
{ 209, __NR_getresuid32, 3 },
|
||||
{ 210, __NR_setresgid32, 3 },
|
||||
{ 211, __NR_getresgid32, 3 },
|
||||
#else
|
||||
// PowerPC uses the same syscalls for 32/64 bit processes.
|
||||
{ 199, __NR_getuid, 0 },
|
||||
@@ -211,6 +217,9 @@ scwrap_t syscallwrap[] = {
|
||||
{ 201, __NR_geteuid, 0 },
|
||||
{ 202, __NR_getegid, 0 },
|
||||
{ 208, __NR_setresuid, 3 },
|
||||
{ 209, __NR_getresuid, 3 },
|
||||
{ 210, __NR_setresgid, 3 },
|
||||
{ 211, __NR_getresgid, 3 },
|
||||
#endif
|
||||
{ 220, __NR_getdents64, 3 },
|
||||
//{ 221, __NR_fcntl64, 3 },
|
||||
@@ -324,6 +333,38 @@ int clone_fn(void* arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef __NR_ipc
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
static int my_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
|
||||
{
|
||||
#define IPC_SEMOP 1
|
||||
#define IPC_SEMGET 2
|
||||
#define IPC_SEMCTL 3
|
||||
#define IPC_SEMTIMEDOP 4
|
||||
#define IPC_MSGSND 11
|
||||
#define IPC_MSGRCV 12
|
||||
#define IPC_MSGGET 13
|
||||
#define IPC_MSGCTL 14
|
||||
#define IPC_SHMAT 21
|
||||
#define IPC_SHMDT 22
|
||||
#define IPC_SHMGET 23
|
||||
#define IPC_SHMCTL 24
|
||||
int version;
|
||||
version = call>>16;
|
||||
call &= 0xffff;
|
||||
switch (call) {
|
||||
case IPC_SHMGET:
|
||||
return semget(first, second, third);
|
||||
default:
|
||||
printf_log(LOG_INFO, "Unsuported IPC call %d (version %d)\n", call, version);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void EXPORT x86Syscall(x86emu_t *emu)
|
||||
{
|
||||
RESET_FLAGS(emu);
|
||||
@@ -347,6 +388,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
emu->quit = 1;
|
||||
return;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
|
||||
return;
|
||||
}
|
||||
@@ -360,21 +403,31 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
break;
|
||||
case 3: // sys_read
|
||||
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 4: // sys_write
|
||||
R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 5: // sys_open
|
||||
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);};
|
||||
//R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 6: // sys_close
|
||||
R_EAX = (uint32_t)close((int)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_waitpid
|
||||
case 7: //sys_waitpid
|
||||
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 11: // sys_execve
|
||||
@@ -385,36 +438,43 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
printf_log(LOG_DEBUG, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
|
||||
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
case 13: // sys_time (it's deprecated and remove on ARM EABI it seems)
|
||||
R_EAX = time(NULL);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 45: // sys_brk
|
||||
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 54: // sys_ioctl
|
||||
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 55: // sys_fcntl
|
||||
if(R_ECX==4) {
|
||||
// filter out O_NONBLOCK so old stacally linked games that access X11 don't get EAGAIN error sometimes
|
||||
int tmp = of_convert((int)R_EDX)&(~O_NONBLOCK);
|
||||
if(R_EDX==0xFFFFF7FF) {
|
||||
// special case for ~O_NONBLOCK...
|
||||
int flags = fcntl(R_EBX, 3);
|
||||
tmp = flags&~O_NONBLOCK;
|
||||
}
|
||||
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, tmp);
|
||||
} else
|
||||
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
|
||||
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_getrlimit
|
||||
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
|
||||
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_select
|
||||
case 82: // select
|
||||
R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 90: // old_mmap
|
||||
@@ -422,9 +482,13 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
|
||||
R_EAX = (uintptr_t)my_mmap(emu, (void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 91: // munmap
|
||||
R_EAX = my_munmap(emu, (void*)R_EBX, (unsigned long)R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef __NR_socketcall
|
||||
case 102: {
|
||||
@@ -455,8 +519,10 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
#endif
|
||||
default:
|
||||
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX);
|
||||
R_EAX = -1;
|
||||
R_EAX = -EINVAL;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -473,6 +539,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
memcpy(old->version, un.version, 9);
|
||||
strcpy(old->machine, "i686");
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -480,6 +548,13 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
case 110: // iopl
|
||||
R_EAX = 0; // only on x86, so return 0...
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_ipc
|
||||
case 117: // ipc
|
||||
R_EAX = (uint32_t)my_ipc(R_EBX, (int)R_ECX, (int)R_EDX, (int)R_ESI, (void*)R_EDI, (long)R_EBP);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 119: // sys_sigreturn
|
||||
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
|
||||
@@ -487,44 +562,53 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
case 120: // clone
|
||||
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
|
||||
// so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, tls=R_ESI, child_tid=R_EDI
|
||||
if(R_ECX)
|
||||
{
|
||||
void* stack_base = (void*)R_ECX;
|
||||
int stack_size = 0;
|
||||
if(!R_ECX) {
|
||||
// allocate a new stack...
|
||||
int currstack = 0;
|
||||
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((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_ESP);
|
||||
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
|
||||
if((R_EBX&~0xff)==0x4100) {
|
||||
// this is a case of vfork...
|
||||
R_EAX = my_vfork(emu);
|
||||
if(R_EAX==0xffffffff)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
} else {
|
||||
if(R_ECX)
|
||||
{
|
||||
void* stack_base = (void*)R_ECX;
|
||||
int stack_size = 0;
|
||||
if(!R_ECX) {
|
||||
// allocate a new stack...
|
||||
int currstack = 0;
|
||||
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((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_ESP);
|
||||
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
|
||||
}
|
||||
}
|
||||
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
|
||||
SetupX86Emu(newemu);
|
||||
CloneEmu(newemu, emu);
|
||||
Push32(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;
|
||||
}
|
||||
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
|
||||
R_EAX = (uint32_t)ret;
|
||||
}
|
||||
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
|
||||
SetupX86Emu(newemu);
|
||||
CloneEmu(newemu, emu);
|
||||
Push32(newemu, 0);
|
||||
PushExit(newemu);
|
||||
void* mystack = NULL;
|
||||
if(my_context->stack_clone_used) {
|
||||
mystack = 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 = malloc(1024*1024);
|
||||
mystack = my_context->stack_clone;
|
||||
my_context->stack_clone_used = 1;
|
||||
}
|
||||
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
|
||||
R_EAX = (uint32_t)ret;
|
||||
else
|
||||
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
}
|
||||
else
|
||||
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
|
||||
break;
|
||||
case 122: // uname
|
||||
{
|
||||
@@ -539,15 +623,23 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
strcpy(old->machine, "i686");
|
||||
}
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 123: // SYS_modify_ldt
|
||||
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 125: // mprotect
|
||||
R_EAX = my_mprotect(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 168: // sys_poll
|
||||
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 173: // sys_rt_sigreturn
|
||||
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
|
||||
@@ -555,12 +647,16 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
case 174: // sys_rt_sigaction
|
||||
//printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 190: // vfork
|
||||
{
|
||||
int r = vfork();
|
||||
int r = my_vfork(emu);
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 192: // mmap2
|
||||
R_EAX = (uint32_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
|
||||
@@ -573,6 +669,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 196: // lstat64
|
||||
{
|
||||
@@ -582,6 +680,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 197: // fstat64
|
||||
{
|
||||
@@ -591,44 +691,60 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
|
||||
R_EAX = r;
|
||||
}
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 221: // sys_fcntl64
|
||||
if(R_ECX==4) {
|
||||
int tmp = of_convert((int)R_EDX);
|
||||
R_EAX = (uint32_t)fcntl((int)R_EBX, R_ECX, tmp);
|
||||
} else
|
||||
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
|
||||
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 243: // set_thread_area
|
||||
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef NOALIGN
|
||||
case 254: // epoll_create
|
||||
R_EAX = my_epoll_create(emu, (int)R_EBX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 255: // epoll_ctl
|
||||
R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
case 256: // epoll_wait
|
||||
R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
case 270: // tgkill
|
||||
R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#ifndef NOALIGN
|
||||
case 329: // epoll_create1
|
||||
R_EAX = my_epoll_create1(emu, of_convert(R_EBX));
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_getrandom
|
||||
case 355: // getrandom
|
||||
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
#ifndef __NR_memfd_create
|
||||
case 356: // memfd_create
|
||||
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
|
||||
if(R_EAX==0xffffffff && errno>0)
|
||||
R_EAX = (uint32_t)-errno;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -684,8 +800,14 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
return (uint32_t)close(i32(4));
|
||||
case 11: // execve
|
||||
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
|
||||
case 45: // brk
|
||||
return (uintptr_t)ElfSetBrk(p(4));
|
||||
case 91: // munmap
|
||||
return (uint32_t)my_munmap(emu, p(4), u32(8));
|
||||
#ifndef __NR_ipc
|
||||
case 117: // ipc
|
||||
return (uint32_t)my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
|
||||
#endif
|
||||
case 120: // clone
|
||||
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
|
||||
// so flags=u(4), stack=p(8), parent_tid=p(12), tls=p(16), child_tid=p(20)
|
||||
@@ -715,10 +837,10 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
PushExit(newemu);
|
||||
void* mystack = NULL;
|
||||
if(my_context->stack_clone_used) {
|
||||
mystack = malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
|
||||
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 = malloc(1024*1024);
|
||||
my_context->stack_clone = box_malloc(1024*1024);
|
||||
mystack = my_context->stack_clone;
|
||||
my_context->stack_clone_used = 1;
|
||||
}
|
||||
@@ -734,7 +856,7 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
case 125: // mprotect
|
||||
return (uint32_t)my_mprotect(emu, p(4), u32(8), i32(12));
|
||||
case 174: // sys_rt_sigaction
|
||||
return (uint32_t)my_sigaction(emu, i32(4), (x86_sigaction_t*)p(8), (x86_sigaction_t*)p(12));
|
||||
return (uint32_t)my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
|
||||
case 192: // mmap2
|
||||
return (uint32_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
|
||||
case 243: // set_thread_area
|
||||
|
||||
+118
-46
@@ -24,19 +24,37 @@ typedef struct thread_area_s
|
||||
unsigned int useable:1;
|
||||
} thread_area_t;
|
||||
|
||||
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
|
||||
#define SUPER() \
|
||||
GO(0) \
|
||||
GO(1) \
|
||||
GO(2) \
|
||||
GO(3) \
|
||||
GO(4) \
|
||||
GO(5) \
|
||||
GO(6) \
|
||||
GO(7) \
|
||||
GO(8) \
|
||||
GO(9) \
|
||||
GO(10) \
|
||||
GO(11) \
|
||||
GO(12) \
|
||||
GO(13) \
|
||||
GO(14) \
|
||||
GO(15) \
|
||||
GO(16) \
|
||||
GO(17) \
|
||||
GO(18) \
|
||||
|
||||
static void thread_key_alloc0() {
|
||||
pthread_key_create(&my_context->segtls[0].key, NULL);
|
||||
}
|
||||
static void thread_key_alloc1() {
|
||||
pthread_key_create(&my_context->segtls[1].key, NULL);
|
||||
}
|
||||
static void thread_key_alloc2() {
|
||||
pthread_key_create(&my_context->segtls[2].key, NULL);
|
||||
#define GO(A) static pthread_once_t thread_key_once##A = PTHREAD_ONCE_INIT;
|
||||
SUPER()
|
||||
|
||||
#undef GO
|
||||
#define GO(A)\
|
||||
static void thread_key_alloc##A() { \
|
||||
pthread_key_create(&my_context->segtls[A].key, NULL); \
|
||||
}
|
||||
SUPER()
|
||||
#undef GO
|
||||
|
||||
uint32_t my_set_thread_area(thread_area_t* td)
|
||||
{
|
||||
@@ -81,11 +99,11 @@ uint32_t my_set_thread_area(thread_area_t* td)
|
||||
my_context->segtls[idx-7].base = td->base_addr;
|
||||
my_context->segtls[idx-7].limit = td->limit;
|
||||
my_context->segtls[idx-7].present = 1;
|
||||
#define GO(A) case A: pthread_once(&thread_key_once##A, thread_key_alloc##A); break;
|
||||
switch (idx-7) {
|
||||
case 0: pthread_once(&thread_key_once0, thread_key_alloc0); break;
|
||||
case 1: pthread_once(&thread_key_once1, thread_key_alloc1); break;
|
||||
case 2: pthread_once(&thread_key_once2, thread_key_alloc2); break;
|
||||
SUPER()
|
||||
}
|
||||
#undef GO
|
||||
|
||||
pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
|
||||
|
||||
@@ -96,32 +114,45 @@ uint32_t my_set_thread_area(thread_area_t* td)
|
||||
|
||||
EXPORT uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
|
||||
{
|
||||
(void)emu;
|
||||
printf_log(/*LOG_DEBUG*/LOG_INFO, "modify_ldt(0x%x, %p[0x%x/base=%p/limit=%u/32bits:%u/%u/%u...], %d)\n", op, td, td->entry_number, (void*)td->base_addr, td->limit_in_pages, td->seg_32bit, td->contents, td->read_exec_only, size);
|
||||
if(!td) {
|
||||
errno = EFAULT;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
if(op==0 && size==8) {
|
||||
td->entry_number = 6;
|
||||
td->base_addr = (uintptr_t)GetSegmentBase(6<<3);
|
||||
return 8;
|
||||
}
|
||||
if(op!=0x11) {
|
||||
errno = ENOSYS;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
if(!td->seg_32bit) {
|
||||
if(!td->seg_32bit && td->base_addr) {
|
||||
// not handling 16bits segments for now
|
||||
errno = EINVAL;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
int idx = td->entry_number - 7;
|
||||
if(idx<0 || idx>2) {
|
||||
if(td->entry_number>=0x1ff0) idx=td->entry_number-0x1ff0+3;
|
||||
if(idx<0 || idx>16+3-1) {
|
||||
printf_log(LOG_DEBUG, "modify_ldt: idx out of range: %d\n", idx);
|
||||
errno = EINVAL;
|
||||
return (uint32_t)-1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
my_context->segtls[idx].base = td->base_addr;
|
||||
my_context->segtls[idx].limit = td->limit;
|
||||
my_context->segtls[idx].present = td->base_addr?1:0;
|
||||
#define GO(A) case A: pthread_once(&thread_key_once##A, thread_key_alloc##A); break;
|
||||
switch (idx-7) {
|
||||
SUPER()
|
||||
}
|
||||
#undef GO
|
||||
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
|
||||
*/
|
||||
|
||||
ResetSegmentsCache(thread_get_emu());
|
||||
|
||||
@@ -130,54 +161,92 @@ EXPORT uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size
|
||||
|
||||
#define POS_TLS 0x50
|
||||
|
||||
static int sizeDTS(box86context_t* context)
|
||||
{
|
||||
return ((context->elfsize+0xff)&~0xff)*8;
|
||||
}
|
||||
static int sizeTLSData(int s)
|
||||
{
|
||||
uint32_t mask = 0xffff/*box64_nogtk?0xffff:0x1fff*/; // x86 does the mapping per 64K blocks, so it makes sense to have it this large
|
||||
return (s+mask)&~mask;
|
||||
}
|
||||
|
||||
static tlsdatasize_t* setupTLSData(box86context_t* context)
|
||||
{
|
||||
// Setup the GS segment:
|
||||
int dtsize = context->elfsize*8;
|
||||
void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
|
||||
memcpy(ptr, context->tlsdata, context->tlssize);
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
|
||||
data->tlsdata = ptr;
|
||||
int dtssize = sizeDTS(context);
|
||||
int datasize = sizeTLSData(context->tlssize);
|
||||
void *ptr_oversized = (char*)box_malloc(dtssize+POS_TLS+datasize);
|
||||
void *ptr = (void*)((uintptr_t)ptr_oversized + datasize);
|
||||
memcpy((void*)((uintptr_t)ptr-context->tlssize), context->tlsdata, context->tlssize);
|
||||
tlsdatasize_t *data = (tlsdatasize_t*)box_calloc(1, sizeof(tlsdatasize_t));
|
||||
data->data = ptr;
|
||||
data->tlssize = context->tlssize;
|
||||
data->ptr = ptr_oversized;
|
||||
data->n_elfs = context->elfsize;
|
||||
pthread_setspecific(context->tlskey, data);
|
||||
// copy canary...
|
||||
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, 4); // put canary in place
|
||||
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
|
||||
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
|
||||
memset((void*)((uintptr_t)ptr), 0, POS_TLS+dtssize); // set to 0 remining bytes
|
||||
memcpy((void*)((uintptr_t)ptr+0x14), context->canary, 4); // put canary in place
|
||||
uintptr_t tlsptr = (uintptr_t)ptr;
|
||||
memcpy((void*)((uintptr_t)ptr+0x0), &tlsptr, 4);
|
||||
uintptr_t dtp = (uintptr_t)ptr+POS_TLS;
|
||||
memcpy((void*)(tlsptr+0x4), &dtp, 4);
|
||||
if(dtsize) {
|
||||
if(dtssize) {
|
||||
for (int i=0; i<context->elfsize; ++i) {
|
||||
// set pointer
|
||||
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8), &dtp, 4);
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
|
||||
dtp = (uintptr_t)ptr + GetTLSBase(context->elfs[i]);
|
||||
memcpy((void*)((uintptr_t)ptr+POS_TLS+i*8), &dtp, 4);
|
||||
memcpy((void*)((uintptr_t)ptr+POS_TLS+i*8+4), &i, 4); // index
|
||||
}
|
||||
}
|
||||
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4); // address of vsyscall
|
||||
memcpy((void*)((uintptr_t)ptr+0x10), &context->vsyscall, 4); // address of vsyscall
|
||||
return data;
|
||||
}
|
||||
|
||||
void* fillTLSData(box86context_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(box86context_t *context, void* oldptr)
|
||||
{
|
||||
pthread_mutex_lock(&context->mutex_tls);
|
||||
mutex_lock(&context->mutex_tls);
|
||||
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
|
||||
tlsdatasize_t *data = setupTLSData(context);
|
||||
// copy the relevent old part, in case something changed
|
||||
memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
|
||||
// all done, update new size, free old pointer and exit
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
free_tlsdatasize(oldptr);
|
||||
return data;
|
||||
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));
|
||||
tlsdatasize_t *data = setupTLSData(context);
|
||||
// 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
|
||||
mutex_unlock(&context->mutex_tls);
|
||||
free_tlsdatasize(oldptr);
|
||||
return data;
|
||||
} else {
|
||||
// keep the same tlsdata, but fill in the blanks
|
||||
// adjust tlsdata
|
||||
void *ptr = oldata->data;
|
||||
if(context->tlssize!=oldata->tlssize) {
|
||||
memcpy((void*)((uintptr_t)ptr-context->tlssize), context->tlsdata, context->tlssize-oldata->tlssize);
|
||||
oldata->tlssize = context->tlssize;
|
||||
}
|
||||
// adjust DTS
|
||||
if(oldata->n_elfs!=context->elfsize) {
|
||||
uintptr_t dtp = (uintptr_t)ptr+POS_TLS;
|
||||
for (int i=oldata->n_elfs; i<context->elfsize; ++i) {
|
||||
// set pointer
|
||||
dtp = (uintptr_t)ptr + GetTLSBase(context->elfs[i]);
|
||||
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8) = dtp;
|
||||
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8+4) = i; // index
|
||||
}
|
||||
oldata->n_elfs = context->elfsize;
|
||||
}
|
||||
mutex_unlock(&context->mutex_tls);
|
||||
return oldata;
|
||||
}
|
||||
}
|
||||
|
||||
static void* GetSeg33Base()
|
||||
@@ -189,7 +258,7 @@ static void* GetSeg33Base()
|
||||
if(ptr->tlssize != my_context->tlssize) {
|
||||
ptr = (tlsdatasize_t*)resizeTLSData(my_context, ptr);
|
||||
}
|
||||
return ptr->tlsdata+ptr->tlssize;
|
||||
return ptr->data;
|
||||
}
|
||||
|
||||
void* GetSegmentBase(uint32_t desc)
|
||||
@@ -204,11 +273,14 @@ void* GetSegmentBase(uint32_t desc)
|
||||
if(base==0x6)
|
||||
return GetSeg33Base();
|
||||
|
||||
if(base>6 && base<10 && my_context->segtls[base-7].present) {
|
||||
if(base>=0x1ff0)
|
||||
base = base - 0x1ff0 + 3 + 7;
|
||||
|
||||
if(base>6 && base<16+3+7 && my_context->segtls[base-7].present) {
|
||||
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
|
||||
printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x (%d) or unset\n", desc, base);
|
||||
return NULL;
|
||||
}
|
||||
+4
-4
@@ -41,7 +41,7 @@ int InitX86Trace(box86context_t *context)
|
||||
{
|
||||
if(context->zydis)
|
||||
return 0;
|
||||
context->zydis = (zydis_t*)calloc(1, sizeof(zydis_t));
|
||||
context->zydis = (zydis_t*)box_calloc(1, sizeof(zydis_t));
|
||||
if(!context->zydis)
|
||||
return 1;
|
||||
context->zydis->lib = dlopen("libZydis.so", RTLD_LAZY);
|
||||
@@ -69,7 +69,7 @@ void DeleteX86Trace(box86context_t *context)
|
||||
return;
|
||||
if(context->zydis->lib)
|
||||
dlclose(context->zydis->lib);
|
||||
free(context->zydis);
|
||||
box_free(context->zydis);
|
||||
context->zydis = NULL;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ zydis_dec_t* InitX86TraceDecoder(box86context_t *context)
|
||||
{
|
||||
if(!context->zydis)
|
||||
return NULL;
|
||||
zydis_dec_t *dec = (zydis_dec_t*)calloc(1, sizeof(zydis_dec_t));
|
||||
zydis_dec_t *dec = (zydis_dec_t*)box_calloc(1, sizeof(zydis_dec_t));
|
||||
dec->ZydisDecoderDecodeBuffer = context->zydis->ZydisDecoderDecodeBuffer;
|
||||
dec->ZydisFormatterFormatInstruction = context->zydis->ZydisFormatterFormatInstruction;
|
||||
context->zydis->ZydisDecoderInit(&dec->decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32);
|
||||
@@ -87,7 +87,7 @@ zydis_dec_t* InitX86TraceDecoder(box86context_t *context)
|
||||
}
|
||||
void DeleteX86TraceDecoder(zydis_dec_t **dec)
|
||||
{
|
||||
free(*dec);
|
||||
box_free(*dec);
|
||||
*dec = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ void reset_fpu(x86emu_t* emu)
|
||||
{
|
||||
memset(emu->x87, 0, sizeof(emu->x87));
|
||||
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
|
||||
emu->cw = 0x37F;
|
||||
emu->cw.x16 = 0x37F;
|
||||
emu->sw.x16 = 0x0000;
|
||||
emu->top = 0;
|
||||
emu->fpu_stack = 0;
|
||||
@@ -73,6 +73,10 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s) {
|
||||
// long double (80bits) -> double (64bits)
|
||||
void LD2D(void* ld, void* d)
|
||||
{
|
||||
if(box86_x87_no80bits) {
|
||||
*(uint64_t*)d = *(uint64_t*)ld;
|
||||
return;
|
||||
}
|
||||
FPU_t result;
|
||||
#pragma pack(push, 1)
|
||||
struct {
|
||||
@@ -112,7 +116,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.ll==0)
|
||||
// zero
|
||||
//if(val.f.ll!=0)
|
||||
@@ -124,6 +128,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;
|
||||
@@ -144,6 +160,10 @@ void LD2D(void* ld, void* d)
|
||||
// double (64bits) -> long double (80bits)
|
||||
void D2LD(void* d, void* ld)
|
||||
{
|
||||
if(box86_x87_no80bits) {
|
||||
*(uint64_t*)ld = *(uint64_t*)d;
|
||||
return;
|
||||
}
|
||||
#pragma pack(push, 1)
|
||||
struct {
|
||||
FPU_t f;
|
||||
@@ -180,6 +200,12 @@ void D2LD(void* d, void* ld)
|
||||
if(exp80!=0){
|
||||
mant80final |= 0x8000000000000000LL;
|
||||
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);
|
||||
@@ -191,7 +217,9 @@ void D2LD(void* d, void* ld)
|
||||
|
||||
double FromLD(void* ld)
|
||||
{
|
||||
double ret;
|
||||
if(box86_x87_no80bits)
|
||||
return *(double*)ld;
|
||||
double ret; // cannot add = 0;
|
||||
LD2D(ld, &ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -213,7 +241,7 @@ long double LD2localLD(void* ld)
|
||||
|
||||
void fpu_loadenv(x86emu_t* emu, char* p, int b16)
|
||||
{
|
||||
emu->cw = *(uint16_t*)p;
|
||||
emu->cw.x16 = *(uint16_t*)p;
|
||||
p+=(b16)?2:4;
|
||||
emu->sw.x16 = *(uint16_t*)p;
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
@@ -231,7 +259,7 @@ void fpu_loadenv(x86emu_t* emu, char* p, int b16)
|
||||
void fpu_savenv(x86emu_t* emu, char* p, int b16)
|
||||
{
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
*(uint16_t*)p = emu->cw;
|
||||
*(uint16_t*)p = emu->cw.x16;
|
||||
p+=2;
|
||||
if(!b16) {*(uint16_t*)p = 0; p+=2;}
|
||||
*(uint16_t*)p = emu->sw.x16;
|
||||
@@ -274,11 +302,11 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
if(top==0) // check if stack is full or empty, based on tag[0]
|
||||
stack = (emu->p_regs[0].tag)?8:0;
|
||||
emu->sw.f.F87_TOP = top;
|
||||
p->ControlWord = emu->cw;
|
||||
p->ControlWord = emu->cw.x16;
|
||||
p->StatusWord = emu->sw.x16;
|
||||
uint8_t tags = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
|
||||
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
|
||||
p->TagWord = tags;
|
||||
p->ErrorOpcode = 0;
|
||||
p->ErrorOffset = 0;
|
||||
@@ -297,12 +325,12 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
{
|
||||
xsave_t *p = (xsave_t*)ed;
|
||||
emu->cw = p->ControlWord;
|
||||
emu->cw.x16 = p->ControlWord;
|
||||
emu->sw.x16 = p->StatusWord;
|
||||
emu->top = emu->sw.f.F87_TOP;
|
||||
uint8_t tags = p->TagWord;
|
||||
for(int i=0; i<8; ++i)
|
||||
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
|
||||
emu->p_regs[i].tag = ((tags>>(i*2))&0b1)?0:0b11;
|
||||
// copy back MMX regs...
|
||||
int top = emu->top&7;
|
||||
int stack = 8-top;
|
||||
|
||||
@@ -124,7 +124,7 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
|
||||
static inline double fpu_round(x86emu_t* emu, double d) {
|
||||
if (!isfinite(d))
|
||||
return d;
|
||||
switch(emu->round) {
|
||||
switch(emu->cw.f.C87_RD) {
|
||||
case ROUND_Nearest:
|
||||
return nearbyint(d);
|
||||
case ROUND_Down:
|
||||
|
||||
+54
-31
@@ -4,6 +4,9 @@
|
||||
#include <pthread.h>
|
||||
#include "pathcoll.h"
|
||||
#include "dictionnary.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct cleanup_s cleanup_t;
|
||||
@@ -42,8 +45,10 @@ typedef void* (*vkprocaddess_t)(void* instance, const char* name);
|
||||
#define MAX_SIGNAL 64
|
||||
|
||||
typedef struct tlsdatasize_s {
|
||||
int32_t tlssize;
|
||||
void* tlsdata;
|
||||
int tlssize;
|
||||
int n_elfs;
|
||||
void* data;
|
||||
void* ptr;
|
||||
} tlsdatasize_t;
|
||||
|
||||
void free_tlsdatasize(void* p);
|
||||
@@ -85,9 +90,10 @@ typedef struct box86context_s {
|
||||
char* fullpath;
|
||||
char* box86path; // path of current box86 executable
|
||||
char* box64path; // path of box64 executable (beside box86, if it exists)
|
||||
char* bashpath; // path of x86 bash (defined with BOX86_BASH or by running bash directly)
|
||||
|
||||
uint32_t stacksz;
|
||||
int stackalign;
|
||||
uint32_t stackalign;
|
||||
void* stack; // alocated stack
|
||||
|
||||
elfheader_t **elfs; // elf headers and memory
|
||||
@@ -98,6 +104,9 @@ typedef struct box86context_s {
|
||||
|
||||
uintptr_t ep; // entry point
|
||||
|
||||
void* brk; // current brk (should be the end of bss segment of main elf)
|
||||
int brksz; // current added sz for brk
|
||||
|
||||
lib_t *maplib; // lib and symbols handling
|
||||
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
|
||||
dic_t *versym; // dictionnary of versionned symbols
|
||||
@@ -113,48 +122,41 @@ typedef struct box86context_s {
|
||||
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
|
||||
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
|
||||
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
|
||||
kh_defaultversion_t *defver; // the default version for symbols (the XXX@@vvvv of symbols)
|
||||
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
|
||||
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
|
||||
vkprocaddess_t vkprocaddress;
|
||||
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_t mutex_once;
|
||||
pthread_mutex_t mutex_once2;
|
||||
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;
|
||||
int trace_dynarec;
|
||||
#endif
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
pthread_mutex_t mutex_bridge;
|
||||
pthread_mutex_t mutex_lock;
|
||||
#else
|
||||
uint32_t mutex_once;
|
||||
uint32_t mutex_once2;
|
||||
uint32_t mutex_trace;
|
||||
uint32_t mutex_tls;
|
||||
uint32_t mutex_thread;
|
||||
uint32_t mutex_bridge;
|
||||
uint32_t mutex_dyndump;
|
||||
int trace_dynarec;
|
||||
#endif
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
|
||||
void* sdl1allocrw;
|
||||
void* sdl1freerw;
|
||||
library_t *sdl1mixerlib;
|
||||
library_t *sdl2lib; // shortcut to SDL2 library (if loaded)
|
||||
void* sdl2allocrw;
|
||||
void* sdl2freerw;
|
||||
library_t *sdl2mixerlib;
|
||||
library_t *x11lib;
|
||||
library_t *libxcb;
|
||||
library_t *libxcbxfixes;
|
||||
library_t *libxcbshape;
|
||||
library_t *libxcbshm;
|
||||
library_t *libxcbrandr;
|
||||
library_t *libxcbimage;
|
||||
library_t *libxcbkeysyms;
|
||||
library_t *libxcbxtest;
|
||||
library_t *zlib;
|
||||
library_t *vorbisfile;
|
||||
library_t *vorbis;
|
||||
library_t *asound;
|
||||
library_t *pulse;
|
||||
library_t *d3dadapter9;
|
||||
|
||||
linkmap_t *linkmap;
|
||||
|
||||
void* sdl1allocrw; // AllocRW/FreeRW functions from SDL1
|
||||
void* sdl1freerw;
|
||||
void* sdl2allocrw; // AllocRW/FreeRW functions from SDL2
|
||||
void* sdl2freerw;
|
||||
|
||||
int deferedInit;
|
||||
elfheader_t **deferedInitList;
|
||||
int deferedInitSz;
|
||||
@@ -163,7 +165,7 @@ typedef struct box86context_s {
|
||||
pthread_key_t tlskey; // then tls key to have actual tlsdata
|
||||
void* tlsdata; // the initial global tlsdata
|
||||
int32_t tlssize; // wanted size of tlsdata
|
||||
base_segment_t segtls[3]; // only handling 0/1/2 descriptors
|
||||
base_segment_t segtls[3+16]; // only handling 0/1/2 descriptors + some special cases
|
||||
|
||||
uintptr_t *auxval_start;
|
||||
|
||||
@@ -192,13 +194,34 @@ typedef struct box86context_s {
|
||||
int no_sigill;
|
||||
void* stack_clone;
|
||||
int stack_clone_used;
|
||||
|
||||
// rolling logs
|
||||
char* *log_call;
|
||||
char* *log_ret;
|
||||
int current_line;
|
||||
} box86context_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) {int tid = GetTID(); while(arm_lock_storeifnull(A, (void*)tid)) sched_yield();}
|
||||
#define mutex_trylock(A) arm_lock_storeifnull(A, (void*)GetTID())
|
||||
#define mutex_unlock(A) arm_lock_storeifref(A, NULL, (void*)GetTID())
|
||||
#endif
|
||||
|
||||
extern box86context_t *my_context; // global context
|
||||
|
||||
box86context_t *NewBox86Context(int argc);
|
||||
void FreeBox86Context(box86context_t** context);
|
||||
|
||||
// Cycle log handling
|
||||
void freeCycleLog(box86context_t* ctx);
|
||||
void initCycleLog(box86context_t* context);
|
||||
void print_cycle_log(int loglevel);
|
||||
|
||||
// return the index of the added header
|
||||
int AddElfHeader(box86context_t* ctx, elfheader_t* head);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ void FreeBridge(bridge_t** bridge);
|
||||
|
||||
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
|
||||
int IsBridge(void* func);
|
||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
void* GetNativeFnc(uintptr_t fnc);
|
||||
|
||||
@@ -11,4 +11,5 @@ uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
// use emu state to run function
|
||||
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
|
||||
|
||||
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
#endif //__CALLBACK_H__
|
||||
+14
-3
@@ -34,8 +34,9 @@ uintptr_t getJumpTable();
|
||||
uintptr_t getJumpTableAddress(uintptr_t addr);
|
||||
#endif
|
||||
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_CUSTOM (PROT_DYNAREC)
|
||||
#define PROT_DYNAREC 0x80
|
||||
#define PROT_DYNAREC_R 0x40
|
||||
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R)
|
||||
|
||||
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
|
||||
@@ -45,7 +46,11 @@ void freeProtection(uintptr_t addr, uintptr_t size);
|
||||
void loadProtectionFromMap();
|
||||
#ifdef DYNAREC
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size);
|
||||
void unprotectDB(uintptr_t addr, uintptr_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
|
||||
int isprotectedDB(uintptr_t addr, size_t size);
|
||||
int IsInHotPage(uintptr_t addr);
|
||||
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);
|
||||
@@ -58,4 +63,10 @@ void relockCustommemMutex(int locks);
|
||||
void init_custommem_helper(box86context_t* ctx);
|
||||
void fini_custommem_helper(box86context_t* ctx);
|
||||
|
||||
#ifdef DYNAREC
|
||||
// ---- StrongMemoryModel
|
||||
void addLockAddress(uintptr_t addr); // add an address to the list of "LOCK"able
|
||||
int isLockAddress(uintptr_t addr); // return 1 is the address is used as a LOCK, 0 else
|
||||
#endif
|
||||
|
||||
#endif //__CUSTOM_MEM__H_
|
||||
+45
-4
@@ -7,17 +7,24 @@ extern int box86_log; // log level
|
||||
extern int box86_dump; // dump elf or not
|
||||
extern int box86_dynarec_log;
|
||||
extern int box86_dynarec;
|
||||
extern int box86_pagesize;
|
||||
extern uintptr_t box86_pagesize;
|
||||
extern uintptr_t box86_load_addr;
|
||||
extern int box86_showbt;
|
||||
#ifdef DYNAREC
|
||||
extern int box86_dynarec_dump;
|
||||
extern int box86_dynarec_trace;
|
||||
extern int box86_dynarec_forced;
|
||||
extern int box86_dynarec_largest;
|
||||
extern int box86_dynarec_bigblock;
|
||||
extern int box86_dynarec_forward;
|
||||
extern int box86_dynarec_strongmem;
|
||||
extern int box86_dynarec_x87double;
|
||||
extern int box86_dynarec_safeflags;
|
||||
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
|
||||
extern int box86_dynarec_fastnan;
|
||||
extern int box86_dynarec_fastround;
|
||||
extern int box86_dynarec_hotpage;
|
||||
extern int box86_dynarec_bleeding_edge;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
@@ -25,8 +32,11 @@ extern int arm_div;
|
||||
#endif
|
||||
#endif
|
||||
extern int dlsym_error; // log dlsym error
|
||||
extern int cycle_log; // if using rolling logs
|
||||
extern int trace_xmm; // include XMM reg in trace?
|
||||
extern int trace_emm; // include EMM reg in trace?
|
||||
extern int box86_sse_flushto0;
|
||||
extern int box86_x87_no80bits;
|
||||
extern int allow_missing_libs;
|
||||
extern int box86_prefer_wrapped;
|
||||
extern int box86_prefer_emulated;
|
||||
@@ -40,10 +50,16 @@ extern int box86_showsegv;
|
||||
extern int allow_missing_symbols;
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern char* trace_func;
|
||||
extern char* trace_init;
|
||||
extern char* box86_trace;
|
||||
extern uint64_t start_cnt;
|
||||
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
|
||||
extern uint32_t default_fs;
|
||||
extern int jit_gdb; // launch gdb when a segfault is trapped
|
||||
extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
extern int box86_x11threads;
|
||||
extern int box86_x11glx;
|
||||
extern char* box86_libGL;
|
||||
#define LOG_NONE 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
@@ -52,11 +68,13 @@ extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
|
||||
|
||||
extern FILE* ftrace;
|
||||
|
||||
#define printf_log(L, ...) do {if(L<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_log(L, ...) do {if((L)<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define printf_dump(L, ...) do {if(box86_dump || (L<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_dump(L, ...) do {if(box86_dump || ((L)<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
#define printf_dlsym(L, ...) do {if(dlsym_error || ((L)<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define dynarec_log(L, ...) do {if((L)<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#ifdef BUILD_DYNAMIC
|
||||
@@ -65,4 +83,27 @@ extern FILE* ftrace;
|
||||
#define EXPORTDYN
|
||||
#endif
|
||||
|
||||
void init_malloc_hook();
|
||||
#ifdef ANDROID
|
||||
#define box_malloc malloc
|
||||
#define box_realloc realloc
|
||||
#define box_calloc calloc
|
||||
#define box_free free
|
||||
#define box_memalign memalign
|
||||
#else
|
||||
extern size_t(*box_malloc_usable_size)(void*);
|
||||
extern void* __libc_malloc(size_t);
|
||||
extern void* __libc_realloc(void*, size_t);
|
||||
extern void* __libc_calloc(size_t, size_t);
|
||||
extern void __libc_free(void*);
|
||||
extern void* __libc_memalign(size_t, size_t);
|
||||
#define box_malloc __libc_malloc
|
||||
#define box_realloc __libc_realloc
|
||||
#define box_calloc __libc_calloc
|
||||
#define box_free __libc_free
|
||||
#define box_memalign __libc_memalign
|
||||
#endif
|
||||
extern char* box_strdup(const char* s);
|
||||
extern char* box_realpath(const char* path, char* ret);
|
||||
|
||||
#endif //__DEBUG_H_
|
||||
@@ -26,16 +26,18 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
|
||||
int RelocateElf(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
|
||||
void CalcStack(elfheader_t* h, uint32_t* stacksz, uint32_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, box86context_t* box86, x86emu_t* emu);
|
||||
uintptr_t GetElfInit(elfheader_t* h);
|
||||
uintptr_t GetElfFini(elfheader_t* h);
|
||||
void RefreshElfTLS(elfheader_t* h);
|
||||
void RunElfInit(elfheader_t* h, x86emu_t* emu);
|
||||
void RunElfFini(elfheader_t* h, x86emu_t* emu);
|
||||
void RunDeferedElfInit(x86emu_t* emu);
|
||||
void MarkElfInitDone(elfheader_t* h);
|
||||
void* GetBaseAddress(elfheader_t* h);
|
||||
void* GetElfDelta(elfheader_t* h);
|
||||
uint32_t GetBaseSize(elfheader_t* h);
|
||||
@@ -53,6 +55,7 @@ dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
|
||||
void ResetSpecialCaseMainElf(elfheader_t* h);
|
||||
void CreateMemorymapFile(box86context_t* context, int fd);
|
||||
void* GetDynamicSection(elfheader_t* h);
|
||||
void* ElfGetBrk(elfheader_t* h);
|
||||
|
||||
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
|
||||
|
||||
@@ -61,6 +64,10 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index);
|
||||
const char* VersionnedName(const char* name, int ver, const char* vername);
|
||||
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
|
||||
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
|
||||
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h);
|
||||
|
||||
void* GetNativeSymbolUnversionned(void* lib, const char* name);
|
||||
|
||||
void AddMainElfToLinkmap(elfheader_t* lib);
|
||||
|
||||
@@ -16,9 +16,16 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
|
||||
// 1: if file is an x86 elf, 0: if not (or not found)
|
||||
int FileIsX86ELF(const char* filename);
|
||||
int FileIsX64ELF(const char* filename);
|
||||
int FileIsShell(const char* filename);
|
||||
|
||||
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
|
||||
// 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(GOA_CLONE) || defined(PYRA)
|
||||
void sanitize_mojosetup_gtk_background();
|
||||
#endif
|
||||
|
||||
#endif //__FILEUTILS_H_
|
||||
#endif //__FILEUTILS_H_
|
||||
+195
-87
@@ -25,6 +25,21 @@ typedef struct my_GObjectClass_s
|
||||
void* pdummy[6];
|
||||
} my_GObjectClass_t;
|
||||
|
||||
typedef struct my_GInitiallyUnownedClass_s
|
||||
{
|
||||
int g_type_class;
|
||||
void* construct_properties;
|
||||
void* (*constructor) (int type, uint32_t n_construct_properties, void* construct_properties);
|
||||
void (*set_property) (void* object, uint32_t property_id, void* value, void* pspec);
|
||||
void (*get_property) (void* object, uint32_t property_id, void* value, void* pspec);
|
||||
void (*dispose) (void* object);
|
||||
void (*finalize) (void* object);
|
||||
void (*dispatch_properties_changed) (void* object, uint32_t n_pspecs, void* pspecs);
|
||||
void (*notify) (void* object, void* pspec);
|
||||
void (*constructed) (void* object);
|
||||
uint32_t flags;
|
||||
void* pdummy[6];
|
||||
} my_GInitiallyUnownedClass_t;
|
||||
|
||||
typedef struct my_GtkObjectClass_s
|
||||
{
|
||||
@@ -34,7 +49,7 @@ typedef struct my_GtkObjectClass_s
|
||||
void (*destroy) (void* object);
|
||||
} my_GtkObjectClass_t;
|
||||
|
||||
typedef struct my_GtkWidgetClass_s
|
||||
typedef struct my_GtkWidget2Class_s
|
||||
{
|
||||
my_GtkObjectClass_t parent_class;
|
||||
uint32_t activate_signal;
|
||||
@@ -108,11 +123,102 @@ typedef struct my_GtkWidgetClass_s
|
||||
void (*_gtk_reserved5) (void);
|
||||
void (*_gtk_reserved6) (void);
|
||||
void (*_gtk_reserved7) (void);
|
||||
} my_GtkWidgetClass_t;
|
||||
} my_GtkWidget2Class_t;
|
||||
|
||||
typedef struct my_GtkContainerClass_s
|
||||
typedef struct my_GtkWidget3Class_s
|
||||
{
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
my_GInitiallyUnownedClass_t parent_class;
|
||||
uint32_t activate_signal;
|
||||
void (*dispatch_child_properties_changed) (void* widget, uint32_t n_pspecs, void* pspecs);
|
||||
void (* destroy) (void* widget);
|
||||
void (* show) (void* widget);
|
||||
void (* show_all) (void* widget);
|
||||
void (* hide) (void* widget);
|
||||
void (* map) (void* widget);
|
||||
void (* unmap) (void* widget);
|
||||
void (* realize) (void* widget);
|
||||
void (* unrealize) (void* widget);
|
||||
void (* size_allocate) (void* widget, void* allocation);
|
||||
void (* state_changed) (void* widget, int previous_state);
|
||||
void (* state_flags_changed) (void* widget, int previous_state_flags);
|
||||
void (* parent_set) (void* widget, void* previous_parent);
|
||||
void (* hierarchy_changed) (void* widget, void* previous_toplevel);
|
||||
void (* style_set) (void* widget, void* previous_style);
|
||||
void (* direction_changed) (void* widget, int previous_direction);
|
||||
void (* grab_notify) (void* widget, int was_grabbed);
|
||||
void (* child_notify) (void* widget, void* child_property);
|
||||
int (* draw) (void* widget, void* cr);
|
||||
int (* get_request_mode) (void* widget);
|
||||
void (* get_preferred_height) (void* widget, void* minimum_height, void* natural_height);
|
||||
void (* get_preferred_width_for_height) (void* widget, int height, void* minimum_width, void* natural_width);
|
||||
void (* get_preferred_width) (void* widget, void* minimum_width, void* natural_width);
|
||||
void (* get_preferred_height_for_width) (void* widget, int width, void* minimum_height, void* natural_height);
|
||||
int (* mnemonic_activate) (void* widget, int group_cycling);
|
||||
void (* grab_focus) (void* widget);
|
||||
int (* focus) (void* widget, int direction);
|
||||
void (* move_focus) (void* widget, int direction);
|
||||
int (* keynav_failed) (void* widget, int direction);
|
||||
int (* event) (void* widget, void* event);
|
||||
int (* button_press_event) (void* widget, void* event);
|
||||
int (* button_release_event) (void* widget, void* event);
|
||||
int (* scroll_event) (void* widget, void* event);
|
||||
int (* motion_notify_event) (void* widget, void* event);
|
||||
int (* delete_event) (void* widget, void* event);
|
||||
int (* destroy_event) (void* widget, void* event);
|
||||
int (* key_press_event) (void* widget, void* event);
|
||||
int (* key_release_event) (void* widget, void* event);
|
||||
int (* enter_notify_event) (void* widget, void* event);
|
||||
int (* leave_notify_event) (void* widget, void* event);
|
||||
int (* configure_event) (void* widget, void* event);
|
||||
int (* focus_in_event) (void* widget, void* event);
|
||||
int (* focus_out_event) (void* widget, void* event);
|
||||
int (* map_event) (void* widget, void* event);
|
||||
int (* unmap_event) (void* widget, void* event);
|
||||
int (* property_notify_event) (void* widget, void* event);
|
||||
int (* selection_clear_event) (void* widget, void* event);
|
||||
int (* selection_request_event) (void* widget, void* event);
|
||||
int (* selection_notify_event) (void* widget, void* event);
|
||||
int (* proximity_in_event) (void* widget, void* event);
|
||||
int (* proximity_out_event) (void* widget, void* event);
|
||||
int (* visibility_notify_event) (void* widget, void* event);
|
||||
int (* window_state_event) (void* widget, void* event);
|
||||
int (* damage_event) (void* widget, void* event);
|
||||
int (* grab_broken_event) (void* widget, void* event);
|
||||
void (* selection_get) (void* widget, void* selection_data, uint32_t info, uint32_t time_);
|
||||
void (* selection_received) (void* widget, void* selection_data, uint32_t time_);
|
||||
void (* drag_begin) (void* widget, void* context);
|
||||
void (* drag_end) (void* widget, void* context);
|
||||
void (* drag_data_get) (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_);
|
||||
void (* drag_data_delete) (void* widget, void* context);
|
||||
void (* drag_leave) (void* widget, void* context, uint32_t time_);
|
||||
int (* drag_motion) (void* widget, void* context, int x, int y, uint32_t time_);
|
||||
int (* drag_drop) (void* widget, void* context, int x, int y, uint32_t time_);
|
||||
void (* drag_data_received) (void* widget, void* context, int x, int y, void* selection_data, uint32_t info, uint32_t time_);
|
||||
int (* drag_failed) (void* widget, void* context, int result);
|
||||
int (* popup_menu) (void* widget);
|
||||
int (* show_help) (void* widget, int help_type);
|
||||
void* (* get_accessible) (void *widget);
|
||||
void (* screen_changed) (void* widget, void* previous_screen);
|
||||
int (* can_activate_accel) (void* widget, uint32_t signal_id);
|
||||
void (* composited_changed) (void* widget);
|
||||
int (* query_tooltip) (void* widget, int x, int y, int keyboard_tooltip, void* tooltip);
|
||||
void (* compute_expand) (void* widget, void*hexpand_p, void* vexpand_p);
|
||||
void (* adjust_size_request) (void* widget, int orientation, void* minimum_size, void* natural_size);
|
||||
void (* adjust_size_allocation) (void*widget, int orientation, void* minimum_size, void* natural_size, void* allocated_pos, void* allocated_size);
|
||||
void (* style_updated) (void* widget);
|
||||
int (* touch_event) (void* widget, void* event);
|
||||
void (* get_preferred_height_and_baseline_for_width) (void* widget, int width, void* minimum_height, void* natural_height, void* minimum_baseline, void* natural_baseline);
|
||||
void (* adjust_baseline_request) (void* widget, void* minimum_baseline, void* natural_baseline);
|
||||
void (* adjust_baseline_allocation) (void* widget, void* baseline);
|
||||
void (*queue_draw_region) (void* widget, void* region);
|
||||
void* priv;
|
||||
void (*_gtk_reserved6) (void);
|
||||
void (*_gtk_reserved7) (void);
|
||||
} my_GtkWidget3Class_t;
|
||||
|
||||
typedef struct my_GtkContainer2Class_s
|
||||
{
|
||||
my_GtkWidget2Class_t parent_class;
|
||||
void (*add) (void* container, void* widget);
|
||||
void (*remove) (void* container, void* widget);
|
||||
void (*check_resize) (void* container);
|
||||
@@ -126,7 +232,7 @@ typedef struct my_GtkContainerClass_s
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkContainerClass_t;
|
||||
} my_GtkContainer2Class_t;
|
||||
|
||||
typedef struct my_GtkActionClass_s
|
||||
{
|
||||
@@ -144,14 +250,14 @@ typedef struct my_GtkActionClass_s
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkActionClass_t;
|
||||
|
||||
typedef struct my_GtkMiscClass_s
|
||||
typedef struct my_GtkMisc2Class_s
|
||||
{
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
} my_GtkMiscClass_t;
|
||||
my_GtkWidget2Class_t parent_class;
|
||||
} my_GtkMisc2Class_t;
|
||||
|
||||
typedef struct my_GtkLabelClass_s
|
||||
typedef struct my_GtkLabel2Class_s
|
||||
{
|
||||
my_GtkMiscClass_t parent_class;
|
||||
my_GtkMisc2Class_t parent_class;
|
||||
void (* move_cursor) (void* label, int step, int count, int extend_selection);
|
||||
void (* copy_clipboard) (void* label);
|
||||
void (* populate_popup) (void* label, void* menu);
|
||||
@@ -159,11 +265,11 @@ typedef struct my_GtkLabelClass_s
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
} my_GtkLabelClass_t;
|
||||
} my_GtkLabel2Class_t;
|
||||
|
||||
typedef struct my_GtkTreeViewClass_s
|
||||
typedef struct my_GtkTreeView2Class_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
my_GtkContainer2Class_t parent_class;
|
||||
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
|
||||
void (* row_activated) (void* tree_view, void* path, void* column);
|
||||
int (* test_expand_row) (void* tree_view, void* iter, void* path);
|
||||
@@ -185,19 +291,19 @@ typedef struct my_GtkTreeViewClass_s
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkTreeViewClass_t;
|
||||
} my_GtkTreeView2Class_t;
|
||||
|
||||
typedef struct my_GtkBinClass_s
|
||||
typedef struct my_GtkBin2Class_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
my_GtkContainer2Class_t parent_class;
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkBinClass_t;
|
||||
} my_GtkBin2Class_t;
|
||||
|
||||
typedef struct my_GtkWindowClass_s {
|
||||
my_GtkBinClass_t parent_class;
|
||||
typedef struct my_GtkWindow2Class_s {
|
||||
my_GtkBin2Class_t parent_class;
|
||||
void (* set_focus) (void* window, void* focus);
|
||||
int (* frame_event) (void* window, void* event);
|
||||
void (* activate_focus) (void* window);
|
||||
@@ -208,10 +314,10 @@ typedef struct my_GtkWindowClass_s {
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkWindowClass_t;
|
||||
} my_GtkWindow2Class_t;
|
||||
|
||||
typedef struct my_GtkButtonClass_s {
|
||||
my_GtkBinClass_t parent_class;
|
||||
typedef struct my_GtkButton2Class_s {
|
||||
my_GtkBin2Class_t parent_class;
|
||||
void (* pressed) (void *button);
|
||||
void (* released) (void *button);
|
||||
void (* clicked) (void *button);
|
||||
@@ -222,37 +328,37 @@ typedef struct my_GtkButtonClass_s {
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkButtonClass_t;
|
||||
} my_GtkButton2Class_t;
|
||||
|
||||
typedef struct my_GtkToggleButtonClass_s {
|
||||
my_GtkButtonClass_t parent_class;
|
||||
typedef struct my_GtkToggleButton2Class_s {
|
||||
my_GtkButton2Class_t parent_class;
|
||||
void (* toggled) (void* toggle_button);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkToggleButtonClass_t;
|
||||
} my_GtkToggleButton2Class_t;
|
||||
|
||||
typedef struct my_GtkCheckButtonClass_s {
|
||||
my_GtkToggleButtonClass_t parent_class;
|
||||
typedef struct my_GtkCheckButton2Class_s {
|
||||
my_GtkToggleButton2Class_t parent_class;
|
||||
void (* draw_indicator) (void* check_button, void* area);
|
||||
void (*_gtk_reserved0) (void);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
} my_GtkCheckButtonClass_t;
|
||||
} my_GtkCheckButton2Class_t;
|
||||
|
||||
typedef struct my_GtkComboBoxClass_s {
|
||||
my_GtkBinClass_t parent_class;
|
||||
typedef struct my_GtkComboBox2Class_s {
|
||||
my_GtkBin2Class_t parent_class;
|
||||
void (* changed) (void* combo_box);
|
||||
void*(* get_active_text)(void* combo_box);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkComboBoxClass_t;
|
||||
} my_GtkComboBox2Class_t;
|
||||
|
||||
typedef struct my_GtkEntryClass_s {
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
typedef struct my_GtkEntry2Class_s {
|
||||
my_GtkWidget2Class_t parent_class;
|
||||
void (* populate_popup) (void* entry, void* menu);
|
||||
void (* activate) (void* entry);
|
||||
void (* move_cursor) (void* entry, int step, int count, int extend_selection);
|
||||
@@ -266,10 +372,10 @@ typedef struct my_GtkEntryClass_s {
|
||||
void (* get_text_area_size) (void* entry, void* x, void* y, void* width, void* height);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
} my_GtkEntryClass_t;
|
||||
} my_GtkEntry2Class_t;
|
||||
|
||||
typedef struct my_GtkSpinButtonClass_s {
|
||||
my_GtkEntryClass_t parent_class;
|
||||
typedef struct my_GtkSpinButton2Class_s {
|
||||
my_GtkEntry2Class_t parent_class;
|
||||
int (*input) (void* spin_button, void* new_value);
|
||||
int (*output) (void* spin_button);
|
||||
void (*value_changed) (void* spin_button);
|
||||
@@ -278,10 +384,10 @@ typedef struct my_GtkSpinButtonClass_s {
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
} my_GtkSpinButtonClass_t;
|
||||
} my_GtkSpinButton2Class_t;
|
||||
|
||||
typedef struct my_GtkProgressClass_s {
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
typedef struct my_GtkProgress2Class_s {
|
||||
my_GtkWidget2Class_t parent_class;
|
||||
void (* paint) (void* progress);
|
||||
void (* update) (void* progress);
|
||||
void (* act_mode_enter) (void* progress);
|
||||
@@ -289,23 +395,23 @@ typedef struct my_GtkProgressClass_s {
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkProgressClass_t;
|
||||
} my_GtkProgress2Class_t;
|
||||
|
||||
typedef struct my_GtkProgressBarClass_s {
|
||||
my_GtkProgressClass_t parent_class;
|
||||
typedef struct my_GtkProgressBar2Class_s {
|
||||
my_GtkProgress2Class_t parent_class;
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkProgressBarClass_t;
|
||||
} my_GtkProgressBar2Class_t;
|
||||
|
||||
typedef struct my_GtkFrameClass_s {
|
||||
my_GtkBinClass_t parent_class;
|
||||
typedef struct my_GtkFrame2Class_s {
|
||||
my_GtkBin2Class_t parent_class;
|
||||
void (*compute_child_allocation) (void* frame, void* allocation);
|
||||
} my_GtkFrameClass_t;
|
||||
} my_GtkFrame2Class_t;
|
||||
|
||||
typedef struct my_GtkMenuShellClass_s {
|
||||
my_GtkContainerClass_t parent_class;
|
||||
typedef struct my_GtkMenuShell2Class_s {
|
||||
my_GtkContainer2Class_t parent_class;
|
||||
void (*deactivate) (void* menu_shell);
|
||||
void (*selection_done) (void* menu_shell);
|
||||
void (*move_current) (void* menu_shell, int direction);
|
||||
@@ -317,31 +423,31 @@ typedef struct my_GtkMenuShellClass_s {
|
||||
int (*move_selected) (void* menu_shell, int distance);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
} my_GtkMenuShellClass_t;
|
||||
} my_GtkMenuShell2Class_t;
|
||||
|
||||
typedef struct my_GtkMenuBarClass_s {
|
||||
my_GtkMenuShellClass_t parent_class;
|
||||
typedef struct my_GtkMenuBar2Class_s {
|
||||
my_GtkMenuShell2Class_t parent_class;
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkMenuBarClass_t;
|
||||
} my_GtkMenuBar2Class_t;
|
||||
|
||||
typedef struct my_MetaFramesClass_s
|
||||
typedef struct my_MetaFrames2Class_s
|
||||
{
|
||||
my_GtkWindowClass_t parent_class;
|
||||
my_GtkWindow2Class_t parent_class;
|
||||
|
||||
} my_MetaFramesClass_t;
|
||||
} my_MetaFrames2Class_t;
|
||||
|
||||
typedef struct my_GtkTableClass_s
|
||||
typedef struct my_GtkTable2Class_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
} my_GtkTableClass_t;
|
||||
my_GtkContainer2Class_t parent_class;
|
||||
} my_GtkTable2Class_t;
|
||||
|
||||
typedef struct my_GtkFixedClass_s
|
||||
typedef struct my_GtkFixed2Class_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
} my_GtkFixedClass_t;
|
||||
my_GtkContainer2Class_t parent_class;
|
||||
} my_GtkFixed2Class_t;
|
||||
|
||||
typedef struct my_GDBusObjectManagerClientClass_s
|
||||
{
|
||||
@@ -406,31 +512,33 @@ my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, int parent);
|
||||
void InitGTKClass(bridge_t *bridge);
|
||||
void FiniGTKClass();
|
||||
|
||||
#define GTKCLASSES() \
|
||||
GTKCLASS(GObject) \
|
||||
GTKCLASS(GtkObject) \
|
||||
GTKCLASS(GtkWidget) \
|
||||
GTKCLASS(GtkContainer) \
|
||||
GTKCLASS(GtkAction) \
|
||||
GTKCLASS(GtkLabel) \
|
||||
GTKCLASS(GtkMisc) \
|
||||
GTKCLASS(GtkTreeView) \
|
||||
GTKCLASS(GtkBin) \
|
||||
GTKCLASS(GtkWindow) \
|
||||
GTKCLASS(GtkTable) \
|
||||
GTKCLASS(GtkFixed) \
|
||||
GTKCLASS(GtkButton) \
|
||||
GTKCLASS(GtkComboBox) \
|
||||
GTKCLASS(GtkToggleButton)\
|
||||
GTKCLASS(GtkCheckButton)\
|
||||
GTKCLASS(GtkEntry) \
|
||||
GTKCLASS(GtkSpinButton) \
|
||||
GTKCLASS(GtkProgress) \
|
||||
GTKCLASS(GtkProgressBar)\
|
||||
GTKCLASS(GtkFrame) \
|
||||
GTKCLASS(GtkMenuShell) \
|
||||
GTKCLASS(GtkMenuBar) \
|
||||
GTKCLASS(MetaFrames) \
|
||||
#define GTKCLASSES() \
|
||||
GTKCLASS(GObject) \
|
||||
GTKCLASS(GInitiallyUnowned) \
|
||||
GTKCLASS(GtkObject) \
|
||||
GTKCLASS(GtkWidget2) \
|
||||
GTKCLASS(GtkWidget3) \
|
||||
GTKCLASS(GtkContainer2) \
|
||||
GTKCLASS(GtkAction) \
|
||||
GTKCLASS(GtkLabel2) \
|
||||
GTKCLASS(GtkMisc2) \
|
||||
GTKCLASS(GtkTreeView2) \
|
||||
GTKCLASS(GtkBin2) \
|
||||
GTKCLASS(GtkWindow2) \
|
||||
GTKCLASS(GtkTable2) \
|
||||
GTKCLASS(GtkFixed2) \
|
||||
GTKCLASS(GtkButton2) \
|
||||
GTKCLASS(GtkComboBox2) \
|
||||
GTKCLASS(GtkToggleButton2) \
|
||||
GTKCLASS(GtkCheckButton2) \
|
||||
GTKCLASS(GtkEntry2) \
|
||||
GTKCLASS(GtkSpinButton2) \
|
||||
GTKCLASS(GtkProgress2) \
|
||||
GTKCLASS(GtkProgressBar2) \
|
||||
GTKCLASS(GtkFrame2) \
|
||||
GTKCLASS(GtkMenuShell2) \
|
||||
GTKCLASS(GtkMenuBar2) \
|
||||
GTKCLASS(MetaFrames2) \
|
||||
GTKCLASS(GDBusObjectManagerClient) \
|
||||
|
||||
#define GTKCLASS(A) void Set##A##ID(int id);
|
||||
|
||||
@@ -21,15 +21,12 @@ dlprivate_t *NewDLPrivate();
|
||||
void FreeDLPrivate(dlprivate_t **lib);
|
||||
|
||||
box86context_t* GetLibrarianContext(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
|
||||
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_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);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername);
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername);
|
||||
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
|
||||
|
||||
+11
-5
@@ -9,6 +9,11 @@ typedef struct kh_symbolmap_s kh_symbolmap_t;
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef struct needed_libs_s needed_libs_t;
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
|
||||
#define LIB_WRAPPED 0
|
||||
#define LIB_EMULATED 1
|
||||
#define LIB_UNNKNOW -1
|
||||
|
||||
library_t *NewLibrary(const char* path, box86context_t* box86);
|
||||
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x86emu_t* emu);
|
||||
@@ -19,9 +24,9 @@ void Free1Library(library_t **lib, x86emu_t* emu);
|
||||
|
||||
char* GetNameLib(library_t *lib);
|
||||
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
|
||||
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
|
||||
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(box86context_t* context);
|
||||
void freeGLProcWrapper(box86context_t* context);
|
||||
void fillALProcWrapper(box86context_t* context);
|
||||
@@ -31,7 +36,8 @@ int GetNeededLibN(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. native)
|
||||
void* GetHandle(library_t* lib); // NULL if not native
|
||||
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
|
||||
|
||||
#endif //__LIBRARY_H_
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef __RCFILE_H__
|
||||
#define __RCFILE_H__
|
||||
|
||||
typedef struct path_collection_s path_collection_t;
|
||||
|
||||
void LoadRCFile(const char* filename);
|
||||
void DeleteParams();
|
||||
void ApplyParams(const char* name, path_collection_t* preload);
|
||||
|
||||
#endif //__RCFILE_H__
|
||||
+53
-14
@@ -178,24 +178,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__)) {
|
||||
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;
|
||||
|
||||
@@ -14,10 +14,11 @@ void FreeMapSymbols(kh_mapsymbols_t** map);
|
||||
|
||||
// replace if already there
|
||||
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local);
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver);
|
||||
// don't add if already there
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local);
|
||||
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver);
|
||||
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver);
|
||||
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
|
||||
|
||||
// default version handling
|
||||
|
||||
@@ -20,7 +20,9 @@ void fini_pthread_helper(box86context_t* context);
|
||||
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
|
||||
void* my_prepare_thread(x86emu_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_
|
||||
@@ -7,15 +7,16 @@ typedef struct box86context_s box86context_t;
|
||||
|
||||
typedef int (*wrappedlib_init_t)(library_t * lib, box86context_t* box86); // 0 = success
|
||||
typedef void (*wrappedlib_fini_t)(library_t * lib);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int version, const char* vername, int local);
|
||||
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t size, int* weak, int version, const char* vername, int local);
|
||||
|
||||
void setNeededLibs(library_t* lib, int n, ...);
|
||||
#define SETALT(A) lib->w.altmy = box_strdup(#A)
|
||||
#define SETALTPREFIX(A) lib->w.altprefix = box_strdup(A)
|
||||
|
||||
typedef struct wrappedlib_s {
|
||||
const char* name;
|
||||
wrappedlib_init_t init;
|
||||
wrappedlib_fini_t fini;
|
||||
wrappedlib_get_t get;
|
||||
wrappedlib_get_t getnoweak;
|
||||
wrappedlib_get_t getlocal;
|
||||
} wrappedlib_t;
|
||||
|
||||
#endif //__WRAPPEDLIBS_H__
|
||||
@@ -20,7 +20,7 @@ void FreeDictionnary(dic_t **d)
|
||||
return;
|
||||
kh_dic_t* dic = (kh_dic_t*)*d;
|
||||
const char* k;
|
||||
kh_foreach_key(dic, k, free((void*)k));
|
||||
kh_foreach_key(dic, k, box_free((void*)k));
|
||||
kh_destroy(dic, dic);
|
||||
*d = NULL;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ const char* AddDictionnary(dic_t* d, const char* s)
|
||||
khint_t k = kh_get(dic, dic, s);
|
||||
if(k!=kh_end(dic))
|
||||
return kh_key(dic, k);
|
||||
char* n = strdup(s);
|
||||
char* n = box_strdup(s);
|
||||
int ret;
|
||||
k = kh_put(dic, dic, n, &ret);
|
||||
return n;
|
||||
|
||||
+124
-104
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "librarian.h"
|
||||
@@ -19,17 +20,13 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
|
||||
|
||||
lib_t *NewLibrarian(box86context_t* context, int ownlibs)
|
||||
{
|
||||
lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t));
|
||||
(void)context;
|
||||
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
|
||||
|
||||
maplib->mapsymbols = NewMapSymbols();
|
||||
maplib->weaksymbols = NewMapSymbols();
|
||||
maplib->localsymbols = NewMapSymbols();
|
||||
maplib->mapoffsets = kh_init(mapoffsets);
|
||||
maplib->globaldata = NewMapSymbols();
|
||||
maplib->bridge = NewBridge();
|
||||
|
||||
maplib->context = context;
|
||||
|
||||
maplib->ownlibs = ownlibs;
|
||||
|
||||
return maplib;
|
||||
@@ -78,7 +75,7 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
|
||||
if((*maplib)->ownlibs && (*maplib)->libsz) {
|
||||
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
|
||||
char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
|
||||
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)
|
||||
@@ -92,15 +89,12 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
}
|
||||
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
|
||||
(*maplib)->libsz = 0;
|
||||
free(freed);
|
||||
box_free(freed);
|
||||
}
|
||||
}
|
||||
free((*maplib)->libraries);
|
||||
box_free((*maplib)->libraries);
|
||||
(*maplib)->libraries = NULL;
|
||||
|
||||
FreeMapSymbols(&(*maplib)->mapsymbols);
|
||||
FreeMapSymbols(&(*maplib)->weaksymbols);
|
||||
FreeMapSymbols(&(*maplib)->localsymbols);
|
||||
if((*maplib)->mapoffsets) {
|
||||
kh_destroy(mapoffsets, (*maplib)->mapoffsets);
|
||||
}
|
||||
@@ -110,29 +104,15 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
|
||||
if((*maplib)->bridge)
|
||||
FreeBridge(&(*maplib)->bridge);
|
||||
|
||||
free(*maplib);
|
||||
box_free(*maplib);
|
||||
*maplib = NULL;
|
||||
|
||||
}
|
||||
|
||||
box86context_t* GetLibrarianContext(lib_t* maplib)
|
||||
{
|
||||
return maplib->context;
|
||||
}
|
||||
|
||||
kh_mapsymbols_t* GetMapSymbol(lib_t* maplib)
|
||||
{
|
||||
return maplib->mapsymbols;
|
||||
}
|
||||
|
||||
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib)
|
||||
{
|
||||
return maplib->weaksymbols;
|
||||
}
|
||||
|
||||
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib)
|
||||
{
|
||||
return maplib->localsymbols;
|
||||
(void)maplib;
|
||||
return my_context;
|
||||
}
|
||||
|
||||
kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
|
||||
@@ -167,7 +147,7 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
|
||||
return;
|
||||
if (maplib->libsz == maplib->libcap) {
|
||||
maplib->libcap += 8;
|
||||
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
|
||||
maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
|
||||
}
|
||||
maplib->libraries[maplib->libsz] = lib;
|
||||
++maplib->libsz;
|
||||
@@ -299,7 +279,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lib->type == 1) {
|
||||
if (lib->type == LIB_EMULATED) {
|
||||
// Need to add library to the linkmap (put here so the link is ordered)
|
||||
linkmap_t *lm = addLinkMapLib(lib);
|
||||
if(!lm) {
|
||||
@@ -307,15 +287,16 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
|
||||
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
|
||||
return 1;
|
||||
}
|
||||
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->priv.n.elf_index]);
|
||||
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]);
|
||||
lm->l_name = lib->name;
|
||||
lm->l_ld = GetDynamicSection(my_context->elfs[lib->priv.n.elf_index]);
|
||||
lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box86context_t* box86, x86emu_t* emu)
|
||||
{
|
||||
(void)neededlibs; (void)deplib;
|
||||
if(!maplib)
|
||||
maplib = (local)?lib->maplib:my_context->maplib;
|
||||
|
||||
@@ -357,14 +338,13 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
|
||||
{
|
||||
box86_mapclean = 0;
|
||||
if(!neededlibs) {
|
||||
neededlibs = alloca(sizeof(needed_libs_t));
|
||||
memset(neededlibs, 0, sizeof(needed_libs_t));
|
||||
neededlibs = box_calloc(1, sizeof(needed_libs_t));
|
||||
}
|
||||
int idx = neededlibs->size;
|
||||
// Add libs and symbol
|
||||
for(int i=0; i<npath; ++i) {
|
||||
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box86, emu)) {
|
||||
printf_log(LOG_INFO, "Error loading needed lib %s\n", paths[i]);
|
||||
printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -403,79 +383,101 @@ uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const c
|
||||
|
||||
static int isLocal(elfheader_t* self, library_t* l)
|
||||
{
|
||||
if(GetElfIndex(l)==-1)
|
||||
return 1;
|
||||
if(my_context->elfs[GetElfIndex(l)]==self)
|
||||
if(GetElf(l)==self)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername)
|
||||
{
|
||||
//excude self if defined
|
||||
if(maplib->context->elfs[0]!=self) {
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
assert(self); // need self for this one
|
||||
//search for the self, to start "next"
|
||||
int go = -1;
|
||||
int weak = 0;
|
||||
for(int i=0; i<maplib->libsz && (go==-1); ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (GetElf(maplib->libraries[i])==self))
|
||||
go = i+1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 0))
|
||||
if(go<0)
|
||||
go = 0; // not found...
|
||||
for(int i=go; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
for(int i=go; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0);
|
||||
// loop done, weak symbol found
|
||||
if(weak && *start)
|
||||
return 1;
|
||||
// if self defined, give it another chance with self...
|
||||
if(self) {
|
||||
if(maplib->context->elfs[0]==self) {
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
|
||||
if(my_context->elfs[0]!=self) {
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
|
||||
if(*start)
|
||||
return 1;
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 1))
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
|
||||
if(*start)
|
||||
return 1;
|
||||
weak = 1;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
for(int i=0; i<go; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
for(int i=0; i<go; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
|
||||
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1);
|
||||
}
|
||||
if(weak && *start)
|
||||
return 1;
|
||||
}
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
|
||||
{
|
||||
int weak = 0;
|
||||
size_t size = 0;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
// search non-weak symbol, from older to newer (first GLOBAL object wins)
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
|
||||
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(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, version, vername, isLocal(self, my_context->neededlibs.libs[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(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
|
||||
// check with default version...
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
int ok = 0;
|
||||
// GetSymbolStartEnd should not change start/end if symbol is not found
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
|
||||
if(*start)
|
||||
return 1;
|
||||
ok = 1;
|
||||
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) // only weak symbol haven't been found yet
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
|
||||
if(*start)
|
||||
return 1;
|
||||
ok = 1;
|
||||
}
|
||||
// nope, not found
|
||||
return 0;
|
||||
return (ok && *start)?1:0;
|
||||
}
|
||||
void** my_GetGTKDisplay();
|
||||
void** my_GetGthreadsGotInitialized();
|
||||
@@ -484,14 +486,14 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
|
||||
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
|
||||
uintptr_t start2, end2;
|
||||
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
|
||||
char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1);
|
||||
strcpy(buff, name);
|
||||
strcat(buff, "_END");
|
||||
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
|
||||
if(end2>*end && start2==end2)
|
||||
*end = end2;
|
||||
}
|
||||
free(buff);
|
||||
box_free(buff);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -508,10 +510,6 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
|
||||
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
|
||||
return 1;
|
||||
}
|
||||
// check with default version...
|
||||
const char* defver;
|
||||
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
|
||||
return GetGlobalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
|
||||
// not found...
|
||||
return 0;
|
||||
}
|
||||
@@ -520,41 +518,62 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
|
||||
{
|
||||
uintptr_t start = 0;
|
||||
uintptr_t end = 0;
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end, version, vername, 1))
|
||||
return maplib->context->elfs[0];
|
||||
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end, version, vername, 1))
|
||||
return maplib->context->elfs[0];
|
||||
size_t size = 0;
|
||||
int weak = 0;
|
||||
elfheader_t* ret = NULL;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
|
||||
return my_context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) {
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
return NULL;
|
||||
}
|
||||
return maplib->context->elfs[idx];
|
||||
if(weak)
|
||||
ret = my_context->elfs[idx];
|
||||
else
|
||||
return my_context->elfs[idx];
|
||||
}
|
||||
}
|
||||
// check with default version...
|
||||
const char* defver;
|
||||
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
|
||||
return GetGlobalSymbolElf(maplib, name, 2, defver);
|
||||
// nope, not found
|
||||
return NULL;
|
||||
|
||||
defver = GetDefaultVersion(my_context->weakdefver, name);
|
||||
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
|
||||
ret = my_context->elfs[0];
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
|
||||
int idx = GetElfIndex(maplib->libraries[i]);
|
||||
if(idx==-1) {
|
||||
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
|
||||
return NULL;
|
||||
}
|
||||
if(weak)
|
||||
ret = my_context->elfs[idx];
|
||||
else
|
||||
return my_context->elfs[idx];
|
||||
}
|
||||
}
|
||||
// return what has been found (maybe nothing)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
|
||||
{
|
||||
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
|
||||
int weak = 0;
|
||||
size_t size = 0;
|
||||
// check with default version...
|
||||
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
|
||||
|
||||
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
// check with default version...
|
||||
const char* defver;
|
||||
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
|
||||
return GetGlobalNoWeakSymbolStartEnd(maplib, name, start, end, 2, defver);
|
||||
// nope, not found
|
||||
return 0;
|
||||
}
|
||||
@@ -562,15 +581,14 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
|
||||
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
|
||||
{
|
||||
uintptr_t start, end;
|
||||
size_t size = 0;
|
||||
int weak;
|
||||
// check with default version...
|
||||
for(int i=0; i<maplib->libsz; ++i)
|
||||
if(GetElfIndex(maplib->libraries[i])==-1)
|
||||
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1))
|
||||
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1))
|
||||
if(start || end)
|
||||
return 1;
|
||||
// check with default version...
|
||||
const char* defver;
|
||||
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
|
||||
return IsGlobalNoWeakSymbolInNative(maplib, name, 2, defver);
|
||||
// nope, not found
|
||||
return 0;
|
||||
|
||||
@@ -578,32 +596,34 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
|
||||
|
||||
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
|
||||
{
|
||||
if(maplib->context->elfs[0]==self || !self) {
|
||||
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
|
||||
// check with default version...
|
||||
int weak;
|
||||
size_t size = 0;
|
||||
|
||||
if(my_context->elfs[0]==self || !self) {
|
||||
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, NULL))
|
||||
if(*start || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
return 0;
|
||||
}
|
||||
for(int i=0; i<maplib->libsz; ++i) {
|
||||
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
|
||||
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
|
||||
if(*start)
|
||||
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 || *end)
|
||||
return 1;
|
||||
if(self)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// check with default version...
|
||||
const char* defver;
|
||||
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
|
||||
return GetLocalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib)
|
||||
{
|
||||
(void)maplib;
|
||||
// first, search in self...
|
||||
const char* ret = NULL;
|
||||
uintptr_t offs = 0;
|
||||
|
||||
@@ -13,9 +13,6 @@ typedef char* cstr_t;
|
||||
KHASH_MAP_DECLARE_INT(mapoffsets, cstr_t);
|
||||
|
||||
typedef struct lib_s {
|
||||
khash_t(mapsymbols) *mapsymbols;
|
||||
khash_t(mapsymbols) *weaksymbols;
|
||||
khash_t(mapsymbols) *localsymbols;
|
||||
khash_t(mapoffsets) *mapoffsets;
|
||||
khash_t(mapsymbols) *globaldata;
|
||||
library_t **libraries;
|
||||
|
||||
+374
-285
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
||||
#ifndef __LIBRARY_INNER_H__
|
||||
#define __LIBRARY_INNER_H__
|
||||
|
||||
void WrappedLib_CommonInit(library_t* lib);
|
||||
void WrappedLib_FinishFini(library_t* lib);
|
||||
|
||||
#endif
|
||||
@@ -8,10 +8,11 @@
|
||||
#include "wrappedlibs.h"
|
||||
#include "box86context.h"
|
||||
|
||||
typedef struct lib_s lib_t;
|
||||
typedef struct bridge_s bridge_t;
|
||||
typedef struct kh_bridgemap_s kh_bridgemap_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
typedef struct lib_s lib_t;
|
||||
typedef struct bridge_s bridge_t;
|
||||
typedef struct elfheader_s elfheader_t;
|
||||
typedef struct kh_bridgemap_s kh_bridgemap_t;
|
||||
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
@@ -35,20 +36,27 @@ typedef struct wlib_s {
|
||||
bridge_t *bridge;
|
||||
void* lib; // dlopen result
|
||||
void* priv; // actual private
|
||||
void* p2; // second private
|
||||
void* box86lib; // ref to the dlopen on box86 itself from context
|
||||
char* altprefix; // if function names are mangled..
|
||||
int needed;
|
||||
char** neededlibs;
|
||||
kh_symbolmap_t *symbolmap;
|
||||
kh_symbolmap_t *wsymbolmap;
|
||||
kh_symbolmap_t *mysymbolmap;
|
||||
kh_symbolmap_t *wmysymbolmap;
|
||||
kh_symbolmap_t *stsymbolmap;
|
||||
kh_symbolmap_t *wstsymbolmap;
|
||||
kh_symbol2map_t *symbol2map;
|
||||
kh_datamap_t *datamap;
|
||||
kh_datamap_t *wdatamap;
|
||||
kh_datamap_t *mydatamap;
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
} wlib_t;
|
||||
|
||||
typedef struct nlib_s {
|
||||
typedef struct elib_s {
|
||||
int elf_index;
|
||||
int finalized;
|
||||
kh_mapsymbols_t *mapsymbols;
|
||||
kh_mapsymbols_t *weaksymbols;
|
||||
kh_mapsymbols_t *localsymbols;
|
||||
} nlib_t;
|
||||
elfheader_t *elf;
|
||||
} elib_t;
|
||||
|
||||
typedef struct library_s {
|
||||
char* name; // <> path
|
||||
@@ -57,29 +65,20 @@ typedef struct library_s {
|
||||
int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined
|
||||
int active;
|
||||
wrappedlib_fini_t fini;
|
||||
wrappedlib_get_t get; // get weak and no weak
|
||||
wrappedlib_get_t getnoweak; // get only non weak symbol
|
||||
wrappedlib_get_t getlocal;
|
||||
wrappedlib_get_t getglobal; // get global symbol (not weak)
|
||||
wrappedlib_get_t getweak; // get weak symbol
|
||||
wrappedlib_get_t getlocal; // get local symbol
|
||||
union {
|
||||
wlib_t w;
|
||||
nlib_t n;
|
||||
} priv; // private lib data
|
||||
box86context_t *context; // parent context
|
||||
kh_bridgemap_t *bridgemap;
|
||||
kh_symbolmap_t *symbolmap;
|
||||
kh_symbolmap_t *wsymbolmap;
|
||||
kh_symbolmap_t *mysymbolmap;
|
||||
kh_symbolmap_t *wmysymbolmap;
|
||||
kh_symbolmap_t *stsymbolmap;
|
||||
kh_symbolmap_t *wstsymbolmap;
|
||||
kh_symbol2map_t *symbol2map;
|
||||
kh_datamap_t *datamap;
|
||||
kh_datamap_t *wdatamap;
|
||||
kh_datamap_t *mydatamap;
|
||||
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
|
||||
elib_t e;
|
||||
}; // private lib data
|
||||
needed_libs_t needed;
|
||||
needed_libs_t dependedby;
|
||||
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
|
||||
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);
|
||||
@@ -104,7 +103,7 @@ typedef struct map_onedata_s {
|
||||
int weak;
|
||||
} map_onedata_t;
|
||||
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int version, const char* vername, int local); // Add bridges to functions
|
||||
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int* weak, int version, const char* vername, int local); // Add bridges to functions
|
||||
|
||||
typedef struct linkmap_s {
|
||||
// actual struct link_map
|
||||
|
||||
+59
-38
@@ -41,7 +41,7 @@ void FreeMapSymbols(kh_mapsymbols_t** map)
|
||||
if(!map || !(*map))
|
||||
return;
|
||||
versymbols_t *v;
|
||||
kh_foreach_value_ref(*map, v, free(v->syms););
|
||||
kh_foreach_value_ref(*map, v, box_free(v->syms););
|
||||
|
||||
kh_destroy(mapsymbols, *map);
|
||||
*map = NULL;
|
||||
@@ -58,86 +58,90 @@ static int SameVersion(versymbol_t* s, int ver, const char* vername)
|
||||
|
||||
}
|
||||
|
||||
static versymbol_t* FindVersionLocal(versymbols_t* s)
|
||||
static versymbol_t* FindVersionLocal(versymbols_t* s, size_t size)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==0)
|
||||
if(s->syms[i].version==0 && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindNoVersion(versymbols_t* s)
|
||||
static versymbol_t* FindNoVersion(versymbols_t* s, size_t size)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==-1)
|
||||
if(s->syms[i].version==-1 && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindVersionGlobal(versymbols_t* s)
|
||||
static versymbol_t* FindVersionGlobal(versymbols_t* s, size_t size)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version==1)
|
||||
if(s->syms[i].version==1 && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindVersion(versymbols_t* s, const char* vername)
|
||||
static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vername)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername))
|
||||
if(s->syms[i].vername && !strcmp(s->syms[i].vername, vername) && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
static versymbol_t* FindFirstVersion(versymbols_t* s)
|
||||
/* static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
for (int i=0; i<s->sz; ++i)
|
||||
if(s->syms[i].version>1)
|
||||
if(s->syms[i].version>1 && (!size || (size==s->syms[i].sym.sz)))
|
||||
return &s->syms[i];
|
||||
return NULL;
|
||||
}
|
||||
} */
|
||||
|
||||
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
|
||||
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, int local)
|
||||
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver)
|
||||
{
|
||||
if(!s || !s->sz)
|
||||
return NULL;
|
||||
versymbol_t* ret = NULL;
|
||||
if(ver==0) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(local) ret = FindVersionLocal(s, size);
|
||||
if(!ret) ret = FindNoVersion(s, size);
|
||||
if(!ret) ret = FindVersionGlobal(s, size);
|
||||
if(!ret && defver) ret = FindVersion(s, size, defver);
|
||||
return ret;
|
||||
}
|
||||
if(ver==-1) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(!ret) ret = FindFirstVersion(s);
|
||||
if(local) ret = FindVersionLocal(s, size);
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
if(ver==-2) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(local) ret = FindVersionLocal(s, size);
|
||||
if(!ret) ret = FindVersionGlobal(s, size);
|
||||
return ret;
|
||||
}
|
||||
if(ver==1) {
|
||||
if(local) ret = FindVersionLocal(s);
|
||||
if(!ret) ret = FindVersionGlobal(s);
|
||||
if(!ret) ret = FindNoVersion(s);
|
||||
if(!ret) ret = FindFirstVersion(s);
|
||||
if(local) ret = FindVersionLocal(s, size);
|
||||
if(!ret) ret = FindVersionGlobal(s, size);
|
||||
if(!ret) ret = FindNoVersion(s, size);
|
||||
if(!ret && defver) ret = FindVersion(s, size, defver);
|
||||
//if(!ret) ret = FindFirstVersion(s);
|
||||
return ret;
|
||||
}
|
||||
ret = FindVersion(s, vername);
|
||||
if(local && !ret) FindVersionLocal(s);
|
||||
if(!ret) return FindVersionGlobal(s);
|
||||
ret = FindVersion(s, size, vername);
|
||||
if(local && !ret) ret = FindVersionLocal(s, size);
|
||||
if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s, size);
|
||||
//if(!ret) return FindVersionGlobal(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -157,7 +161,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
|
||||
// add a new record
|
||||
if(v->sz == v->cap) {
|
||||
v->cap+=4;
|
||||
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
v->syms = (versymbol_t*)box_realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
}
|
||||
int idx = v->sz++;
|
||||
v->syms[idx].version = ver;
|
||||
@@ -166,7 +170,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
|
||||
v->syms[idx].sym.sz = sz;
|
||||
}
|
||||
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local)
|
||||
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
return 0;
|
||||
@@ -174,13 +178,13 @@ uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, con
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t * s = MatchVersion(v, ver, vername, local);
|
||||
versymbol_t * s = MatchVersion(v, ver, vername, 0, local, defver);
|
||||
if(s)
|
||||
return s->sym.offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
|
||||
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
|
||||
{
|
||||
int ret;
|
||||
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
|
||||
@@ -194,7 +198,7 @@ void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr
|
||||
// add a new record
|
||||
if(v->sz == v->cap) {
|
||||
v->cap+=4;
|
||||
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
v->syms = (versymbol_t*)box_realloc(v->syms, v->cap*sizeof(versymbol_t));
|
||||
}
|
||||
int idx = v->sz++;
|
||||
v->syms[idx].version = ver;
|
||||
@@ -203,7 +207,7 @@ void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr
|
||||
v->syms[idx].sym.sz = sz;
|
||||
}
|
||||
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local)
|
||||
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
return 0;
|
||||
@@ -211,7 +215,24 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t* s = MatchVersion(v, ver, vername, local);
|
||||
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver);
|
||||
if(s) {
|
||||
*start = s->sym.offs;
|
||||
*end = *start + s->sym.sz;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetSizedSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int ver, const char* vername, int local, const char* defver)
|
||||
{
|
||||
if(!mapsymbols)
|
||||
return 0;
|
||||
khint_t k = kh_get(mapsymbols, mapsymbols, name);
|
||||
if(k==kh_end(mapsymbols))
|
||||
return 0;
|
||||
versymbols_t * v = &kh_val(mapsymbols, k);
|
||||
versymbol_t* s = MatchVersion(v, ver, vername, size, local, defver);
|
||||
if(s) {
|
||||
*start = s->sym.offs;
|
||||
*end = *start + s->sym.sz;
|
||||
@@ -250,7 +271,7 @@ void FreeDefaultVersion(kh_defaultversion_t** def)
|
||||
if(!def || !*def)
|
||||
return;
|
||||
const char* v;
|
||||
kh_foreach_value(*def, v, free((char*)v););
|
||||
kh_foreach_value(*def, v, box_free((char*)v););
|
||||
|
||||
kh_destroy(defaultversion, *def);
|
||||
*def = NULL;
|
||||
@@ -261,7 +282,7 @@ void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char
|
||||
int ret;
|
||||
khint_t k = kh_put(defaultversion, def, symname, &ret);
|
||||
if(!ret) return; // already set!
|
||||
kh_value(def, k) = strdup(vername);
|
||||
kh_value(def, k) = box_strdup(vername);
|
||||
}
|
||||
const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,7 @@ GO("libXext.so.6", libxext)
|
||||
GO("libXfixes.so.3", libxfixes)
|
||||
GO("libXcursor.so.1", libxcursor)
|
||||
GO("libXrender.so.1", libxrender)
|
||||
GO("libXpresent.so.1", libxpresent)
|
||||
GO("libXft.so.2", libxft)
|
||||
GO("libXi.so.6", libxi)
|
||||
GO("libXss.so.1", libxss)
|
||||
@@ -105,16 +106,21 @@ GO("libdbusmenu-glib.so.4", dbusmenuglib)
|
||||
GO("libdbus-glib-1.so.2", dbusglib1)
|
||||
GO("libgudev-1.0.so.0", gudev1)
|
||||
GO("libappindicator.so.1", appindicator)
|
||||
GO("libappindicator3.so.1", appindicator3)
|
||||
GO("libatk-1.0.so.0", atk)
|
||||
GO("libatk-bridge-2.0.so.0", atkbridge)
|
||||
GO("libpangoft2-1.0.so", pangoft2)
|
||||
GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
GO("libcairo.so.2", cairo)
|
||||
GO("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("libbz2.so.1", bz2)
|
||||
GO("libexpat.so.1", expat)
|
||||
@@ -164,6 +170,9 @@ GO("libgsttag-1.0.so.0", gsttag)
|
||||
GO("libgstvideo-1.0.so.0", gstvideo)
|
||||
GO("libgomp.so.1", gomp)
|
||||
GO("libcap.so.2", cap)
|
||||
GO("libpcap.so.0", pcap)
|
||||
GO("libFAudio.so.0", faudio)
|
||||
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
|
||||
|
||||
#ifdef ANDROID
|
||||
GO("libc.so", libc)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
static uintptr_t* auxval_start = NULL;
|
||||
|
||||
int init_auxval(int argc, const char **argv, char **env) {
|
||||
(void)argc; (void)argv;
|
||||
// auxval vector is after envs...
|
||||
while(*env)
|
||||
env++;
|
||||
@@ -56,4 +57,4 @@ EXPORT unsigned long my_getauxval(x86emu_t* emu, unsigned long type)
|
||||
p+=2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 361 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user