mirror of
https://github.com/ptitSeb/box86.git
synced 2026-11-08 17:39:19 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27e5262f1d | ||
|
|
363464092e | ||
|
|
b2cab70427 | ||
|
|
44d5301244 | ||
|
|
8e4f4feb3c | ||
|
|
e9f6f8824c | ||
|
|
be6f9870d0 | ||
|
|
bb086223c7 | ||
|
|
be6a3bff3f | ||
|
|
adfc5fda2e | ||
|
|
d833f136a0 | ||
|
|
1703e9d1b7 | ||
|
|
011b9f93e4 | ||
|
|
e449a4e247 | ||
|
|
fe7f0ff842 | ||
|
|
2033e5764d | ||
|
|
55175263ac | ||
|
|
c484221cd6 | ||
|
|
e9862cb30d | ||
|
|
0c7b99cbc6 | ||
|
|
824f39e4db | ||
|
|
66a5ce1e52 | ||
|
|
f39637a652 | ||
|
|
eaf7d0a277 | ||
|
|
b61bb908a2 | ||
|
|
2e891b807c | ||
|
|
f0b236df88 | ||
|
|
08904dbe0d | ||
|
|
c9c4e226af | ||
|
|
ab3dc70145 | ||
|
|
4d8c841f3f | ||
|
|
a8b247cde9 | ||
|
|
416e161285 | ||
|
|
cc8d1f9bf2 | ||
|
|
ae95f1b0e5 | ||
|
|
c10441bec4 | ||
|
|
6ab334fc34 | ||
|
|
10e849ce60 | ||
|
|
c2206f5452 | ||
|
|
3b66cd3cee | ||
|
|
731a083bb7 | ||
|
|
d35c6ab864 | ||
|
|
e9cade872c | ||
|
|
b2a8146851 | ||
|
|
6fd3d6c452 | ||
|
|
bc3e72a87d | ||
|
|
e50e050aa9 | ||
|
|
c1a75607fa | ||
|
|
b203cd2af3 | ||
|
|
84063f026f | ||
|
|
3ec1ce25d7 | ||
|
|
0e70c543ee | ||
|
|
e4d522a8d2 | ||
|
|
272ecbd8ff | ||
|
|
369fa03f9b | ||
|
|
1675ea3ba2 | ||
|
|
5b7a1bb9e6 | ||
|
|
ace3effa2d | ||
|
|
bd0a14b3ce | ||
|
|
29a82f83c5 | ||
|
|
f7232f09de | ||
|
|
f3eeae9edd | ||
|
|
874468ca07 | ||
|
|
7a972af610 | ||
|
|
4ed42c38c9 | ||
|
|
6a73719a6b | ||
|
|
6efcfc6b93 | ||
|
|
25f30c220e | ||
|
|
2e9665f10e | ||
|
|
197881b430 | ||
|
|
96fe98d71f | ||
|
|
d1ecd4c933 | ||
|
|
fad25caa08 | ||
|
|
98c481e045 | ||
|
|
6082e655e6 | ||
|
|
6a97367242 | ||
|
|
bbcfffdab9 | ||
|
|
2dfb6c1012 | ||
|
|
82317343aa | ||
|
|
0ea0d0ec98 | ||
|
|
33aa27c590 | ||
|
|
c31f990183 | ||
|
|
791956bee0 | ||
|
|
6cebf4f6fd | ||
|
|
1782136e02 | ||
|
|
2f381192dd | ||
|
|
dac2009cab | ||
|
|
d592af694f | ||
|
|
e5ea3f9e49 | ||
|
|
f0af865401 | ||
|
|
1e20a9effe | ||
|
|
ce968f7756 | ||
|
|
00aaf316ef | ||
|
|
3ad9a0ca73 | ||
|
|
14a2d24fba | ||
|
|
e374886fcf | ||
|
|
e25b373f00 | ||
|
|
6fbd270d24 | ||
|
|
6adb55a9c4 | ||
|
|
16aa5cac04 | ||
|
|
dca0009df5 | ||
|
|
1cae441cbc | ||
|
|
8b21d8f74a | ||
|
|
ff141e30ee | ||
|
|
2c970a1b8d | ||
|
|
b433f8194e | ||
|
|
7b2f5e5de0 | ||
|
|
3d1400e347 | ||
|
|
8b5d68f79b | ||
|
|
ded4b461b4 | ||
|
|
13a7be57f2 | ||
|
|
e8fdcd5c06 | ||
|
|
b8e263d7e6 | ||
|
|
b76d17e7b9 | ||
|
|
ce3151b256 | ||
|
|
dd0c3ac51e | ||
|
|
f06c5897db | ||
|
|
7dac72f796 | ||
|
|
e5a55114b7 | ||
|
|
a66d0b3d39 | ||
|
|
b01ad69ba1 | ||
|
|
bbe183e8d4 | ||
|
|
f6c9e5079a | ||
|
|
0b8408d50a | ||
|
|
51682eac11 | ||
|
|
aea38c682c | ||
|
|
6edbe97290 | ||
|
|
304eaab4d2 | ||
|
|
f4e5839931 | ||
|
|
4bac9ea9d5 | ||
|
|
64c9b21849 | ||
|
|
34828b66a2 | ||
|
|
957ba00723 | ||
|
|
d548ee48c1 | ||
|
|
d0e93a22a2 | ||
|
|
fe6c1e260b | ||
|
|
1e5add91d3 | ||
|
|
f4c7329c30 | ||
|
|
b1742ccb8e | ||
|
|
870a0d8361 | ||
|
|
1f0adf92d4 | ||
|
|
18ce562698 | ||
|
|
77af926336 | ||
|
|
33f2269896 | ||
|
|
c477e14a04 | ||
|
|
373494094a | ||
|
|
72ca666007 | ||
|
|
5be299b897 | ||
|
|
49afd5077b | ||
|
|
e7336de8a7 | ||
|
|
5b0f4f5b94 | ||
|
|
0edc037441 | ||
|
|
d4a7f7e658 | ||
|
|
fcf9668e8b | ||
|
|
76e53e0869 | ||
|
|
74764253b4 | ||
|
|
c029c6c152 | ||
|
|
bb4b0d5f92 | ||
|
|
a355cf941b | ||
|
|
e7c5ef1cca | ||
|
|
09d0f7a3cb | ||
|
|
3e7dd07b4c | ||
|
|
c536eed349 | ||
|
|
93948021e6 | ||
|
|
77317f87c0 | ||
|
|
b091ea9c6d | ||
|
|
208493da88 | ||
|
|
7015745c4f | ||
|
|
41a5c72d46 | ||
|
|
2b428641fb | ||
|
|
4ebb1e60db | ||
|
|
5e4c1feed1 | ||
|
|
d13e1da1a7 | ||
|
|
9f57cff43b | ||
|
|
b9d9776d5c | ||
|
|
b57ab8470d | ||
|
|
fe402d2faa | ||
|
|
3d38210752 | ||
|
|
6c4b047b58 | ||
|
|
e861d3415a | ||
|
|
cb251fe88b | ||
|
|
b1e594f4d7 | ||
|
|
f9505f3c9f | ||
|
|
52ee2bb769 | ||
|
|
f0471fac14 | ||
|
|
7baac98959 | ||
|
|
9119443c2a | ||
|
|
c9c33929f0 | ||
|
|
60717d38d4 | ||
|
|
858757f8d1 | ||
|
|
f15a22a3cb | ||
|
|
f6022de7d3 | ||
|
|
8214301231 | ||
|
|
a4745098c5 | ||
|
|
647b06a615 | ||
|
|
a7cbafee07 | ||
|
|
ee0eb2345c | ||
|
|
d37c42761d | ||
|
|
d4984fd0ee | ||
|
|
c770ea1859 | ||
|
|
4d1307e223 | ||
|
|
e9308c11ba | ||
|
|
5206ec0fcb | ||
|
|
c65671a6f9 | ||
|
|
ec99203dc6 | ||
|
|
1cdde047ff | ||
|
|
2375d70782 | ||
|
|
5b0c395293 | ||
|
|
ea0c1abb0b | ||
|
|
cc841812ce | ||
|
|
5104bce7bb | ||
|
|
357ce483a8 | ||
|
|
1a40b4b984 | ||
|
|
cdd0e542f1 | ||
|
|
a9d87a938d | ||
|
|
549ff980a3 | ||
|
|
545af93972 | ||
|
|
72b9ed9f54 | ||
|
|
536c7dd04b | ||
|
|
274d5d1e75 | ||
|
|
7b478e42c0 | ||
|
|
d0ac1e61d4 | ||
|
|
31d73927a3 | ||
|
|
7713bd042a | ||
|
|
664dab76e3 | ||
|
|
6e2c33866d | ||
|
|
7b6dd6765e | ||
|
|
d55d2d0303 | ||
|
|
4df7bec913 | ||
|
|
4ddab1b691 | ||
|
|
b0c0e96fca | ||
|
|
aeee2fc391 | ||
|
|
4f28cb5617 | ||
|
|
a442a841f2 | ||
|
|
9201170ab8 | ||
|
|
4f06cfa0da | ||
|
|
fe03daa01f | ||
|
|
b64c4f6043 | ||
|
|
5884c78b56 | ||
|
|
b01b7373ac | ||
|
|
3cc9482a08 | ||
|
|
83c6b01fae | ||
|
|
1f169bc67e | ||
|
|
ea25675264 | ||
|
|
c302cd680c | ||
|
|
ebf46d0cfd | ||
|
|
2c9b504688 | ||
|
|
41d3de565c | ||
|
|
88430d845d | ||
|
|
c6e5e5d27e | ||
|
|
cd673028b7 | ||
|
|
2cafe12e4f | ||
|
|
febbaca66b | ||
|
|
e410ca748a | ||
|
|
524c04296e | ||
|
|
ef360bf93e | ||
|
|
bd4f7a4783 | ||
|
|
3c2c242225 | ||
|
|
a8e657c86e | ||
|
|
70e103af49 | ||
|
|
006f7a79b4 | ||
|
|
c7a4dbe84b | ||
|
|
31c0c52d7f | ||
|
|
a4590d3771 | ||
|
|
02b5e39c39 | ||
|
|
85dd704f86 | ||
|
|
b4d4efd40c | ||
|
|
8745b0f31a | ||
|
|
3787b3bbfc | ||
|
|
765e1b1231 | ||
|
|
2a2e2bf957 | ||
|
|
c93913732b | ||
|
|
f5bbc99d7d | ||
|
|
27ce42b9b0 | ||
|
|
008d51aeec | ||
|
|
8d0d264c0f | ||
|
|
28717352b4 | ||
|
|
f9e492dfdc | ||
|
|
a8e029f0e0 | ||
|
|
f5be4503c5 | ||
|
|
cd1d3f5026 | ||
|
|
4f55733bdd | ||
|
|
81819d04e8 | ||
|
|
4d4adea6eb | ||
|
|
ca981fbc8e | ||
|
|
b4c64abd1e | ||
|
|
a8787330d8 | ||
|
|
7725234b69 | ||
|
|
062d897fb1 | ||
|
|
e1ed95a638 | ||
|
|
7ffa5d076c | ||
|
|
1ae0ae630a | ||
|
|
d3e8daa9b5 | ||
|
|
5f8be26b73 | ||
|
|
0eb575b472 | ||
|
|
1888d905a4 | ||
|
|
3bc4dc8450 | ||
|
|
78719df8d4 | ||
|
|
d3616b335f | ||
|
|
e72cd086b4 | ||
|
|
c82e67c39a | ||
|
|
9885cf6f10 | ||
|
|
d923b5bc0f | ||
|
|
611d2fcaff | ||
|
|
9b2b312719 | ||
|
|
f84161dafc | ||
|
|
8546a0d0bd | ||
|
|
09f5873806 | ||
|
|
18dc905a8c | ||
|
|
30d64a0aa5 | ||
|
|
8359c9e19f | ||
|
|
571f0c0564 | ||
|
|
736a9ef442 | ||
|
|
aee94b0e14 | ||
|
|
4cfed0d394 | ||
|
|
c714d5d881 | ||
|
|
1c2d07ee56 | ||
|
|
96f7f3d88f | ||
|
|
c743577369 | ||
|
|
e5ea60fe88 | ||
|
|
330d93f335 | ||
|
|
f4936144d0 | ||
|
|
bbaa5dde92 | ||
|
|
e6b46151ec | ||
|
|
655a8de652 | ||
|
|
771d69f38b | ||
|
|
2a46dbf149 | ||
|
|
95a0535462 | ||
|
|
041758fead | ||
|
|
d6bb723c6a | ||
|
|
95f97e1c9f | ||
|
|
b029292dd2 | ||
|
|
82ba663c24 | ||
|
|
fabd5b9d32 | ||
|
|
58736b707d | ||
|
|
9219384650 | ||
|
|
14a904cfa9 | ||
|
|
e73f7a9c10 | ||
|
|
09acd36c08 | ||
|
|
69a6f44b8b | ||
|
|
3ee8fd4ec6 | ||
|
|
4f6c0b45f8 | ||
|
|
06a756a5eb | ||
|
|
b312df3b53 | ||
|
|
8e4b2a90a4 | ||
|
|
85b3091b8a | ||
|
|
3838fc3d22 | ||
|
|
0f4722d580 | ||
|
|
4241258158 | ||
|
|
13c446c918 | ||
|
|
9255026b84 | ||
|
|
119eb57a38 | ||
|
|
731f379bed | ||
|
|
bedcf304e1 | ||
|
|
a4655484cb | ||
|
|
babc5aba4f | ||
|
|
763a6f8b02 | ||
|
|
b08960d4b9 | ||
|
|
2c6e91622f | ||
|
|
4679977612 | ||
|
|
0e387904b0 | ||
|
|
f4238621a6 | ||
|
|
2fa19e8cae | ||
|
|
ab644d0638 | ||
|
|
8d1db88e1a | ||
|
|
12215ac5dd | ||
|
|
97d0b386ba | ||
|
|
f8526be667 | ||
|
|
22624f6a29 | ||
|
|
e70584e7fc | ||
|
|
ebd2346f3e | ||
|
|
03ce553620 | ||
|
|
9418a37846 | ||
|
|
4f186dec68 | ||
|
|
5867fd9912 | ||
|
|
cd327cfc5a | ||
|
|
a3f95871b2 | ||
|
|
53021b770b | ||
|
|
7f93731d0c | ||
|
|
570f82d7f8 | ||
|
|
2c8a069f47 | ||
|
|
bbf23be1f3 | ||
|
|
accca4e700 | ||
|
|
ecc8ebef6a | ||
|
|
6c8a807c8c | ||
|
|
dfb2d5eaaa | ||
|
|
71c7ec6fed | ||
|
|
55d216f024 | ||
|
|
5e22febd54 | ||
|
|
436d871ea9 | ||
|
|
02099912c5 | ||
|
|
601aedb25a | ||
|
|
c65aa3d507 | ||
|
|
9b02837d5a | ||
|
|
dbbff7b833 | ||
|
|
e306db4d0c | ||
|
|
985266fc77 | ||
|
|
a3f771cc7c | ||
|
|
71a1bea9c7 | ||
|
|
565543fbba | ||
|
|
9193194596 | ||
|
|
83ea28ded7 | ||
|
|
1a69782f51 | ||
|
|
394ea0f3d3 | ||
|
|
0241bbdbc0 | ||
|
|
5e00739776 | ||
|
|
5d214ac965 | ||
|
|
d35ae51fbb | ||
|
|
717f319dc7 | ||
|
|
fbd2f52da2 | ||
|
|
853d89ca9c | ||
|
|
9c9e3cef29 | ||
|
|
2237afceff | ||
|
|
180d036fd4 | ||
|
|
7248ee7ed2 | ||
|
|
d1e7944ad2 | ||
|
|
2f53752e05 | ||
|
|
3c0de68a00 | ||
|
|
ef22236f35 | ||
|
|
563fc27eae | ||
|
|
d453e120c8 | ||
|
|
57bd72f147 | ||
|
|
298c62e00b | ||
|
|
3d4abfeba2 | ||
|
|
b412118a79 | ||
|
|
c2b5c32a14 | ||
|
|
06cd0a518f | ||
|
|
947dcc3f3d | ||
|
|
fa5eb23cae | ||
|
|
c43895b602 | ||
|
|
18cb2a2047 | ||
|
|
91637c7b11 | ||
|
|
7b70e987ba | ||
|
|
74dfef3424 | ||
|
|
65255edec5 | ||
|
|
5b00412ba0 | ||
|
|
ef43e3f8a0 | ||
|
|
3fa06d865a | ||
|
|
96f2f12dec | ||
|
|
972079532c | ||
|
|
996d4efa32 | ||
|
|
4704bfb7e6 | ||
|
|
5d3b237854 | ||
|
|
dca290b3f0 | ||
|
|
a84473036d | ||
|
|
1b3cb7abb5 | ||
|
|
7dd99ae13e | ||
|
|
7af511b01a | ||
|
|
bb3dc2d889 | ||
|
|
76268c41bc | ||
|
|
b6963ba7c6 | ||
|
|
bd3ff8f828 | ||
|
|
385326f3a8 | ||
|
|
d896fd9106 | ||
|
|
9c18afee35 | ||
|
|
f0b87c8312 | ||
|
|
297b7d548a | ||
|
|
7c406e8f8a | ||
|
|
f458d8dc39 | ||
|
|
66ed78cf4d | ||
|
|
f6205182b9 | ||
|
|
a661016824 | ||
|
|
448afcea7a | ||
|
|
23881ad861 | ||
|
|
9d41f49741 | ||
|
|
b302ebfbb5 | ||
|
|
88d428f03c | ||
|
|
7396b30615 | ||
|
|
6fe1cc9ed7 | ||
|
|
7622959657 | ||
|
|
6f94fdf133 | ||
|
|
b348ce3660 | ||
|
|
f8638fef92 | ||
|
|
9e895da7ed | ||
|
|
cb659fef0d | ||
|
|
1a9042c8d1 | ||
|
|
aac8cb9775 | ||
|
|
99962a68b6 | ||
|
|
8ce6d7f369 | ||
|
|
3bc5a586fa |
No files matched your search
@@ -3,3 +3,4 @@ build*/
|
||||
.vscode
|
||||
.gdb_history
|
||||
src/git_head.h
|
||||
backup/
|
||||
@@ -1,3 +1,32 @@
|
||||
v0.1.6
|
||||
======
|
||||
* Changes in Dynarec to make flags optimizations before CALL and RET opcode less aggressive
|
||||
* Added Vulkan wrapper
|
||||
* Improved wrapping of SDL_mixer/ SDL2_mixer lib
|
||||
* Improved wrapping of some gtk structures
|
||||
* Added a quick and dirty wrapping of Gtk3 (based on current gtk2)
|
||||
* Improved the signal handling, should be more stable now (the signal handler from syscall still need some works)
|
||||
* Added RK3399 profile, and some hints to build the 32bits box86 on 64bits OS
|
||||
* Fixed some wrapped printf formating not handled correctly
|
||||
* Fixed some buserror with the new LOCK mecanism handling
|
||||
* A few more Dynarec opcodes added
|
||||
* If winedbg is tried to be launched, exit without launching it (it doesn't work anyway)
|
||||
|
||||
v0.1.4
|
||||
======
|
||||
* Change in Dynarec memory handling, to simplify it (and hopefully optimized it)
|
||||
* Even more opcodes added.
|
||||
* And some more Dynarec opcodes.
|
||||
* Fixed some issue were PltResolver was injected but should not
|
||||
* Fixed many Dynarec and non dynarec opcodes
|
||||
* Improved Signal handling
|
||||
* Added a few more wrapped lib (like curl)
|
||||
* Gallium9 is wrapped (thx @icecream95)
|
||||
* Fixed and simplied many wrapped functions (especialy the one were a callback is involved)
|
||||
* Fixed Dynarec "freeing" a Dynablock somthime corrupting the heap (happens in case of JIT mainly)
|
||||
* Optimized the way LOCK prefix work when using Dynarec on ARM
|
||||
* Printer of ARM opcode (for dumping Dynarec blocks) improvement (thx @rajdakin)
|
||||
|
||||
v0.1.2
|
||||
======
|
||||
* The Dynarec now handle JIT code
|
||||
|
||||
+103
-74
@@ -1,25 +1,26 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
project(box86)
|
||||
|
||||
enable_testing()
|
||||
enable_language(C)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
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(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
|
||||
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
|
||||
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
|
||||
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 RK3399)
|
||||
set(LD80BITS OFF CACHE BOOL "")
|
||||
set(NOALIGN OFF CACHE BOOL "")
|
||||
set(ARM_DYNAREC ON CACHE BOOL "")
|
||||
endif()
|
||||
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
|
||||
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
|
||||
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
|
||||
option(USE_FLOAT "Set to ON to use only float, no double, in all x87 Emulation" ${USE_FLOAT})
|
||||
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
|
||||
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation (WIP, don't use yet)" ${ARM_DYNAREC})
|
||||
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
|
||||
find_package(PythonInterp 3)
|
||||
@@ -37,6 +38,16 @@ else()
|
||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
|
||||
endif()
|
||||
|
||||
if(RK3399)
|
||||
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)
|
||||
endif()
|
||||
|
||||
project(box86 C ASM)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(default_build_type "RelwithDebInfo")
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
@@ -44,69 +55,63 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
|
||||
# Pandora
|
||||
if(PANDORA)
|
||||
add_definitions(-DPANDORA)
|
||||
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
|
||||
# Gameshell
|
||||
if(GAMESHELL)
|
||||
add_definitions(-DGAMEHELL)
|
||||
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
|
||||
if(PYRA)
|
||||
add_definitions(-DPYRA)
|
||||
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
|
||||
if(RPI2)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI2)
|
||||
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
if(RPI3)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI3)
|
||||
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")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
if(RPI4)
|
||||
add_definitions(-DRPI)
|
||||
add_definitions(-DRPI3)
|
||||
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")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
if(ODROID)
|
||||
add_definitions(-DODROID)
|
||||
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
|
||||
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
|
||||
set(ARM_DYNAREC ON)
|
||||
set(LD80BITS OFF)
|
||||
set(NOALIGN OFF)
|
||||
endif()
|
||||
if(RK3399)
|
||||
add_definitions(-DRK3399)
|
||||
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
|
||||
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
|
||||
endif()
|
||||
|
||||
set(BOX86_ELF_ADDRESS "0x02800000")
|
||||
if(NOGIT)
|
||||
add_definitions(-DNOGIT)
|
||||
endif()
|
||||
|
||||
if(BOX86LIB)
|
||||
set(BOX86 box86)
|
||||
elseif(HAVE_TRACE)
|
||||
set(BOX86 box86t)
|
||||
else()
|
||||
set(BOX86 box86)
|
||||
endif()
|
||||
|
||||
|
||||
set(BOX86_ELF_ADDRESS "0x62800000")
|
||||
|
||||
if(LD80BITS)
|
||||
add_definitions(-DHAVE_LD80BITS)
|
||||
@@ -120,10 +125,6 @@ if(HAVE_TRACE)
|
||||
add_definitions(-DHAVE_TRACE)
|
||||
endif()
|
||||
|
||||
if(USE_FLOAT)
|
||||
add_definitions(-DUSE_FLOAT)
|
||||
endif()
|
||||
|
||||
if(ARM_DYNAREC)
|
||||
add_definitions(-DDYNAREC)
|
||||
add_definitions(-DARM)
|
||||
@@ -145,11 +146,11 @@ if(BOX86LIB)
|
||||
message(FATAL_ERROR "BOX86_ROOT not set when build as lib")
|
||||
endif()
|
||||
else()
|
||||
set(BOX86_ROOT ${CMAKE_HOME_DIRECTORY})
|
||||
set(BOX86_ROOT ${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
|
||||
add_definitions(-std=gnu99 -funwind-tables -fvisibility=hidden)
|
||||
add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden)
|
||||
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
@@ -165,15 +166,13 @@ include_directories(
|
||||
"${BOX86_ROOT}/src/wrapped/generated"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\"\>${BOX86_ROOT}/src/git_head.h"
|
||||
DEPEND "${BOX86_ROOT}/src/build_info.c"
|
||||
VERBATIM
|
||||
)
|
||||
# git_head.h is a generated file
|
||||
set_source_files_properties(
|
||||
"${BOX86_ROOT}/src/git_head.h"
|
||||
PROPERTIES GENERATED TRUE
|
||||
HEADER_FILE_ONLY TRUE)
|
||||
|
||||
set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/git_head.h"
|
||||
"${BOX86_ROOT}/src/main.c"
|
||||
"${BOX86_ROOT}/src/box86context.c"
|
||||
"${BOX86_ROOT}/src/build_info.c"
|
||||
@@ -193,6 +192,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/emu/x86emu.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run66.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run660f.c"
|
||||
"${BOX86_ROOT}/src/emu/x86run_private.c"
|
||||
"${BOX86_ROOT}/src/emu/x86syscall.c"
|
||||
"${BOX86_ROOT}/src/emu/x86primop.c"
|
||||
@@ -210,6 +210,7 @@ set(ELFLOADER_SRC
|
||||
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
|
||||
"${BOX86_ROOT}/src/libtools/signals.c"
|
||||
"${BOX86_ROOT}/src/libtools/threads.c"
|
||||
"${BOX86_ROOT}/src/libtools/vkalign.c"
|
||||
"${BOX86_ROOT}/src/dynarec/dynarec.c"
|
||||
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
|
||||
)
|
||||
@@ -252,6 +253,16 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxdmcp.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibx11xcb.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcb.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshape.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshm.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbimage.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbpresent.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxtst.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxt.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibxcomposite.c"
|
||||
@@ -261,6 +272,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
|
||||
@@ -289,6 +301,8 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgtk3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgdk3.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgio2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
|
||||
@@ -298,6 +312,7 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
|
||||
@@ -310,10 +325,14 @@ set(WRAPPEDS
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedmpg123.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedgnutls.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedlibcups.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedvulkan.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedwaylandclient.c"
|
||||
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
|
||||
)
|
||||
|
||||
set(WRAPPEDS_HEAD "")
|
||||
set(WRAPPEDS_HEAD "${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
|
||||
foreach(A ${WRAPPEDS})
|
||||
string(REPLACE ".c" "_private.h" B ${A})
|
||||
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
|
||||
@@ -324,7 +343,7 @@ set(WRAPPER "${BOX86_ROOT}/src/wrapped/generated/wrapper.c" "${BOX86_ROOT}/src/w
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "USE_FLOAT" "--" ${WRAPPEDS_HEAD}
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--" ${WRAPPEDS_HEAD}
|
||||
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
|
||||
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
|
||||
BYPRODUCTS ${WRAPPER}
|
||||
@@ -341,9 +360,6 @@ add_custom_command(
|
||||
add_custom_target(WRAPPERS DEPENDS "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt")
|
||||
add_custom_target(PRINTER DEPENDS "${BOX86_ROOT}/src/dynarec/last_run.txt")
|
||||
|
||||
#this is to force build_info.c to be rebuilt all the time
|
||||
set_source_files_properties("${BOX86_ROOT}/src/build_info.c" PROPERTIES OBJECT_OUTPUTS "dummy.c")
|
||||
|
||||
if(ARM_DYNAREC)
|
||||
set(DYNAREC_SRC
|
||||
"${BOX86_ROOT}/src/dynarec/dynablock.c"
|
||||
@@ -356,6 +372,7 @@ if(ARM_DYNAREC)
|
||||
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_linker.S"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_table.S"
|
||||
"${BOX86_ROOT}/src/dynarec/arm_lock_helper.S"
|
||||
)
|
||||
|
||||
set(DYNAREC_PASS
|
||||
@@ -409,37 +426,48 @@ if(ARM_DYNAREC)
|
||||
$<TARGET_OBJECTS:arm_pass2>
|
||||
$<TARGET_OBJECTS:arm_pass3>
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
# creates git_head.h
|
||||
if(ARM_DYNAREC)
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${BOX86_ROOT}/src/git_head.h"
|
||||
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
|
||||
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
if(BOX86LIB)
|
||||
#build a static or dynamic lib...
|
||||
if(BOX86DYNAMIC)
|
||||
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS})
|
||||
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
|
||||
else()
|
||||
add_library(box86 OBJECT ${ELFLOADER_SRC} ${WRAPPEDS})
|
||||
add_library(${BOX86} OBJECT ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
|
||||
endif()
|
||||
if(ARM_DYNAREC)
|
||||
target_link_libraries(box86 dynarec m dl rt pthread)
|
||||
target_link_libraries(${BOX86} dynarec m dl rt pthread)
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13")
|
||||
set_target_properties(box86 PROPERTIES LINK_FLAGS -rdynamic)
|
||||
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
|
||||
else()
|
||||
target_link_options(box86 PUBLIC -rdynamic)
|
||||
target_link_options(${BOX86} PUBLIC -rdynamic)
|
||||
endif()
|
||||
add_dependencies(box86 WRAPPERS)
|
||||
add_dependencies(box86 PRINTER)
|
||||
add_dependencies(${BOX86} WRAPPERS)
|
||||
add_dependencies(${BOX86} PRINTER)
|
||||
|
||||
add_custom_target(buildinfo ${BOX86}
|
||||
DEPENDS dynarec ${BOX86} )
|
||||
|
||||
else(BOX86LIB)
|
||||
|
||||
if(USE_FLOAT)
|
||||
set(BOX86 box86f)
|
||||
elseif(HAVE_TRACE)
|
||||
set(BOX86 box86t)
|
||||
else()
|
||||
set(BOX86 box86)
|
||||
endif()
|
||||
|
||||
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS})
|
||||
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
|
||||
add_dependencies(${BOX86} WRAPPERS)
|
||||
add_dependencies(${BOX86} PRINTER)
|
||||
target_link_libraries(${BOX86} m dl rt pthread)
|
||||
@@ -466,7 +494,8 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
|
||||
if(NOT _x86 AND NOT _x86_64)
|
||||
install(TARGETS ${BOX86}
|
||||
RUNTIME DESTINATION bin)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
|
||||
configure_file(system/box86.conf.cmake system/box86.conf)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
|
||||
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/)
|
||||
|
||||
+18
-1
@@ -16,7 +16,14 @@ Compiling
|
||||
|
||||
_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)_
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
|
||||
```
|
||||
git clone https://github.com/ptitSeb/box86
|
||||
cd box86
|
||||
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
make -j4
|
||||
sudo make install
|
||||
sudo systemctl restart systemd-binfmt
|
||||
```
|
||||
|
||||
_For Pi4. Change to RPI2 or RPI3 for other models._
|
||||
|
||||
@@ -24,6 +31,12 @@ Compiling
|
||||
|
||||
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
|
||||
|
||||
#### for RK3399
|
||||
|
||||
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
|
||||
|
||||
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch env, and an armhf gcc: use `sudo apt install gcc-arm-linux-gnueabihf` to install it.
|
||||
|
||||
#### for Other ARM Linux
|
||||
|
||||
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
|
||||
@@ -54,6 +67,10 @@ To have a trace enabled build (warning, it will be slower), add `-DHAVE_TRACE=1`
|
||||
|
||||
The Dynarec is only avaiable on ARM Cpu. 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).
|
||||
|
||||
*not building from a git clone*
|
||||
|
||||
If you are not building from a git clone (for example downloading a release sources 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).
|
||||
|
||||
----
|
||||
|
||||
Testing
|
||||
|
||||
@@ -5,7 +5,7 @@ Linux Userspace x86 Emulator with a twist
|
||||
|
||||
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux, like ARM (host system needs to be 32bit little-endian).
|
||||
|
||||
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 support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized).
|
||||
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 support 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 environnement).
|
||||
|
||||
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use, and performance can be surprisingly high in some cases.
|
||||
|
||||
@@ -32,6 +32,16 @@ Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list
|
||||
|
||||
Logo and Icon made by @grayduck, thanks!
|
||||
|
||||
Note that this project is not to be mystaken with [86box](https://github.com/86Box/86Box), a nice "Full system" emulator specialized in early (to fairly recent) PC hardware.
|
||||
|
||||
----
|
||||
|
||||
Discord
|
||||
----
|
||||
|
||||
If you want to discuss about box86 on Discord, there is a frendly server there: [PI Lab Discord](https://discord.gg/Fh8sjmu)
|
||||
|
||||
|
||||
----
|
||||
|
||||
Compiling
|
||||
@@ -73,7 +83,17 @@ A note 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 he new "protected memory" mechanism implemented it is 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 Mono games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct 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.
|
||||
|
||||
----
|
||||
|
||||
A note about Steam
|
||||
----
|
||||
|
||||
Linux Steam can run now with box86. But it's still a bit unstable., and not everything works. First is steam crashes after the Sign in, you may need to add libappindicator. On debian it's `sudo apt install libappindicator1`.
|
||||
Once open, Steam will only work on "Small mode" and in "Big Picture", not in the regular "Browser mode". So go in the "View" menu and witch to Small view (or Compact view?), else the list will stay empty (this is because some steam component used in the browser view are only 64bits now).
|
||||
Final word, to avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` export.
|
||||
(Steam for Windows install fine but doesn't work yet)
|
||||
|
||||
----
|
||||
|
||||
@@ -81,6 +101,7 @@ A note about Wine
|
||||
----
|
||||
|
||||
Wine is now partly supported. Wine integreted program all runs, annd some windows program and games now run fine. Don't forget most Windows games use Direct3D, that may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
|
||||
A not if you plan to use box86 with wine on Raspberry PI 3 or earlier: those model use a default OS that have a kernle with a 2/2 Split (meaning 2G of space for user program, and 2G of space for Kernel). This is not compatible with wine, that need to access memory > 2Gb address. So you'll need to reconfigure your kernel for a 3G/1G split. Use your favorite search engine to find tutos on how to do that.
|
||||
|
||||
----
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ Usage
|
||||
|
||||
There are many environment variable to control Box86 behaviour.
|
||||
|
||||
##### BOX86_LOG
|
||||
#### BOX86_LOG
|
||||
Controls the Verbose level of the log
|
||||
* 0
|
||||
* NONE : No message (except some fatal error)
|
||||
@@ -14,6 +14,11 @@ Controls the Verbose level of the log
|
||||
* 3
|
||||
* DUMP : All DEBUG plus DUMP of all ELF Info
|
||||
|
||||
#### BOX86_NOBANNER
|
||||
Control Box86 printing it's version and build
|
||||
* 0 : Enabled the printing
|
||||
* 1 : Diable the printing
|
||||
|
||||
#### BOX86_LD_LIBRARY_PATH
|
||||
Controls the folder scanned to look for x86 libs. Default is current folder and `lib` in current folder.
|
||||
Also `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exists
|
||||
@@ -126,7 +131,18 @@ Allow box86 to continue even if a lib is missing
|
||||
* 0 : default, stop if a lib cannot be loaded
|
||||
* 1 : continue even if a needed lib cannot be loaded. Unadvised, this will, in most cases, crash later on.
|
||||
|
||||
#### BOX86_NOPULSE
|
||||
Disable the load of pulseaudio libs
|
||||
* 0 : default, load pulseaudio libs if present
|
||||
* 1 : disable the load of pulse audio libs (libpulse and libpulse-simple), both native and x86 version
|
||||
|
||||
#### BOX86_FIX_64BIT_INODES
|
||||
* 0 : Don't fix 64bit inodes (default)
|
||||
* 1 : Fix 64bit inodes. Helps when running on filesystems with 64bit inodes, the program uses API functions which don't support it and the program doesn't use inodes information.
|
||||
|
||||
#### 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.
|
||||
When in gdb, you need to find the correct thread yourself (the one with `my_box86signalhandler` in is stack)
|
||||
then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box86signalhandler`,
|
||||
just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-arm-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-gameshell-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-odroid-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-pandora-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-pyra-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-rpi-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('armv7h')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
# Check for Pi version number
|
||||
if [[ ${_pimodel} ~= "Raspberry Pi 4" ]]; then
|
||||
_piversion=4
|
||||
elif [[ ${_pimodel} ~= "Raspberry Pi 3" ]]; then
|
||||
_piversion=3
|
||||
elif [[ ${_pimodel} ~= "Raspberry Pi 2" ]]; then
|
||||
_piversion=2
|
||||
else
|
||||
# Your RPI is not supported or this device is not a pi, cancel build then
|
||||
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 not supported).\033[00m"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# Maintainer: SpacingBat3 <[email protected]>
|
||||
# Contributor: Sebastien Chevalier
|
||||
pkgname=box86-x86-git
|
||||
pkgver=r2798.0edc0374
|
||||
pkgrel=1
|
||||
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
|
||||
arch=('i386')
|
||||
url="https://github.com/ptitSeb/box86"
|
||||
license=('MIT')
|
||||
makedepends=('git' 'cmake' 'make')
|
||||
provides=("${pkgname%-git}")
|
||||
conflicts=("${pkgname%-git}")
|
||||
source=('git+https://github.com/ptitSeb/box86')
|
||||
md5sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/${pkgname%-git}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${pkgname%-git}"
|
||||
if [[ ! -d ./build ]]; then
|
||||
mkdir build && cd build
|
||||
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make -j$(nproc)
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/${pkgname%-git}/build"
|
||||
make DESTDIR="${pkgdir}/" install
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# The directory containing all PKGBUILDs for BOX86
|
||||
## FAQ
|
||||
### 1. How to use it?
|
||||
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
|
||||
```sh
|
||||
mv ./PKGBUILD-<your-platform> ./PKGBUILD
|
||||
cd ..
|
||||
makepkg -si
|
||||
```
|
||||
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 32-bit Archlinux ARM.
|
||||
|
||||
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
|
||||
|
||||
### 2. What platforms are currently supported.
|
||||
All specified in [COMPILE.md](../COMPILE.md).
|
||||
|
||||
### 3. Any advantages with that sollution?
|
||||
This might give you some advantages like those:
|
||||
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
|
||||
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
|
||||
- your `box86` installation is recognized as a package (where it wasn't when installing with `make install`).
|
||||
+5
-5
@@ -575,11 +575,11 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
append("int rot = (opcode >> " + str(variables["r"]) + ") & 3;\nchar tmprot[8] = {0};\n")
|
||||
append("if (rot) {\nsprintf(tmprot, \" ror %d\", rot * 8);\n}\n")
|
||||
if variables["sb"][0] != -1:
|
||||
append("int lsb = (opcode >> " + str(variables["sb"][0]) + ") & 0xF;\n")
|
||||
append("int lsb = (opcode >> " + str(variables["sb"][0]) + ") & 0x1F;\n")
|
||||
if variables["sb"][1] != -1:
|
||||
append("int msb = (opcode >> " + str(variables["sb"][1]) + ") & 0xF;\n")
|
||||
append("int msb = (opcode >> " + str(variables["sb"][1]) + ") & 0x1F;\n")
|
||||
if variables["sb"][2] != -1:
|
||||
append("int widthm1 = (opcode >> " + str(variables["sb"][2]) + ") & 0xF;\n")
|
||||
append("int widthm1 = (opcode >> " + str(variables["sb"][2]) + ") & 0x1F;\n")
|
||||
if variables["reglist16"] != -1:
|
||||
append("int reglist = (opcode >> " + str(variables["reglist16"]) + ") & 0xFFFF;\n")
|
||||
if imms != []:
|
||||
@@ -1105,7 +1105,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
|
||||
|
||||
l = len(imms) == 2
|
||||
if l:
|
||||
append("uint8_t l = (opcode >> " + str(imms[1][1]) + ") & 0x1;\n")
|
||||
append("uint8_t l = (opcode >> " + str(imms[1][0]) + ") & 0x1;\n")
|
||||
|
||||
immssz = 6
|
||||
append("uint8_t imm6 = (opcode >> " + str(imms[0][0]) + ") & 0x3F;\n")
|
||||
@@ -1774,7 +1774,7 @@ const char* print_shift(int shift, int comma) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (imm12 >> 8)) | ((imm12 & 0xFF) << (32 - (imm12 >> 8))))
|
||||
#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;
|
||||
|
||||
+127
-65
@@ -3,7 +3,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S']
|
||||
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G']
|
||||
def splitchar(s):
|
||||
try:
|
||||
ret = [len(s), values.index(s[0])]
|
||||
@@ -230,6 +230,11 @@ typedef union ui64_s {
|
||||
uint32_t d[2];
|
||||
} ui64_t;
|
||||
|
||||
typedef struct _2uint_struct_s {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
} _2uint_struct_t;
|
||||
|
||||
extern void* my__IO_2_1_stderr_;
|
||||
extern void* my__IO_2_1_stdin_ ;
|
||||
extern void* my__IO_2_1_stdout_;
|
||||
@@ -247,11 +252,35 @@ static void* io_convert(void* v)
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef USE_FLOAT
|
||||
#define ST0val ST0.f
|
||||
#else
|
||||
typedef struct my_GValue_s
|
||||
{
|
||||
int g_type;
|
||||
union {
|
||||
int v_int;
|
||||
int64_t v_int64;
|
||||
uint64_t v_uint64;
|
||||
float v_float;
|
||||
double v_double;
|
||||
void* v_pointer;
|
||||
} data[2];
|
||||
} my_GValue_t;
|
||||
|
||||
static void alignGValue(my_GValue_t* v, void* value)
|
||||
{
|
||||
v->g_type = *(int*)value;
|
||||
memcpy(v->data, value+4, 2*sizeof(double));
|
||||
}
|
||||
static void unalignGValue(void* value, my_GValue_t* v)
|
||||
{
|
||||
*(int*)value = v->g_type;
|
||||
memcpy(value+4, v->data, 2*sizeof(double));
|
||||
}
|
||||
|
||||
void* VulkanFromx86(void* src, void** save);
|
||||
void VulkanTox86(void* src, void* save);
|
||||
|
||||
#define ST0val ST0.d
|
||||
#endif
|
||||
|
||||
int of_convert(int);
|
||||
""",
|
||||
"wrapper.h": """/*****************************************************************
|
||||
@@ -260,6 +289,7 @@ int of_convert(int);
|
||||
#ifndef __WRAPPER_H_
|
||||
#define __WRAPPER_H_
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
@@ -279,7 +309,9 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
// O = libc O_ flags bitfield
|
||||
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
|
||||
// Q = ...
|
||||
// S8 = struct, 8 bytes
|
||||
// 2 = struct of 2 uint
|
||||
// P = Vulkan struture pointer
|
||||
// G = a single GValue pointer
|
||||
|
||||
"""
|
||||
}
|
||||
@@ -315,8 +347,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
|
||||
# First part: typedefs
|
||||
for v in gbl["()"]:
|
||||
# E e v c w i I C W u U f d D K l L p V O S
|
||||
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
|
||||
# E e v c w i I C W u U f d D K l L p V O S 2 P G
|
||||
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*"]
|
||||
if len(values) != len(types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
|
||||
|
||||
@@ -325,8 +357,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
for k in gbl_idxs:
|
||||
file.write("\n#if " + k + "\n")
|
||||
for v in gbl[k]:
|
||||
# E e v c w i I C W u U f d D K l L p V O S
|
||||
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*"]
|
||||
# E e v c w i I C W u U f d D K l L p V O S 2 P G
|
||||
types = ["x86emu_t*", "x86emu_t**", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*"]
|
||||
if len(values) != len(types):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
|
||||
|
||||
@@ -335,8 +367,72 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
file.write("#endif\n")
|
||||
|
||||
file.write("\n")
|
||||
|
||||
# Next part: function definitions
|
||||
|
||||
# Helper variables
|
||||
arg = [
|
||||
"emu, ", # E
|
||||
"&emu, ", # e
|
||||
"", # v
|
||||
"*(int8_t*)(R_ESP + {p}), ", # c
|
||||
"*(int16_t*)(R_ESP + {p}), ", # w
|
||||
"*(int32_t*)(R_ESP + {p}), ", # i
|
||||
"*(int64_t*)(R_ESP + {p}), ", # I
|
||||
"*(uint8_t*)(R_ESP + {p}), ", # C
|
||||
"*(uint16_t*)(R_ESP + {p}), ", # W
|
||||
"*(uint32_t*)(R_ESP + {p}), ", # u
|
||||
"*(uint64_t*)(R_ESP + {p}), ", # U
|
||||
"*(float*)(R_ESP + {p}), ", # f
|
||||
"*(double*)(R_ESP + {p}), ", # d
|
||||
"*(long double*)(R_ESP + {p}), ", # D
|
||||
"FromLD((void*)(R_ESP + {p})), ", # K
|
||||
"*(intptr_t*)(R_ESP + {p}), ", # l
|
||||
"*(uintptr_t*)(R_ESP + {p}), ", # L
|
||||
"*(void**)(R_ESP + {p}), ", # p
|
||||
"(void*)(R_ESP + {p}), ", # V
|
||||
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
|
||||
"io_convert(*(void**)(R_ESP + {p})), ", # S
|
||||
"(_2uint_struct_t){{*(uintptr_t*)(R_ESP + {p}),*(uintptr_t*)(R_ESP + {p} + 4)}}, ", #2
|
||||
"arg{p}, ", # P
|
||||
"&arg{p}, ", # G
|
||||
]
|
||||
# E e v c w i I C W u U f d D K l L p V O S 2 P G
|
||||
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4, 8, 4, 4]
|
||||
vals = [
|
||||
"\n#error Invalid return type: emulator\n", # E
|
||||
"\n#error Invalid return type: &emulator\n", # e
|
||||
"fn({0});", # v
|
||||
"R_EAX=fn({0});", # c
|
||||
"R_EAX=fn({0});", # w
|
||||
"R_EAX=fn({0});", # i
|
||||
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
|
||||
"R_EAX=(unsigned char)fn({0});", # C
|
||||
"R_EAX=(unsigned short)fn({0});", # W
|
||||
"R_EAX=(uint32_t)fn({0});", # u
|
||||
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
|
||||
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
|
||||
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
|
||||
"R_EAX=(intptr_t)fn({0});", # l
|
||||
"R_EAX=(uintptr_t)fn({0});", # L
|
||||
"R_EAX=(uintptr_t)fn({0});", # p
|
||||
"\n#error Invalid return type: va_list\n", # V
|
||||
"\n#error Invalid return type: at_flags\n", # O
|
||||
"\n#error Invalid return type: _io_file*\n", # S
|
||||
"\n#error Invalid return type: _2uint_struct\n", # 2
|
||||
"\n#error Invalid return type: Vulkan Struct\n", # P
|
||||
"\n#error Invalid return type: GValue Pointer\n", # G
|
||||
]
|
||||
# Asserts
|
||||
if len(values) != len(arg):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
|
||||
if len(values) != len(deltas):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
|
||||
if len(values) != len(vals):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
|
||||
|
||||
# Helper functions to write the function definitions
|
||||
def function_args(args, d=4):
|
||||
if len(args) == 0:
|
||||
@@ -349,65 +445,31 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
|
||||
elif args[0] == "1":
|
||||
return "1, " + function_args(args[1:], d)
|
||||
|
||||
arg = [
|
||||
"emu, ", # E
|
||||
"&emu, ", # e
|
||||
"", # v
|
||||
"*(int8_t*)(R_ESP + {p}), ", # c
|
||||
"*(int16_t*)(R_ESP + {p}), ", # w
|
||||
"*(int32_t*)(R_ESP + {p}), ", # i
|
||||
"*(int64_t*)(R_ESP + {p}), ", # I
|
||||
"*(uint8_t*)(R_ESP + {p}), ", # C
|
||||
"*(uint16_t*)(R_ESP + {p}), ", # W
|
||||
"*(uint32_t*)(R_ESP + {p}), ", # u
|
||||
"*(uint64_t*)(R_ESP + {p}), ", # U
|
||||
"*(float*)(R_ESP + {p}), ", # f
|
||||
"*(double*)(R_ESP + {p}), ", # d
|
||||
"*(long double*)(R_ESP + {p}), ", # D
|
||||
"FromLD((void*)(R_ESP + {p})), ", # K
|
||||
"*(intptr_t*)(R_ESP + {p}), ", # l
|
||||
"*(uintptr_t*)(R_ESP + {p}), ", # L
|
||||
"*(void**)(R_ESP + {p}), ", # p
|
||||
"(void*)(R_ESP + {p}), ", # V
|
||||
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
|
||||
"io_convert(*(void**)(R_ESP + {p})), ", # S
|
||||
]
|
||||
# E e v c w i I C W u U f d D K l L p V O S
|
||||
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4]
|
||||
if len(values) != len(arg):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
|
||||
if len(values) != len(deltas):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
|
||||
return arg[values.index(args[0])].format(p=d) + function_args(args[1:], d + deltas[values.index(args[0])])
|
||||
|
||||
def function_writer(f, N, W, rettype, args):
|
||||
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
|
||||
vals = [
|
||||
"\n#error Invalid return type: emulator\n", # E
|
||||
"\n#error Invalid return type: &emulator\n", # e
|
||||
"fn({0});", # v
|
||||
"R_EAX=fn({0});", # c
|
||||
"R_EAX=fn({0});", # w
|
||||
"R_EAX=fn({0});", # i
|
||||
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
|
||||
"R_EAX=(unsigned char)fn({0});", # C
|
||||
"R_EAX=(unsigned short)fn({0});", # W
|
||||
"R_EAX=(uint32_t)fn({0});", # u
|
||||
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
|
||||
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
|
||||
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
|
||||
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
|
||||
"R_EAX=(intptr_t)fn({0});", # l
|
||||
"R_EAX=(uintptr_t)fn({0});", # L
|
||||
"R_EAX=(uintptr_t)fn({0});", # p
|
||||
"\n#error Invalid return type: va_list\n", # V
|
||||
"\n#error Invalid return type: at_flags\n", # O
|
||||
"\n#error Invalid return type: _io_file*\n", # S
|
||||
]
|
||||
if len(values) != len(vals):
|
||||
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
|
||||
if any(cc in 'PG' for cc in args):
|
||||
# Vulkan struct or GValue pointer, need to unwrap functions at the end
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("void* save{d}=NULL; void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d}), &save{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[values.index(c)]
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " ")
|
||||
delta = 4
|
||||
for c in args:
|
||||
if c == 'P':
|
||||
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
|
||||
if c == 'G':
|
||||
f.write("unalignGValue(*(void**)(R_ESP + {d}), &arg{d}); ".format(d=delta))
|
||||
delta = delta + deltas[values.index(c)]
|
||||
f.write("}\n")
|
||||
else:
|
||||
# Generic function
|
||||
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
|
||||
|
||||
for v in gbl["()"]:
|
||||
function_writer(file, v, v + "_t", v[0], v[2:])
|
||||
|
||||
@@ -13,6 +13,7 @@ if( NOT TEST_REFERENCE )
|
||||
endif( NOT TEST_REFERENCE )
|
||||
|
||||
set(ENV{BOX86_LOG} 0)
|
||||
set(ENV{BOX86_NOBANNER} 1)
|
||||
if( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
|
||||
# we are inside box86 folder
|
||||
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x86lib)
|
||||
|
||||
+74
-36
@@ -25,6 +25,7 @@
|
||||
|
||||
#define MMAPSIZE (4*1024*1024) // allocate 4Mo sized blocks
|
||||
#define MMAPBLOCK 256 // minimum size of a block
|
||||
//#define USE_MMAP
|
||||
|
||||
typedef struct mmaplist_s {
|
||||
void* block;
|
||||
@@ -73,11 +74,20 @@ static void freeBlock(mmaplist_t *map, int start, int size)
|
||||
uintptr_t AllocDynarecMap(int size, int nolinker)
|
||||
{
|
||||
if(size>MMAPSIZE) {
|
||||
#ifdef USE_MMAP
|
||||
void* p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
dynarec_log(LOG_DEBUG, "Cannot create dynamic map of %d bytes\n", size);
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
void *p = NULL;
|
||||
if(posix_memalign(&p, box86_pagesize, size)) {
|
||||
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
|
||||
return 0;
|
||||
}
|
||||
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
return (uintptr_t)p;
|
||||
}
|
||||
pthread_mutex_lock(&my_context->mutex_mmap);
|
||||
@@ -102,13 +112,24 @@ uintptr_t AllocDynarecMap(int size, int nolinker)
|
||||
int i = my_context->mmapsize++; // yeah, useful post incrementation
|
||||
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", my_context->mmapsize);
|
||||
my_context->mmaplist = (mmaplist_t*)realloc(my_context->mmaplist, my_context->mmapsize*sizeof(mmaplist_t));
|
||||
#ifdef USE_MMAP
|
||||
void* p = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if(p==MAP_FAILED) {
|
||||
dynarec_log(LOG_DEBUG, "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, i);
|
||||
--my_context->mmapsize;
|
||||
pthread_mutex_unlock(&my_context->mutex_mmap);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
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);
|
||||
--my_context->mmapsize;
|
||||
pthread_mutex_unlock(&my_context->mutex_mmap);
|
||||
return 0;
|
||||
}
|
||||
mprotect(p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
my_context->mmaplist[i].block = p;
|
||||
memset(my_context->mmaplist[i].map, 0, sizeof(my_context->mmaplist[i].map));
|
||||
allocBlock(my_context->mmaplist+i, 0, bsize);
|
||||
@@ -139,32 +160,33 @@ void FreeDynarecMap(uintptr_t addr, uint32_t size)
|
||||
// each dynmap is 64k of size
|
||||
dynablocklist_t* getDBFromAddress(uintptr_t addr)
|
||||
{
|
||||
int idx = (addr>>16);
|
||||
int idx = (addr>>DYNAMAP_SHIFT);
|
||||
if(!my_context->dynmap[idx]) {
|
||||
return NULL;
|
||||
}
|
||||
return my_context->dynmap[idx]->dynablocks;
|
||||
}
|
||||
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
|
||||
uintptr_t idx = (addr>>16);
|
||||
uintptr_t end = ((addr+size-1)>>16);
|
||||
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
if(!my_context->dynmap[i]) {
|
||||
my_context->dynmap[i] = (dynmap_t*)calloc(1, sizeof(dynmap_t));
|
||||
my_context->dynmap[i]->dynablocks = NewDynablockList(i<<16, i<<16, 1<<16, 1, 0);
|
||||
my_context->dynmap[i]->dynablocks = NewDynablockList(i<<DYNAMAP_SHIFT, i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, nolinker, 0);
|
||||
} else {
|
||||
ProtectkDynablockList(&my_context->dynmap[i]->dynablocks);
|
||||
}
|
||||
}
|
||||
protectDB(addr, size);
|
||||
}
|
||||
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
|
||||
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>16):(addr>>16);
|
||||
uintptr_t end = ((addr+size-1)>>16);
|
||||
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>DYNAMAP_SHIFT):(addr>>DYNAMAP_SHIFT);
|
||||
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
|
||||
for (uintptr_t i=idx; i<=end; ++i) {
|
||||
dynmap_t* dynmap = my_context->dynmap[i];
|
||||
if(dynmap) {
|
||||
@@ -222,7 +244,7 @@ void initAllHelpers(box86context_t* context)
|
||||
return;
|
||||
my_context = context;
|
||||
init_pthread_helper();
|
||||
init_signal_helper();
|
||||
init_signal_helper(context);
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
@@ -234,6 +256,7 @@ void finiAllHelpers()
|
||||
return;
|
||||
fini_pthread_helper();
|
||||
fini_signal_helper();
|
||||
cleanAlternate();
|
||||
finied = 1;
|
||||
}
|
||||
|
||||
@@ -297,9 +320,14 @@ box86context_t *NewBox86Context(int argc)
|
||||
pthread_mutex_init(&context->mutex_once, NULL);
|
||||
pthread_mutex_init(&context->mutex_once2, NULL);
|
||||
pthread_mutex_init(&context->mutex_trace, NULL);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_lock, NULL);
|
||||
#endif
|
||||
pthread_mutex_init(&context->mutex_tls, NULL);
|
||||
pthread_mutex_init(&context->mutex_thread, NULL);
|
||||
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_init(&context->mutex_dyndump, NULL);
|
||||
#endif
|
||||
pthread_key_create(&context->tlskey, free_tlsdatasize);
|
||||
|
||||
#ifdef DYNAREC
|
||||
@@ -345,24 +373,6 @@ void FreeBox86Context(box86context_t** context)
|
||||
if(ctx->local_maplib)
|
||||
FreeLibrarian(&ctx->local_maplib);
|
||||
|
||||
#ifdef DYNAREC
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
if(ctx->dynablocks)
|
||||
FreeDynablockList(&ctx->dynablocks);
|
||||
for (int i=0; i<ctx->mmapsize; ++i)
|
||||
if(ctx->mmaplist[i].block)
|
||||
munmap(ctx->mmaplist[i].block, MMAPSIZE);
|
||||
free(ctx->mmaplist);
|
||||
pthread_mutex_destroy(&ctx->mutex_blocks);
|
||||
pthread_mutex_destroy(&ctx->mutex_mmap);
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
cleanDBFromAddressRange(0, 0xffffffff, 1);
|
||||
#endif
|
||||
|
||||
*context = NULL; // bye bye my_context
|
||||
|
||||
CleanStackSize(ctx);
|
||||
|
||||
FreeCollection(&ctx->box86_path);
|
||||
FreeCollection(&ctx->box86_ld_lib);
|
||||
FreeCollection(&ctx->box86_emulated_libs);
|
||||
@@ -375,6 +385,34 @@ void FreeBox86Context(box86context_t** context)
|
||||
if(ctx->deferedInitList)
|
||||
free(ctx->deferedInitList);
|
||||
|
||||
free(ctx->argv);
|
||||
|
||||
for (int i=0; i<ctx->envc; ++i)
|
||||
free(ctx->envv[i]);
|
||||
free(ctx->envv);
|
||||
|
||||
#ifdef DYNAREC
|
||||
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
|
||||
if(ctx->dynablocks)
|
||||
FreeDynablockList(&ctx->dynablocks);
|
||||
for (int i=0; i<ctx->mmapsize; ++i)
|
||||
if(ctx->mmaplist[i].block)
|
||||
#ifdef USE_MMAP
|
||||
munmap(ctx->mmaplist[i].block, MMAPSIZE);
|
||||
#else
|
||||
free(ctx->mmaplist[i].block);
|
||||
#endif
|
||||
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
|
||||
cleanDBFromAddressRange(0, 0xffffffff, 1);
|
||||
pthread_mutex_destroy(&ctx->mutex_blocks);
|
||||
pthread_mutex_destroy(&ctx->mutex_mmap);
|
||||
free(ctx->mmaplist);
|
||||
#endif
|
||||
|
||||
*context = NULL; // bye bye my_context
|
||||
|
||||
CleanStackSize(ctx);
|
||||
|
||||
#ifndef BUILD_LIB
|
||||
if(ctx->box86lib)
|
||||
dlclose(ctx->box86lib);
|
||||
@@ -382,12 +420,6 @@ void FreeBox86Context(box86context_t** context)
|
||||
|
||||
FreeDLPrivate(&ctx->dlprivate);
|
||||
|
||||
free(ctx->argv);
|
||||
|
||||
for (int i=0; i<ctx->envc; ++i)
|
||||
free(ctx->envv[i]);
|
||||
free(ctx->envv);
|
||||
|
||||
free(ctx->stack);
|
||||
|
||||
free(ctx->fullpath);
|
||||
@@ -420,8 +452,14 @@ void FreeBox86Context(box86context_t** context)
|
||||
pthread_mutex_destroy(&ctx->mutex_once);
|
||||
pthread_mutex_destroy(&ctx->mutex_once2);
|
||||
pthread_mutex_destroy(&ctx->mutex_trace);
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_lock);
|
||||
#endif
|
||||
pthread_mutex_destroy(&ctx->mutex_tls);
|
||||
pthread_mutex_destroy(&ctx->mutex_thread);
|
||||
#ifdef DYNAREC
|
||||
pthread_mutex_destroy(&ctx->mutex_dyndump);
|
||||
#endif
|
||||
|
||||
free_neededlib(&ctx->neededlibs);
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX86_MAJOR 0
|
||||
#define BOX86_MINOR 1
|
||||
#define BOX86_REVISION 2
|
||||
#define BOX86_REVISION 6
|
||||
|
||||
#endif //__BOX86_VERSION_H_
|
||||
+5
-6
@@ -1,11 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include "debug.h"
|
||||
#include "box86version.h"
|
||||
#ifdef NOGIT
|
||||
#define GITREV "nogit"
|
||||
#else
|
||||
#include "git_head.h"
|
||||
#endif
|
||||
|
||||
void PrintBox86Version()
|
||||
{
|
||||
printf("Box86%s%s%s v%d.%d.%d %s built on %s %s\n",
|
||||
printf("Box86%s%s v%d.%d.%d %s built on %s %s\n",
|
||||
#ifdef HAVE_TRACE
|
||||
" with trace",
|
||||
#else
|
||||
@@ -15,11 +19,6 @@ void PrintBox86Version()
|
||||
" with Dynarec",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
#ifdef USE_FLOAT
|
||||
" (float only)",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
BOX86_MAJOR, BOX86_MINOR, BOX86_REVISION,
|
||||
GITREV,
|
||||
|
||||
+101
-12
@@ -122,7 +122,7 @@ Op is 20-27
|
||||
#define SUB_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// sub cond dst, src, #(imm8)
|
||||
#define SUB_COND_IMM8(dst, src, imm8) \
|
||||
#define SUB_COND_IMM8(cond, dst, src, imm8) \
|
||||
EMIT((cond) | 0x02400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// sub.s dst, src, #(imm8)
|
||||
#define SUBS_IMM8(dst, src, imm8) \
|
||||
@@ -178,6 +178,9 @@ Op is 20-27
|
||||
// add dst, src, #(imm8)
|
||||
#define ADD_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// add dst, src, #imm8 ror rot*2
|
||||
#define ADD_IMM8_ROR(dst, src, imm8, rot) \
|
||||
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM((imm8)) )
|
||||
// add.s dst, src, #(imm8)
|
||||
#define ADDS_IMM8(dst, src, imm8) \
|
||||
EMIT(0xe2900000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
@@ -316,6 +319,8 @@ Op is 20-27
|
||||
|
||||
// str reg, [addr, #+/-imm9]
|
||||
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
// str with cond reg, [addr, #+/-imm9]
|
||||
#define STR_IMM9_COND(cond, reg, addr, imm9) EMIT(cond | 0x05000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
// strb reg, [addr, #+/-imm9]
|
||||
#define STRB_IMM9(reg, addr, imm9) EMIT(0xe5400000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
|
||||
// str reg, [addr], #+/-imm9
|
||||
@@ -382,8 +387,14 @@ Op is 20-27
|
||||
#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))
|
||||
|
||||
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
|
||||
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
|
||||
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
|
||||
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
|
||||
#define LDRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 1, addr, reg, 0, 1, abs(imm8)))
|
||||
#define LDRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
|
||||
#define STRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 0, addr, reg, 0, 1, abs(imm8)))
|
||||
#define STRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
|
||||
#define PUSH16(reg, addr) EMIT(HWS_OFF(c__, 1, 0, 1, 0, addr, reg, 0, 1, 2))
|
||||
#define POP16(reg, addr) EMIT(HWS_OFF(c__, 0, 1, 0, 1, addr, reg, 0, 1, 2))
|
||||
|
||||
// Mul Long construction
|
||||
#define MULLONG(Cond, U, A, S, RdHi, RdLo, Rs, Rm) (Cond | 0b00001<<23 | (U)<<22 | (A)<<21 | (S)<<20 | (RdHi)<<16 | (RdLo)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
|
||||
@@ -438,11 +449,33 @@ Op is 20-27
|
||||
|
||||
#define LDREXD_gen(cond, Rn, Rt) (cond | 0b000<<25 | 0b11011<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
|
||||
// Load Exclusive Rt/Rt+1 from Rn (tagging the memory)
|
||||
#define LDREXD(Rn, Rt) EMIT(LDREXD_gen(c__, Rn, Rt))
|
||||
#define LDREXD(Rt, Rn) EMIT(LDREXD_gen(c__, Rn, Rt))
|
||||
#define LDREXD_COND(cond, Rt, Rn) EMIT(LDREXD_gen(cond, Rn, Rt))
|
||||
|
||||
#define STREXD_gen(cond, Rd, Rn, Rt) (cond | 0b000<<25 | 0b11010<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
|
||||
// Store Exclusive Rt/Rt+1 to Rn, with result in Rd if tag is ok (Rd!=Rn && Rd!=Rt && Rd!=Rt+1), Rd==1 if store failed
|
||||
#define STREXD(Rd, Rn, Rt) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
|
||||
#define STREXD(Rd, Rt, Rn) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
|
||||
#define STREXD_COND(cond, Rd, Rt, Rn) EMIT(STREXD_gen(cond, Rd, Rn, Rt))
|
||||
|
||||
#define LDREX_gen(cond, Rn, Rt) (cond | 0b0001100<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
|
||||
// Load Exclusive Rt from Rn (tagging the memory)
|
||||
#define LDREX(Rt, Rn) EMIT(LDREX_gen(c__, Rn, Rt))
|
||||
#define LDREX_COND(cond, Rt, Rn) EMIT(LDREX_gen(cond, Rn, Rt))
|
||||
|
||||
#define STREX_gen(cond, Rd, Rn, Rt) (cond | 0b0001100<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
|
||||
// Store Exclusive Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
|
||||
#define STREX(Rd, Rt, Rn) EMIT(STREX_gen(c__, Rd, Rn, Rt))
|
||||
#define STREX_COND(cond, Rd, Rt, Rn) EMIT(STREX_gen(cond, Rd, Rn, Rt))
|
||||
|
||||
#define LDREXB_gen(cond, Rn, Rt) (cond | 0b0001110<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
|
||||
// Load Exclusive Byte Rt from Rn (tagging the memory)
|
||||
#define LDREXB(Rt, Rn) EMIT(LDREXB_gen(c__, Rn, Rt))
|
||||
#define LDREXB_COND(cond, Rt, Rn) EMIT(LDREXB_gen(cond, Rn, Rt))
|
||||
|
||||
#define STREXB_gen(cond, Rd, Rn, Rt) (cond | 0b0001110<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
|
||||
// Store Exclusive byte Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
|
||||
#define STREXB(Rd, Rt, Rn) EMIT(STREXB_gen(c__, Rd, Rn, Rt))
|
||||
#define STREXB_COND(cond, Rd, Rt, Rn) EMIT(STREXB_gen(cond, Rd, Rn, Rt))
|
||||
|
||||
// Count leading 0 bit of Rm, store result in Rd
|
||||
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
|
||||
@@ -469,6 +502,9 @@ Op is 20-27
|
||||
// Unsigned Div Rd <- Rn/Rm
|
||||
#define UDIV(Rd, Rm, Rn) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
|
||||
|
||||
// Yield
|
||||
#define YIELD(cond) EMIT(cond | 0b00110010<<20 | 0b1111<<12 | 1)
|
||||
|
||||
// VFPU
|
||||
#define TRANSFERT64(C, op) ((0b1100<<24) | (0b010<<21) | (0b101<<9) | ((C)<<8) | ((op)<<4))
|
||||
|
||||
@@ -553,9 +589,9 @@ Op is 20-27
|
||||
// Convert from int32 Sm to single Dd
|
||||
#define VCVT_F32_S32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b000<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
|
||||
|
||||
#define VCVT_16_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
|
||||
#define VCVT_FP_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
|
||||
// Inplace convert from F64 to S16. Rounding is not selectable
|
||||
#define VCVT_S16_F64(Dd) EMIT(VCVT_16_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
|
||||
#define VCVT_S16_F64(Dd) EMIT(VCVT_FP_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
|
||||
|
||||
// Mutiply F64 Dd = Dn*Dm
|
||||
#define VMUL_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b10<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
|
||||
@@ -658,16 +694,26 @@ Op is 20-27
|
||||
#define VEORQ(Dd, Dn, Dm) EMIT(VEOR_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VMOVL_gen(U, D, imm3, Vd, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm3)<<19 | (Vd)<<12 | 0b1010<<8 | (M)<<5 | 1<<4 | (Vm))
|
||||
#define VMOVL_S8(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMOVL_U8(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMOVL_S32(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VMOVL_U32(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VMOV_gen(D,Vd, M, Vm, Q) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | 0b10<<20 | (Vm)<<16 | (Vd)<<12 | 0b0001<<8 | (M)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
|
||||
#define VMOVD(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0))
|
||||
#define VMOVQ(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1))
|
||||
#define VMOVD(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0));}
|
||||
#define VMOVQ(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1));}
|
||||
|
||||
#define VMOV_igen(i, D, imm3, Vd, cmode, Q, op, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | (op)<<5 | 1<<4 | (imm4))
|
||||
#define VMOV_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 0, (imm)&15))
|
||||
#define VMOVQ_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 1, 0, (imm)&15))
|
||||
// Dd <= imm8 in high bits
|
||||
#define VMOV_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 0, 0, (imm8)&15))
|
||||
// Dd <= imm8 in high bits
|
||||
#define VMOV_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 0, 0, (imm8)&15))
|
||||
// Qd <= imm8 in high bits
|
||||
#define VMOVQ_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 1, 0, (imm8)&15))
|
||||
// Qd <= imm8 in high bits
|
||||
#define VMOVQ_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 1, 0, (imm8)&15))
|
||||
|
||||
#define VLD1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
|
||||
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
|
||||
@@ -732,6 +778,14 @@ Op is 20-27
|
||||
#define VCEQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VCEQ_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b010<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VCEQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCEQQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VCGT_I_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VCGT_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCGTQ_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
@@ -757,6 +811,15 @@ Op is 20-27
|
||||
#define VCGE_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCGEQ_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VCLT_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b100<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VCLT_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCLT_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCLT_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCLTQ_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCLTQ_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VCLTQ_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
|
||||
#define VSHR_gen(U, D, imm6, Vd, L, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | (L)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
|
||||
#define VSHR_U8(Dd, Dm, imm3) EMIT(VSHR_gen(1, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VSHR_S8(Dd, Dm, imm3) EMIT(VSHR_gen(0, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
@@ -803,6 +866,11 @@ Op is 20-27
|
||||
#define VSHLQ_S32(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VSHLQ_S64(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VSHRN_gen(D, imm6, Vd, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | 1<<11 | (M)<<5 | 1<<4 | (Vm))
|
||||
#define VSHRN_16(Dd, Dm, imm3) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VSHRN_32(Dd, Dm, imm4) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b01<<4 | (16-(imm4)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VSHRN_64(Dd, Dm, imm5) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b1<<5 | (32-(imm5)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VTRN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b10<<16 | (Vd)<<12 | 0b0000<<8 | 1<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VTRN_32(Dd, Dm) EMIT(VTRN_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
@@ -855,8 +923,8 @@ Op is 20-27
|
||||
#define VMUL_16(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VEXT_gen(D, Vn, Vd, imm4, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (Vn)<<16 | (Vd)<<12 | (imm4)<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4), ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4), ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VMVN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b1011<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
|
||||
#define VMVNQ(Dd, Dm) EMIT(VMVN_gen(((Dd)>>4)&1, 0, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
@@ -1062,7 +1130,7 @@ Op is 20-27
|
||||
|
||||
#define VPADD_Fgen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1101<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
|
||||
// Add pair of F32, store result in F32
|
||||
#define VPADD_F32(Dd, Dn, Dm) EMIT(VPADD_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VPADD_F32(Dd, Dn, Dm) EMIT(VPADD_Fgen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VMINMAX_gen(U, D, size, Vn, Vd, N, Q, M, op, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b110<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (op)<<4 | (Vm))
|
||||
#define VMIN_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
|
||||
@@ -1113,4 +1181,25 @@ Op is 20-27
|
||||
#define VRHADDQ_S16(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VRHADDQ_S32(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VQRDMULH_gen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011 <<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
// Dd <= (2*Dn*Dm + 1<<(size-1))>>size
|
||||
#define VQRDMULH_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VQRDMULH_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VQRDMULHQ_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VQRDMULHQ_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VDUP_sgen(D, imm4, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (imm4)<<16 | (Vd)<<12 | 0b1100<<8 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
// Dd <= Dup(Dm[x])
|
||||
#define VDUP_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#define VABS_vgen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b110<<7 | (Q)<<6 | (M)<<5 | (Vm))
|
||||
#define VABS_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABS_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABS_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABS_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABSQ_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABSQ_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
|
||||
|
||||
#endif //__ARM_EMITTER_H__
|
||||
@@ -89,10 +89,10 @@ NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
@@ -135,12 +135,12 @@ NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt>
|
||||
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
|
||||
|
||||
# Special case for VMOVL (harder to do it on the documented place)
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
|
||||
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
@@ -150,7 +150,7 @@ NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #
|
||||
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
|
||||
@@ -194,7 +194,7 @@ NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l si
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
|
||||
@@ -557,7 +557,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>,
|
||||
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
|
||||
|
||||
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
|
||||
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
//arm lock helper
|
||||
//there is 2 part: read and write
|
||||
// write return 0 on success, 1 on fail (value has been changed)
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
.global arm_lock_read_b
|
||||
.global arm_lock_write_b
|
||||
.global arm_lock_read_d
|
||||
.global arm_lock_write_d
|
||||
.global arm_lock_read_dd
|
||||
.global arm_lock_write_dd
|
||||
|
||||
arm_lock_read_b:
|
||||
// address is r0, return is r0
|
||||
ldrexb r0, [r0]
|
||||
bx lr
|
||||
|
||||
arm_lock_write_b:
|
||||
// address is r0, value is r1, return is r0
|
||||
mov r2, r0
|
||||
strexb r0, r1, [r2]
|
||||
bx lr
|
||||
|
||||
arm_lock_read_d:
|
||||
// address is r0, return is r0
|
||||
// r0 needs to be aligned
|
||||
ldrex r0, [r0]
|
||||
bx lr
|
||||
|
||||
arm_lock_write_d:
|
||||
// address is r0, value is r1, return is r0
|
||||
// r0 needs to be aligned
|
||||
mov r2, r0
|
||||
strex r0, r1, [r2]
|
||||
bx lr
|
||||
|
||||
arm_lock_read_dd:
|
||||
// address is r2, return is r0, r1
|
||||
ldrexd r2, r3, [r2]
|
||||
str r2, [r0]
|
||||
str r3, [r1]
|
||||
bx lr
|
||||
|
||||
arm_lock_write_dd:
|
||||
// address is r2, value is r0, r1, return is r0
|
||||
// r0 needs to be aligned
|
||||
strexd r3, r0, r1, [r2]
|
||||
mov r0, r3
|
||||
bx lr
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#ifndef __ARM_LOCK_HELPER__H__
|
||||
#define __ARM_LOCK_HELPER__H__
|
||||
#include <stdint.h>
|
||||
|
||||
// LDREXB of ADDR
|
||||
extern uint8_t arm_lock_read_b(void* addr);
|
||||
// STREXB of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm_lock_write_b(void* addr, uint8_t val);
|
||||
|
||||
// LDREX of ADDR
|
||||
extern uint32_t arm_lock_read_d(void* addr);
|
||||
// STREX of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm_lock_write_d(void* addr, uint32_t val);
|
||||
|
||||
// LDREXD of ADDR
|
||||
extern void arm_lock_read_dd(uint32_t* a, uint32_t* b, void* addr);
|
||||
// STREX of ADDR, return 0 if ok, 1 if not
|
||||
extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
|
||||
|
||||
#endif //__ARM_LOCK_HELPER__H__
|
||||
+28
-27
@@ -96,7 +96,7 @@ const char* print_shift(int shift, int comma) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (imm12 >> 8)) | ((imm12 & 0xFF) << (32 - (imm12 >> 8))))
|
||||
#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;
|
||||
@@ -396,7 +396,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
|
||||
sprintf(ret, "VSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
|
||||
} else if ((opcode & 0xFE800F10) == 0xF2000410) {
|
||||
int u = (opcode >> 24) & 1;
|
||||
int size = (opcode >> 20) & 0x3;
|
||||
@@ -405,7 +405,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VQSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
|
||||
sprintf(ret, "VQSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
|
||||
} else if ((opcode & 0xFE800F10) == 0xF2000500) {
|
||||
int u = (opcode >> 24) & 1;
|
||||
int size = (opcode >> 20) & 0x3;
|
||||
@@ -414,7 +414,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
|
||||
sprintf(ret, "VRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
|
||||
} else if ((opcode & 0xFE800F10) == 0xF2000510) {
|
||||
int u = (opcode >> 24) & 1;
|
||||
int size = (opcode >> 20) & 0x3;
|
||||
@@ -423,7 +423,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int n = ((opcode >> 7) & 1) << 4 | ((opcode >> 16) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VQRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + n], vecname[(q << 5) + 0x20 + m]);
|
||||
sprintf(ret, "VQRSHL.%s %s, %s, %s", dts[(u << 2) + size], vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m], vecname[(q << 5) + 0x20 + n]);
|
||||
} else if ((opcode & 0xFE800F00) == 0xF2000600) {
|
||||
int op = (opcode >> 4) & 1;
|
||||
int u = (opcode >> 24) & 1;
|
||||
@@ -797,38 +797,38 @@ const char* arm_print(uint32_t opcode) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.S8 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.S8 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFFBF0FD0) == 0xF2900A10) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.S16 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.S16 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFFBF0FD0) == 0xF2A00A10) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.S32 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.S32 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFFBF0FD0) == 0xF3880A10) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.U8 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.U8 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFFBF0FD0) == 0xF3900A10) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.U16 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.U16 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFFBF0FD0) == 0xF3A00A10) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
sprintf(ret, "VMOVL.U32 %s, %s", vecname[0x40 + d], vecname[0x40 + m]);
|
||||
sprintf(ret, "VMOVL.U32 %s, %s", vecname[0x40 + d], vecname[0x20 + m]);
|
||||
} else if ((opcode & 0xFE800F10) == 0xF2800010) {
|
||||
int u = (opcode >> 24) & 1;
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -851,7 +851,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -874,7 +874,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -897,7 +897,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -919,7 +919,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -941,7 +941,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -963,7 +963,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -987,7 +987,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int q = (opcode >> 6) & 1;
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
uint8_t l = (opcode >> 1) & 0x1;
|
||||
uint8_t l = (opcode >> 7) & 0x1;
|
||||
uint8_t imm6 = (opcode >> 16) & 0x3F;
|
||||
uint8_t decodedImm = 0;
|
||||
uint8_t size = 0;
|
||||
@@ -1021,6 +1021,8 @@ const char* arm_print(uint32_t opcode) {
|
||||
decodedImm = 16 - imm6;
|
||||
}
|
||||
|
||||
++size;
|
||||
|
||||
sprintf(ret, "VSHRN.I%d %s, %s, #%d", 8 << size, vecname[0x20 + d], vecname[0x40 + m], decodedImm);
|
||||
} else if ((opcode & 0xFF800FD0) == 0xF2800850) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
@@ -1316,7 +1318,6 @@ const char* arm_print(uint32_t opcode) {
|
||||
int d = ((opcode >> 22) & 1) << 4 | ((opcode >> 12) & 0xF);
|
||||
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
|
||||
|
||||
u = 1 - u;
|
||||
++size;
|
||||
|
||||
sprintf(ret, "VQMOVN.%s %s, %s", dts[(u << 2) + size], vecname[0x20 + d], vecname[0x40 + m]);
|
||||
@@ -4446,24 +4447,24 @@ const char* arm_print(uint32_t opcode) {
|
||||
} else if ((opcode & 0x0FE0007F) == 0x07C0001F) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rd = (opcode >> 12) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0xF;
|
||||
int msb = (opcode >> 16) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0x1F;
|
||||
int msb = (opcode >> 16) & 0x1F;
|
||||
|
||||
sprintf(ret, "BFC%s %s, #%d, #%d", cond, regname[rd], lsb, msb - lsb + 1);
|
||||
} else if ((opcode & 0x0FE00070) == 0x07C00010) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rd = (opcode >> 12) & 0xF;
|
||||
int rn = (opcode >> 0) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0xF;
|
||||
int msb = (opcode >> 16) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0x1F;
|
||||
int msb = (opcode >> 16) & 0x1F;
|
||||
|
||||
sprintf(ret, "BFI%s %s, %s, #%d, #%d", cond, regname[rd], regname[rn], lsb, msb - lsb + 1);
|
||||
} else if ((opcode & 0x0FE00070) == 0x07E00050) {
|
||||
const char* cond = conds[(opcode >> 28) & 0xF];
|
||||
int rd = (opcode >> 12) & 0xF;
|
||||
int rn = (opcode >> 0) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0xF;
|
||||
int widthm1 = (opcode >> 16) & 0xF;
|
||||
int lsb = (opcode >> 7) & 0x1F;
|
||||
int widthm1 = (opcode >> 16) & 0x1F;
|
||||
|
||||
sprintf(ret, "UBFX%s %s, %s, #%d, #%d", cond, regname[rd], regname[rn], lsb, widthm1 + 1);
|
||||
} else if ((opcode & 0x0FDF0000) == 0x080D0000) {
|
||||
@@ -4826,7 +4827,7 @@ const char* arm_print(uint32_t opcode) {
|
||||
int param1_2 = (opcode >> 21) & 0x3;
|
||||
int param2_2 = (opcode >> 5) & 0x3;
|
||||
|
||||
uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2;
|
||||
uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2;
|
||||
uint8_t shift, size;
|
||||
if ((opc & 0b01000) == 0b01000) {
|
||||
shift = 0;
|
||||
|
||||
+162
-67
@@ -68,14 +68,6 @@ void FreeDynablock(dynablock_t* db)
|
||||
if(addr>=startdb && addr<enddb)
|
||||
db->parent->direct[addr-startdb] = NULL;
|
||||
}
|
||||
// remove from hash if there
|
||||
if (db->parent->blocks) {
|
||||
khint_t kdb;
|
||||
kdb = kh_get(dynablocks, db->parent->blocks, (uintptr_t) db->x86_addr - db->parent->base);
|
||||
if(kdb!=kh_end(db->parent->blocks))
|
||||
kh_del(dynablocks, db->parent->blocks, kdb);
|
||||
}
|
||||
|
||||
if(db->marks) {
|
||||
// Follow mark and set arm_linker instead
|
||||
khint_t k;
|
||||
@@ -101,6 +93,15 @@ void FreeDynablock(dynablock_t* db)
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "\n");
|
||||
}
|
||||
// remove from hash if there
|
||||
if (db->parent->blocks) {
|
||||
pthread_rwlock_wrlock(&db->parent->rwlock_blocks);
|
||||
khint_t kdb;
|
||||
kdb = kh_get(dynablocks, db->parent->blocks, (uintptr_t) db->x86_addr - db->parent->base);
|
||||
if(kdb!=kh_end(db->parent->blocks))
|
||||
kh_del(dynablocks, db->parent->blocks, kdb);
|
||||
pthread_rwlock_unlock(&db->parent->rwlock_blocks);
|
||||
}
|
||||
// remove and free the sons
|
||||
for (int i=0; i<db->sons_size; ++i) {
|
||||
dynablock_t *son = db->sons[i];
|
||||
@@ -124,7 +125,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
return;
|
||||
if(!*dynablocks)
|
||||
return;
|
||||
dynarec_log(LOG_INFO, "Free %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %s\n", (*dynablocks)->blocks?kh_size((*dynablocks)->blocks):0, (*dynablocks)->blocks?kh_n_buckets((*dynablocks)->blocks):0, (*dynablocks)->nolinker, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
|
||||
dynarec_log(LOG_DEBUG, "Free %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %s\n", (*dynablocks)->blocks?kh_size((*dynablocks)->blocks):0, (*dynablocks)->blocks?kh_n_buckets((*dynablocks)->blocks):0, (*dynablocks)->nolinker, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
|
||||
dynablock_t* db;
|
||||
if((*dynablocks)->blocks) {
|
||||
// create a list of the parent db to delete (because there are sons in the middle that will be invalid if father is removed)
|
||||
@@ -147,7 +148,6 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
|
||||
free((*dynablocks)->direct);
|
||||
}
|
||||
(*dynablocks)->direct = 0;
|
||||
|
||||
pthread_rwlock_destroy(&(*dynablocks)->rwlock_blocks);
|
||||
|
||||
free(*dynablocks);
|
||||
@@ -225,6 +225,8 @@ void MarkDynablockList(dynablocklist_t** dynablocks)
|
||||
return;
|
||||
if(!*dynablocks)
|
||||
return;
|
||||
if(!(*dynablocks)->nolinker)
|
||||
return;
|
||||
dynarec_log(LOG_DEBUG, "Marked %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
|
||||
dynablock_t* db;
|
||||
if((*dynablocks)->blocks) {
|
||||
@@ -271,28 +273,12 @@ uintptr_t EndDynablockList(dynablocklist_t* db)
|
||||
return db->text+db->textsz;
|
||||
return 0;
|
||||
}
|
||||
void FreeDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i)
|
||||
if(dynablocks->direct[i-startdb]) {
|
||||
FreeDynablock(dynablocks->direct[i-startdb]);
|
||||
}
|
||||
}
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!dynablocks->nolinker)
|
||||
return;
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
@@ -328,23 +314,59 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(dynablocks->direct)
|
||||
FreeDirectDynablock(dynablocks, addr, size);
|
||||
if(dynablocks->blocks) {
|
||||
|
||||
if(dynablocks->blocks || dynablocks->direct) {
|
||||
dynablock_t* db;
|
||||
uintptr_t s, e;
|
||||
kh_foreach_value(dynablocks->blocks, db,
|
||||
s = (uintptr_t)db->x86_addr;
|
||||
e = (uintptr_t)db->x86_addr+db->x86_size-1;
|
||||
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
|
||||
ProtectDynablock(db);
|
||||
int ret;
|
||||
khint_t k;
|
||||
kh_dynablocks_t *blocks = kh_init(dynablocks);
|
||||
// copy in a temporary list
|
||||
if(dynablocks->blocks) {
|
||||
kh_foreach_value(dynablocks->blocks, db,
|
||||
if(db->father)
|
||||
db =db->father;
|
||||
s = (uintptr_t)db->x86_addr;
|
||||
e = (uintptr_t)db->x86_addr+db->x86_size-1;
|
||||
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size))) {
|
||||
//ProtectDynablock(db);
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
);
|
||||
}
|
||||
if(dynablocks->direct) {
|
||||
uintptr_t startdb = dynablocks->text;
|
||||
uintptr_t enddb = startdb + dynablocks->textsz;
|
||||
uintptr_t start = addr;
|
||||
uintptr_t end = addr+size;
|
||||
if(start<startdb)
|
||||
start = startdb;
|
||||
if(end>enddb)
|
||||
end = enddb;
|
||||
if(end>startdb && start<enddb)
|
||||
for(uintptr_t i = start; i<end; ++i)
|
||||
if(dynablocks->direct[i-startdb]) {
|
||||
db = dynablocks->direct[i-startdb];
|
||||
if(db->father)
|
||||
db =db->father;
|
||||
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
|
||||
kh_value(blocks, k) = db;
|
||||
}
|
||||
}
|
||||
// purge the list
|
||||
kh_foreach_value(blocks, db,
|
||||
FreeDynablock(db);
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
}
|
||||
}
|
||||
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!dynablocks)
|
||||
return;
|
||||
if(!dynablocks->nolinker)
|
||||
return;
|
||||
if(dynablocks->direct)
|
||||
MarkDirectDynablock(dynablocks, addr, size);
|
||||
if(dynablocks->blocks) {
|
||||
@@ -365,11 +387,11 @@ dynablock_t* FindDynablockDynablocklist(void* addr, dynablocklist_t* dynablocks)
|
||||
return NULL;
|
||||
if(dynablocks->direct)
|
||||
for(int i=0; i<dynablocks->textsz; ++i) {
|
||||
if(dynablocks->direct[i]) {
|
||||
dynablock_t* db = dynablocks->direct[i];
|
||||
dynablock_t* db;
|
||||
if((db = dynablocks->direct[i])) {
|
||||
uintptr_t s = (uintptr_t)db->block;
|
||||
uintptr_t e = (uintptr_t)db->block+db->size;
|
||||
if(s>=(uintptr_t)addr && e<(uintptr_t)addr)
|
||||
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
|
||||
return db->father?db->father:db;
|
||||
}
|
||||
}
|
||||
@@ -391,14 +413,11 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr)
|
||||
// unoptimized search through all dynablockslist for the dynablock that contains native addr (NULL if not found)
|
||||
// search "volatile" dynarec first
|
||||
dynablock_t *ret = NULL;
|
||||
for(int idx=0; idx<65536 && !ret; ++idx)
|
||||
for(int idx=0; idx<DYNAMAP_SIZE && !ret; ++idx)
|
||||
if(my_context->dynmap[idx])
|
||||
ret = FindDynablockDynablocklist(addr, my_context->dynmap[idx]->dynablocks);
|
||||
if(ret)
|
||||
return ret;
|
||||
// search elfs
|
||||
for(int idx=0; idx<my_context->elfsize && !ret; ++idx)
|
||||
ret = FindDynablockDynablocklist(addr, GetDynablocksFromElf(my_context->elfs[idx]));
|
||||
// last, search context dynablocks
|
||||
if(my_context->dynablocks)
|
||||
ret = FindDynablockDynablocklist(addr, my_context->dynablocks);
|
||||
@@ -432,11 +451,55 @@ void ConvertHash2Direct(dynablocklist_t* dynablocks)
|
||||
);
|
||||
// destroy old and do the swap (should swap before destroy, but hash access is always behind mutex)
|
||||
kh_destroy(dynablocks, dynablocks->blocks);
|
||||
dynablocks->blocks = blocks;
|
||||
dynablocks->blocks = NULL;
|
||||
dynablocks->direct = direct;
|
||||
// move the one that doesn't fit to other dynablocks
|
||||
// first check if everything can be moved
|
||||
int ok = 1;
|
||||
kh_foreach(blocks, key, db,
|
||||
key += dynablocks->base;
|
||||
dynablocklist_t *newdbs = getDBFromAddress(key); // will crash if no dynablocks is found
|
||||
if(!newdbs)
|
||||
ok = 0;
|
||||
else {
|
||||
if(newdbs->direct) {
|
||||
if(newdbs->direct[key-newdbs->text])
|
||||
ok = 0;
|
||||
} else {
|
||||
khint_t k;
|
||||
pthread_rwlock_rdlock(&newdbs->rwlock_blocks);
|
||||
k = kh_get(dynablocks, newdbs->blocks, key-newdbs->base);
|
||||
if(k!=kh_end(newdbs->blocks))
|
||||
ok = 0;
|
||||
pthread_rwlock_unlock(&newdbs->rwlock_blocks);
|
||||
}
|
||||
}
|
||||
);
|
||||
if(ok) {
|
||||
kh_foreach(blocks, key, db,
|
||||
key += dynablocks->base;
|
||||
dynablocklist_t *newdbs = getDBFromAddress(key); // will crash if no dynablocks is found
|
||||
if(newdbs->direct) {
|
||||
newdbs->direct[key-newdbs->text] = db;
|
||||
} else {
|
||||
khint_t k;
|
||||
int ret;
|
||||
pthread_rwlock_wrlock(&newdbs->rwlock_blocks);
|
||||
k = kh_put(dynablocks, newdbs->blocks, key-newdbs->base, &ret);
|
||||
kh_value(newdbs->blocks, k) = db;
|
||||
pthread_rwlock_unlock(&newdbs->rwlock_blocks);
|
||||
}
|
||||
);
|
||||
kh_destroy(dynablocks, blocks);
|
||||
} else {
|
||||
dynablocks->blocks = blocks;
|
||||
dynarec_log(LOG_DEBUG, "Cannot convert dynablocks(%p) to pure direct\n", (void*)dynablocks->text);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAGIC_SIZE 256
|
||||
// a block is 4096 byte, so get a low magic size or no block will get "direct" treatment
|
||||
#define MAGIC_SIZE 8
|
||||
#define MAGIC_SIZE2 16
|
||||
|
||||
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created)
|
||||
{
|
||||
@@ -460,15 +523,18 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
|
||||
|
||||
if(dynablocks->blocks) {
|
||||
pthread_rwlock_rdlock(&dynablocks->rwlock_blocks);
|
||||
// check if the block exist
|
||||
khint_t k;
|
||||
k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
|
||||
if(k!=kh_end(dynablocks->blocks)) {
|
||||
block = kh_value(dynablocks->blocks, k);
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
// check again, in case it's been converted to direct in another thread
|
||||
if(dynablocks->blocks) {
|
||||
// check if the block exist
|
||||
khint_t k;
|
||||
k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
|
||||
if(k!=kh_end(dynablocks->blocks)) {
|
||||
block = kh_value(dynablocks->blocks, k);
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
}
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
}
|
||||
@@ -476,14 +542,19 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
|
||||
return block;
|
||||
|
||||
// Lock as write now!
|
||||
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
|
||||
int need_unlock = 0;
|
||||
if(dynablocks->blocks) {
|
||||
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
|
||||
need_unlock = 1;
|
||||
}
|
||||
// create and add new block
|
||||
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
|
||||
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
|
||||
block = dynablocks->direct[addr-dynablocks->text] = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
} else {
|
||||
if(dynablocks->nolinker && ((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz)))) {
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
if(dynablocks->textsz && ((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz)))) {
|
||||
if(need_unlock)
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
|
||||
//*created = 0;
|
||||
//return NULL;
|
||||
@@ -494,13 +565,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
|
||||
// Ooops, block is already there? retreive it and bail out
|
||||
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
|
||||
block = kh_value(dynablocks->blocks, k);
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
if(need_unlock)
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
*created = 0;
|
||||
return block;
|
||||
}
|
||||
block = kh_value(dynablocks->blocks, k) = (dynablock_t*)calloc(1, sizeof(dynablock_t));
|
||||
// check if size of hash map == magic size, if yes, convert to direct before unlocking
|
||||
if(!dynablocks->direct && kh_size(dynablocks->blocks)==MAGIC_SIZE)
|
||||
if(!dynablocks->direct && dynablocks->textsz && kh_size(dynablocks->blocks)>=MAGIC_SIZE && kh_size(dynablocks->blocks)<(MAGIC_SIZE2))
|
||||
ConvertHash2Direct(dynablocks);
|
||||
}
|
||||
block->parent = dynablocks;
|
||||
@@ -509,7 +581,8 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
|
||||
block->marks = kh_init(mark);
|
||||
|
||||
// create an empty block first, so if other thread want to execute the same block, they can, but using interpretor path
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
if(need_unlock)
|
||||
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
|
||||
|
||||
*created = 1;
|
||||
return block;
|
||||
@@ -519,7 +592,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
*/
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t* current)
|
||||
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
|
||||
{
|
||||
// try the quickest way first: get parent of current and check if ok!
|
||||
dynablocklist_t *dynablocks = NULL;
|
||||
@@ -551,12 +624,12 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, int create
|
||||
return block; // existing block...
|
||||
|
||||
if(box86_dynarec_dump)
|
||||
pthread_mutex_lock(&my_context->mutex_lock);
|
||||
pthread_mutex_lock(&my_context->mutex_dyndump);
|
||||
// fill the block
|
||||
block->x86_addr = (void*)addr;
|
||||
FillBlock(block);
|
||||
FillBlock(block, filladdr);
|
||||
if(box86_dynarec_dump)
|
||||
pthread_mutex_unlock(&my_context->mutex_lock);
|
||||
pthread_mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, %swith %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+block->x86_size), block->block, block->size, block->marks?"with Marks, ":"", block->sons_size);
|
||||
|
||||
@@ -565,10 +638,10 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, int create
|
||||
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
|
||||
{
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, create, *current);
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
|
||||
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X)%s with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->marks?" with Mark,":"", father->sons_size);
|
||||
// no more current if it gets invalidated too
|
||||
@@ -577,7 +650,29 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, create, *current);
|
||||
db = internalDBGetBlock(emu, addr, addr, create, *current);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
}
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
|
||||
{
|
||||
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
|
||||
int create = 1;
|
||||
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
if(db && (db->need_test || (db->father && db->father->need_test))) {
|
||||
dynablock_t *father = db->father?db->father:db;
|
||||
uint32_t hash = father->nolinker?X31_hash_code(father->x86_addr, father->x86_size):0;
|
||||
if(hash!=father->hash) {
|
||||
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X)%s with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->marks?" with Mark,":"", father->sons_size);
|
||||
// Free father, it's now invalid!
|
||||
FreeDynablock(father);
|
||||
// start again... (will create a new block)
|
||||
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
|
||||
} else {
|
||||
father->need_test = 0;
|
||||
protectDB((uintptr_t)father->x86_addr, father->x86_size);
|
||||
|
||||
@@ -5,6 +5,14 @@ typedef struct dynablocklist_s dynablocklist_t;
|
||||
typedef struct kh_dynablocks_s kh_dynablocks_t;
|
||||
typedef struct kh_mark_s kh_mark_t;
|
||||
|
||||
typedef union instsize_s {
|
||||
uint8_t c;
|
||||
struct {
|
||||
unsigned int x86:4;
|
||||
unsigned int nat:4;
|
||||
};
|
||||
} instsize_t;
|
||||
|
||||
typedef struct dynablock_s {
|
||||
dynablocklist_t* parent;
|
||||
kh_mark_t* marks; // List of blocks that marked this block
|
||||
@@ -21,6 +29,8 @@ typedef struct dynablock_s {
|
||||
dynablock_t** sons; // sons (kind-of dummy dynablock...)
|
||||
int sons_size;
|
||||
dynablock_t* father; // set only in the case of a son
|
||||
int nolinker;
|
||||
instsize_t *instsize;
|
||||
} dynablock_t;
|
||||
|
||||
typedef struct dynablocklist_s {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86context.h"
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "callback.h"
|
||||
#include "emu/x86run_private.h"
|
||||
#include "x86trace.h"
|
||||
#include "threads.h"
|
||||
#ifdef DYNAREC
|
||||
#include "dynablock.h"
|
||||
#include "dynablock_private.h"
|
||||
@@ -92,6 +94,21 @@ void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
|
||||
|
||||
void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
emu_jmpbuf_t *ejb = NULL;
|
||||
int jmpbuf_reset = 0;
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
if(!ejb->jmpbuf_ok) {
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_EIP; // not sure if it should still be inside DynaCall!
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box86_dynarec)
|
||||
#endif
|
||||
@@ -130,6 +147,16 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x86emu_fork(emu, forktype);
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
addr = R_EIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emu->quit = 0; // reset Quit flags...
|
||||
@@ -146,10 +173,26 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// clear the setjmp
|
||||
if(ejb && jmpbuf_reset)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
}
|
||||
|
||||
int DynaRun(x86emu_t* emu)
|
||||
{
|
||||
// prepare setjump for signal handling
|
||||
emu_jmpbuf_t *ejb = NULL;
|
||||
int jmpbuf_reset = 1;
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
if(!ejb->jmpbuf_ok) {
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(!box86_dynarec)
|
||||
#endif
|
||||
@@ -178,9 +221,20 @@ int DynaRun(x86emu_t* emu)
|
||||
emu->quit = 0;
|
||||
emu->fork = 0;
|
||||
emu = x86emu_fork(emu, forktype);
|
||||
if(emu->type == EMUTYPE_MAIN) {
|
||||
ejb = GetJmpBuf();
|
||||
ejb->emu = emu;
|
||||
ejb->jmpbuf_ok = 1;
|
||||
jmpbuf_reset = 1;
|
||||
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
|
||||
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear the setjmp
|
||||
if(ejb && jmpbuf_reset)
|
||||
ejb->jmpbuf_ok = 0;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -114,8 +114,11 @@ int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
|
||||
|
||||
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
|
||||
{
|
||||
if(ninst == dyn->size || (recurse==5))
|
||||
return X_ALL; // no more instructions, or too many jmp loop, stop
|
||||
if(recurse == 10)
|
||||
return X_PEND;
|
||||
if(ninst == dyn->size)
|
||||
return X_PEND; // no more instructions, or too many jmp loop, stop
|
||||
|
||||
uint32_t needed = dyn->insts[ninst].x86.use_flags;
|
||||
if(needed) {
|
||||
setf &= ~needed;
|
||||
@@ -156,14 +159,44 @@ uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
|
||||
return needed;
|
||||
}
|
||||
|
||||
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
|
||||
{
|
||||
// x86 instruction is <16 bytes anyway
|
||||
if(!x86_size && !arm_size)
|
||||
return insts;
|
||||
int toadd;
|
||||
if(x86_size>arm_size)
|
||||
toadd = 1 + x86_size/15;
|
||||
else
|
||||
toadd = 1 + arm_size/15;
|
||||
if(*size+toadd>*cap) {
|
||||
*cap = *size+toadd;
|
||||
insts = (instsize_t*)realloc(insts, *cap*sizeof(instsize_t));
|
||||
}
|
||||
while(toadd) {
|
||||
if(x86_size>15)
|
||||
insts[*size].x86 = 15;
|
||||
else
|
||||
insts[*size].x86 = x86_size;
|
||||
x86_size -= insts[*size].x86;
|
||||
if(arm_size>15)
|
||||
insts[*size].nat = 15;
|
||||
else
|
||||
insts[*size].nat = arm_size;
|
||||
arm_size -= insts[*size].nat;
|
||||
++(*size);
|
||||
--toadd;
|
||||
}
|
||||
return insts;
|
||||
}
|
||||
|
||||
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
|
||||
|
||||
void* FillBlock(dynablock_t* block) {
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr) {
|
||||
// init the helper
|
||||
uintptr_t addr = (uintptr_t)block->x86_addr;
|
||||
dynarec_arm_t helper = {0};
|
||||
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
|
||||
helper.start = addr;
|
||||
@@ -232,9 +265,30 @@ void* FillBlock(dynablock_t* block) {
|
||||
}
|
||||
helper.arm_size = 0;
|
||||
arm_pass3(&helper, addr);
|
||||
if(sz!=helper.arm_size) {printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);}
|
||||
if(sz!=helper.arm_size) {
|
||||
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
|
||||
uint8_t *dump = (uint8_t*)helper.start;
|
||||
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
|
||||
for(int i=0; i<helper.size; ++i) {
|
||||
printf_log(LOG_NONE, "%p:", dump);
|
||||
for(; dump<(uint8_t*)helper.insts[i+1].x86.addr; ++dump)
|
||||
printf_log(LOG_NONE, " %02X", *dump);
|
||||
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
|
||||
}
|
||||
printf_log(LOG_NONE, " ------------\n");
|
||||
}
|
||||
// all done...
|
||||
__builtin___clear_cache(p, p+sz); // need to clear the cache before execution...
|
||||
__clear_cache(p, p+sz); // need to clear the cache before execution...
|
||||
// keep size of instructions for signal handling
|
||||
{
|
||||
size_t cap = helper.size+1;
|
||||
size_t size = 0;
|
||||
block->instsize = (instsize_t*)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);
|
||||
addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
|
||||
}
|
||||
// ok, free the helper now
|
||||
free(helper.insts);
|
||||
free(helper.next);
|
||||
block->table = helper.table;
|
||||
@@ -244,8 +298,9 @@ void* FillBlock(dynablock_t* block) {
|
||||
block->size = sz;
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->nolinker = helper.nolinker;
|
||||
block->need_test = 0;
|
||||
block->x86_addr = (void*)start;
|
||||
//block->x86_addr = (void*)start;
|
||||
block->x86_size = end-start;
|
||||
if(box86_dynarec_largest<block->x86_size)
|
||||
box86_dynarec_largest = block->x86_size;
|
||||
|
||||
+187
-115
@@ -23,15 +23,12 @@
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
|
||||
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop, opcode;
|
||||
uintptr_t natcall;
|
||||
int retn;
|
||||
uint8_t gd, ed;
|
||||
int8_t i8;
|
||||
int32_t i32, tmp;
|
||||
int32_t i32, j32, tmp;
|
||||
uint8_t u8;
|
||||
uint8_t gb1, gb2, eb1, eb2;
|
||||
uint32_t u32;
|
||||
@@ -42,6 +39,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(tmp);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
@@ -590,15 +588,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOV_REG(x1, xESP);
|
||||
// cannot use PUSH (STMdb!) because order of regs are reversed!
|
||||
//PUSH(x1, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI));
|
||||
PUSH(x1, (1<<xEAX));
|
||||
PUSH(x1, (1<<xECX));
|
||||
PUSH(x1, (1<<xEDX));
|
||||
PUSH(x1, (1<<xEBX));
|
||||
PUSH(x1, (1<<xESP));
|
||||
PUSH(x1, (1<<xEBP));
|
||||
PUSH(x1, (1<<xESI));
|
||||
PUSH(x1, (1<<xEDI));
|
||||
MOV_REG(xESP, x1);
|
||||
PUSH(xESP, (1<<xEAX));
|
||||
PUSH(xESP, (1<<xECX));
|
||||
PUSH(xESP, (1<<xEDX));
|
||||
PUSH(xESP, (1<<xEBX));
|
||||
PUSH(xESP, (1<<x1));
|
||||
PUSH(xESP, (1<<xEBP));
|
||||
PUSH(xESP, (1<<xESI));
|
||||
PUSH(xESP, (1<<xEDI));
|
||||
break;
|
||||
case 0x61:
|
||||
INST_NAME("POPAD");
|
||||
@@ -636,8 +633,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x68:
|
||||
INST_NAME("PUSH Id");
|
||||
i32 = F32S;
|
||||
MOV32(x3, i32);
|
||||
PUSH(xESP, 1<<x3);
|
||||
if(PK(0)==0xC3) {
|
||||
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
|
||||
MOV32(x3, ip+1);
|
||||
LDR_IMM9(x1, x3, 0);
|
||||
PUSH(xESP, 1<<x1);
|
||||
} else {
|
||||
MOV32(x3, i32);
|
||||
PUSH(xESP, 1<<x3);
|
||||
}
|
||||
break;
|
||||
case 0x69:
|
||||
INST_NAME("IMUL Gd, Ed, Id");
|
||||
@@ -1001,25 +1005,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(gb1, x1, gb2*8, 8);
|
||||
BFI(eb1, x12, eb2*8, 8);
|
||||
} else {
|
||||
if(0/*arm_swap*/) {
|
||||
// use atomic swap...
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
GETGB(x12);
|
||||
SWPB(x12, x12, ed);
|
||||
BFI(gb1, x12, gb2*8, 8);
|
||||
} else {
|
||||
// Lock
|
||||
LOCK;
|
||||
// do the swap
|
||||
GETGB(x12);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0);
|
||||
LDRB_IMM9(x1, ed, fixedaddress); // 1 gets eb
|
||||
// do the swap 12 -> strb(ed), 1 -> gd
|
||||
BFI(gb1, x1, gb2*8, 8);
|
||||
STRB_IMM9(x12, ed, fixedaddress);
|
||||
// Unlock
|
||||
UNLOCK;
|
||||
}
|
||||
GETGB(x12);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
// do the swap with exclusive locking
|
||||
LDREXB(x1, ed);
|
||||
// do the swap 12 -> strb(ed), 1 -> gd
|
||||
STREXB(x3, x12, ed);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
BFI(gb1, x1, gb2*8, 8);
|
||||
}
|
||||
break;
|
||||
case 0x87:
|
||||
@@ -1034,24 +1029,21 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
|
||||
}
|
||||
} else {
|
||||
if(0/*arm_swap*/) { // swap doesn't seem to really work like that, plus there seems to be alignement need on arm7
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
// use atomic swap
|
||||
SWP(gd, gd, ed);
|
||||
} else {
|
||||
LOCK;
|
||||
GETGD;
|
||||
GETED;
|
||||
// xor swap to avoid one more tmp reg
|
||||
if(gd!=ed) {
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
|
||||
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
|
||||
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
|
||||
}
|
||||
WBACK;
|
||||
UNLOCK;
|
||||
}
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
TSTS_IMM8(ed, 3);
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDREX(x1, ed);
|
||||
STREX(x3, gd, ed);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
B_MARK2(c__);
|
||||
MARK;
|
||||
LDR_IMM9(x1, ed, 0);
|
||||
STR_IMM9(gd, ed, 0);
|
||||
MARK2;
|
||||
MOV_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
case 0x88:
|
||||
@@ -1124,7 +1116,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x8C:
|
||||
INST_NAME("MOV Ed, Seg");
|
||||
nextop=F8;
|
||||
MOV32(x3, offsetof(x86emu_t, segs[(nextop&38)>>3]));
|
||||
MOV32(x3, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
if((nextop&0xC0)==0xC0) { // reg <= seg
|
||||
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
|
||||
} else { // mem <= seg
|
||||
@@ -1140,7 +1132,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);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
|
||||
MOV_REG(gd, ed);
|
||||
}
|
||||
@@ -1156,15 +1148,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(ed, xEmu, x2);
|
||||
if(((nextop&38)>>3)==_FS) {
|
||||
if(((nextop&0x38)>>3)==_FS) {
|
||||
// update default_fs, hack for wine
|
||||
MOV32(x2, &default_fs);
|
||||
STRH_IMM8(ed, x2, 0);
|
||||
}
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&38)>>3]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&0x38)>>3]));
|
||||
break;
|
||||
case 0x8F:
|
||||
INST_NAME("POP Ed");
|
||||
@@ -1556,7 +1548,8 @@ 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...)
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
READFLAGS(X_PEND); // lets play safe here too
|
||||
BARRIER(2);
|
||||
i32 = F16;
|
||||
retn_to_epilog(dyn, ninst, i32);
|
||||
@@ -1565,7 +1558,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 0xC3:
|
||||
INST_NAME("RET");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
// 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
|
||||
BARRIER(2);
|
||||
ret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
@@ -1628,6 +1623,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
*need_epilog = 1;
|
||||
} else {
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
|
||||
x87_forget(dyn, ninst, x3, x12, 0);
|
||||
MOV32(x12, ip+1); // read the 0xCC
|
||||
addr+=4+4;
|
||||
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
|
||||
@@ -1674,7 +1670,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xCF:
|
||||
INST_NAME("IRET");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
|
||||
SETFLAGS(X_ALL, SF_SET); // Not a hack, EFLAGS are restored
|
||||
BARRIER(2);
|
||||
iret_to_epilog(dyn, ninst);
|
||||
*need_epilog = 0;
|
||||
@@ -1942,7 +1938,39 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD4:
|
||||
INST_NAME("AAM Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
UBFX(x1, xEAX, 0, 8); // load AL
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
CALL_(aam16, x1, 0);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
case 0xD5:
|
||||
INST_NAME("AAD Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
UBFX(x1, xEAX, 0, 16); // load AX
|
||||
u8 = F8;
|
||||
MOVW(x2, u8);
|
||||
CALL_(aam16, x1, 0);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
case 0xD6:
|
||||
INST_NAME("SALC");
|
||||
READFLAGS(X_CF);
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
|
||||
CMPS_IMM8(x3, 1);
|
||||
MOVW_COND(cEQ, x3, 0xff);
|
||||
MOVW_COND(cNE, x3, 0x00);
|
||||
BFI(xEAX, x3, 0, 8);
|
||||
break;
|
||||
case 0xD7:
|
||||
INST_NAME("XLAT");
|
||||
UBFX(x1, xEAX, 0, 8); // x1 = AL
|
||||
LDRB_REG_LSL_IMM5(x1, xEBX, x1, 0); //x1 = byte ptr[EBX+AL]
|
||||
BFI(xEAX, x1, 0, 8);
|
||||
break;
|
||||
case 0xD8:
|
||||
addr = dynarecD8(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
@@ -2018,64 +2046,102 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
|
||||
case 0xE8:
|
||||
INST_NAME("CALL Id");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
i32 = F32S;
|
||||
if(addr+i32==0) {
|
||||
#if STEP == 3
|
||||
printf_log(LOG_NONE, "Warning, jump to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
|
||||
printf_log(LOG_NONE, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
|
||||
#endif
|
||||
}
|
||||
if(isNativeCall(dyn, addr+i32, &natcall, &retn)) {
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
MOV32(x2, addr);
|
||||
PUSH(xESP, 1<<x2);
|
||||
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(natcall-1)), retn);
|
||||
// calling a native function
|
||||
MOV32(x12, natcall); // read the 0xCC
|
||||
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
|
||||
CALL_(x86Int3, -1, 0);
|
||||
LDM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
|
||||
MOV32(x3, natcall+2+4+4);
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
B_MARK(cNE); // Not the expected address, exit dynarec block
|
||||
POP(xESP, (1<<xEIP)); // pop the return address
|
||||
if(retn) {
|
||||
ADD_IMM8(xESP, xESP, retn);
|
||||
}
|
||||
MOV32(x3, addr);
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
B_MARK(cNE); // Not the expected address again
|
||||
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
|
||||
CMPS_IMM8(x1, 1);
|
||||
B_NEXT(cNE); // not quitting, so lets continue
|
||||
MARK;
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
} else if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F))) {
|
||||
MESSAGE(LOG_DUMP, "Hack for Call 0, Pop reg\n");
|
||||
u8 = F8;
|
||||
gd = xEAX+(u8&7);
|
||||
MOV32(gd, addr-1);
|
||||
} else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3)) {
|
||||
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
|
||||
u8 = PK(i32+1);
|
||||
gd = xEAX+((u8&0x38)>>3);
|
||||
MOV32(gd, addr);
|
||||
} else {
|
||||
// regular call
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
|
||||
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
|
||||
//cstatck_push put addr in x2, don't need to put it again
|
||||
} else {
|
||||
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
#if STEP == 0
|
||||
if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F)))
|
||||
tmp = 1;
|
||||
else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3))
|
||||
tmp = 2;
|
||||
else if(isNativeCall(dyn, addr+i32, NULL, NULL))
|
||||
tmp = 3;
|
||||
else
|
||||
tmp = 0;
|
||||
#elif STEP < 2
|
||||
if ((i32==0) && ((PK(0)>=0x58) && (PK(0)<=0x5F)))
|
||||
tmp = dyn->insts[ninst].pass2choice = 1;
|
||||
else if (((addr+i32)>0x10000) && (PK(i32+0)==0x8B) && (((PK(i32+1))&0xC7)==0x04) && (PK(i32+2)==0x24) && (PK(i32+3)==0xC3))
|
||||
tmp = dyn->insts[ninst].pass2choice = 2;
|
||||
else if(isNativeCall(dyn, addr+i32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
|
||||
tmp = dyn->insts[ninst].pass2choice = 3;
|
||||
else
|
||||
tmp = dyn->insts[ninst].pass2choice = 0;
|
||||
#else
|
||||
tmp = dyn->insts[ninst].pass2choice;
|
||||
#endif
|
||||
switch(tmp) {
|
||||
case 1:
|
||||
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call 0, Pop reg\n");
|
||||
u8 = F8;
|
||||
gd = xEAX+(u8&7);
|
||||
MOV32(gd, addr-1);
|
||||
break;
|
||||
case 2:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
|
||||
u8 = PK(i32+1);
|
||||
gd = xEAX+((u8&0x38)>>3);
|
||||
MOV32(gd, addr);
|
||||
break;
|
||||
case 3:
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
MOV32(x2, addr);
|
||||
}
|
||||
PUSH(xESP, 1<<x2);
|
||||
jump_to_linker(dyn, addr+i32, 0, ninst);
|
||||
PUSH(xESP, 1<<x2);
|
||||
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, x12, 0);
|
||||
MOV32(x12, dyn->insts[ninst].natcall); // read the 0xCC already
|
||||
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
|
||||
CALL_(x86Int3, -1, 0);
|
||||
LDM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
|
||||
MOV32(x3, dyn->insts[ninst].natcall+2+4+4);
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
B_MARK(cNE); // Not the expected address, exit dynarec block
|
||||
POP(xESP, (1<<xEIP)); // pop the return address
|
||||
if(dyn->insts[ninst].retn) {
|
||||
ADD_IMM8(xESP, xESP, dyn->insts[ninst].retn);
|
||||
}
|
||||
MOV32(x3, addr);
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
B_MARK(cNE); // Not the expected address again
|
||||
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
|
||||
CMPS_IMM8(x1, 1);
|
||||
B_NEXT(cNE); // not quitting, so lets continue
|
||||
MARK;
|
||||
jump_to_epilog(dyn, 0, xEIP, ninst);
|
||||
break;
|
||||
default:
|
||||
if(ninst && dyn->insts && 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
|
||||
}
|
||||
// regular call
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
|
||||
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
|
||||
//cstatck_push put addr in x2, don't need to put it again
|
||||
} else {
|
||||
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
MOV32(x2, addr);
|
||||
}
|
||||
PUSH(xESP, 1<<x2);
|
||||
if(addr+i32==0) { // self modifying code maybe? so use indirect address fetching
|
||||
MOV32(x12, addr-4);
|
||||
LDR_IMM9(x12, x12, 0);
|
||||
}
|
||||
jump_to_linker(dyn, addr+i32, (addr+i32)?0:x12, ninst);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xE9:
|
||||
@@ -2090,7 +2156,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
JUMP(addr+i32);
|
||||
if(dyn->insts) {
|
||||
if(dyn->insts[ninst].x86.jmp_insts==-1) {
|
||||
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
|
||||
// out of the block
|
||||
jump_to_linker(dyn, addr+i32, 0, ninst);
|
||||
} else {
|
||||
@@ -2196,8 +2262,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x7D:
|
||||
case 0x7E:
|
||||
case 0x7F:
|
||||
case 0x9C:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
if(opcode==0xF2) {INST_NAME("BND");} else {INST_NAME("F3");}
|
||||
--addr; // put back opcode
|
||||
break;
|
||||
@@ -2594,7 +2662,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
case 2: // CALL Ed
|
||||
INST_NAME("CALL Ed");
|
||||
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
|
||||
PASS2IF(ninst && dyn->insts && 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
|
||||
}
|
||||
GETEDH(xEIP);
|
||||
BARRIER(1);
|
||||
BARRIER_NEXT(1);
|
||||
|
||||
+236
-78
@@ -19,6 +19,7 @@
|
||||
#include "dynarec_arm_private.h"
|
||||
#include "arm_printer.h"
|
||||
#include "my_cpuid.h"
|
||||
#include "emu/x87emu_private.h"
|
||||
|
||||
#include "dynarec_arm_functions.h"
|
||||
#include "dynarec_arm_helper.h"
|
||||
@@ -54,7 +55,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32, i32_;
|
||||
int32_t i32, i32_, j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t eb1, eb2;
|
||||
@@ -73,11 +74,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(wb2);
|
||||
#if PASS == 3
|
||||
MAYUSE(j32);
|
||||
#if STEP == 3
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("UD2");
|
||||
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
|
||||
@@ -87,11 +90,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVUPS Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
//LDRD also have alignment requirements
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
@@ -145,10 +149,17 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
VMOVD(v1, v0);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VST1_32(v0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
|
||||
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x14:
|
||||
@@ -184,9 +195,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
INST_NAME("MOVHPS Gx,Ex");
|
||||
GETGX(v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255, 0);
|
||||
LDRD_IMM8(x2, ed, fixedaddress);
|
||||
VMOVtoV_D(v0+1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VLD1_64(v0+1, ed);
|
||||
}
|
||||
break;
|
||||
case 0x17:
|
||||
@@ -197,9 +207,17 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
VMOVD(v1, v0+1);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255, 0);
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
STRD_IMM8(x2, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 2);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VST1_32(v0+1, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
|
||||
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0+1);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x18:
|
||||
@@ -237,11 +255,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVAPS Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VLD1Q_32(v0, ed);
|
||||
}
|
||||
@@ -350,7 +369,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
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, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
GETED;
|
||||
@@ -377,16 +396,36 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
//SSE3
|
||||
nextop=F8;
|
||||
switch(nextop) {
|
||||
case 0x00:
|
||||
INST_NAME("PSHUFB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
v1 = fpu_get_scratch_double(dyn);
|
||||
VMOV_8(v1, 0b10000111);
|
||||
VANDD(v1, d1, v1); // mask the index
|
||||
VTBL1_8(d0, d0, v1);
|
||||
break;
|
||||
case 0x04:
|
||||
INST_NAME("PMADDUBSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMULL_U16_U8(v0, d0, d1);
|
||||
VPADDLQ_U16(v0, v0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVL_U8(v0, d0); // this is unsigned, so 0 extended
|
||||
VMOVL_S8(v1, d1); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
VPADDLQ_S16(v0, v0);
|
||||
VQMOVN_S32(d0, v0);
|
||||
break;
|
||||
case 0x0B:
|
||||
INST_NAME("PMULHRSW Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VQRDMULH_S16(d0, d0, d1);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -556,10 +595,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
v2 = fpu_get_scratch_quad(dyn);
|
||||
#if 0
|
||||
VRSQRTEQ_F32(v2, q0);
|
||||
//step?
|
||||
VRECPEQ_F32(v0, v2);
|
||||
//step?
|
||||
#else
|
||||
// more precise
|
||||
if(v0==q0)
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
v1 = v0;
|
||||
VRSQRTEQ_F32(v2, q0);
|
||||
VMULQ_F32(v1, v2, q0);
|
||||
VRSQRTSQ_F32(v1, v1, v2);
|
||||
VMULQ_F32(v1, v1, v2);
|
||||
VMULQ_F32(v0, v1, q0);
|
||||
#endif
|
||||
break;
|
||||
case 0x52:
|
||||
INST_NAME("RSQRTPS Gx, Ex");
|
||||
@@ -567,8 +619,21 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEX(q0);
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
#if 0
|
||||
VRSQRTEQ_F32(v0, q0);
|
||||
//step?
|
||||
#else
|
||||
v2 = fpu_get_scratch_quad(dyn);
|
||||
// more precise
|
||||
if(v0==q0)
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
v1 = v0;
|
||||
VRSQRTEQ_F32(v2, q0);
|
||||
VMULQ_F32(v1, v2, q0);
|
||||
VRSQRTSQ_F32(v1, v1, v2);
|
||||
VMULQ_F32(v0, v1, v2);
|
||||
#endif
|
||||
break;
|
||||
case 0x53:
|
||||
INST_NAME("RCPPS Gx, Ex");
|
||||
@@ -824,11 +889,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("MOVQ Gm, Em");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, v1);
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VLD1_64(v0, ed);
|
||||
}
|
||||
@@ -1015,7 +1081,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x74:
|
||||
INST_NAME("PCMPEQB Gm,Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VCEQ_8(d0, d0, d1);
|
||||
break;
|
||||
case 0x75:
|
||||
INST_NAME("PCMPEQW Gm,Em");
|
||||
nextop = F8;
|
||||
@@ -1466,7 +1538,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fxsave, -1, 0);
|
||||
CALL(fpu_fxsave, -1, 0);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@@ -1477,7 +1549,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fxrstor, -1, 0);
|
||||
CALL(fpu_fxrstor, -1, 0);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
@@ -1521,26 +1593,14 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df)); // d_none == 0
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_AF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_SF]));
|
||||
GETEB(x2)
|
||||
UXTB(x1, xEAX, 0);
|
||||
// Use a quick CMP, without setting A or P...
|
||||
CMPS_REG_LSL_IMM5(x1, ed, 0);
|
||||
MOVW_COND(cEQ, x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
B_MARK(cNE);
|
||||
// AL == Eb
|
||||
GETGB(x1);
|
||||
MOV_REG(ed, x1);
|
||||
EBBACK;
|
||||
MOVW(x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
// done
|
||||
B_MARK3(c__);
|
||||
MARK;
|
||||
// AL != Eb
|
||||
@@ -1548,36 +1608,27 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
MARK3;
|
||||
// done, do the cmp now
|
||||
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
|
||||
break;
|
||||
case 0xB1:
|
||||
INST_NAME("CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df)); // d_none == 0
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_AF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_SF]));
|
||||
GETED;
|
||||
GETGD;
|
||||
// Use a quick CMP, without setting A or P...
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
MOVW_COND(cEQ, x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
MOV_REG(x3, ed);
|
||||
MOV_REG(ed, gd);
|
||||
WBACK;
|
||||
MOVW(x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
// done
|
||||
emit_cmp32(dyn, ninst, xEAX, x3, x1, x12);
|
||||
B_MARK3(c__); // not next, in case its called with a LOCK prefix
|
||||
MARK;
|
||||
// EAX != Ed
|
||||
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
|
||||
MOV_REG(xEAX, ed);
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
MARK3
|
||||
break;
|
||||
case 0xB3:
|
||||
@@ -1641,29 +1692,60 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
switch((nextop>>3)&7) {
|
||||
case 4:
|
||||
INST_NAME("BT Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>5)*4;
|
||||
LDR_IMM9(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8&=0x1f;
|
||||
if(u8) {
|
||||
MOV_REG_LSR_IMM5(x1, ed, u8);
|
||||
ed = x1;
|
||||
}
|
||||
AND_IMM8(x1, ed, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
break;
|
||||
case 5:
|
||||
INST_NAME("BTS Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x1, ed, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x1, fixedaddress);
|
||||
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x1, ed, x2);
|
||||
AND_IMM8(x1, x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
MOV_REG_LSR_REG(x12, ed, x2);
|
||||
ANDS_IMM8(x12, x12, 1);
|
||||
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
B_MARK3(cNE); // bit already set, jump to next instruction
|
||||
MOVW(x12, 1);
|
||||
XOR_REG_LSL_REG(ed, ed, x12, x2);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
@@ -1692,6 +1774,36 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("BTC Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
|
||||
LDR_IMM9(x1, x3, fixedaddress);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x12, ed, x2);
|
||||
ANDS_IMM8(x12, x12, 1);
|
||||
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
MOVW_COND(cEQ, x12, 1); // may already 0x01
|
||||
XOR_REG_LSL_REG(ed, ed, x12, x2);
|
||||
if(wback) {
|
||||
STR_IMM9(ed, wback, fixedaddress);
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -1834,7 +1946,18 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break; // not NaN
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC3:
|
||||
INST_NAME("MOVNTI Ed, Gd");
|
||||
// ignoring "NTI"
|
||||
nextop=F8;
|
||||
GETGD;
|
||||
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);
|
||||
STR_IMM9(gd, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0xC4:
|
||||
INST_NAME("PINSRW Gm,Ed,Ib");
|
||||
nextop = F8;
|
||||
@@ -1997,25 +2120,29 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
case 0xD7:
|
||||
INST_NAME("PMOVMSKB Gd, Em");
|
||||
nextop = F8;
|
||||
GETEM(d0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
#if PASS == 3
|
||||
MOV32_(x1, &mask_shift8);
|
||||
#else
|
||||
MOV32_(x1, 0);
|
||||
#endif
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
VLD1_8(d1, x1); // load shift
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
VMOV_8(v2, 0x80); // load mask
|
||||
VANDD(v2, v2, d0); // keep highest bit
|
||||
VSHL_S8(v2, v2, d1);// shift
|
||||
VPADD_8(v2, v2, v2);// accumulate the bits
|
||||
VPADD_8(v2, v2, v2);// ...
|
||||
VPADD_8(v2, v2, v2);// ...
|
||||
VMOVfrDx_U8(gd, v2, 0);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
INST_NAME("PMOVMSKB Gd, Em");
|
||||
GETEM(d0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
#if STEP == 3
|
||||
MOV32_(x1, &mask_shift8);
|
||||
#else
|
||||
MOV32_(x1, 0);
|
||||
#endif
|
||||
d1 = fpu_get_scratch_double(dyn);
|
||||
VLD1_8(d1, x1); // load shift
|
||||
v2 = fpu_get_scratch_double(dyn);
|
||||
VMOV_8(v2, 0x80); // load mask
|
||||
VANDD(v2, v2, d0); // keep highest bit
|
||||
VSHL_U8(v2, v2, d1);// shift
|
||||
VPADD_8(v2, v2, v2);// accumulate the bits
|
||||
VPADD_8(v2, v2, v2);// ...
|
||||
VPADD_8(v2, v2, v2);// ...
|
||||
VMOVfrDx_U8(gd, v2, 0);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gm,Em");
|
||||
@@ -2031,7 +2158,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(d1);
|
||||
VQSUB_U16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xDA:
|
||||
INST_NAME("PMINUB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VMIN_U8(d0, d0, d1);
|
||||
break;
|
||||
case 0xDB:
|
||||
INST_NAME("PAND Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -2053,7 +2186,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(d1);
|
||||
VQADD_U16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xDE:
|
||||
INST_NAME("PMAXUB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VMAX_U8(d0, d0, d1);
|
||||
break;
|
||||
case 0xDF:
|
||||
INST_NAME("PANDN Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -2061,6 +2200,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(v1);
|
||||
VBICD(v0, v1, v0);
|
||||
break;
|
||||
case 0xE0:
|
||||
INST_NAME("PAVGB Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(v0);
|
||||
GETEM(v1);
|
||||
VRHADD_U8(v0, v0, v1);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
INST_NAME("PMULHUW Gm,Em");
|
||||
@@ -2090,7 +2236,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
|
||||
v0 = mmx_get_reg(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VST1_64(v0, ed);
|
||||
}
|
||||
@@ -2109,7 +2255,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(d1);
|
||||
VQSUB_S16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xEA:
|
||||
INST_NAME("PMINPS Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VMIN_S16(d0, d0, d1);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("POR Gm, Em");
|
||||
nextop = F8;
|
||||
@@ -2131,7 +2283,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETEM(d1);
|
||||
VQADD_S16(d0, d0, d1);
|
||||
break;
|
||||
|
||||
case 0xEE:
|
||||
INST_NAME("PMAXSW Gm, Em");
|
||||
nextop = F8;
|
||||
GETGM(d0);
|
||||
GETEM(d1);
|
||||
VMAX_S16(d0, d0, d1);
|
||||
break;
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gm, Em");
|
||||
nextop = F8;
|
||||
|
||||
@@ -25,12 +25,36 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
int32_t i32;
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x12);
|
||||
emit_add32(dyn, ninst, gd, ed, x3, x12);
|
||||
break;
|
||||
|
||||
case 0x2B:
|
||||
INST_NAME("SUB Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x12);
|
||||
emit_sub32(dyn, ninst, gd, ed, x3, x12);
|
||||
break;
|
||||
|
||||
case 0x33:
|
||||
INST_NAME("XOR Gd, FS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
@@ -51,6 +75,97 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
// reduced EA size...
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ew16, Gw");
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
GETGD; // don't need GETGW here
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(ed, gd, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
STRH_REG(gd, x12, ed);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
MOV_REG(gd, xEAX+(nextop&7));
|
||||
} else { // mem <= reg
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8F:
|
||||
INST_NAME("POP FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
POP(xESP, (1<<x2));
|
||||
STR_REG_LSL_IMM5(x2, x1, x12, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX, FS:Ow");
|
||||
grab_fsdata(dyn, addr, ninst, x1);
|
||||
u32 = F16;
|
||||
if(u32) {
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
LDR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV FS:Ow, EAX");
|
||||
grab_fsdata(dyn, addr, ninst, x1);
|
||||
u32 = F16;
|
||||
if(u32) {
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
STR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ew");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
|
||||
PUSH(xESP, 1<<x3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ed, Gd");
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
@@ -98,18 +213,20 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
LDR_IMM9(xEAX, x1, i32);
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
LDR_IMM9(xEAX, x1, 0);
|
||||
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV FS:Od, EAX");
|
||||
grab_fsdata(dyn, addr, ninst, x1);
|
||||
u32 = F32;
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
|
||||
STR_IMM9(xEAX, x2, 0);
|
||||
i32 = F32S;
|
||||
if(i32>-4096 && i32<4096) {
|
||||
STR_IMM9(xEAX, x1, i32);
|
||||
} else {
|
||||
MOV32(x2, i32);
|
||||
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
@@ -128,12 +245,18 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
INST_NAME("(ignored) FS:");
|
||||
--addr;
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH Ed");
|
||||
INST_NAME("PUSH FS:Ed");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
|
||||
@@ -25,12 +25,19 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
int32_t i32;
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint8_t wback, wb1, wb2;
|
||||
uint8_t u8;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(j32);
|
||||
MAYUSE(wback);
|
||||
MAYUSE(wb2);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
case 0x03:
|
||||
INST_NAME("ADD Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
@@ -61,6 +68,101 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
emit_xor32(dyn, ninst, gd, ed, x3, x12);
|
||||
break;
|
||||
|
||||
case 0x3B:
|
||||
INST_NAME("CMP Gd, GS:Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x12);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETEDO(x12);
|
||||
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
case 0x82:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
INST_NAME("ADD GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_add8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 1: //OR
|
||||
INST_NAME("OR GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_or8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 2: //ADC
|
||||
INST_NAME("ADC GS:Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 3: //SBB
|
||||
INST_NAME("SBB GS:Eb, Ib");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 4: //AND
|
||||
INST_NAME("AND GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_and8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 5: //SUB
|
||||
INST_NAME("SUB GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_sub8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 6: //XOR
|
||||
INST_NAME("XOR GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
emit_xor8c(dyn, ninst, x1, u8, x2, x12);
|
||||
EBBACK;
|
||||
break;
|
||||
case 7: //CMP
|
||||
INST_NAME("CMP GS:Eb, Ib");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
GETEBO(x1);
|
||||
u8 = F8;
|
||||
if(u8) {
|
||||
MOVW(x2, u8);
|
||||
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
|
||||
} else {
|
||||
emit_cmp8_0(dyn, ninst, x1, x3, x12);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
INST_NAME("MOV GS:Ed, Gd");
|
||||
grab_tlsdata(dyn, addr, ninst, x12);
|
||||
@@ -87,6 +189,19 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8F:
|
||||
INST_NAME("POP GS:Ed");
|
||||
grab_tlsdata(dyn, addr, ninst, x12);
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP(xESP, (1<<(xEAX+(nextop&7))));
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
POP(xESP, (1<<x2));
|
||||
STR_REG_LSL_IMM5(x2, ed, x12, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX, GS:Id");
|
||||
grab_tlsdata(dyn, addr, ninst, x1);
|
||||
@@ -125,6 +240,31 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
INST_NAME("(ignored) GS:");
|
||||
--addr;
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_tlsdata(dyn, addr, ninst, x12);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH GS:Ed");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
|
||||
PUSH(xESP, 1<<x3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "arm_printer.h"
|
||||
|
||||
#include "dynarec_arm_helper.h"
|
||||
#include "dynarec_arm_functions.h"
|
||||
|
||||
|
||||
uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
@@ -27,7 +28,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
uint32_t u32;
|
||||
int32_t i32;
|
||||
int32_t i32, j32;
|
||||
int16_t i16;
|
||||
uint16_t u16;
|
||||
uint8_t gd, ed;
|
||||
@@ -35,6 +36,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
int fixedaddress;
|
||||
MAYUSE(u16);
|
||||
MAYUSE(u8);
|
||||
MAYUSE(j32);
|
||||
while(opcode==0x66) opcode = F8; // "unlimited" 0x66 as prefix for variable sized NOP
|
||||
if(opcode==0x2E) opcode = F8; // cs: is ignored
|
||||
switch(opcode) {
|
||||
@@ -168,10 +170,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("SBB AX, Iw");
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
i32 = F16;
|
||||
MOV32(x2, i32);
|
||||
i16 = F16;
|
||||
UXTH(x1, xEAX, 0);
|
||||
emit_sbb16c(dyn, ninst, x1, i32, x3, x12);
|
||||
emit_sbb16c(dyn, ninst, x1, i16, x3, x12);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
|
||||
@@ -324,8 +325,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
INST_NAME("PUSH Reg16");
|
||||
SUB_IMM8(xESP, xESP, 2);
|
||||
STRH_IMM8(xEAX+(opcode&7), xESP, 0); //TODO: use a single STRH pre-decrement instruction
|
||||
PUSH16(xEAX+(opcode&7), xESP);
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
@@ -336,17 +336,45 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
INST_NAME("POP Reg16");
|
||||
LDRH_IMM8(x1, xESP, 0); //TODO: use a single LDRH post-increment instruction
|
||||
POP16(x1, xESP);
|
||||
BFI(xEAX+(opcode&7), x1, 0, 16);
|
||||
ADD_IMM8(xESP, xESP, 2);
|
||||
break;
|
||||
case 0x60:
|
||||
INST_NAME("PUSHA");
|
||||
MOV_REG(x1, xESP);
|
||||
PUSH16(xEAX, xESP);
|
||||
PUSH16(xECX, xESP);
|
||||
PUSH16(xEDX, xESP);
|
||||
PUSH16(xEBX, xESP);
|
||||
PUSH16(x1, xESP);
|
||||
PUSH16(xEBP, xESP);
|
||||
PUSH16(xESI, xESP);
|
||||
PUSH16(xEDI, xESP);
|
||||
break;
|
||||
case 0x61:
|
||||
INST_NAME("POPA");
|
||||
POP16(x1, xESP);
|
||||
BFI(xEDI, x1, 0, 16);
|
||||
POP16(x1, xESP);
|
||||
BFI(xESI, x1, 0, 16);
|
||||
POP16(x1, xESP);
|
||||
BFI(xEBP, x1, 0, 16);
|
||||
ADD_IMM8(xESP, xESP, 2); //POP16(xESP, xESP);
|
||||
POP16(x1, xESP);
|
||||
BFI(xEBX, x1, 0, 16);
|
||||
POP16(x1, xESP);
|
||||
BFI(xEDX, x1, 0, 16);
|
||||
POP16(x1, xESP);
|
||||
BFI(xECX, x1, 0, 16);
|
||||
POP16(x1, xESP);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0x68:
|
||||
INST_NAME("PUSH Iw");
|
||||
u16 = F16;
|
||||
MOVW(x2, u16);
|
||||
SUB_IMM8(xESP, xESP, 2);
|
||||
STRH_IMM8(x2, xESP, 0);
|
||||
PUSH16(x2, xESP);
|
||||
break;
|
||||
case 0x69:
|
||||
INST_NAME("IMUL Gw,Ew,Iw");
|
||||
@@ -364,8 +392,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
INST_NAME("PUSH Ib");
|
||||
i16 = F8S;
|
||||
MOVW(x2, i16);
|
||||
SUB_IMM8(xESP, xESP, 2);
|
||||
STRH_IMM8(x2, xESP, 0);
|
||||
PUSH16(x2, xESP);
|
||||
break;
|
||||
case 0x6B:
|
||||
INST_NAME("IMUL Gw,Ew,Ib");
|
||||
@@ -501,7 +528,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0x8C:
|
||||
INST_NAME("MOV Ew,Seg");
|
||||
nextop = F8;
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
LDRH_REG(x1, xEmu, x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
@@ -517,16 +544,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
|
||||
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);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&38)>>3]));
|
||||
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
|
||||
STRH_REG(x1, xEmu, x2);
|
||||
}
|
||||
MOVW(x1, 0);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&38)>>3]));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&0x38)>>3]));
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
@@ -545,12 +572,32 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
BFI(xEAX, gd, 0, 16);
|
||||
BFI(gd, x2, 0, 16);
|
||||
break;
|
||||
|
||||
case 0x98:
|
||||
INST_NAME("CBW");
|
||||
SXTB(x1, xEAX, 0);
|
||||
BFI(xEAX, x1, 0, 16);
|
||||
break;
|
||||
case 0x99:
|
||||
INST_NAME("CWD");
|
||||
SXTH(x1, xEAX, 0);
|
||||
BFI(xEDX, x1, 16, 16);
|
||||
break;
|
||||
|
||||
case 0x9C:
|
||||
INST_NAME("PUSHF (16b)");
|
||||
READFLAGS(X_ALL);
|
||||
CALL(PackFlags, -1, 0);
|
||||
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, packed_eflags.x32));
|
||||
STRHB_IMM8(x1, xESP, -2);
|
||||
break;
|
||||
case 0x9D:
|
||||
INST_NAME("POPF (16b)");
|
||||
SETFLAGS(X_ALL, SF_SET); // lower 16bits is all flags handled in dynarec
|
||||
LDRHA_IMM8(x1, xESP, 2);
|
||||
CALL(arm_popf16, -1, 0);
|
||||
MOVW(x1, d_none);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV, AX, Od");
|
||||
@@ -974,6 +1021,30 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("CLC");
|
||||
i32 = dyn->state_flags; //TODO: find a better way to do this
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
if(i32!=SF_SET) {
|
||||
MOVW(x1, d_none);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
|
||||
} else {
|
||||
MOVW(x1, 0);
|
||||
}
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
break;
|
||||
case 0xF9:
|
||||
INST_NAME("STC");
|
||||
i32 = dyn->state_flags; //TODO: find a better way to do this
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
if(i32!=SF_SET) {
|
||||
MOVW(x1, d_none);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
MOVW(x1, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
|
||||
+400
-86
@@ -39,7 +39,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32;
|
||||
int32_t i32, j32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback, wb1;
|
||||
uint8_t eb1, eb2;
|
||||
@@ -54,6 +54,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
MAYUSE(q1);
|
||||
MAYUSE(eb1);
|
||||
MAYUSE(eb2);
|
||||
MAYUSE(j32);
|
||||
#if STEP == 3
|
||||
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
|
||||
#endif
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -61,11 +65,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVUPD Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -84,7 +89,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, 255-8, 0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0);
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
STR_IMM9(x2, ed, fixedaddress+0);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -114,8 +119,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VSTR_64(v0, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VSTR_64(v0, ed, fixedaddress);
|
||||
} else {
|
||||
VMOVfrV_D(x2, x3, v0);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
break;
|
||||
case 0x14:
|
||||
INST_NAME("UNPCKLPD Gx, Ex");
|
||||
@@ -151,8 +164,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v0+1, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v0+1, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0+1,x2, x3);
|
||||
}
|
||||
break;
|
||||
case 0x17:
|
||||
INST_NAME("MOVHPD Ed, Gx");
|
||||
@@ -163,8 +184,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
DEFAULT;
|
||||
return addr;
|
||||
}
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VSTR_64(v0+1, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
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);
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
STR_IMM9(x3, ed, fixedaddress+4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
@@ -177,11 +206,12 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVAPD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VLD1Q_32(v0, ed);
|
||||
}
|
||||
@@ -223,31 +253,165 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(q1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VLD1Q_64(q1, ed);
|
||||
v0 = q1;
|
||||
}
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ_8(v1, 0b10001111);
|
||||
VANDQ(q1, q1, v1); // mask the index
|
||||
VANDQ(q1, v0, v1); // mask the index
|
||||
VMOVQ(v1, q0);
|
||||
VTBL2_8(q0+0, v1, q1+0);
|
||||
VTBL2_8(q0+1, v1, q1+1);
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("PHADDW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VPADD_16(q0, q0, q0+1);
|
||||
if(q0==q1) {
|
||||
VMOVD(q0+1, q0);
|
||||
} else {
|
||||
VPADD_16(q0+1, q1, q1+1);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
INST_NAME("PHADDD Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VPADD_32(q0, q0, q0+1);
|
||||
if(q0==q1) {
|
||||
VMOVD(q0+1, q0);
|
||||
} else {
|
||||
VPADD_32(q0+1, q1, q1+1);
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
INST_NAME("PHADDSW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
if((nextop&0xC0) == 0xC0) {
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(v1, q1);
|
||||
} else
|
||||
v1 = q1;
|
||||
VUZPQ_16(q0, v1);
|
||||
VQADDQ_S16(q0, q0, v1);
|
||||
break;
|
||||
case 0x04:
|
||||
INST_NAME("PMADDUBSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMULL_U16_U8(v0, q0+0, q1+0);
|
||||
VPADDLQ_U16(v0, v0);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVL_U8(v0, q0+0); // this is unsigned, so 0 extended
|
||||
VMOVL_S8(v1, q1+0); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
VPADDLQ_S16(v0, v0);
|
||||
VQMOVN_S32(q0+0, v0);
|
||||
VMULL_U16_U8(v0, q0+1, q1+1);
|
||||
VPADDLQ_U16(v0, v0);
|
||||
VMOVL_U8(v0, q0+1); // this is unsigned
|
||||
VMOVL_S8(v1, q1+1); // this is signed
|
||||
VMULQ_16(v0, v0, v1);
|
||||
VPADDLQ_S16(v0, v0);
|
||||
VQMOVN_S32(q0+1, v0);
|
||||
break;
|
||||
case 0x05:
|
||||
INST_NAME("PHSUBW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
if((nextop&0xC0) == 0xC0) {
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(v1, q1);
|
||||
} else
|
||||
v1 = q1;
|
||||
VUZPQ_16(q0, v1);
|
||||
VSUBQ_16(q0, q0, v1);
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
INST_NAME("PSIGNB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VNEGNQ_8(v0, q0); // get NEG
|
||||
VCLTQ_0_8(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
VCEQQ_0_8(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
case 0x09:
|
||||
INST_NAME("PSIGNW Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VNEGNQ_16(v0, q0); // get NEG
|
||||
VCLTQ_0_16(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
VCEQQ_0_16(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
case 0x0A:
|
||||
INST_NAME("PSIGND Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
v1 = fpu_get_scratch_quad(dyn);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VNEGNQ_32(v0, q0); // get NEG
|
||||
VCLTQ_0_32(v1, q1); // calculate mask
|
||||
VBICQ(q0, q0, v1); // apply not mask on dest
|
||||
VANDQ(v0, v0, v1); // apply mask on src
|
||||
VORRQ(q0, q0, v0); // merge
|
||||
VCEQQ_0_32(v1, q1); // handle case where Ex is 0
|
||||
VBICQ(q0, q0, v1);
|
||||
break;
|
||||
|
||||
case 0x0B:
|
||||
INST_NAME("PMULHRSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VQRDMULHQ_S16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0x1C:
|
||||
INST_NAME("PABSB Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VABSQ_S8(q0, q1);
|
||||
break;
|
||||
case 0x1D:
|
||||
INST_NAME("PABSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VABSQ_S16(q0, q1);
|
||||
break;
|
||||
case 0x1E:
|
||||
INST_NAME("PABSD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETEX(q1);
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VABSQ_S32(q0, q1);
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
@@ -265,10 +429,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if(u8>31) {
|
||||
VEORQ(q0, q0, q0);
|
||||
} else if(u8>15) {
|
||||
VEORQ(q0, q0, q0);
|
||||
VEXTQ_8(q0, q1, q0, u8-16);
|
||||
d0 = fpu_get_scratch_quad(dyn);
|
||||
VEORQ(d0, d0, d0);
|
||||
VEXTQ_8(q0, q0, d0, u8-16);
|
||||
} else {
|
||||
VEXTQ_8(q0, q0, q1, u8);
|
||||
VEXTQ_8(q0, q1, q0, u8);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -397,7 +562,20 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
, cNE, cEQ, X_OF|X_SF|X_ZF)
|
||||
break;
|
||||
#undef GO
|
||||
|
||||
case 0x50:
|
||||
INST_NAME("MOVMSKPD Gd, Ex");
|
||||
nextop = F8;
|
||||
GETEX(q0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
if((nextop&0xC0)==0xC0)
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
q1 = q0;
|
||||
VSHRQ_U64(q1, q0, 63); // only bit 63 left
|
||||
VSHL_U64(q1+1, q1+1, 1); // shift 1 left for higher bit
|
||||
VADD_8(q1, q1, q1+1); // add low and high
|
||||
VMOVfrDx_U8(gd, q1, 0); // grab the 2 sign bits
|
||||
break;
|
||||
case 0x54:
|
||||
INST_NAME("ANDPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -460,7 +638,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1);
|
||||
VCVTQ_F32_S32(v0, v1);
|
||||
VCVTQ_S32_F32(v0, v1);
|
||||
break;
|
||||
case 0x5C:
|
||||
INST_NAME("SUBPD Gx, Ex");
|
||||
@@ -528,11 +706,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
gd = (nextop&0x38)>>3;
|
||||
GETEX(q0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, q0);
|
||||
} else q1 = q0;
|
||||
VZIPQ_32(v0, q1);
|
||||
VMOVD(v0+1, q0); // get a copy
|
||||
VTRN_32(v0, v0+1); // same as VZIP_32
|
||||
break;
|
||||
case 0x63:
|
||||
INST_NAME("PACKSSWB Gx,Ex");
|
||||
@@ -540,7 +715,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VQMOVN_S16(q0+0, q0);
|
||||
VQMOVN_S16(q0+1, q1);
|
||||
if(q0==q1) {
|
||||
VMOVD(q0+1, q0+0);
|
||||
} else {
|
||||
VQMOVN_S16(q0+1, q1);
|
||||
}
|
||||
break;
|
||||
case 0x64:
|
||||
INST_NAME("PCMPGTB Gx,Ex");
|
||||
@@ -602,12 +781,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
gd = (nextop&0x38)>>3;
|
||||
GETEX(q0);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, q0);
|
||||
} else q1 = q0;
|
||||
VZIPQ_32(v0, q1);
|
||||
VMOVQ(v0, q1);
|
||||
VMOVD(v0, v0+1); // get high part into low
|
||||
VMOVD(v0+1, q0+1); // get a copy
|
||||
VZIP_32(v0, v0+1);
|
||||
break;
|
||||
case 0x6B:
|
||||
INST_NAME("PACKSSDW Gx,Ex");
|
||||
@@ -651,12 +827,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVD Gx, Ed");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
VEOR(d0, d0, d0); // d0 = U32{0, 0}
|
||||
GETED;
|
||||
VMOVtoV(d0*2, ed);// d0 = U32{ed, 0}
|
||||
VMOVL_U32(v0, d0);// U32/U32 -> U64/U64
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VEORQ(v0, v0, v0); // v0 = U32{0, 0}
|
||||
VMOVtoDx_32(v0, 0, ed);// d0 = U32{ed, 0}
|
||||
break;
|
||||
case 0x6F:
|
||||
INST_NAME("MOVDQA Gx,Ex");
|
||||
@@ -681,26 +855,35 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
u8 = F8;
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
// use stack as temporary storage
|
||||
SUB_IMM8(xSP, xSP, 4);
|
||||
if(v1==v0) {
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q0, v1);
|
||||
} else q0 = v1;
|
||||
if (u8) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
int32_t idx = (u8>>(i*2))&3;
|
||||
if(idx!=i32) {
|
||||
VST1LANE_32(q0+(idx/2), xSP, idx&1);
|
||||
i32 = idx;
|
||||
}
|
||||
VLD1LANE_32(v0+(i/2), xSP, i&1);
|
||||
if(u8==0x4E) {
|
||||
if(v0==v1) {
|
||||
VSWP(v0, v0+1);
|
||||
} else {
|
||||
VMOVD(v0, v1+1);
|
||||
VMOVD(v0+1, v1);
|
||||
}
|
||||
} else {
|
||||
VST1LANE_32(v1, xSP, 0);
|
||||
VLD1QALL_32(v0, xSP);
|
||||
uint32_t swp[4] = {
|
||||
(0)|(1<<8)|(2<<16)|(3<<24),
|
||||
(4)|(5<<8)|(6<<16)|(7<<24),
|
||||
(8)|(9<<8)|(10<<16)|(11<<24),
|
||||
(12)|(13<<8)|(14<<16)|(15<<24)
|
||||
};
|
||||
d0 = fpu_get_scratch_double(dyn);
|
||||
if(v0==v1) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else
|
||||
q1 = v1;
|
||||
MOV32(x2, swp[(u8>>(0*2))&3]);
|
||||
MOV32(x3, swp[(u8>>(1*2))&3]);
|
||||
VMOVtoV_D(d0, x2, x3);
|
||||
MOV32(x2, swp[(u8>>(2*2))&3]);
|
||||
MOV32(x3, swp[(u8>>(3*2))&3]);
|
||||
VTBL2_8(v0+0, q1, d0);
|
||||
VMOVtoV_D(d0, x2, x3);
|
||||
VTBL2_8(v0+1, q1, d0);
|
||||
}
|
||||
ADD_IMM8(xSP, xSP, 4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
u8 = F8;
|
||||
@@ -1110,6 +1293,19 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
break;
|
||||
case 0xB7:
|
||||
INST_NAME("MOVZX Gw, Ew");
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX + (nextop&7);
|
||||
UXTH(x1, ed, 0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
|
||||
LDRH_IMM8(x1, ed, fixedaddress);
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
case 0xBB:
|
||||
INST_NAME("BTC Ew, Gw");
|
||||
@@ -1175,7 +1371,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
BFI(gd, x1, 0, 16);
|
||||
break;
|
||||
|
||||
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPD Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1249,13 +1445,18 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETGX(v0);
|
||||
GETEX(v1);
|
||||
u8 = F8;
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
if(v0==v1 && u8==0) {
|
||||
VMOVD(q0+1, q0);
|
||||
VMOVD(v0+1, v0);
|
||||
} else {
|
||||
if(v0==v1)
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
else
|
||||
q0 = v0;
|
||||
VMOVD(q0, v0+(u8&1));
|
||||
VMOVD(q0+1, v1+((u8>>1)&1));
|
||||
VMOVQ(v0, q0);
|
||||
if(v0==v1) {
|
||||
VMOVQ(v0, q0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1287,7 +1488,19 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVD(v0+1, v0);
|
||||
VSHLQ_U32(q0, q0, v0);
|
||||
break;
|
||||
|
||||
case 0xD3:
|
||||
INST_NAME("PSRLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
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
|
||||
VSHLQ_U64(q0, q0, v0);
|
||||
break;
|
||||
case 0xD4:
|
||||
INST_NAME("PADDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1324,7 +1537,40 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD7:
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
INST_NAME("PMOVMSKB Gd, Ex");
|
||||
GETEX(q0);
|
||||
gd = xEAX+((nextop&0x38)>>3);
|
||||
#if STEP == 3
|
||||
MOV32_(x1, &mask_shift8);
|
||||
#else
|
||||
MOV32_(x1, 0);
|
||||
#endif
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VLD1_8(v0, x1); // load shift
|
||||
v1 = fpu_get_scratch_double(dyn);
|
||||
VMOV_8(v1, 0x80); // load mask
|
||||
VANDD(v1, v1, q0+0); // keep highest bit
|
||||
VSHL_U8(v1, v1, v0);// shift
|
||||
VPADD_8(v1, v1, v1);// accumulate the bits
|
||||
VPADD_8(v1, v1, v1);// ...
|
||||
VPADD_8(v1, v1, v1);// ...
|
||||
VMOVfrDx_U8(gd, v1, 0);
|
||||
// and now the high part
|
||||
VMOV_8(v1, 0x80); // load mask
|
||||
VANDD(v1, v1, q0+1); // keep highest bit
|
||||
VSHL_U8(v1, v1, v0);// shift
|
||||
VPADD_8(v1, v1, v1);// accumulate the bits
|
||||
VPADD_8(v1, v1, v1);// ...
|
||||
VPADD_8(v1, v1, v1);// ...
|
||||
VMOVfrDx_U8(x1, v1, 0);
|
||||
BFI(gd, x1, 8, 8);
|
||||
} else {
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xD8:
|
||||
INST_NAME("PSUBUSB Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1339,7 +1585,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q1);
|
||||
VQSUBQ_U16(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0xDA:
|
||||
INST_NAME("PMINUB Gx, Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VMINQ_U8(q0, q0, q1);
|
||||
break;
|
||||
case 0xDB:
|
||||
INST_NAME("PAND Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1354,7 +1606,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q1);
|
||||
VQADDQ_U8(q0, q0, q1);
|
||||
break;
|
||||
|
||||
case 0xDD:
|
||||
INST_NAME("PADDUSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
VQADDQ_U16(q0, q0, q1);
|
||||
break;
|
||||
case 0xDE:
|
||||
INST_NAME("PMAXUB Gx, Ex");
|
||||
nextop = F8;
|
||||
@@ -1411,7 +1669,17 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q0);
|
||||
VRHADDQ_U16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xE4:
|
||||
INST_NAME("PMULHUW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VMULL_U32_U16(q0, v0, v1);
|
||||
VSHRN_32(v0, q0, 16);
|
||||
VMULL_U32_U16(q0, v0+1, v1+1);
|
||||
VSHRN_32(v0+1, q0, 16);
|
||||
break;
|
||||
case 0xE5:
|
||||
INST_NAME("PMULHW Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1419,11 +1687,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(v1);
|
||||
q0 = fpu_get_scratch_quad(dyn);
|
||||
VMULL_S32_S16(q0, v0, v1);
|
||||
VUZP_16(q0, q0+1);
|
||||
VMOVD(v0, q0+1);
|
||||
VSHRN_32(v0, q0, 16);
|
||||
VMULL_S32_S16(q0, v0+1, v1+1);
|
||||
VUZP_16(q0, q0+1);
|
||||
VMOVD(v0+1, q0+1);
|
||||
VSHRN_32(v0+1, q0, 16);
|
||||
break;
|
||||
case 0xE6:
|
||||
INST_NAME("CVTTPD2DQ Gx, Ex");
|
||||
@@ -1451,7 +1717,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
VST1Q_32(v0, ed);
|
||||
VST1Q_64(v0, ed);
|
||||
}
|
||||
break;
|
||||
case 0xE8:
|
||||
@@ -1468,7 +1734,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q0);
|
||||
VQSUBQ_S16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEA:
|
||||
INST_NAME("PMINSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0);
|
||||
VMINQ_S16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEB:
|
||||
INST_NAME("POR Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1490,15 +1762,64 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
GETEX(q0);
|
||||
VQADDQ_S16(v0, v0, q0);
|
||||
break;
|
||||
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gx,Ex");
|
||||
case 0xEE:
|
||||
INST_NAME("PMAXSW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(q0);
|
||||
VEORQ(v0, v0, q0);
|
||||
VMAXQ_S16(v0, v0, q0);
|
||||
break;
|
||||
case 0xEF:
|
||||
INST_NAME("PXOR Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if(nextop==0xC0+gd) {
|
||||
// special case for PXOR Gx, Gx
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VEORQ(q0, q0, q0);
|
||||
} else {
|
||||
q0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
GETEX(q1);
|
||||
VEORQ(q0, q0, q1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xF1:
|
||||
INST_NAME("PSLLW Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
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);
|
||||
VSHLQ_U16(q0, q0, v0);
|
||||
break;
|
||||
case 0xF2:
|
||||
INST_NAME("PSLLD Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
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);
|
||||
VSHLQ_U32(q0, q0, v0);
|
||||
break;
|
||||
case 0xF3:
|
||||
INST_NAME("PSLLQ Gx,Ex");
|
||||
nextop = F8;
|
||||
GETGX(q0);
|
||||
GETEX(q1);
|
||||
v0 = fpu_get_scratch_quad(dyn);
|
||||
VMOVD(v0, q1);
|
||||
VMOVD(v0+1, q1);
|
||||
VSHLQ_U64(q0, q0, v0);
|
||||
break;
|
||||
case 0xF4:
|
||||
INST_NAME("PMULUDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
@@ -1521,18 +1842,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
GETGX(v0);
|
||||
GETEX(v1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMOVQ(q1, v1);
|
||||
} else {
|
||||
q1 = v1;
|
||||
}
|
||||
VUZP_16(v0, v0+1);
|
||||
VUZP_16(q1, q1+1);
|
||||
VSWP(v0, q1+1);
|
||||
VMULL_S32_S16(q1, q1, q1+1);
|
||||
VMULL_S32_S16(v0, v0, v0+1);
|
||||
VADDQ_32(v0, v0, q1);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VMULL_S32_S16(q1, v0, v1);
|
||||
VPADD_32(v0, q1, q1+1);
|
||||
VMULL_S32_S16(q1, v0+1, v1+1);
|
||||
VPADD_32(v0+1, q1, q1+1);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("PSADBW Gx, Ex");
|
||||
|
||||
@@ -21,17 +21,117 @@
|
||||
|
||||
#include "dynarec_arm_helper.h"
|
||||
|
||||
|
||||
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop;
|
||||
uint8_t nextop, opcode;
|
||||
int8_t i8;
|
||||
int32_t i32;
|
||||
int32_t i32, j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
int fixedaddress;
|
||||
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
|
||||
nextop = F8;
|
||||
|
||||
switch(nextop) {
|
||||
|
||||
|
||||
case 0x64:
|
||||
// reduced EA size...
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x89:
|
||||
INST_NAME("MOV FS:Ew16, Gw");
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
GETGD; // don't need GETGW here
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(ed, gd, 0, 16);
|
||||
}
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
STRH_REG(gd, x12, ed);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8B:
|
||||
INST_NAME("MOV Gd, FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) { // reg <= reg
|
||||
ed = xEAX+(nextop&7);
|
||||
if(ed!=gd) {
|
||||
BFI(gd, ed, 0, 16);
|
||||
}
|
||||
} else { // mem <= reg
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(gd, x12, ed, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8F:
|
||||
INST_NAME("POP FS:Ew16");
|
||||
nextop=F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
|
||||
} else {
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
POP(xESP, (1<<x2));
|
||||
STR_REG_LSL_IMM5(x2, x12, ed, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA1:
|
||||
INST_NAME("MOV EAX, FS:Ow");
|
||||
grab_fsdata(dyn, addr, ninst, x1);
|
||||
u32 = F16;
|
||||
if(u32) {
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
LDR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xA3:
|
||||
INST_NAME("MOV FS:Ow, EAX");
|
||||
grab_fsdata(dyn, addr, ninst, x1);
|
||||
u32 = F16;
|
||||
if(u32) {
|
||||
MOV32(x2, u32);
|
||||
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
|
||||
}
|
||||
STR_IMM9(xEAX, x1, 0);
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = F8;
|
||||
grab_fsdata(dyn, addr, ninst, x12);
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: // Push Ed
|
||||
INST_NAME("PUSH FS:Ew");
|
||||
if((nextop&0xC0)==0xC0) { // reg
|
||||
DEFAULT;
|
||||
} else { // mem <= i32
|
||||
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
|
||||
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
|
||||
PUSH(xESP, 1<<x3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
#define GO(NO, YES) \
|
||||
BARRIER(2); \
|
||||
JUMP(addr+i8);\
|
||||
|
||||
@@ -205,6 +205,28 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fxtract, -1, 0);
|
||||
break;
|
||||
case 0xF5:
|
||||
INST_NAME("FPREM1");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
x87_forget(dyn, ninst, x1, x2, 1);
|
||||
CALL(arm_fprem1, -1, 0);
|
||||
break;
|
||||
case 0xF6:
|
||||
INST_NAME("FDECSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
SUB_IMM8(x2, x2, 1);
|
||||
AND_IMM8(x2, x2, 7);
|
||||
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
break;
|
||||
case 0xF7:
|
||||
INST_NAME("FINCSTP");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
ADD_IMM8(x2, x2, 1);
|
||||
AND_IMM8(x2, x2, 7);
|
||||
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
break;
|
||||
case 0xF8:
|
||||
INST_NAME("FPREM");
|
||||
x87_forget(dyn, ninst, x1, x2, 0);
|
||||
@@ -260,9 +282,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
case 0xEF:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
DEFAULT;
|
||||
break;
|
||||
|
||||
@@ -331,6 +350,16 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
UBFX(x1, x1, 10, 2); // extract round
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("FNSTENV Ed");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
if(ed!=x1) {
|
||||
MOV_REG(x1, ed);
|
||||
}
|
||||
MOVW(x2, 0);
|
||||
CALL(fpu_savenv, -1, 0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTCW Ew");
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
int32_t i32;
|
||||
int32_t j32;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
int v1, v2;
|
||||
@@ -39,7 +39,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(ed);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
|
||||
@@ -26,7 +26,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int32_t j32;
|
||||
uint8_t ed;
|
||||
uint8_t wback;
|
||||
int v1, v2;
|
||||
@@ -37,7 +37,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -105,6 +105,9 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
TSTS_REG_LSL_IMM5(x1, x1, 0);
|
||||
VMOVcond_64(cEQ, v1, v2); // F_PF==0
|
||||
break;
|
||||
case 0xE1:
|
||||
INST_NAME("FDISI8087_NOP"); // so.. NOP?
|
||||
break;
|
||||
case 0xE2:
|
||||
INST_NAME("FNCLEX");
|
||||
MOVW(x1, 0);
|
||||
@@ -150,7 +153,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
|
||||
@@ -144,16 +144,16 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
#else
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if (parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v1, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress + 4);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress + 4);
|
||||
VMOVtoV_D(v1, x2, x3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
@@ -207,6 +207,17 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
CALL(arm_fsave, -1, 0);
|
||||
break;
|
||||
case 7:
|
||||
INST_NAME("FNSTSW m2byte");
|
||||
fpu_purgecache(dyn, ninst, x1, x2, x3);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x12, &fixedaddress, 0, 0);
|
||||
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
|
||||
MOVW(x2, offsetof(x86emu_t, sw));
|
||||
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
|
||||
LDRH_IMM8(x3, x2, 0);
|
||||
BFI(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
|
||||
STRH_IMM8(x3, ed, 0); // store whole sw flags
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,23 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
VMUL_F64(v2, v2, v1);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
case 0xD9: /* FCOMPP */
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
INST_NAME("FCOMP ST0, STx");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
|
||||
VCMP_F64(v1, v2);
|
||||
FCOM(x1, x2);
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xD9:
|
||||
INST_NAME("FCOMPP ST0, ST1");
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
|
||||
@@ -125,14 +141,6 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
|
||||
@@ -28,7 +28,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
{
|
||||
uint8_t nextop = F8;
|
||||
uint8_t u8;
|
||||
int32_t i32;
|
||||
int32_t j32;
|
||||
uint8_t wback;
|
||||
uint8_t ed;
|
||||
int v1, v2;
|
||||
@@ -38,9 +38,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
MAYUSE(s0);
|
||||
MAYUSE(v2);
|
||||
MAYUSE(v1);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
INST_NAME("FFREEP STx");
|
||||
// not handling Tag...
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
INST_NAME("FNSTSW AX");
|
||||
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
|
||||
@@ -82,14 +95,6 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
x87_do_pop(dyn, ninst);
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
|
||||
@@ -432,7 +432,7 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int
|
||||
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_or8);
|
||||
@@ -543,7 +543,7 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_xor8);
|
||||
@@ -654,7 +654,7 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOV32(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_and8);
|
||||
@@ -766,7 +766,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_or16);
|
||||
@@ -783,7 +783,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 {MOV32(s3, c);}
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
IFX(X_ALL) {
|
||||
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -886,7 +886,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_xor16);
|
||||
@@ -903,7 +903,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 {MOV32(s3, c);}
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
IFX(X_ALL) {
|
||||
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -1006,7 +1006,7 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOV32(s3, c);
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s4, d_and16);
|
||||
@@ -1023,7 +1023,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_ALL) {} else {MOVW(s3, c);}
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
IFX(X_ALL) {
|
||||
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
|
||||
+137
-185
@@ -104,7 +104,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
ORR_IMM8(s3, s1, c, 0); // s3 = op1 | op2
|
||||
AND_IMM8(s4, s1, c); // s4 = op1 & op2
|
||||
} else {
|
||||
MOV32(s3, c);
|
||||
IFX(X_PEND) {} else {MOV32(s3, c);}
|
||||
MOV_REG(s4, s3);
|
||||
ORR_REG_LSL_IMM5(s3, s1, s3, 0);
|
||||
AND_REG_LSL_IMM5(s4, s1, s4, 0);
|
||||
@@ -118,7 +118,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
ADD_IMM8(s1, s1, c);
|
||||
}
|
||||
} else {
|
||||
MOV32(s3, c);
|
||||
IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);}
|
||||
IFX(X_ALL) {
|
||||
ADDS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -251,7 +251,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
AND_IMM8(s4, s3, c); // s4 = ~op1 & op2
|
||||
ORR_IMM8(s3, s3, c, 0); // s3 = ~op1 | op2
|
||||
} else {
|
||||
MOV32(s3, c);
|
||||
IFX(X_PEND) {} else {MOV32(s3, c);}
|
||||
MVN_REG_LSL_IMM5(s4, s1, 0);
|
||||
ORR_REG_LSL_IMM5(s3, s4, s3, 0);
|
||||
MOV32(s4, c);
|
||||
@@ -266,7 +266,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
SUB_IMM8(s1, s1, c);
|
||||
}
|
||||
} else {
|
||||
MOV32(s3, c);
|
||||
IFXN(X_PEND, X_AF) {} else {MOV32(s3, c);}
|
||||
IFX(X_ALL) {
|
||||
SUBS_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
} else {
|
||||
@@ -353,13 +353,11 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
UBFX(s3, s1, 8, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -385,7 +383,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
MOVW(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_add8);
|
||||
@@ -419,14 +417,11 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
UBFX(s3, s1, 8, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -468,11 +463,8 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
}
|
||||
|
||||
SUB_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
|
||||
@@ -493,6 +485,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -518,7 +511,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
MOVW(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_sub8);
|
||||
@@ -530,16 +523,13 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
MVN_REG_LSL_IMM5(s3, s1, 0);
|
||||
MOVW(s4, c);
|
||||
MOVW(s4, c&0xff);
|
||||
ORR_IMM8(s3, s3, c, 0); // s3 = ~op1 | op2
|
||||
BIC_REG_LSL_IMM5(s4, s4, s1, 0); // s4 = ~op1 & op2
|
||||
}
|
||||
SUB_IMM8(s1, s1, c);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
|
||||
@@ -560,6 +550,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -618,13 +609,11 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
UBFX(s3, s1, 16, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -654,12 +643,12 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_add16);
|
||||
MOVW(s4, d_add16);
|
||||
} else IFX(X_ALL) {
|
||||
MOVW(s3, d_none);
|
||||
MOVW(s4, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
MOV_REG(s4, s1);
|
||||
@@ -667,7 +656,7 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
if(c>=0 && c<256) {
|
||||
ADD_IMM8(s1, s1, c);
|
||||
} else {
|
||||
MOVW(s3, c);
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
ADD_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
}
|
||||
|
||||
@@ -700,13 +689,11 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
UBFX(s3, s1, 16, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -749,11 +736,8 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
}
|
||||
|
||||
SUB_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
|
||||
@@ -774,6 +758,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -803,12 +788,12 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
MOVW(s3, c);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_sub16);
|
||||
MOVW(s4, d_sub16);
|
||||
} else IFX(X_ALL) {
|
||||
MOVW(s3, d_none);
|
||||
MOVW(s4, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
MVN_REG_LSL_IMM5(s4, s1, 0);
|
||||
@@ -816,14 +801,11 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
if(c>=0 && c<255) {
|
||||
SUB_IMM8(s1, s1, c);
|
||||
} else {
|
||||
MOVW(s3, c);
|
||||
IFX(X_PEND) {} else {MOVW(s3, c);}
|
||||
SUB_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
if(c>=0 && c<256) {
|
||||
@@ -854,6 +836,7 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -881,10 +864,10 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(s4, d_inc32);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s4, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF) {
|
||||
@@ -937,10 +920,10 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(s3, d_inc8);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s3, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
@@ -948,7 +931,9 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
AND_IMM8(s4, s1, 1); // s4 = op1 & op2
|
||||
}
|
||||
ADD_IMM8(s1, s1, 1);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
BIC_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (op1 | op2) & ~ res
|
||||
ORR_REG_LSL_IMM5(s3, s3, s4, 0); // s4 = (op1 & op2) | ((op1 | op2) & ~ res)
|
||||
@@ -964,13 +949,8 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -997,17 +977,19 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(s3, d_inc16);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s3, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
MOV_REG(s4, s1);
|
||||
}
|
||||
ADD_IMM8(s1, s1, 1);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_IMM8(s3, s4, 1, 0); // s3 = op1 | op2
|
||||
AND_IMM8(s4, s4, 1); // s4 = op1 & op2
|
||||
@@ -1025,13 +1007,8 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -1059,10 +1036,10 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(s4, d_dec32);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s4, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF) {
|
||||
@@ -1116,10 +1093,10 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_dec8);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s3, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
@@ -1128,11 +1105,8 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
ORR_IMM8(s3, s3, 1, 0); // s3 = ~op1 | op2
|
||||
}
|
||||
SUB_IMM8(s1, s1, 1);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
AND_REG_LSL_IMM5(s3, s3, s1, 0); // s3 = (~op1 | op2) & res
|
||||
@@ -1149,6 +1123,7 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -1175,21 +1150,18 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
MOVW(s3, d_dec16);
|
||||
} else IFX(X_ALL) {
|
||||
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
MOVW(s3, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
IFX(X_PEND|X_ZF|X_OF|X_AF|X_SF|X_PF) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
MVN_REG_LSL_IMM5(s4, s1, 0);
|
||||
}
|
||||
SUB_IMM8(s1, s1, 1);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_IMM8(s3, s4, 1, 0); // s3 = ~op1 | op2
|
||||
@@ -1208,6 +1180,7 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -1247,7 +1220,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
|
||||
}
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
IFX(X_ALL) {
|
||||
IFX(X_ZF|X_CF|X_OF) {
|
||||
ADCS_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
} else {
|
||||
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
@@ -1397,6 +1370,9 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = op1 | op2
|
||||
AND_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = op1 & op2
|
||||
@@ -1417,13 +1393,8 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
UBFX(s3, s1, 8, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -1449,15 +1420,15 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
MOVW(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_adc8);
|
||||
MOVW(s4, d_adc8);
|
||||
} else IFX(X_ALL) {
|
||||
MOVW(s3, d_none);
|
||||
MOVW(s4, d_none);
|
||||
}
|
||||
IFX(X_PEND|X_ALL) {
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
|
||||
}
|
||||
IFX(X_AF | X_OF) {
|
||||
MOV_REG(s4, s1);
|
||||
@@ -1465,7 +1436,9 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
ADC_IMM8(s1, s1, c);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_IMM8(s3, s4, c, 0); // s3 = op1 | op2
|
||||
AND_IMM8(s4, s4, c); // s4 = op1 & op2
|
||||
@@ -1486,17 +1459,11 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
UBFX(s3, s1, 8, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
|
||||
IFX(X_PEND|X_ZF) {
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 7, 1);
|
||||
@@ -1534,7 +1501,9 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF])); // load CC
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
ADC_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = op1 | op2
|
||||
AND_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = op1 & op2
|
||||
@@ -1555,17 +1524,12 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
UBFX(s3, s1, 16, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 15, 1);
|
||||
@@ -1609,7 +1573,9 @@ void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
MOVW(s3, c);
|
||||
ADC_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
}
|
||||
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
if(c>=0 && c<256) {
|
||||
ORR_IMM8(s3, s4, c, 0); // s3 = op1 | op2
|
||||
@@ -1639,17 +1605,12 @@ void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
UBFX(s3, s1, 16, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 15, 1);
|
||||
@@ -1839,16 +1800,8 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
SBC_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = ~op1 | op2
|
||||
@@ -1870,6 +1823,12 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 7, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
|
||||
@@ -1891,7 +1850,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
|
||||
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
{
|
||||
IFX(X_PEND) {
|
||||
MOVW(s3, c);
|
||||
MOVW(s3, c&0xff);
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
|
||||
MOVW(s3, d_sbb8);
|
||||
@@ -1908,11 +1867,8 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
SBC_IMM8(s1, s1, c);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
ORR_IMM8(s3, s4, c, 0); // s3 = ~op1 | op2
|
||||
@@ -1935,6 +1891,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
@@ -1977,11 +1934,8 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
XOR_IMM8(s3, s3, 1); // invert CC because it's reverted for SUB on ARM
|
||||
MOVS_REG_LSR_IMM5(s3, s3, 1); // load into ARM CF
|
||||
SBC_REG_LSL_IMM5(s1, s1, s2, 0);
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
ORR_REG_LSL_IMM5(s3, s4, s2, 0); // s3 = ~op1 | op2
|
||||
@@ -2004,6 +1958,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -2052,11 +2007,8 @@ void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
MOVW(s3, c);
|
||||
SBC_REG_LSL_IMM5(s1, s1, s3, 0);
|
||||
}
|
||||
IFX(X_PEND|X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF|X_CF) {
|
||||
if(c>=0 && c<256) {
|
||||
@@ -2087,6 +2039,7 @@ void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cNE, s3, 0);
|
||||
MOVW_COND(cEQ, s3, 1);
|
||||
@@ -2134,6 +2087,9 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
} else {
|
||||
RSB_IMM8(s1, s1, 0);
|
||||
}
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
@@ -2187,17 +2143,8 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MOV_REG_LSL_IMM5(s3, s1, 0);
|
||||
}
|
||||
RSB_IMM8(s1, s1, 0);
|
||||
IFX(X_ZF) {
|
||||
BFI(s1, s1, 0, 16);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_OF) {
|
||||
MOVW_COND(cVC, s4, 0);
|
||||
MOVW_COND(cVS, s4, 1);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_REG_LSL_IMM5(s3, s3, s1, 0); // bc = op1 | res
|
||||
@@ -2211,7 +2158,14 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
AND_IMM8(s4, s4, 1);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
|
||||
}
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
UXTH(s1, s1, 0);
|
||||
TSTS_REG_LSL_IMM5(s1, s1, 0);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 15, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
|
||||
@@ -2250,16 +2204,8 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
MOV_REG_LSL_IMM5(s3, s1, 0);
|
||||
}
|
||||
RSB_IMM8(s1, s1, 0);
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_OF) {
|
||||
MOVW_COND(cVC, s4, 0);
|
||||
MOVW_COND(cVS, s4, 1);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
|
||||
IFX(X_PEND) {
|
||||
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
|
||||
}
|
||||
IFX(X_AF|X_OF) {
|
||||
ORR_REG_LSL_IMM5(s3, s3, s1, 0); // bc = op1 | res
|
||||
@@ -2273,7 +2219,13 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
|
||||
AND_IMM8(s4, s4, 1);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
|
||||
}
|
||||
}
|
||||
}
|
||||
IFX(X_ZF) {
|
||||
ANDS_IMM8(s1, s1, 0xff);
|
||||
MOVW_COND(cEQ, s4, 1);
|
||||
MOVW_COND(cNE, s4, 0);
|
||||
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
}
|
||||
IFX(X_SF) {
|
||||
UBFX(s3, s1, 7, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
|
||||
|
||||
@@ -48,8 +48,10 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
|
||||
return;
|
||||
}
|
||||
IFX(X_CF) {
|
||||
UBFX(s3, s1, c, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
if(c<31) {
|
||||
UBFX(s3, s1, 32-c, 1);
|
||||
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
}
|
||||
}
|
||||
IFX(X_ZF|X_OF) {
|
||||
MOVS_REG_LSL_IMM5(s1, s1, c);
|
||||
|
||||
+827
-33
@@ -24,13 +24,477 @@
|
||||
|
||||
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
|
||||
{
|
||||
uint8_t nextop = PK(0); // don't increment addr
|
||||
int locked = 0;
|
||||
switch(nextop) {
|
||||
// generic case
|
||||
uint8_t nextop, opcode = F8;
|
||||
uint8_t wback, wb1, wb2, gb1, gb2;
|
||||
uint8_t ed, gd, u8;
|
||||
int fixedaddress;
|
||||
int32_t i32, j32;
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
MAYUSE(gb1);
|
||||
MAYUSE(gb2);
|
||||
MAYUSE(wb1);
|
||||
MAYUSE(wb2);
|
||||
switch(opcode) {
|
||||
case 0x00:
|
||||
INST_NAME("LOCK ADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_add8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_add8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
INST_NAME("LOCK ADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_add32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x08:
|
||||
INST_NAME("LOCK OR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_or8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_or8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
INST_NAME("LOCK OR Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_or32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x10:
|
||||
INST_NAME("LOCK ADC Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_adc8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_adc8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
INST_NAME("LOCK ADC Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_adc32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x18:
|
||||
INST_NAME("LOCK SBB Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_sbb8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_sbb8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x19:
|
||||
INST_NAME("LOCK SBB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sbb32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
INST_NAME("LOCK AND Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_and8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_and8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x21:
|
||||
INST_NAME("LOCK AND Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_and32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x28:
|
||||
INST_NAME("LOCK SUB Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_sub8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_sub8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x29:
|
||||
INST_NAME("LOCK SUB Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sub32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 0x38:
|
||||
INST_NAME("LOCK XOR Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x2);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x1, wback, wb2);
|
||||
emit_xor8(dyn, ninst, x1, x2, x12, x3, 0);
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x1, wback);
|
||||
emit_xor8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
}
|
||||
break;
|
||||
case 0x39:
|
||||
INST_NAME("LOCK XOR Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_xor32(dyn, ninst, x1, gd, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: //ADD
|
||||
if(opcode==0x81) {
|
||||
INST_NAME("LOCK ADD Ed, Id");
|
||||
} else {
|
||||
INST_NAME("LOCK ADD Ed, Ib");
|
||||
}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_add32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
TSTS_IMM8(wback, 0x3);
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_add32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
B_NEXT(c__);
|
||||
MARK; // unaligned! also, not enough
|
||||
LDR_IMM9(x1, wback, 0);
|
||||
LDREXB(x12, wback);
|
||||
BFI(x1, x12, 0, 8); // re-inject
|
||||
emit_add32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREXB(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0); // put the whole value
|
||||
}
|
||||
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);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_or32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_or32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
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);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_adc32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_adc32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
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);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sbb32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sbb32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
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);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_and32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_and32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 5: //SUB
|
||||
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_sub32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
TSTS_IMM8(wback, 0x3);
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
B_NEXT(c__);
|
||||
MARK; // unaligned! also, not enough
|
||||
LDR_IMM9(x1, wback, 0);
|
||||
LDREXB(x12, wback);
|
||||
BFI(x1, x12, 0, 8); // re-inject
|
||||
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREXB(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x1, wback, 0); // put the whole value
|
||||
}
|
||||
break;
|
||||
case 6: //XOR
|
||||
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_xor32c(dyn, ninst, ed, i32, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_xor32c(dyn, ninst, x1, i32, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
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);
|
||||
GETEDH(x1);
|
||||
// No need to LOCK, this is readonly
|
||||
if(opcode==0x81) i32 = F32S; else i32 = F8S;
|
||||
if(i32) {
|
||||
MOV32(x2, i32);
|
||||
emit_cmp32(dyn, ninst, ed, x2, x3, x12);
|
||||
} else {
|
||||
emit_cmp32_0(dyn, ninst, ed, x3, x12);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
|
||||
#define GO(A) \
|
||||
case A+0x00: \
|
||||
case A+0x01: \
|
||||
case A+0x02: \
|
||||
case A+0x03: \
|
||||
case A+0x04: \
|
||||
@@ -43,62 +507,392 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GO(0x28);
|
||||
GO(0x30);
|
||||
#undef GO
|
||||
|
||||
case 0x81:
|
||||
case 0x83:
|
||||
MESSAGE(LOG_DUMP, "LOCK\n");
|
||||
locked = 1;
|
||||
LOCK;
|
||||
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
break;
|
||||
|
||||
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
|
||||
case 0x87:
|
||||
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
--addr;
|
||||
break;
|
||||
|
||||
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
--addr;
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
nextop = PK(1);
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xB0:
|
||||
INST_NAME("LOCK CMPXCHG Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x2, wback, wb2);
|
||||
ed = x2;
|
||||
wb1 = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x2, wback);
|
||||
ed = x2;
|
||||
wb1 = 1;
|
||||
}
|
||||
UXTB(x1, xEAX, 0);
|
||||
CMPS_REG_LSL_IMM5(x1, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// AL == Eb
|
||||
GETGB(x1);
|
||||
if(wb1) {
|
||||
STREXB(x12, x1, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE); // write failed, try again
|
||||
if(!(gb1==xEAX && gb2==0)) {
|
||||
UXTB(x1, xEAX, 0); // readback AL if needed
|
||||
}
|
||||
} else {
|
||||
BFI(wback, x1, wb2*8, 8);
|
||||
}
|
||||
// done
|
||||
B_MARK3(c__);
|
||||
MARK;
|
||||
// AL != Eb
|
||||
BFI(xEAX, ed, 0, 8);
|
||||
MARK3;
|
||||
// done, do the cmp now
|
||||
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
|
||||
break;
|
||||
case 0xB1:
|
||||
INST_NAME("LOCK CMPXCHG Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
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...
|
||||
ed = x1;
|
||||
}
|
||||
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
|
||||
B_MARK(cNE);
|
||||
// EAX == Ed
|
||||
if(wback) {
|
||||
TSTS_IMM8(wback, 3);
|
||||
STREX_COND(cEQ, x12, gd, wback);
|
||||
STREXB_COND(cNE, x12, gd, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
TSTS_IMM8(wback, 3); // anoying, all those test
|
||||
STR_IMM9_COND(cNE, gd, wback, 0);
|
||||
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
|
||||
} else {
|
||||
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
|
||||
MOV_REG(ed, gd);
|
||||
}
|
||||
// done
|
||||
B_MARK3(c__); // not next, in case its called with a LOCK prefix
|
||||
MARK;
|
||||
// EAX != Ed
|
||||
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
|
||||
MOV_REG(xEAX, ed);
|
||||
MARK3
|
||||
break;
|
||||
case 0xB3:
|
||||
INST_NAME("LOCK BTR Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
wback = x3;
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
ed = x1;
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x12, ed, x2);
|
||||
ANDS_IMM8(x12, x12, 1);
|
||||
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
B_MARK3(cEQ); // bit already clear, jump to end of instruction
|
||||
MOVW(x12, 1);
|
||||
XOR_REG_LSL_REG(ed, ed, x12, x2);
|
||||
if(wback) {
|
||||
STREX(x12, ed, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4:
|
||||
INST_NAME("(LOCK) BT Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0);
|
||||
u8 = F8;
|
||||
fixedaddress+=(u8>>5)*4;
|
||||
LDR_IMM9(x1, ed, fixedaddress);
|
||||
ed = x1;
|
||||
}
|
||||
u8&=0x1f;
|
||||
if(u8) {
|
||||
MOV_REG_LSR_IMM5(x1, ed, u8);
|
||||
ed = x1;
|
||||
}
|
||||
AND_IMM8(x1, ed, 1);
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
break;
|
||||
case 6:
|
||||
INST_NAME("LOCK BTR Ed, Ib");
|
||||
SETFLAGS(X_CF, SF_SUBSET);
|
||||
gd = x2;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0, 0);
|
||||
u8 = F8;
|
||||
MOVW(gd, u8);
|
||||
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
|
||||
MARKLOCK;
|
||||
LDREX(x1, x3);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x12, ed, x2);
|
||||
ANDS_IMM8(x12, x12, 1);
|
||||
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
B_MARK3(cEQ); // bit already clear, jump to next instruction
|
||||
//MOVW(x12, 1); // already 0x01
|
||||
XOR_REG_LSL_REG(ed, ed, x12, x2);
|
||||
if(wback) {
|
||||
STREX(x12, ed, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
MARK3;
|
||||
break;
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
break;
|
||||
case 0xBB:
|
||||
INST_NAME("LOCK BTC Ed, Gd");
|
||||
SETFLAGS(X_CF, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
wback = 0;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
|
||||
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
|
||||
MARKLOCK;
|
||||
LDREX(x1, x3);
|
||||
ed = x1;
|
||||
wback = x3;
|
||||
}
|
||||
AND_IMM8(x2, gd, 0x1f);
|
||||
MOV_REG_LSR_REG(x12, ed, x2);
|
||||
AND_IMM8(x12, x12, 1);
|
||||
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
|
||||
MOVW(x12, 1);
|
||||
XOR_REG_LSL_REG(ed, ed, x12, x2);
|
||||
if(wback) {
|
||||
STREX(x12, ed, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
INST_NAME("LOCK XADD Gb, Eb");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGB(x1);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
wback = (nextop&7);
|
||||
wb2 = (wback>>2);
|
||||
wback = xEAX+(wback&3);
|
||||
UXTB(x2, wback, wb2);
|
||||
wb1 = 0;
|
||||
ed = x2;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREXB(x2, wback);
|
||||
wb1 = 1;
|
||||
ed = x2;
|
||||
}
|
||||
BFI(gb1, ed, gb2*8, 8); // gb <- eb
|
||||
emit_add8(dyn, ninst, ed, gd, x12, x3, 1);
|
||||
if(wb1) {
|
||||
STREXB(x12, ed, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
} else {
|
||||
BFI(wback, ed, wb2*8, 8);
|
||||
}
|
||||
break;
|
||||
case 0xC1:
|
||||
INST_NAME("LOCK XADD Gd, Ed");
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
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);
|
||||
}
|
||||
emit_add32(dyn, ninst, ed, gd, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
TSTS_IMM8(wback, 3);
|
||||
B_MARK(cNE); // unaligned
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
|
||||
STREX(x3, x12, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOV_REG(x2, x1);
|
||||
emit_add32(dyn, ninst, x2, gd, x3, x12);
|
||||
}
|
||||
MOV_REG(gd, x1);
|
||||
B_NEXT(c__);
|
||||
MARK;
|
||||
LDR_IMM9(x1, wback, 0);
|
||||
LDREXB(x12, wback);
|
||||
BFI(x1, x12, 0, 8);
|
||||
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
|
||||
STREXB(x3, x12, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARK(cNE);
|
||||
STR_IMM9(x12, wback, 0);
|
||||
IFX(X_ALL|X_PEND) {
|
||||
MOV_REG(x2, x1);
|
||||
emit_add32(dyn, ninst, x2, gd, x3, x12);
|
||||
}
|
||||
MOV_REG(gd, x1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC7:
|
||||
MESSAGE(LOG_DUMP, "LOCK\n");
|
||||
locked = 1;
|
||||
LOCK;
|
||||
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog);
|
||||
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
|
||||
SETFLAGS(X_ZF, SF_SET);
|
||||
nextop = F8;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
TSTS_IMM8(wback, 7);
|
||||
LDREXD_COND(cEQ, x2, wback);
|
||||
LDREX_COND(cNE, x2, wback);
|
||||
LDR_IMM9_COND(cNE, x3, wback, 4);
|
||||
CMPS_REG_LSL_IMM5(xEAX, x2, 0);
|
||||
B_MARK(cNE); // EAX != Ed[0]
|
||||
CMPS_REG_LSL_IMM5(xEDX, x3, 0);
|
||||
B_MARK(cNE); // EDX != Ed[1]
|
||||
MOV_REG(x2, xEBX);
|
||||
MOV_REG(x3, xECX);
|
||||
TSTS_IMM8(wback, 7);
|
||||
STREXD_COND(cEQ, x12, x2, wback);
|
||||
STREX_COND(cNE, x12, x2, wback);
|
||||
CMPS_IMM8(x12, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
TSTS_IMM8(wback, 7);
|
||||
STR_IMM9_COND(cNE, x3, wback, 4);
|
||||
MOVW(x1, 1);
|
||||
B_MARK3(c__);
|
||||
MARK;
|
||||
MOV_REG(xEAX, x2);
|
||||
MOV_REG(xEDX, x3);
|
||||
MOVW(x1, 0);
|
||||
MARK3;
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
|
||||
break;
|
||||
|
||||
default:
|
||||
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog); // no lock, regular instruction...
|
||||
// dafault to NO LOCK
|
||||
addr-=2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
nextop = PK(1);
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
MESSAGE(LOG_DUMP, "LOCK\n");
|
||||
locked = 1;
|
||||
LOCK;
|
||||
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
|
||||
case 0: // INC Ed
|
||||
INST_NAME("INC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_inc32(dyn, ninst, ed, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_inc32(dyn, ninst, x1, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
case 1: //DEC Ed
|
||||
INST_NAME("DEC Ed");
|
||||
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
ed = xEAX+(nextop&7);
|
||||
emit_dec32(dyn, ninst, ed, x3, x12);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
|
||||
MARKLOCK;
|
||||
LDREX(x1, wback);
|
||||
emit_dec32(dyn, ninst, x1, x3, x12);
|
||||
STREX(x3, x1, wback);
|
||||
CMPS_IMM8(x3, 0);
|
||||
B_MARKLOCK(cNE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
|
||||
// dafault to NO LOCK
|
||||
addr-=2;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
|
||||
// dafault to NO LOCK
|
||||
--addr;
|
||||
}
|
||||
if(locked) {UNLOCK;}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -58,16 +58,17 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
MAYUSE(d0);
|
||||
|
||||
switch(nextop) {
|
||||
|
||||
|
||||
case 0x10:
|
||||
INST_NAME("MOVSD Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
VMOVD(v0, d0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
@@ -94,18 +95,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
INST_NAME("MOVDDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVD(v0, d0);
|
||||
VMOVD(v0+1, d0);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
VMOVD(v0+1, v0);
|
||||
}
|
||||
VMOVD(v0+1, v0);
|
||||
break;
|
||||
|
||||
case 0x2A:
|
||||
@@ -308,6 +309,26 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
VMOVtoV_D(v0, x2, x2);
|
||||
break;
|
||||
|
||||
case 0xF0:
|
||||
INST_NAME("LDDQ Gx,Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VMOVQ(v0, v1);
|
||||
} else {
|
||||
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress+0);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
LDR_IMM9(x2, ed, fixedaddress+8);
|
||||
LDR_IMM9(x3, ed, fixedaddress+12);
|
||||
VMOVtoV_D(v0+1, x2, x3);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
{
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop, u8;
|
||||
int32_t i32;
|
||||
int32_t j32;
|
||||
uint32_t u32;
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
@@ -63,12 +63,13 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
int v0, v1;
|
||||
int s0, s1, s2;
|
||||
int d0, d1;
|
||||
int q0;
|
||||
int q0, q1;
|
||||
int parity;
|
||||
|
||||
MAYUSE(q1);
|
||||
MAYUSE(s1);
|
||||
MAYUSE(s2);
|
||||
MAYUSE(i32);
|
||||
MAYUSE(j32);
|
||||
|
||||
switch(opcode) {
|
||||
|
||||
@@ -132,6 +133,38 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
STR_IMM9(x2, ed, fixedaddress);
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
INST_NAME("MOVSLDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VDUP_32(q0+0, q1+0, 0);
|
||||
VDUP_32(q0+1, q1+1, 0);
|
||||
break;
|
||||
|
||||
case 0x16:
|
||||
INST_NAME("MOVSHDUP Gx, Ex");
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
|
||||
q1 = fpu_get_scratch_quad(dyn);
|
||||
VLD1Q_64(q1, ed);
|
||||
}
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
VDUP_32(q0+0, q1+0, 1);
|
||||
VDUP_32(q0+1, q1+1, 1);
|
||||
break;
|
||||
|
||||
|
||||
case 0x1E:
|
||||
INST_NAME("NOP / ENDBR32 / ENDBR64");
|
||||
@@ -179,8 +212,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
VMOV_32(s0, d0*2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
}
|
||||
VCVT_S32_F32(s0, s0);
|
||||
VMOVfrV(gd, s0);
|
||||
@@ -201,8 +241,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
VMOV_32(s0, d0*2);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_32(s0, ed, fixedaddress);
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
VMOVtoV(s0, x2);
|
||||
}
|
||||
}
|
||||
VCVTR_S32_F32(s0, s0);
|
||||
VMOVfrV(gd, s0);
|
||||
@@ -502,8 +549,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
nextop = F8;
|
||||
gd = (nextop&0x38)>>3;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
|
||||
VMOVQ(v1, v0);
|
||||
} else {
|
||||
v0 = sse_get_reg(dyn, ninst, x1, gd);
|
||||
@@ -566,6 +613,37 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
|
||||
}
|
||||
VMOVtoDx_32(v0, 0, x2);
|
||||
break;
|
||||
|
||||
case 0xE6:
|
||||
INST_NAME("CVTDQ2PD Gx, Ex");
|
||||
nextop = F8;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
|
||||
if(v1<16)
|
||||
v0 = v1;
|
||||
else {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
VMOV_64(v0, v1); // vfpu opcode here
|
||||
}
|
||||
} else {
|
||||
v0 = fpu_get_scratch_double(dyn);
|
||||
parity = getedparity(dyn, ninst, addr, nextop, 3);
|
||||
if(parity) {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
|
||||
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
|
||||
LDR_IMM9(x2, ed, fixedaddress);
|
||||
LDR_IMM9(x3, ed, fixedaddress+4);
|
||||
VMOVtoV_D(v0, x2, x3);
|
||||
}
|
||||
}
|
||||
gd = (nextop&0x38)>>3;
|
||||
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
|
||||
//v0 is a low reg now
|
||||
VCVT_F64_S32(q0+1, v0*2+1);
|
||||
VCVT_F64_S32(q0+0, v0*2+0);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEFAULT;
|
||||
|
||||
@@ -32,6 +32,14 @@ void arm_popf(x86emu_t* emu, uint32_t f)
|
||||
RESET_FLAGS(emu);
|
||||
}
|
||||
|
||||
void arm_popf16(x86emu_t* emu, uint32_t f)
|
||||
{
|
||||
emu->packed_eflags.x32 &= 0xffff0000;
|
||||
emu->packed_eflags.x32 |= (f & 0x7FD7) | 0x2; // mask off res2 and res3 and on res1
|
||||
UnpackFlags(emu);
|
||||
RESET_FLAGS(emu);
|
||||
}
|
||||
|
||||
void arm_fstp(x86emu_t* emu, void* p)
|
||||
{
|
||||
if(ST0.ll!=STld(0).ref)
|
||||
@@ -109,8 +117,10 @@ void arm_fbld(x86emu_t* emu, uint8_t* ed)
|
||||
|
||||
void arm_fild64(x86emu_t* emu, int64_t* ed)
|
||||
{
|
||||
ST0.d = *ed;
|
||||
STll(0).ll = *ed;
|
||||
int64_t tmp;
|
||||
memcpy(&tmp, ed, sizeof(tmp));
|
||||
ST0.d = tmp;
|
||||
STll(0).ll = tmp;
|
||||
STll(0).ref = ST0.ll;
|
||||
}
|
||||
|
||||
@@ -121,13 +131,16 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
|
||||
|
||||
void arm_fistp64(x86emu_t* emu, int64_t* ed)
|
||||
{
|
||||
// used of memcpy to avoid aligments issues
|
||||
if(STll(0).ref==ST(0).ll) {
|
||||
*ed = STll(0).ll;
|
||||
memcpy(ed, &STll(0).ll, sizeof(int64_t));
|
||||
} else {
|
||||
int64_t tmp;
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
|
||||
*ed = 0x8000000000000000LL;
|
||||
tmp = 0x8000000000000000LL;
|
||||
else
|
||||
*ed = (int64_t)ST0.d;
|
||||
tmp = (int64_t)ST0.d;
|
||||
memcpy(ed, &tmp, sizeof(tmp));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,31 +156,6 @@ void arm_ud(x86emu_t* emu)
|
||||
kill(getpid(), SIGILL);
|
||||
}
|
||||
|
||||
void arm_fxsave(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
// should save flags & all
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(ed+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(ed+160, &emu->xmm[0], sizeof(emu->xmm));
|
||||
// put also FPU regs in a reserved area...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(ed+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
|
||||
}
|
||||
|
||||
void arm_fxrstor(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
// should restore flags & all
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx[i], ed+32+i*16, sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], ed+160/4, sizeof(emu->xmm));
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->fpu[0], ed+416+i*8, sizeof(emu->fpu[0]));
|
||||
}
|
||||
|
||||
void arm_fsave(x86emu_t* emu, uint8_t* ed)
|
||||
{
|
||||
fpu_savenv(emu, (char*)ed, 0);
|
||||
@@ -175,12 +163,7 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed)
|
||||
uint8_t* p = ed;
|
||||
p += 28;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
d = ST(i).f;
|
||||
LD2D(p, &d);
|
||||
#else
|
||||
LD2D(p, &ST(i).d);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
@@ -191,17 +174,23 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
|
||||
uint8_t* p = ed;
|
||||
p += 28;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
D2LD(&d, p);
|
||||
ST(i).f = d;
|
||||
#else
|
||||
D2LD(&ST(i).d, p);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void arm_fprem1(x86emu_t* emu)
|
||||
{
|
||||
// simplified version
|
||||
int32_t tmp32s = round(ST0.d / ST1.d);
|
||||
ST0.d -= ST1.d*tmp32s;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = (tmp32s&1);
|
||||
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
|
||||
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
|
||||
}
|
||||
|
||||
|
||||
// Get a FPU single scratch reg
|
||||
int fpu_get_scratch_single(dynarec_arm_t* dyn)
|
||||
@@ -218,6 +207,13 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn)
|
||||
// Get a FPU quad scratch reg
|
||||
int fpu_get_scratch_quad(dynarec_arm_t* dyn)
|
||||
{
|
||||
if(dyn->fpu_scratch>4) {
|
||||
if(dyn->fpu_extra_qscratch) {
|
||||
dynarec_log(LOG_NONE, "Warning, Extra QScratch slot taken and need another one!\n");
|
||||
} else
|
||||
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn);
|
||||
return dyn->fpu_extra_qscratch;
|
||||
}
|
||||
int i = (dyn->fpu_scratch+3)&(~3);
|
||||
dyn->fpu_scratch = i+4;
|
||||
return i/2; // Return a Dx, not a Qx
|
||||
@@ -226,6 +222,10 @@ int fpu_get_scratch_quad(dynarec_arm_t* dyn)
|
||||
void fpu_reset_scratch(dynarec_arm_t* dyn)
|
||||
{
|
||||
dyn->fpu_scratch = 0;
|
||||
if(dyn->fpu_extra_qscratch) {
|
||||
fpu_free_reg_quad(dyn, dyn->fpu_extra_qscratch);
|
||||
dyn->fpu_extra_qscratch = 0;
|
||||
}
|
||||
}
|
||||
#define FPUFIRST 8
|
||||
// Get a FPU double reg
|
||||
@@ -306,3 +306,29 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
|
||||
#undef F8
|
||||
#undef F32
|
||||
}
|
||||
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
|
||||
{
|
||||
#define PK(a) *(uint8_t*)(addr+a)
|
||||
#define PK32(a) *(uint32_t*)(addr+a)
|
||||
|
||||
if(!addr)
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
|
||||
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = *(uint32_t*)a1;
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
|
||||
// found !
|
||||
if(retn) *retn = (b->C3==0xC2)?b->N:0;
|
||||
if(calladdress) *calladdress = addr+1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#undef PK32
|
||||
#undef PK
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
void arm_popf(x86emu_t* emu, uint32_t f);
|
||||
void arm_popf16(x86emu_t* emu, uint32_t f);
|
||||
void arm_fstp(x86emu_t* emu, void* p);
|
||||
|
||||
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
|
||||
@@ -25,10 +26,9 @@ void arm_fild64(x86emu_t* emu, int64_t* ed);
|
||||
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fistp64(x86emu_t* emu, int64_t* ed);
|
||||
void arm_fld(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fxsave(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fxrstor(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fsave(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_frstor(x86emu_t* emu, uint8_t* ed);
|
||||
void arm_fprem1(x86emu_t* emu);
|
||||
|
||||
void arm_ud(x86emu_t* emu);
|
||||
|
||||
@@ -54,4 +54,7 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
|
||||
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
|
||||
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
|
||||
|
||||
// Is what pointed at addr a native call? And if yes, to what function?
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
|
||||
|
||||
#endif //__DYNAREC_ARM_FUNCTIONS_H__
|
||||
@@ -177,6 +177,81 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
|
||||
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask)
|
||||
{
|
||||
uint8_t ret = x2;
|
||||
uint8_t scratch = x3;
|
||||
*fixaddress = 0;
|
||||
if(hint>0) ret = hint;
|
||||
if(scratch==ret) scratch = x2;
|
||||
MAYUSE(scratch);
|
||||
uint32_t m = nextop&0xC7;
|
||||
uint32_t n = (m>>6)&3;
|
||||
int32_t offset = 0;
|
||||
if(!n && m==6) {
|
||||
offset = F16;
|
||||
MOVW(ret, offset);
|
||||
} else {
|
||||
switch(n) {
|
||||
case 0: offset = 0; break;
|
||||
case 1: offset = F8S; break;
|
||||
case 2: offset = F16S; break;
|
||||
}
|
||||
if(offset && (abs(offset)>absmax || (offset&mask))) {
|
||||
*fixaddress = offset;
|
||||
offset = 0;
|
||||
}
|
||||
switch(m&7) {
|
||||
case 0: //R_BX + R_SI
|
||||
UBFX(ret, xEBX, 0, 16);
|
||||
UBFX(scratch, xESI, 0, 16);
|
||||
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
|
||||
break;
|
||||
case 1: //R_BX + R_DI
|
||||
UBFX(ret, xEBX, 0, 16);
|
||||
UBFX(scratch, xEDI, 0, 16);
|
||||
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
|
||||
break;
|
||||
case 2: //R_BP + R_SI
|
||||
UBFX(ret, xEBP, 0, 16);
|
||||
UBFX(scratch, xESI, 0, 16);
|
||||
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
|
||||
break;
|
||||
case 3: //R_BP + R_DI
|
||||
UBFX(ret, xEBP, 0, 16);
|
||||
UBFX(scratch, xEDI, 0, 16);
|
||||
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
|
||||
break;
|
||||
case 4: //R_SI
|
||||
UBFX(ret, xESI, 0, 16);
|
||||
break;
|
||||
case 5: //R_DI
|
||||
UBFX(ret, xEDI, 0, 16);
|
||||
break;
|
||||
case 6: //R_BP
|
||||
UBFX(ret, xEBP, 0, 16);
|
||||
break;
|
||||
case 7: //R_BX
|
||||
UBFX(ret, xEBX, 0, 16);
|
||||
break;
|
||||
}
|
||||
if(offset) {
|
||||
if(offset<0 && offset>-256) {
|
||||
SUB_IMM8(ret, ret, -offset);
|
||||
} else if(offset>0 && offset<256) {
|
||||
ADD_IMM8(ret, ret, offset);
|
||||
} else {
|
||||
MOVW(scratch, offset);
|
||||
ADD_REG_LSL_IMM5(ret, ret, scratch, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ed = ret;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Jump to epilog\n");
|
||||
@@ -195,8 +270,8 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
{
|
||||
MESSAGE(LOG_DUMP, "Jump to linker (#%d) nolinker=%d\n", dyn->tablei, dyn->nolinker);
|
||||
int i32;
|
||||
MAYUSE(i32);
|
||||
int j32;
|
||||
MAYUSE(j32);
|
||||
if(dyn->nolinker==2) {
|
||||
jump_to_epilog(dyn, ip, reg, ninst);
|
||||
} else {
|
||||
@@ -218,12 +293,12 @@ void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
|
||||
// TODO: This is not thread safe.
|
||||
if(!ip) { // no IP, jump address in a reg, so need smart linker
|
||||
MARK;
|
||||
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
|
||||
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
BXcond(cEQ, x2);
|
||||
MOV32_(x2, (uintptr_t)arm_linker);
|
||||
MOV_REG(x3, x12);
|
||||
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
|
||||
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
|
||||
// x12 now contain success / falure for write
|
||||
CMPS_IMM8(x12, 1);
|
||||
MOV_REG(x12, x3); // put back IP in place...
|
||||
@@ -263,12 +338,12 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
|
||||
dyn->tablei+=4; // smart linker
|
||||
MOV32_(x1, (uintptr_t)table);
|
||||
MARK;
|
||||
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
|
||||
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
BXcond(cEQ, x2);
|
||||
MOV32_(x2, (uintptr_t)arm_linker);
|
||||
MOV_REG(x3, x12);
|
||||
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
|
||||
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
|
||||
// x12 now contain success / falure for write
|
||||
CMPS_IMM8(x12, 1);
|
||||
MOV_REG(x12, x3); // put back IP in place...
|
||||
@@ -287,7 +362,12 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
#endif
|
||||
MESSAGE(LOG_DUMP, "Retn epilog\n");
|
||||
POP(xESP, 1<<xEIP);
|
||||
ADD_IMM8(xESP, xESP, n);
|
||||
if(n>0xff) {
|
||||
MOVW(x1, n);
|
||||
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
|
||||
} else {
|
||||
ADD_IMM8(xESP, xESP, n);
|
||||
}
|
||||
cstack_pop(dyn, ninst, xEIP, x1, x2);
|
||||
PASS3(void* epilog = arm_epilog);
|
||||
MOV32_(x2, (uintptr_t)epilog);
|
||||
@@ -306,12 +386,12 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
|
||||
dyn->tablei+=4; // smart linker
|
||||
MOV32_(x1, (uintptr_t)table);
|
||||
MARK;
|
||||
LDREXD(x1, x2); // load dest address in x2 and planned ip in x3
|
||||
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
|
||||
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
|
||||
BXcond(cEQ, x2);
|
||||
MOV32_(x2, (uintptr_t)arm_linker);
|
||||
MOV_REG(x3, x12);
|
||||
STREXD(x12, x1, x2); // nope, putting back linker & IP in place
|
||||
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
|
||||
// x12 now contain success / falure for write
|
||||
CMPS_IMM8(x12, 1);
|
||||
MOV_REG(x12, x3); // put back IP in place...
|
||||
@@ -378,8 +458,8 @@ void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
|
||||
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
{
|
||||
int32_t i32;
|
||||
MAYUSE(i32);
|
||||
int32_t j32;
|
||||
MAYUSE(j32);
|
||||
MESSAGE(LOG_DUMP, "Get FS: Offset\n");
|
||||
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_clean[_FS]));
|
||||
CMPS_IMM8(x12, 1);
|
||||
@@ -391,48 +471,6 @@ void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
|
||||
MESSAGE(LOG_DUMP, "----FS: Offset\n");
|
||||
}
|
||||
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
|
||||
{
|
||||
if(!addr)
|
||||
return 0;
|
||||
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
|
||||
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
|
||||
addr = *(uint32_t*)a1;
|
||||
}
|
||||
if(addr<0x10000) // too low, that is suspicious
|
||||
return 0;
|
||||
onebridge_t *b = (onebridge_t*)(addr);
|
||||
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0) {
|
||||
// found !
|
||||
if(retn) *retn = (b->C3==0xC2)?b->N:0;
|
||||
if(calladdress) *calladdress = addr+1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// emit "lock", x1, x2 and x3 are lost
|
||||
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst)
|
||||
{
|
||||
PUSH(xSP, (1<<xEmu)); // save Emu
|
||||
LDR_IMM9(xEmu, xEmu, offsetof(x86emu_t, context));
|
||||
MOV32(x1, offsetof(box86context_t, mutex_lock)); // offset is way to big for imm8
|
||||
ADD_REG_LSL_IMM5(xEmu, xEmu, x1, 0);
|
||||
CALL(pthread_mutex_lock, -2, 0);
|
||||
POP(xSP, (1<<xEmu));
|
||||
}
|
||||
|
||||
// emit "unlock", x1, x2 and x3 are lost
|
||||
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst)
|
||||
{
|
||||
PUSH(xSP, (1<<xEmu)); // save Emu
|
||||
LDR_IMM9(xEmu, xEmu, offsetof(x86emu_t, context));
|
||||
MOV32(x1, offsetof(box86context_t, mutex_lock)); // offset is way to big for imm8
|
||||
ADD_REG_LSL_IMM5(xEmu, xEmu, x1, 0);
|
||||
CALL(pthread_mutex_unlock, -2, 0);
|
||||
POP(xSP, (1<<xEmu));
|
||||
}
|
||||
|
||||
// x87 stuffs
|
||||
static void x87_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
@@ -547,8 +585,13 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
if(a>0) {
|
||||
// new tag to fulls
|
||||
MOVW(s3, 0);
|
||||
MOVW(s1, offsetof(x86emu_t, p_regs));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<a; ++i) {
|
||||
SUB_IMM8(s2, s2, 1);
|
||||
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
|
||||
@@ -557,8 +600,13 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
|
||||
} else {
|
||||
// empty tags
|
||||
MOVW(s3, 0b11);
|
||||
MOVW(s1, offsetof(x86emu_t, p_regs));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, p_regs);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOVW(s1, offsetof(x86emu_t, p_regs));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
for (int i=0; i<-a; ++i) {
|
||||
STR_REG_LSL_IMM5(s3, s1, s2, 2); // empty slot before leaving it
|
||||
ADD_IMM8(s2, s2, 1);
|
||||
@@ -839,8 +887,13 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
if(dyn->mmxcache[a]!=-1)
|
||||
return dyn->mmxcache[a];
|
||||
int ret = dyn->mmxcache[a] = fpu_get_reg_double(dyn);
|
||||
MOV32(s1, offsetof(x86emu_t, mmx[a]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, mmx[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
VLD1_32(ret, s1);
|
||||
return ret;
|
||||
#else
|
||||
@@ -868,8 +921,13 @@ static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
|
||||
MOV32(s1, offsetof(x86emu_t, mmx[i]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, mmx[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
old = i+1; //+1 because VST1 with write back
|
||||
} else {
|
||||
if(old!=i) {
|
||||
@@ -894,8 +952,13 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->mmxcache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MOV32(s1, offsetof(x86emu_t, mmx[i]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, mmx[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
old = i+1;
|
||||
} else {
|
||||
if(old!=i) {
|
||||
@@ -925,8 +988,13 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
|
||||
if(dyn->ssecache[a]!=-1)
|
||||
return dyn->ssecache[a];
|
||||
int ret = dyn->ssecache[a] = fpu_get_reg_quad(dyn);
|
||||
MOV32(s1, offsetof(x86emu_t, xmm[a]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, xmm[a]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, (offs>>2), 0xf);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
VLD1Q_32(ret, s1);
|
||||
return ret;
|
||||
#else
|
||||
@@ -954,8 +1022,13 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MESSAGE(LOG_DUMP, "\tPurge SSE Cache ------\n");
|
||||
MOV32(s1, offsetof(x86emu_t, xmm[i]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, xmm[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
old = i+1; //+1 because VST1Q with write back
|
||||
} else {
|
||||
if(old!=i) {
|
||||
@@ -980,8 +1053,13 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
|
||||
for (int i=0; i<8; ++i)
|
||||
if(dyn->ssecache[i]!=-1) {
|
||||
if (old==-1) {
|
||||
MOV32(s1, offsetof(x86emu_t, xmm[i]));
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
int offs = offsetof(x86emu_t, xmm[i]);
|
||||
if(!(offs&3) && (offs>>2)<256) {
|
||||
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
|
||||
} else {
|
||||
MOV32(s1, offs);
|
||||
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
|
||||
}
|
||||
old = i+1;
|
||||
} else {
|
||||
if(old!=i) {
|
||||
|
||||
@@ -132,6 +132,21 @@
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
|
||||
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
|
||||
wback = (nextop&7); \
|
||||
wb2 = (wback>>2); \
|
||||
wback = xEAX+(wback&3); \
|
||||
UXTB(i, wback, wb2); \
|
||||
wb1 = 0; \
|
||||
ed = i; \
|
||||
} else { \
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
|
||||
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
|
||||
LDRB_IMM9(i, wback, fixedaddress); \
|
||||
wb1 = 1; \
|
||||
ed = i; \
|
||||
}
|
||||
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
|
||||
#define GETSEB(i) if((nextop&0xC0)==0xC0) { \
|
||||
wback = (nextop&7); \
|
||||
@@ -186,31 +201,38 @@
|
||||
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
|
||||
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
|
||||
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
|
||||
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
|
||||
|
||||
// Branch to MARK if cond (use i32)
|
||||
// Branch to MARK if cond (use j32)
|
||||
#define B_MARK(cond) \
|
||||
i32 = GETMARK-(dyn->arm_size+8); \
|
||||
Bcond(cond, i32)
|
||||
// Branch to MARK2 if cond (use i32)
|
||||
j32 = GETMARK-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK2 if cond (use j32)
|
||||
#define B_MARK2(cond) \
|
||||
i32 = GETMARK2-(dyn->arm_size+8); \
|
||||
Bcond(cond, i32)
|
||||
// Branch to MARK3 if cond (use i32)
|
||||
j32 = GETMARK2-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARK3 if cond (use j32)
|
||||
#define B_MARK3(cond) \
|
||||
i32 = GETMARK3-(dyn->arm_size+8); \
|
||||
Bcond(cond, i32)
|
||||
// Branch to next instruction if cond (use i32)
|
||||
j32 = GETMARK3-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to next instruction if cond (use j32)
|
||||
#define B_NEXT(cond) \
|
||||
i32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
|
||||
Bcond(cond, i32)
|
||||
// Branch to MARKSEG if cond (use i32)
|
||||
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKSEG if cond (use j32)
|
||||
#define B_MARKSEG(cond) \
|
||||
i32 = GETMARKSEG-(dyn->arm_size+8); \
|
||||
Bcond(cond, i32)
|
||||
j32 = GETMARKSEG-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
// Branch to MARKLOCK if cond (use j32)
|
||||
#define B_MARKLOCK(cond) \
|
||||
j32 = GETMARKLOCK-(dyn->arm_size+8); \
|
||||
Bcond(cond, j32)
|
||||
|
||||
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
|
||||
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
|
||||
#define IFX2X(A, B) if(dyn->insts && (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 && (dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
|
||||
|
||||
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOM(s1, s2) \
|
||||
@@ -265,8 +287,8 @@
|
||||
if(dyn->state_flags!=SF_PENDING) { \
|
||||
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
|
||||
TSTS_REG_LSL_IMM5(x3, x3, 0); \
|
||||
i32 = (GETMARKF)-(dyn->arm_size+8); \
|
||||
Bcond(cEQ, i32); \
|
||||
j32 = (GETMARKF)-(dyn->arm_size+8); \
|
||||
Bcond(cEQ, j32); \
|
||||
} \
|
||||
CALL_(UpdateFlags, -1, 0); \
|
||||
MARKF; \
|
||||
@@ -301,11 +323,13 @@
|
||||
#define NEW_BARRIER_INST
|
||||
#endif
|
||||
|
||||
// Emit the LOCK mutex (x1, x2 and x3 are lost)
|
||||
#define LOCK emit_lock(dyn, addr, ninst)
|
||||
// Emit the UNLOCK mutex (x1, x2 and x3 are lost)
|
||||
#define UNLOCK emit_unlock(dyn, addr, ninst)
|
||||
|
||||
#if STEP < 2
|
||||
#define PASS2IF(A, B) if(A)
|
||||
#elif STEP == 2
|
||||
#define PASS2IF(A, B) if(A) dyn->insts[ninst].pass2choice = B; if(dyn->insts[ninst].pass2choice == B)
|
||||
#else
|
||||
#define PASS2IF(A, B) if(dyn->insts[ninst].pass2choice == B)
|
||||
#endif
|
||||
|
||||
void arm_epilog();
|
||||
void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
|
||||
@@ -339,6 +363,7 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
|
||||
|
||||
#define geted STEPNAME(geted_)
|
||||
#define fakeed STEPNAME(fakeed_)
|
||||
#define geted16 STEPNAME(geted16_)
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog_)
|
||||
#define jump_to_linker STEPNAME(jump_to_linker_)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog_)
|
||||
@@ -347,9 +372,6 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
|
||||
#define call_c STEPNAME(call_c_)
|
||||
#define grab_fsdata STEPNAME(grab_fsdata_)
|
||||
#define grab_tlsdata STEPNAME(grab_tlsdata_)
|
||||
#define isNativeCall STEPNAME(isNativeCall_)
|
||||
#define emit_lock STEPNAME(emit_lock)
|
||||
#define emit_unlock STEPNAME(emit_unlock)
|
||||
#define emit_cmp8 STEPNAME(emit_cmp8)
|
||||
#define emit_cmp16 STEPNAME(emit_cmp16)
|
||||
#define emit_cmp32 STEPNAME(emit_cmp32)
|
||||
@@ -454,6 +476,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
|
||||
// Do the GETED, but don't emit anything...
|
||||
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
// generic x86 helper
|
||||
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
@@ -463,7 +489,6 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
|
||||
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask);
|
||||
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
|
||||
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
|
||||
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
|
||||
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
|
||||
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
|
||||
|
||||
@@ -48,13 +48,13 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
|
||||
#ifdef HAVE_TRACE
|
||||
if(my_context->dec && box86_dynarec_trace) {
|
||||
if((trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip <= trace_end))) {
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) {
|
||||
MESSAGE(LOG_DUMP, "TRACE ----\n");
|
||||
fpu_reflectcache(dyn, ninst, x1, x2, x3);
|
||||
MOV32(1, ip);
|
||||
STM(0, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
|
||||
STR_IMM9(1, 0, offsetof(x86emu_t, ip));
|
||||
MOV32(2, 1);
|
||||
MOV32(x1, ip);
|
||||
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
|
||||
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
|
||||
MOVW(x2, 1);
|
||||
CALL(PrintTrace, -1, 0);
|
||||
MESSAGE(LOG_DUMP, "----------\n");
|
||||
}
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
#define DEFAULT \
|
||||
--dyn->size; \
|
||||
*ok = -1; \
|
||||
dynarec_log(LOG_INFO, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X (%s)\n", \
|
||||
if(box86_dynarec_log>=LOG_INFO) {\
|
||||
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), \
|
||||
PKip(1), PKip(2), PKip(3), \
|
||||
PKip(4), PKip(5), PKip(6), \
|
||||
PKip(7), PKip(8), PKip(9), \
|
||||
PKip(10),PKip(11),PKip(12), \
|
||||
PKip(13),PKip(14), \
|
||||
GetNativeName((void*)addr))
|
||||
PKip(13),PKip(14)); \
|
||||
printFunctionAddr(ip, " => "); \
|
||||
dynarec_log(LOG_NONE, "\n"); \
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
#define FINI
|
||||
#define EMIT(A) \
|
||||
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
|
||||
*(uint32_t*)(dyn->block) = A; \
|
||||
dyn->block += 4; dyn->arm_size += 4
|
||||
*(uint32_t*)(dyn->block) = A; \
|
||||
dyn->block += 4; dyn->arm_size += 4;\
|
||||
dyn->insts[ninst].size2 += 4
|
||||
|
||||
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
|
||||
#define NEW_INST
|
||||
|
||||
@@ -10,9 +10,14 @@ typedef struct instruction_arm_s {
|
||||
uintptr_t address; // (start) address of the arm emited instruction
|
||||
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
|
||||
int size; // size of the arm emited instruction
|
||||
int size2; // size of the arm emited instrucion after pass2
|
||||
uintptr_t mark, mark2, mark3;
|
||||
uintptr_t markf;
|
||||
uintptr_t markseg;
|
||||
uintptr_t marklock;
|
||||
int pass2choice;// value for choices that are fixed on pass2 for pass3
|
||||
uintptr_t natcall;
|
||||
int retn;
|
||||
} instruction_arm_t;
|
||||
|
||||
typedef struct dynarec_arm_s {
|
||||
@@ -35,6 +40,7 @@ typedef struct dynarec_arm_s {
|
||||
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
|
||||
int x87stack; // cache stack counter
|
||||
int fpu_scratch;// scratch counter
|
||||
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
|
||||
int fpu_reg; // x87/sse/mmx reg counter
|
||||
int nolinker; // disable use of (smart) linker in the block
|
||||
uintptr_t* next; // variable array of "next" jump address
|
||||
|
||||
+13
-13
@@ -8,10 +8,10 @@ NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
|
||||
@@ -50,12 +50,12 @@ NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt>
|
||||
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
|
||||
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
@@ -64,7 +64,7 @@ NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #
|
||||
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
|
||||
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
|
||||
@@ -104,7 +104,7 @@ NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l si
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set u = 1 - u@ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
|
||||
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
|
||||
@@ -445,7 +445,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>,
|
||||
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
|
||||
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
|
||||
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 3) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
|
||||
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
|
||||
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
|
||||
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
|
||||
|
||||
@@ -40,6 +40,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
|
||||
GO(SHT_HIPROC);
|
||||
GO(SHT_LOUSER);
|
||||
GO(SHT_HIUSER);
|
||||
#ifdef SHT_GNU_versym
|
||||
GO(SHT_GNU_versym);
|
||||
GO(SHT_GNU_ATTRIBUTES);
|
||||
GO(SHT_GNU_HASH);
|
||||
@@ -51,6 +52,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
|
||||
GO(SHT_SUNW_syminfo);
|
||||
GO(SHT_GNU_verdef);
|
||||
GO(SHT_GNU_verneed);
|
||||
#endif
|
||||
#undef GO
|
||||
default:
|
||||
sprintf(buff, "0x%X unknown type", s->sh_type);
|
||||
@@ -98,6 +100,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
|
||||
GO(DT_RUNPATH, 0);
|
||||
GO(DT_FLAGS, 0);
|
||||
GO(DT_ENCODING, 0);
|
||||
#ifdef DT_NUM
|
||||
GO(DT_NUM, 0);
|
||||
GO(DT_VALRNGLO, 0);
|
||||
GO(DT_GNU_PRELINKED, 0);
|
||||
@@ -133,6 +136,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
|
||||
GO(DT_VERNEEDNUM, 0);
|
||||
GO(DT_AUXILIARY, 0);
|
||||
GO(DT_FILTER, 0);
|
||||
#endif
|
||||
#undef GO
|
||||
default:
|
||||
sprintf(buff, "0x%X unknown type", s->d_tag);
|
||||
@@ -154,11 +158,13 @@ const char* DumpPHEntry(Elf32_Phdr *e)
|
||||
GO(PT_SHLIB);
|
||||
GO(PT_PHDR);
|
||||
GO(PT_TLS);
|
||||
#ifdef PT_NUM
|
||||
GO(PT_NUM);
|
||||
GO(PT_LOOS);
|
||||
GO(PT_GNU_EH_FRAME);
|
||||
GO(PT_GNU_STACK);
|
||||
GO(PT_GNU_RELRO);
|
||||
#endif
|
||||
#undef GO
|
||||
default: sprintf(buff, "type: %x, Off=%x vaddr=%p paddr=%p filesz=%u memsz=%u flags=%x align=%u", e->p_type, e->p_offset, (void*)e->p_vaddr, (void*)e->p_paddr, e->p_filesz, e->p_memsz, e->p_flags, e->p_align); break;
|
||||
}
|
||||
|
||||
+65
-58
@@ -64,8 +64,10 @@ void FreeElfHeader(elfheader_t** head)
|
||||
return;
|
||||
elfheader_t *h = *head;
|
||||
#ifdef DYNAREC
|
||||
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
|
||||
FreeDynablockList(&h->blocks);
|
||||
if(h->text) {
|
||||
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
|
||||
cleanDBFromAddressRange(h->text, h->textsz, 1);
|
||||
}
|
||||
#endif
|
||||
free(h->name);
|
||||
free(h->path);
|
||||
@@ -155,7 +157,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
if(head->vaddr) {
|
||||
head->multiblock_n = 0; // count PHEntrie with LOAD
|
||||
for (int i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
|
||||
++head->multiblock_n;
|
||||
head->multiblock_size = (uint32_t*)calloc(head->multiblock_n, sizeof(uint32_t));
|
||||
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
|
||||
@@ -164,7 +166,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
head->memory = (char*)0xffffffff;
|
||||
int n = 0;
|
||||
for (int i=0; i<head->numPHEntries; ++i)
|
||||
if(head->PHEntries[i].p_type == PT_LOAD) {
|
||||
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
|
||||
Elf32_Phdr * e = &head->PHEntries[i];
|
||||
uintptr_t bstart = e->p_vaddr;
|
||||
uint32_t bsize = e->p_memsz;
|
||||
@@ -235,10 +237,6 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
|
||||
|
||||
head->tlsbase = AddTLSPartition(context, head->tlssize);
|
||||
|
||||
#ifdef DYNAREC
|
||||
head->blocks = NewDynablockList((uintptr_t)GetBaseAddress(head), head->text + head->delta, head->textsz, 0, mainbin);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -266,7 +264,13 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%d)\n", i, e->p_filesz);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#ifdef DYNAREC
|
||||
if(e->p_flags & PF_X) {
|
||||
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
|
||||
addDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// zero'd difference between filesz and memsz
|
||||
/*if(e->p_filesz != e->p_memsz)
|
||||
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation
|
||||
@@ -302,7 +306,7 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
|
||||
if(e->p_filesz) {
|
||||
ssize_t r = -1;
|
||||
#ifdef DYNAREC
|
||||
unprotectDB((uintptr_t)dest, e->p_filesz);
|
||||
unprotectDB((uintptr_t)dest, e->p_memsz);
|
||||
#endif
|
||||
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
|
||||
printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%d (dest=%p, size=%d, return=%d, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
|
||||
@@ -354,7 +358,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
switch(t) {
|
||||
case R_386_NONE:
|
||||
// can be ignored
|
||||
printf_log(LOG_DEBUG, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
|
||||
printf_log(LOG_DUMP, "Ignoring %s @%p (%p)\n", DumpRelType(t), p, (void*)(p?(*p):0));
|
||||
break;
|
||||
case R_386_TLS_TPOFF:
|
||||
// Negated offset in static TLS block
|
||||
@@ -369,7 +373,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
}
|
||||
if(h_tls) {
|
||||
delta = *(int*)p;
|
||||
printf_log(LOG_DEBUG, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
|
||||
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%d -> %d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int32_t)offs + h_tls->tlsbase);
|
||||
*p = (uint32_t)((int32_t)offs + h_tls->tlsbase);
|
||||
} else {
|
||||
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
|
||||
@@ -382,7 +386,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
}
|
||||
offs = (offs - (uintptr_t)p);
|
||||
if(!offs)
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_PC32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+offs));
|
||||
*p += offs;
|
||||
break;
|
||||
case R_386_GLOB_DAT:
|
||||
@@ -396,12 +400,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
// return -1;
|
||||
} else {
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
|
||||
*p = offs;
|
||||
}
|
||||
break;
|
||||
case R_386_RELATIVE:
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
|
||||
*p += head->delta;
|
||||
break;
|
||||
case R_386_32:
|
||||
@@ -409,7 +413,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
// return -1;
|
||||
} else {
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint32_t*)p));
|
||||
*p += offs;
|
||||
}
|
||||
break;
|
||||
@@ -427,7 +431,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
offs = getElfIndex(my_context, h_tls);
|
||||
}
|
||||
if(p) {
|
||||
printf_log(LOG_DEBUG, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
printf_log(LOG_DUMP, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
|
||||
@@ -447,7 +451,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
offs = sym->st_value;
|
||||
if(p) {
|
||||
int tlsoffset = offs; // it's not an offset in elf memory
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_TLS_DTPOFF32 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
|
||||
*p = tlsoffset;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
|
||||
@@ -455,7 +459,8 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
}
|
||||
break;
|
||||
case R_386_JMP_SLOT:
|
||||
if(bind==STB_LOCAL) {
|
||||
// apply immediatly for gobject closure marshal or for LOCAL binding
|
||||
if(bind==STB_LOCAL || ((symname && strstr(symname, "g_cclosure_marshal_")==symname))) {
|
||||
if (!offs) {
|
||||
if(bind==STB_WEAK) {
|
||||
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
|
||||
@@ -465,14 +470,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
// return -1;
|
||||
} else {
|
||||
if(p) {
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_JMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
|
||||
*p = offs;
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_DEBUG, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
|
||||
printf_log(LOG_DUMP, "Preparing (if needed) %s R_386_JMP_SLOT @%p (0x%x->0x%0x) with sym=%s to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname);
|
||||
*p += head->delta;
|
||||
}
|
||||
break;
|
||||
@@ -483,13 +488,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
|
||||
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head);
|
||||
if(!offs)
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head); // get original copy if any
|
||||
printf_log(LOG_DEBUG, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
|
||||
printf_log(LOG_DUMP, "Apply %s R_386_COPY @%p with sym=%s, @%p size=%d (", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)offs, sym->st_size);
|
||||
memmove(p, (void*)offs, sym->st_size);
|
||||
if(LOG_DEBUG<=box86_log) {
|
||||
if(LOG_DUMP<=box86_log) {
|
||||
uint32_t*k = (uint32_t*)p;
|
||||
for (int i=0; i<((sym->st_size>128)?128:sym->st_size); i+=4, ++k)
|
||||
printf_log(LOG_DEBUG, "%s0x%08X", i?" ":"", *k);
|
||||
printf_log(LOG_DEBUG, "%s)\n", (sym->st_size>128)?" ...":"");
|
||||
printf_log(LOG_DUMP, "%s0x%08X", i?" ":"", *k);
|
||||
printf_log(LOG_DUMP, "%s)\n", (sym->st_size>128)?" ...":"");
|
||||
}
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
@@ -522,7 +527,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|
||||
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head);
|
||||
if(offs) {
|
||||
// add r_addend to p?
|
||||
printf_log(LOG_DEBUG, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
|
||||
printf_log(LOG_DUMP, "Apply R_386_COPY @%p with sym=%s, @%p size=%d\n", p, symname, (void*)offs, sym->st_size);
|
||||
memcpy(p, (void*)(offs+rela[i].r_addend), sym->st_size);
|
||||
} else {
|
||||
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
|
||||
@@ -556,18 +561,6 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
|
||||
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
{
|
||||
if(pltResolver==~0) {
|
||||
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0);
|
||||
}
|
||||
if(head->pltgot) {
|
||||
*(uintptr_t*)(head->pltgot+head->delta+8) = pltResolver;
|
||||
*(uintptr_t*)(head->pltgot+head->delta+4) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+8));
|
||||
} else if(head->got) {
|
||||
*(uintptr_t*)(head->got+head->delta+8) = pltResolver;
|
||||
*(uintptr_t*)(head->got+head->delta+4) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+8));
|
||||
}
|
||||
if(head->pltrel) {
|
||||
int cnt = head->pltsz / head->pltent;
|
||||
if(head->pltrel==DT_REL) {
|
||||
@@ -581,6 +574,18 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
|
||||
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf32_Rela *)(head->jmprel + head->delta)))
|
||||
return -1;
|
||||
}
|
||||
if(pltResolver==~0) {
|
||||
pltResolver = AddBridge(my_context->system, vFE, PltResolver, 0);
|
||||
}
|
||||
if(head->pltgot) {
|
||||
*(uintptr_t*)(head->pltgot+head->delta+8) = pltResolver;
|
||||
*(uintptr_t*)(head->pltgot+head->delta+4) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+8));
|
||||
} else if(head->got) {
|
||||
*(uintptr_t*)(head->got+head->delta+8) = pltResolver;
|
||||
*(uintptr_t*)(head->got+head->delta+4) = (uintptr_t)head;
|
||||
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+8));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -598,7 +603,8 @@ Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
|
||||
{
|
||||
// TODO: create a hash on named to avoid this loop
|
||||
for (int i=0; i<h->numSymTab; ++i) {
|
||||
if(h->SymTab[i].st_info == 18) { // TODO: this "18" is probably defined somewhere
|
||||
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
|
||||
if(/*h->SymTab[i].st_info == 18*/type==STT_FUNC) { // TODO: this "18" is probably defined somewhere
|
||||
const char * symname = h->StrTab+h->SymTab[i].st_name;
|
||||
if(strcmp(symname, name)==0) {
|
||||
return h->SymTab+i;
|
||||
@@ -611,7 +617,8 @@ Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
|
||||
Elf32_Sym* GetElfObject(elfheader_t* h, const char* name)
|
||||
{
|
||||
for (int i=0; i<h->numSymTab; ++i) {
|
||||
if(h->SymTab[i].st_info == 16) {
|
||||
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
|
||||
if(/*h->SymTab[i].st_info == 16*/type==STT_OBJECT) {
|
||||
const char * symname = h->StrTab+h->SymTab[i].st_name;
|
||||
if(strcmp(symname, name)==0) {
|
||||
return h->SymTab+i;
|
||||
@@ -672,8 +679,9 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
const char * symname = h->StrTab+h->SymTab[i].st_name;
|
||||
int bind = ELF32_ST_BIND(h->SymTab[i].st_info);
|
||||
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
|
||||
int vis = h->SymTab[i].st_other&0x3;
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (h->SymTab[i].st_other==0) && (h->SymTab[i].st_shndx!=0)) {
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
|
||||
if(bind==10/*STB_GNU_UNIQUE*/ && FindGlobalSymbol(maplib, symname))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
|
||||
@@ -695,9 +703,10 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
|
||||
const char * symname = h->DynStr+h->DynSym[i].st_name;
|
||||
int bind = ELF32_ST_BIND(h->DynSym[i].st_info);
|
||||
int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
|
||||
int vis = h->DynSym[i].st_other&0x3;
|
||||
//st_shndx==65521 means ABS value
|
||||
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
|
||||
&& (h->DynSym[i].st_other==0) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
|
||||
if(bind==10/*STB_GNU_UNIQUE*/ && FindGlobalSymbol(maplib, symname))
|
||||
continue;
|
||||
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
|
||||
@@ -976,25 +985,23 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
|
||||
if(ret) {
|
||||
return ret;
|
||||
}
|
||||
// nope, then find in elfs
|
||||
elfheader_t* elf = FindElfAddress(context, addr);
|
||||
if(!elf) {
|
||||
// still nope
|
||||
if(addr>0x100)
|
||||
if((*(uint8_t*)addr)==0xCC || (((*(uint8_t*)addr)==0xC3 || (*(uint8_t*)addr)==0xC2) && (*(uint8_t*)(addr-11))==0xCC) )
|
||||
return context->dynablocks;
|
||||
if(box86_dynarec_forced)
|
||||
// nope
|
||||
if(addr>0x100)
|
||||
if((*(uint8_t*)addr)==0xCC || (((*(uint8_t*)addr)==0xC3 || (*(uint8_t*)addr)==0xC2) /*&& (*(uint8_t*)(addr-11))==0xCC*/) )
|
||||
return context->dynablocks;
|
||||
dynarec_log(LOG_INFO, "Address %p not found in Elf memory and is not a native call wrapper\n", (void*)addr);
|
||||
if(box86_dynarec_forced)
|
||||
return context->dynablocks;
|
||||
// check if the adress has an alternate one
|
||||
if(hasAlternate((void*)addr))
|
||||
return context->dynablocks;
|
||||
//check if address is in an elf... if yes, grant a block (should I warn)
|
||||
Dl_info info;
|
||||
if(dladdr((void*)addr, &info)) {
|
||||
printf_log(LOG_INFO, "Address %p is in a native Elf memory space (function \"%s\" in %s)\n", (void*)addr, info.dli_sname, info.dli_fname);
|
||||
return NULL;
|
||||
}
|
||||
return elf->blocks;
|
||||
}
|
||||
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h)
|
||||
{
|
||||
if(!h)
|
||||
return NULL;
|
||||
return h->blocks;
|
||||
dynarec_log(LOG_INFO, "Address %p not found in Elf memory and is not a native call wrapper\n", (void*)addr);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -76,9 +76,7 @@ struct elfheader_s {
|
||||
uintptr_t* multiblock_offs;
|
||||
uint32_t* multiblock_size;
|
||||
int multiblock_n;
|
||||
#ifdef DYNAREC
|
||||
dynablocklist_t *blocks;
|
||||
#endif
|
||||
|
||||
library_t *lib;
|
||||
needed_libs_t *neededlibs;
|
||||
};
|
||||
|
||||
@@ -61,8 +61,9 @@ void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const ch
|
||||
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(LOG_INFO, "Cannot read ELF Header\n");
|
||||
printf_log(level, "Cannot read ELF Header\n");
|
||||
return NULL;
|
||||
}
|
||||
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
|
||||
@@ -96,7 +97,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
}
|
||||
|
||||
if(header.e_machine != EM_386) {
|
||||
printf_log(LOG_INFO, "Not an i386 ELF (%d)\n", header.e_machine);
|
||||
printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -119,7 +120,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
h->numPHEntries = header.e_phnum;
|
||||
h->numSHEntries = header.e_shnum;
|
||||
h->SHIdx = header.e_shstrndx;
|
||||
if(header.e_shentsize!=0) {
|
||||
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");
|
||||
@@ -159,7 +160,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(header.e_shentsize!=0) {
|
||||
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");
|
||||
h->SHIdx = h->SHEntries[0].sh_link;
|
||||
|
||||
@@ -47,6 +47,52 @@
|
||||
base+=(nextop&0x80)?(F32S):(F8S); \
|
||||
A = (T*)(base+O); \
|
||||
}
|
||||
|
||||
#define getecommon16(A, T) \
|
||||
{ \
|
||||
uint32_t m = nextop&0xC7; \
|
||||
uint32_t base = 0; \
|
||||
switch(m&7) { \
|
||||
case 0: base = R_BX+R_SI; break; \
|
||||
case 1: base = R_BX+R_DI; break; \
|
||||
case 2: base = R_BP+R_SI; break; \
|
||||
case 3: base = R_BP+R_DI; break; \
|
||||
case 4: base = R_SI; break; \
|
||||
case 5: base = R_DI; break; \
|
||||
case 6: base = R_BP; break; \
|
||||
case 7: base = R_BX; break; \
|
||||
} \
|
||||
switch((m>>6)&3) { \
|
||||
case 0: if(m==6) base = F16; break; \
|
||||
case 1: base += F8S; break; \
|
||||
case 2: base += F16S; break; \
|
||||
} \
|
||||
A = (T*)base; \
|
||||
}
|
||||
|
||||
#define getecommon16o(A, T, O) \
|
||||
{ \
|
||||
uint32_t m = nextop&0xC7; \
|
||||
uint32_t base = 0; \
|
||||
switch(m&7) { \
|
||||
case 0: base = R_BX+R_SI; break; \
|
||||
case 1: base = R_BX+R_DI; break; \
|
||||
case 2: base = R_BP+R_SI; break; \
|
||||
case 3: base = R_BP+R_DI; break; \
|
||||
case 4: base = R_SI; break; \
|
||||
case 5: base = R_DI; break; \
|
||||
case 6: base = R_BP; break; \
|
||||
case 7: base = R_BX; break; \
|
||||
} \
|
||||
switch((m>>6)&3) { \
|
||||
case 0: if(m==6) base = F16; break; \
|
||||
case 1: base += F8S; break; \
|
||||
case 2: base += F16S; break; \
|
||||
} \
|
||||
A = (T*)(base+O); \
|
||||
}
|
||||
|
||||
|
||||
#define geteb(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
|
||||
@@ -71,6 +117,15 @@
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->xmm[(nextop&7)]; \
|
||||
} else getecommon(A, sse_regs_t)
|
||||
#define getew16(A) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16(A, reg32_t)
|
||||
#define getew16o(A, O) \
|
||||
if((nextop&0xC0)==0xC0) { \
|
||||
A = &emu->regs[(nextop&7)]; \
|
||||
} else getecommon16o(A, reg32_t, O)
|
||||
|
||||
// Macros for ModR/M gets
|
||||
#define GET_EB geteb(oped)
|
||||
#define GET_ED geted(oped)
|
||||
@@ -78,6 +133,8 @@
|
||||
#define GET_EB_OFFS(o) getebo(oped, o)
|
||||
#define GET_EM getem(opem)
|
||||
#define GET_EX getex(opex)
|
||||
#define GET_EW16 getew16(oped)
|
||||
#define GET_EW16_OFFS(o) getew16o(oped, o)
|
||||
#define EB oped
|
||||
#define ED oped
|
||||
#define EM opem
|
||||
|
||||
+99
-18
@@ -15,6 +15,18 @@
|
||||
goto _default;
|
||||
}
|
||||
NEXT;
|
||||
_0f_0x01:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 4: /* SMSW Ew */
|
||||
GET_ED;
|
||||
// dummy for now... Do I need to track CR0 state?
|
||||
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0x0B: /* UD2 */
|
||||
kill(getpid(), SIGILL); // this is undefined instruction
|
||||
@@ -84,6 +96,15 @@
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_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_0x1F: /* NOP (multi-byte) */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -169,14 +190,56 @@
|
||||
_0f_0x38: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x00: /* PSHUFB */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
eam1 = GM;
|
||||
for (int i=0; i<8; ++i) {
|
||||
if(EM->ub[i]&128)
|
||||
GM.ub[i] = 0;
|
||||
else
|
||||
GM.ub[i] = eax1.ub[EM->ub[i]&7];
|
||||
}
|
||||
break;
|
||||
case 0x04: /* PMADDUBSW Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = (int32_t)(GM.ub[i*2+0])*EM->ub[i*2+0] + (int32_t)(GM.ub[i*2+1])*EM->ub[i*2+1];
|
||||
GM.sw[i] = (tmp32s>32767)?32767:tmp32s; // no negative value to test
|
||||
tmp32s = (int32_t)(GM.ub[i*2+0])*EM->sb[i*2+0] + (int32_t)(GM.ub[i*2+1])*EM->sb[i*2+1];
|
||||
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
|
||||
}
|
||||
break;
|
||||
case 0x0B: /* PMULHRSW Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = ((((int32_t)(GM.sw[i])*(int32_t)(EM->sw[i]))>>14) + 1)>>1;
|
||||
GM.uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1C: /* PABSB Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<8; ++i) {
|
||||
GM.sb[i] = abs(EM->sb[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1D: /* PABSW Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<4; ++i) {
|
||||
GM.sw[i] = abs(EM->sw[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1E: /* PABSD Gm, Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<2; ++i) {
|
||||
GM.sd[i] = abs(EM->sd[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
@@ -699,22 +762,22 @@
|
||||
// should save flags & all
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(ED->dword+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
|
||||
memcpy(((void*)(ED))+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(ED->dword+160, &emu->xmm[0], sizeof(emu->xmm));
|
||||
memcpy(((void*)(ED))+160, &emu->xmm[0], sizeof(emu->xmm));
|
||||
// put also FPU regs in a reserved area...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(ED->dword+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
|
||||
memcpy(((void*)(ED))+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
|
||||
break;
|
||||
case 1: /* FXRSTOR m512byte */
|
||||
// should restore flags & all
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx[i], ED->dword+32+i*16, sizeof(emu->mmx[0]));
|
||||
memcpy(&emu->mmx[i], ((void*)(ED))+32+i*16, sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], ED->dword+160/4, sizeof(emu->xmm));
|
||||
memcpy(&emu->xmm[0], ((void*)(ED))+160/4, sizeof(emu->xmm));
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->fpu[0], ED->dword+416+i*8, sizeof(emu->fpu[0]));
|
||||
memcpy(&emu->fpu[0], ((void*)(ED))+416+i*8, sizeof(emu->fpu[0]));
|
||||
break;
|
||||
case 2: /* LDMXCSR Md */
|
||||
emu->mxcsr = ED->dword[0];
|
||||
@@ -809,9 +872,10 @@
|
||||
tmp8u&=31;
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else
|
||||
} else {
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
break;
|
||||
case 6: /* BTR Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -936,7 +1000,11 @@
|
||||
GX.ud[i]=(tmp8s)?0xffffffff:0;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0xC3: /* MOVNTI Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
ED->dword[0] = GD.dword[0];
|
||||
NEXT;
|
||||
_0f_0xC4: /* PINSRW Gm,Ew,Ib */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -1033,12 +1101,15 @@
|
||||
|
||||
_0f_0xD7: /* PMOVMSKB Gd,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(EM->ub[i]&0x80)
|
||||
GD.dword[0] |= (1<<i);
|
||||
NEXT;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GET_EM;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
if(EM->ub[i]&0x80)
|
||||
GD.dword[0] |= (1<<i);
|
||||
NEXT;
|
||||
} else
|
||||
goto _default;
|
||||
_0f_0xD8: /* PSUBUSB Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
@@ -1055,7 +1126,12 @@
|
||||
GM.uw[i] = (tmp32s < 0) ? 0 : tmp32s;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0xDA: /* PMINUB Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<8; ++i)
|
||||
GM.ub[i] = (GM.ub[i]<EM->ub[i])?GM.ub[i]:EM->ub[i];
|
||||
NEXT;
|
||||
_0f_0xDB: /* PAND Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
@@ -1077,7 +1153,12 @@
|
||||
GM.uw[i] = (tmp32u>65535) ? 65535 : tmp32u;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_0f_0xDE: /* PMAXUB Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
for (int i=0; i<8; ++i)
|
||||
GM.ub[i] = (GM.ub[i]>EM->ub[i])?GM.ub[i]:EM->ub[i];
|
||||
NEXT;
|
||||
_0f_0xDF: /* PANDN Gm,Em */
|
||||
nextop = F8;
|
||||
GET_EM;
|
||||
|
||||
+7
-2
@@ -34,7 +34,12 @@
|
||||
NEXT;
|
||||
|
||||
_66_0x0F: /* 66 0f prefix */
|
||||
#include "run660f.h"
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-2; // don't count 66 0F yet
|
||||
Run660F(emu); // implemented in Run660f.c
|
||||
ip = R_EIP;
|
||||
if(emu->quit) goto fini;
|
||||
NEXT;
|
||||
|
||||
_66_0x26: /* ES: */
|
||||
// ignored
|
||||
@@ -203,7 +208,7 @@
|
||||
_66_0x8C: /* MOV Ew,Seg */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
EW->word[0] = emu->segs[(nextop&38)>>3];
|
||||
EW->word[0] = emu->segs[(nextop&0x38)>>3];
|
||||
NEXT;
|
||||
|
||||
_66_0x8E: /* MOV Seg,Ew */
|
||||
|
||||
+8
-88
@@ -10,11 +10,7 @@
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7: /* FADD */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f += ST(nextop&7).f;
|
||||
#else
|
||||
ST0.d += ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -24,11 +20,7 @@
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* FMUL */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= ST(nextop&7).f;
|
||||
#else
|
||||
ST0.d *= ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -38,11 +30,7 @@
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7: /* FCOM */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
#endif
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
@@ -52,11 +40,7 @@
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF: /* FCOMP */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE0:
|
||||
@@ -67,11 +51,7 @@
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7: /* FSUB */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f -= ST(nextop&7).f;
|
||||
#else
|
||||
ST0.d -= ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -81,11 +61,7 @@
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF: /* FSUBR */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = ST(nextop&7).f - ST0.f;
|
||||
#else
|
||||
ST0.d = ST(nextop&7).d - ST0.d;
|
||||
#endif
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -95,11 +71,7 @@
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7: /* FDIV */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f /= ST(nextop&7).f;
|
||||
#else
|
||||
ST0.d /= ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -109,46 +81,26 @@
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF: /* FDIVR */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = ST(nextop&7).f / ST0.f;
|
||||
#else
|
||||
ST0.d = ST(nextop&7).d / ST0.d;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f += *(float*)ED;
|
||||
#else
|
||||
ST0.d += *(float*)ED;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f += f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d += f;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 1: /* FMUL ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= *(float*)ED;
|
||||
#else
|
||||
ST0.d *= *(float*)ED;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d *= f;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 2: /* FCOM ST0, float */
|
||||
@@ -156,7 +108,7 @@
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
fpu_fcom(emu, f);
|
||||
}
|
||||
break;
|
||||
@@ -165,7 +117,7 @@
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
fpu_fcom(emu, *(float*)ED);
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
fpu_fcom(emu, f);
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
@@ -173,69 +125,37 @@
|
||||
case 4: /* FSUB ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f -= *(float*)ED;
|
||||
#else
|
||||
ST0.d -= *(float*)ED;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f -= f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d -= f;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 5: /* FSUBR ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = *(float*)ED - ST0.f;
|
||||
#else
|
||||
ST0.d = *(float*)ED - ST0.d;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = f - ST0.f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f - ST0.d;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 6: /* FDIV ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f /= *(float*)ED;
|
||||
#else
|
||||
ST0.d /= *(float*)ED;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f /= f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d /= f;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 7: /* FDIVR ST0, float */
|
||||
GET_ED;
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = *(float*)ED / ST0.f;
|
||||
#else
|
||||
ST0.d = *(float*)ED / ST0.d;
|
||||
#endif
|
||||
else {
|
||||
*(uint32_t*)&f = ED->dword[0];
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = f / ST0.f;
|
||||
#else
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f / ST0.d;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
+37
-151
@@ -1,5 +1,3 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0:
|
||||
@@ -31,18 +29,10 @@
|
||||
break;
|
||||
|
||||
case 0xE0: /* FCHS */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = -ST0.f;
|
||||
#else
|
||||
ST0.d = -ST0.d;
|
||||
#endif
|
||||
break;
|
||||
case 0xE1: /* FABS */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = fabsf(ST0.f);
|
||||
#else
|
||||
ST0.d = fabs(ST0.d);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xE4: /* FTST */
|
||||
@@ -54,153 +44,96 @@
|
||||
|
||||
case 0xE8: /* FLD1 */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = 1.0f;
|
||||
#else
|
||||
ST0.d = 1.0;
|
||||
#endif
|
||||
break;
|
||||
case 0xE9: /* FLDL2T */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = L2T;
|
||||
#else
|
||||
ST0.d = L2T;
|
||||
#endif
|
||||
break;
|
||||
case 0xEA: /* FLDL2E */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = L2E;
|
||||
#else
|
||||
ST0.d = L2E;
|
||||
#endif
|
||||
break;
|
||||
case 0xEB: /* FLDPI */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = PI;
|
||||
#else
|
||||
ST0.d = PI;
|
||||
#endif
|
||||
break;
|
||||
case 0xEC: /* FLDLG2 */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = LG2;
|
||||
#else
|
||||
ST0.d = LG2;
|
||||
#endif
|
||||
break;
|
||||
case 0xED: /* FLDLN2 */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = LN2;
|
||||
#else
|
||||
ST0.d = LN2;
|
||||
#endif
|
||||
break;
|
||||
case 0xEE: /* FLDZ */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = 0.0f;
|
||||
#else
|
||||
ST0.d = 0.0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xF0: /* F2XM1 */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = exp2f(ST0.f) - 1.0f;
|
||||
#else
|
||||
ST0.d = exp2(ST0.d) - 1.0;
|
||||
#endif
|
||||
break;
|
||||
case 0xF1: /* FYL2X */
|
||||
#ifdef USE_FLOAT
|
||||
ST(1).f = log2f(ST0.f)*ST(1).f;
|
||||
#else
|
||||
ST(1).d = log2(ST0.d)*ST(1).d;
|
||||
#endif
|
||||
ST(1).d *= log2(ST0.d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF2: /* FPTAN */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = tanf(ST0.f);
|
||||
fpu_do_push(emu);
|
||||
ST0.f = 1.0f;
|
||||
#else
|
||||
ST0.d = tan(ST0.d);
|
||||
fpu_do_push(emu);
|
||||
ST0.d = 1.0;
|
||||
#endif
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
break;
|
||||
case 0xF3: /* FPATAN */
|
||||
#ifdef USE_FLOAT
|
||||
ST1.f = atan2f(ST1.f, ST0.f);
|
||||
#else
|
||||
ST1.d = atan2(ST1.d, ST0.d);
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF4: /* FXTRACT */
|
||||
#ifdef USE_FLOAT
|
||||
tmp32s = (ST0.ll&0x7f700000)>>23;
|
||||
tmp32s -= 127;
|
||||
ST0.f /= exp2f(tmp32s);
|
||||
fpu_do_push(emu);
|
||||
ST0.f = tmp32s;
|
||||
#else
|
||||
tmp32s = (ST0.ll&0x7ff0000000000000LL)>>52;
|
||||
tmp32s -= 1023;
|
||||
ST0.d /= exp2(tmp32s);
|
||||
ST0.d = frexp(ST0.d, &tmp32s);
|
||||
fpu_do_push(emu);
|
||||
ST0.d = tmp32s;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xF8: /* FPREM */
|
||||
#ifdef USE_FLOAT
|
||||
ll = ST0.f / ST1.f;
|
||||
ST0.f -= ST1.f * ll;
|
||||
#else
|
||||
ll = ST0.d / ST1.d;
|
||||
ST0.d -= ST1.d * ll;
|
||||
#endif
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = (ll&1);
|
||||
emu->sw.f.F87_C3 = ((ll>>1)&1);
|
||||
emu->sw.f.F87_C1 = ((ll>>2)&1);
|
||||
break;
|
||||
case 0xF5: /* FPREM1 */
|
||||
// get exponant(ST(0))-exponant(ST(1)) in temp32s
|
||||
#ifdef USE_FLOAT
|
||||
tmp32s = ((ST0.ll&0x7f700000)>>23) - ((ST1.ll&0x7f700000)>>23);
|
||||
#else
|
||||
tmp32s = ((ST0.ll&0x7ff0000000000000LL)>>52) - ((ST1.ll&0x7ff0000000000000LL)>>52);
|
||||
#endif
|
||||
{
|
||||
int e0, e1;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
tmp32s = e0 - e1;
|
||||
}
|
||||
if(tmp32s<64)
|
||||
{
|
||||
#ifdef USE_FLOAT
|
||||
ll = (int64_t)round(ST0.f/ST1.f);
|
||||
ST0.f = ST0.f - (ST1.f*ll);
|
||||
#else
|
||||
ll = (int64_t)round(ST0.d/ST1.d);
|
||||
ll = (int64_t)floor(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
#endif
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
#ifdef USE_FLOAT
|
||||
ll = (int64_t)(floor((ST0.f/ST1.f))/powf(2, tmp32s - 32));
|
||||
ST0.f = ST0.f - ST1.f*ll*powf(2, 32);
|
||||
#else
|
||||
ll = (int64_t)(floor((ST0.d/ST1.d))/pow(2, tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*pow(2, tmp32s - 32);
|
||||
#endif
|
||||
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
break;
|
||||
case 0xF5: /* FPREM1 */
|
||||
// get exponant(ST(0))-exponant(ST(1)) in temp32s
|
||||
{
|
||||
int e0, e1;
|
||||
frexp(ST0.d, &e0);
|
||||
frexp(ST1.d, &e1);
|
||||
tmp32s = e0 - e1;
|
||||
}
|
||||
if(tmp32s<64)
|
||||
{
|
||||
ll = (int64_t)round(ST0.d/ST1.d);
|
||||
ST0.d = ST0.d - (ST1.d*ll);
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C1 = (ll&1)?1:0;
|
||||
emu->sw.f.F87_C3 = (ll&2)?1:0;
|
||||
emu->sw.f.F87_C0 = (ll&4)?1:0;
|
||||
} else {
|
||||
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
|
||||
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
}
|
||||
break;
|
||||
@@ -211,56 +144,28 @@
|
||||
emu->top=(emu->top+1)&7; // this will probably break a few things
|
||||
break;
|
||||
case 0xF9: /* FYL2XP1 */
|
||||
#ifdef USE_FLOAT
|
||||
ST(1).f = log2f(ST0.f + 1.0f)*ST(1).f;
|
||||
#else
|
||||
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
|
||||
#endif
|
||||
ST(1).d *= log2(ST0.d + 1.0);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xFA: /* FSQRT */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = sqrtf(ST0.f);
|
||||
#else
|
||||
ST0.d = sqrt(ST0.d);
|
||||
#endif
|
||||
break;
|
||||
case 0xFB: /* FSINCOS */
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
sincosf(ST1.f, &ST1.f, &ST0.f);
|
||||
#else
|
||||
sincos(ST1.d, &ST1.d, &ST0.d);
|
||||
#endif
|
||||
break;
|
||||
case 0xFC: /* FRNDINT */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = fpu_round(emu, ST0.f);
|
||||
#else
|
||||
ST0.d = fpu_round(emu, ST0.d);
|
||||
#endif
|
||||
break;
|
||||
case 0xFD: /* FSCALE */
|
||||
// this could probably be done by just altering the exponant part of the float...
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= exp2f(truncf(ST1.f));
|
||||
#else
|
||||
ST0.d *= exp2(trunc(ST1.d));
|
||||
#endif
|
||||
break;
|
||||
case 0xFE: /* FSIN */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = sinf(ST0.f);
|
||||
#else
|
||||
ST0.d = sin(ST0.d);
|
||||
#endif
|
||||
break;
|
||||
case 0xFF: /* FCOS */
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = cosf(ST0.f);
|
||||
#else
|
||||
ST0.d = cos(ST0.d);
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
@@ -288,42 +193,30 @@
|
||||
case 0: /* FLD ST0, Ed float */
|
||||
GET_ED;
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.ll = ED->dword[0];
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
ST0.d = *(float*)ED;
|
||||
else {
|
||||
memcpy(&f, ED->dword, sizeof(float));
|
||||
memcpy(&f, ED, sizeof(float));
|
||||
ST0.d = f;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2: /* FST Ed, ST0 */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
*(float*)ED = ST0.f;
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
f = ST0.d;
|
||||
memcpy(ED->dword, &f, sizeof(float));
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 3: /* FSTP Ed, ST0 */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ED->dword[0] = ST0.ll;
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&3))
|
||||
*(float*)ED = ST0.d;
|
||||
else {
|
||||
f = ST0.d;
|
||||
memcpy(ED->dword, &f, sizeof(float));
|
||||
memcpy(ED, &f, sizeof(float));
|
||||
}
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FLDENV m */
|
||||
@@ -341,12 +234,6 @@
|
||||
// warning, incomplete
|
||||
GET_ED;
|
||||
fpu_savenv(emu, (char*)ED, 0);
|
||||
ED->dword[0] = emu->cw;
|
||||
ED->dword[1] = emu->sw.x16;
|
||||
// tagword: 2bits*8
|
||||
ED->word[4] = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
ED->word[4] |= (emu->p_regs[i].tag)<<(i*2);
|
||||
// intruction pointer: 48bits
|
||||
// data (operand) pointer: 48bits
|
||||
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
|
||||
@@ -359,4 +246,3 @@
|
||||
goto _default;
|
||||
}
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
+2
-30
@@ -51,11 +51,7 @@
|
||||
break;
|
||||
|
||||
case 0xE9: /* FUCOMPP */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST1.f);
|
||||
#else
|
||||
fpu_fcom(emu, ST1.d); // bad, should handle QNaN and IA interrupt
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
@@ -76,19 +72,11 @@
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f += ED->sdword[0];
|
||||
#else
|
||||
ST0.d += ED->sdword[0];
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FIMUL ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= ED->sdword[0];
|
||||
#else
|
||||
ST0.d *= ED->sdword[0];
|
||||
#endif
|
||||
break;
|
||||
case 2: /* FICOM ST0, Ed int */
|
||||
GET_ED;
|
||||
@@ -101,35 +89,19 @@
|
||||
break;
|
||||
case 4: /* FISUB ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f -= ED->sdword[0];
|
||||
#else
|
||||
ST0.d -= ED->sdword[0];
|
||||
#endif
|
||||
break;
|
||||
case 5: /* FISUBR ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = ED->sdword[0] - ST0.f;
|
||||
#else
|
||||
ST0.d = ED->sdword[0] - ST0.d;
|
||||
#endif
|
||||
ST0.d = (double)ED->sdword[0] - ST0.d;
|
||||
break;
|
||||
case 6: /* FIDIV ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f /= ED->sdword[0];
|
||||
#else
|
||||
ST0.d /= ED->sdword[0];
|
||||
#endif
|
||||
break;
|
||||
case 7: /* FIDIVR ST0, Ed int */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = ED->sdword[0] / ST0.f;
|
||||
#else
|
||||
ST0.d = ED->sdword[0] / ST0.d;
|
||||
#endif
|
||||
ST0.d = (double)ED->sdword[0] / ST0.d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
+8
-100
@@ -49,6 +49,8 @@
|
||||
ST0.ll = ST(nextop&7).ll;
|
||||
break;
|
||||
|
||||
case 0xE1: /* FDISI8087_NOP */
|
||||
break;
|
||||
case 0xE2: /* FNCLEX */
|
||||
//Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE),
|
||||
// the exception summary status flag (ES), the stack fault flag (SF), and the busy flag (B) in the FPU status word
|
||||
@@ -73,11 +75,7 @@
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcomi(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xF0: /* FCOMI ST0, STx */
|
||||
@@ -88,14 +86,9 @@
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcomi(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcomi(emu, ST(nextop&7).d);
|
||||
#endif
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
@@ -103,134 +96,49 @@
|
||||
goto _default;
|
||||
default:
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FILD ST0, Gd */
|
||||
case 0: /* FILD ST0, Ed */
|
||||
GET_ED;
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = ED->sdword[0];
|
||||
#else
|
||||
ST0.d = ED->sdword[0];
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FISTTP Ed, ST0 */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
tmp32s = ST0.f; // TODO: Handling of FPU Exception
|
||||
if(tmp32s==0x7fffffff && isgreater(ST0.f, (float)(int32_t)0x7fffffff))
|
||||
tmp32s = 0x80000000;
|
||||
#else
|
||||
tmp32s = ST0.d; // TODO: Handling of FPU Exception
|
||||
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
|
||||
tmp32s = 0x80000000;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
ED->sdword[0] = tmp32s;
|
||||
break;
|
||||
case 2: /* FIST Ed, ST0 */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
ED->sdword[0] = floorf(ST0.f+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
ED->sdword[0] = floorf(ST0.f);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
ED->sdword[0] = ceilf(ST0.f);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
ED->sdword[0] = ST0.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
ED->sdword[0] = floor(ST0.d+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
ED->sdword[0] = floor(ST0.d);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
ED->sdword[0] = ceil(ST0.d);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
ED->sdword[0] = ST0.d;
|
||||
break;
|
||||
}
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
ED->sdword[0] = tmp;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 3: /* FISTP Ed, ST0 */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(int32_t)0x7fffffff))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
ED->sdword[0] = floorf(ST0.f+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
ED->sdword[0] = floorf(ST0.f);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
ED->sdword[0] = ceilf(ST0.f);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
ED->sdword[0] = ST0.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
|
||||
ED->sdword[0] = 0x80000000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
ED->sdword[0] = floor(ST0.d+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
ED->sdword[0] = floor(ST0.d);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
ED->sdword[0] = ceil(ST0.d);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
ED->sdword[0] = ST0.d;
|
||||
break;
|
||||
}
|
||||
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
|
||||
ED->sdword[0] = tmp;
|
||||
}
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 5: /* FLD ST0, Gt */
|
||||
case 5: /* FLD ST0, Et */
|
||||
GET_ED;
|
||||
fpu_do_push(emu);
|
||||
memcpy(&STld(0).ld, ED, 10);
|
||||
#ifdef USE_FLOAT
|
||||
LD2D(&STld(0), &d);
|
||||
ST0.f = d;
|
||||
#else
|
||||
LD2D(&STld(0), &ST(0).d);
|
||||
#endif
|
||||
STld(0).ref = ST0.ll;
|
||||
break;
|
||||
case 7: /* FSTP tbyte */
|
||||
GET_ED;
|
||||
if(ST0.ll!=STld(0).ref)
|
||||
#ifdef USE_FLOAT
|
||||
{d = ST0.f; D2LD(&d, ED);}
|
||||
#else
|
||||
D2LD(&ST0.d, ED);
|
||||
#endif
|
||||
else
|
||||
memcpy(ED, &STld(0).ld, 10);
|
||||
fpu_do_pop(emu);
|
||||
|
||||
+8
-96
@@ -1,5 +1,3 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
nextop = F8;
|
||||
switch(nextop) {
|
||||
case 0xC0:
|
||||
@@ -10,11 +8,7 @@
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7: /* FADD */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f += ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d += ST0.d;
|
||||
#endif
|
||||
break;
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
@@ -24,11 +18,7 @@
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF: /* FMUL */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f *= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d *= ST0.d;
|
||||
#endif
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
@@ -38,11 +28,7 @@
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7: /* FCOM */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
#endif
|
||||
break;
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
@@ -52,11 +38,7 @@
|
||||
case 0xDD:
|
||||
case 0xDE:
|
||||
case 0xDF: /* FCOMP */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d); // TODO: is this ok?
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE0:
|
||||
@@ -67,11 +49,7 @@
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7: /* FSUBR */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f = ST0.f -ST(nextop&7).f;
|
||||
#else
|
||||
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
@@ -81,11 +59,7 @@
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF: /* FSUB */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f -= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d -= ST0.d;
|
||||
#endif
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -95,11 +69,7 @@
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7: /* FDIVR */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
|
||||
#else
|
||||
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
|
||||
#endif
|
||||
break;
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
@@ -109,54 +79,32 @@
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF: /* FDIV */
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f /= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
GET_ED;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FADD ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f += *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f += d;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d += *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d += d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FMUL ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f *= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f *= d;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d *= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d *= d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 2: /* FCOM ST0, double */
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
fpu_fcom(emu, *(double*)ED);
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
fpu_fcom(emu, d);
|
||||
}
|
||||
break;
|
||||
@@ -164,78 +112,42 @@
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
fpu_fcom(emu, *(double*)ED);
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
fpu_fcom(emu, d);
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FSUB ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f -= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f -= d;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d -= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d -= d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 5: /* FSUBR ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f = *(double*)ED - ST0.f;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f = d - ST0.f;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED - ST0.d;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d = d - ST0.d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 6: /* FDIV ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f /= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f /= d;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d /= *(double*)ED;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d /= d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 7: /* FDIVR ST0, double */
|
||||
#ifdef USE_FLOAT
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.f = *(double*)ED / ST0.f;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
ST0.f = d / ST0.f;
|
||||
}
|
||||
#else
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED / ST0.d;
|
||||
else {
|
||||
*(uint64_t*)&d = *(uint64_t*)ED;
|
||||
memcpy(&d, ED, sizeof(double));
|
||||
ST0.d = d / ST0.d;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
|
||||
+21
-41
@@ -41,11 +41,7 @@
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
|
||||
#endif
|
||||
break;
|
||||
case 0xE8: /* FUCOMP ST0, STx */
|
||||
case 0xE9:
|
||||
@@ -55,11 +51,7 @@
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
@@ -94,39 +86,37 @@
|
||||
case 0: /* FLD double */
|
||||
GET_ED;
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
*(uint64_t*)&d = *(int64_t*)ED;
|
||||
ST0.f = d;
|
||||
#else
|
||||
ST0.ll = *(int64_t*)ED;
|
||||
#endif
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
ST0.d = *(double*)ED;
|
||||
else {
|
||||
memcpy(&ST0.d, ED, sizeof(double));
|
||||
}
|
||||
break;
|
||||
case 1: /* FISTTP ED qword */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
*(int64_t*)ED = ST0.f;
|
||||
#else
|
||||
*(int64_t*)ED = ST0.d;
|
||||
#endif
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(int64_t*)ED = ST0.d;
|
||||
else {
|
||||
int64_t i64 = ST0.d;
|
||||
memcpy(ED, &i64, sizeof(int64_t));
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FST double */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
d = ST0.f;
|
||||
*(int64_t*)ED = *(uint64_t*)&d;
|
||||
#else
|
||||
*(int64_t*)ED = ST0.ll;
|
||||
#endif
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
memcpy(ED, &ST0.d, sizeof(double));
|
||||
}
|
||||
break;
|
||||
case 3: /* FSTP double */
|
||||
GET_ED;
|
||||
#ifdef USE_FLOAT
|
||||
d = ST0.f;
|
||||
*(int64_t*)ED = *(uint64_t*)&d;
|
||||
#else
|
||||
*(int64_t*)ED = ST0.ll;
|
||||
#endif
|
||||
if(!(((uintptr_t)ED)&7))
|
||||
*(double*)ED = ST0.d;
|
||||
else {
|
||||
memcpy(ED, &ST0.d, sizeof(double));
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FRSTOR m108byte */
|
||||
@@ -137,12 +127,7 @@
|
||||
char* p =(char*)ED;
|
||||
p += 28;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
d = ST(i).f;
|
||||
LD2D(p, &d);
|
||||
#else
|
||||
LD2D(p, &ST(i).d);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
@@ -157,12 +142,7 @@
|
||||
char* p =(char*)ED;
|
||||
p += 28;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
D2LD(&d, p);
|
||||
ST(i).f = d;
|
||||
#else
|
||||
D2LD(&ST(i).d, p);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-87
@@ -1,55 +1,41 @@
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC1: /* FADDP ST1, ST0 */
|
||||
#ifdef USE_FLOAT
|
||||
ST(1).f += ST0.f;
|
||||
#else
|
||||
ST(1).d += ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xC0: /* FADDP STx, ST0 */
|
||||
case 0xC1: /* FADDP ST1, ST0 */
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f += ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d += ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xC9: /* FMULP ST1, ST0 */
|
||||
#ifdef USE_FLOAT
|
||||
ST1.f *= ST0.f;
|
||||
#else
|
||||
ST1.d *= ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xC8: /* FMULP STx, ST0 */
|
||||
case 0xC9: /* FMULP ST1, ST0 */
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f *= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d *= ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7: /* FCOMP */
|
||||
fpu_fcom(emu, ST(nextop&7).d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xD9: /* FCOMPP */
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcom(emu, ST1.f);
|
||||
#else
|
||||
fpu_fcom(emu, ST1.d);
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
@@ -65,33 +51,18 @@
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f = ST0.f - ST(nextop&7).f;
|
||||
#else
|
||||
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE9: /* FSUBP ST1, ST0 */
|
||||
#ifdef USE_FLOAT
|
||||
ST1.f -= ST0.f;
|
||||
#else
|
||||
ST1.d -= ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xE8: /* FSUBP STx, ST0 */
|
||||
case 0xE9: /* FSUBP ST1, ST0 */
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f -= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d -= ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF0: /* FDIVRP STx, ST0 */
|
||||
@@ -102,11 +73,7 @@
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
|
||||
#else
|
||||
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 0xF8: /* FDIVP STx, ST0 */
|
||||
@@ -117,23 +84,11 @@
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
#ifdef USE_FLOAT
|
||||
ST(nextop&7).f /= ST0.f;
|
||||
#else
|
||||
ST(nextop&7).d /= ST0.d;
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
case 0xD8:
|
||||
case 0xDA:
|
||||
case 0xDB:
|
||||
case 0xDC:
|
||||
@@ -146,51 +101,27 @@
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* FIADD ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f += EW->sword[0];
|
||||
#else
|
||||
ST0.d += EW->sword[0];
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FIMUL ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f *= EW->sword[0];
|
||||
#else
|
||||
ST0.d *= EW->sword[0];
|
||||
#endif
|
||||
break;
|
||||
case 4: /* FISUB ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f -= EW->sword[0];
|
||||
#else
|
||||
ST0.d -= EW->sword[0];
|
||||
#endif
|
||||
break;
|
||||
case 5: /* FISUBR ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = EW->sword[0] - ST0.f;
|
||||
#else
|
||||
ST0.d = EW->sword[0] - ST0.d;
|
||||
#endif
|
||||
ST0.d = (double)EW->sword[0] - ST0.d;
|
||||
break;
|
||||
case 6: /* FIDIV ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f /= EW->sword[0];
|
||||
#else
|
||||
ST0.d /= EW->sword[0];
|
||||
#endif
|
||||
break;
|
||||
case 7: /* FIDIVR ST0, Ew int */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = EW->sword[0] / ST0.f;
|
||||
#else
|
||||
ST0.d = EW->sword[0] / ST0.d;
|
||||
#endif
|
||||
ST0.d = (double)EW->sword[0] / ST0.d;
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
|
||||
+19
-96
@@ -1,5 +1,17 @@
|
||||
nextop = F8;
|
||||
switch (nextop) {
|
||||
case 0xC0: /* FFREEP STx */
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
fpu_do_free(emu, nextop-0xC0);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xE0: /* FNSTSW AX */
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
R_AX = emu->sw.x16;
|
||||
@@ -13,11 +25,7 @@
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcomi(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
@@ -29,22 +37,10 @@
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
#ifdef USE_FLOAT
|
||||
fpu_fcomi(emu, ST(nextop&7).f);
|
||||
#else
|
||||
fpu_fcomi(emu, ST(nextop&7).d);
|
||||
#endif
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
case 0xC1:
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xCA:
|
||||
@@ -92,44 +88,16 @@
|
||||
GET_EW;
|
||||
tmp16s = EW->sword[0];
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = tmp16s;
|
||||
#else
|
||||
ST0.d = tmp16s;
|
||||
#endif
|
||||
break;
|
||||
case 1: /* FISTTP Ew, ST0 */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
tmp16s = ST0.f;
|
||||
#else
|
||||
tmp16s = ST0.d;
|
||||
#endif
|
||||
EW->sword[0] = tmp16s;
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 2: /* FIST Ew, ST0 */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
|
||||
EW->sword[0] = 0x8000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
EW->sword[0] = floorf(ST0.f+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
EW->sword[0] = floorf(ST0.f);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
EW->sword[0] = ceilf(ST0.f);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
EW->sword[0] = ST0.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
|
||||
EW->sword[0] = 0x8000;
|
||||
else {
|
||||
@@ -148,49 +116,13 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 3: /* FISTP Ew, ST0 */
|
||||
GET_EW;
|
||||
#ifdef USE_FLOAT
|
||||
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(int32_t)0x7fff))
|
||||
EW->sword[0] = 0x8000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
EW->sword[0] = floorf(ST0.f+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
EW->sword[0] = floorf(ST0.f);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
EW->sword[0] = ceilf(ST0.f);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
EW->sword[0] = ST0.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
|
||||
EW->sword[0] = 0x8000;
|
||||
else {
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
EW->sword[0] = floor(ST0.d+0.5);
|
||||
break;
|
||||
case ROUND_Down:
|
||||
EW->sword[0] = floor(ST0.d);
|
||||
break;
|
||||
case ROUND_Up:
|
||||
EW->sword[0] = ceil(ST0.d);
|
||||
break;
|
||||
case ROUND_Chop:
|
||||
EW->sword[0] = ST0.d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
EW->sword[0] = fpu_round(emu, ST0.d);
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
case 4: /* FBLD ST0, tbytes */
|
||||
@@ -202,11 +134,7 @@
|
||||
GET_ED;
|
||||
tmp64s = *(int64_t*)ED;
|
||||
fpu_do_push(emu);
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = tmp64s;
|
||||
#else
|
||||
ST0.d = tmp64s;
|
||||
#endif
|
||||
STll(0).ll = tmp64s;
|
||||
STll(0).ref = ST0.ll;
|
||||
break;
|
||||
@@ -220,17 +148,12 @@
|
||||
if(STll(0).ref==ST(0).ll) {
|
||||
*(int64_t*)ED = STll(0).ll;
|
||||
} else {
|
||||
#ifdef USE_FLOAT
|
||||
if(isgreater(ST0.f, (float)(int64_t)0x7fffffffffffffffLL) || isless(ST0.f, (float)(int64_t)0x8000000000000000LL))
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL))
|
||||
*(int64_t*)ED = 0x8000000000000000LL;
|
||||
else
|
||||
*(int64_t*)ED = (int64_t)ST0.f;
|
||||
#else
|
||||
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
|
||||
*(int64_t*)ED = 0x8000000000000000LL;
|
||||
else
|
||||
*(int64_t*)ED = (int64_t)ST0.d;
|
||||
#endif
|
||||
else {
|
||||
int64_t i64 = fpu_round(emu, ST0.d);
|
||||
*(int64_t*)ED = i64;
|
||||
}
|
||||
}
|
||||
fpu_do_pop(emu);
|
||||
break;
|
||||
|
||||
@@ -125,6 +125,93 @@
|
||||
}
|
||||
break;
|
||||
|
||||
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
|
||||
case BASE+0: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+1: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_OF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+2: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_CF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+3: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_CF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+4: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_ZF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+5: \
|
||||
PREFIX \
|
||||
if(!ACCESS_FLAG(F_ZF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+6: \
|
||||
PREFIX \
|
||||
if((ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+7: \
|
||||
PREFIX \
|
||||
if(!(ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+8: \
|
||||
PREFIX \
|
||||
if(ACCESS_FLAG(F_SF)) \
|
||||
CONDITIONAL \
|
||||
break; \
|
||||
case BASE+9: \
|
||||
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(0x80
|
||||
, tmp32s = F32S; CHECK_FLAGS(emu);
|
||||
, ip += tmp32s;
|
||||
) /* 0x80 -> 0x8F Jxx */
|
||||
|
||||
case 0xC2: /* CMPSD Gx, Ex, Ib */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -143,6 +230,15 @@
|
||||
GX.q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
|
||||
break;
|
||||
|
||||
case 0xD0: /* ADDSUBPS Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.f[0] -= EX->f[0];
|
||||
GX.f[1] += EX->f[1];
|
||||
GX.f[2] -= EX->f[2];
|
||||
GX.f[3] += EX->f[3];
|
||||
break;
|
||||
|
||||
case 0xD6: /* MOVDQ2Q Gm, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -157,6 +253,12 @@
|
||||
GX.q[1] = 0;
|
||||
break;
|
||||
|
||||
case 0xF0: /* LDDQU Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
memcpy(&GX, EX, 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,19 @@
|
||||
GET_EX;
|
||||
EX->ud[0] = GX.ud[0];
|
||||
break;
|
||||
case 0x12: /* MOVSLDUP Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.ud[1] = GX.ud[0] = EX->ud[0];
|
||||
GX.ud[3] = GX.ud[2] = EX->ud[2];
|
||||
break;
|
||||
|
||||
case 0x16: /* MOVSHDUP Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.ud[1] = GX.ud[0] = EX->ud[1];
|
||||
GX.ud[3] = GX.ud[2] = EX->ud[3];
|
||||
break;
|
||||
|
||||
case 0x1E: /* NOP / ENDBR32 / ENDBR64 */
|
||||
nextop = F8;
|
||||
|
||||
@@ -310,11 +310,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
|
||||
// start with FPU regs...
|
||||
if(emu->fpu_stack) {
|
||||
for (int i=0; i<emu->fpu_stack; i++) {
|
||||
#ifdef USE_FLOAT
|
||||
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].f);
|
||||
#else
|
||||
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
|
||||
#endif
|
||||
strcat(buff, tmp);
|
||||
int c = 10-strlen(tmp);
|
||||
if(c<1) c=1;
|
||||
|
||||
@@ -83,8 +83,14 @@ typedef struct x86emu_s {
|
||||
|
||||
i386_ucontext_t *uc_link; // to handle setcontext
|
||||
|
||||
int type; // EMUTYPE_xxx define
|
||||
|
||||
} x86emu_t;
|
||||
|
||||
#define EMUTYPE_NONE 0
|
||||
#define EMUTYPE_MAIN 1
|
||||
#define EMUTYPE_SIGNAL 2
|
||||
|
||||
//#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
|
||||
|
||||
|
||||
+35
-5
@@ -1,3 +1,5 @@
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -33,6 +35,7 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
|
||||
for (int i=my_context->atfork_sz-1; i>=0; --i)
|
||||
if(my_context->atforks[i].prepare)
|
||||
EmuCall(emu, my_context->atforks[i].prepare);
|
||||
int type = emu->type;
|
||||
int v;
|
||||
if(forktype==2) {
|
||||
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
|
||||
@@ -40,6 +43,8 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
|
||||
emu->forkpty_info = NULL;
|
||||
} else
|
||||
v = fork();
|
||||
if(type == EMUTYPE_MAIN)
|
||||
thread_set_emu(emu);
|
||||
if(v==EAGAIN || v==ENOMEM) {
|
||||
// error...
|
||||
} else if(v!=0) {
|
||||
@@ -64,6 +69,9 @@ void x86Int3(x86emu_t* emu)
|
||||
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
|
||||
{
|
||||
R_EIP += 2;
|
||||
#ifdef RK3399
|
||||
volatile // to avoid addr to be put in an VFPU register
|
||||
#endif
|
||||
uint32_t addr = Fetch32(emu);
|
||||
if(addr==0) {
|
||||
//printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
|
||||
@@ -86,7 +94,13 @@ void x86Int3(x86emu_t* emu)
|
||||
int post = 0;
|
||||
int perr = 0;
|
||||
uint32_t *pu32 = NULL;
|
||||
const char *s = GetNativeName((void*)addr);
|
||||
const char *s = NULL;
|
||||
{
|
||||
Dl_info info;
|
||||
if(dladdr((void*)addr, &info))
|
||||
s = info.dli_sname;
|
||||
}
|
||||
if(!s) s = GetNativeName((void*)addr);
|
||||
if(addr==(uintptr_t)PltResolver) {
|
||||
snprintf(buff, 256, "%s", " ... ");
|
||||
} else
|
||||
@@ -110,9 +124,16 @@ void x86Int3(x86emu_t* emu)
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
perr = 1;
|
||||
} 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));
|
||||
perr = 1;
|
||||
} 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));
|
||||
perr = 2;
|
||||
@@ -137,6 +158,9 @@ void x86Int3(x86emu_t* emu)
|
||||
} 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));
|
||||
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));
|
||||
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));
|
||||
perr = 1;
|
||||
@@ -184,6 +208,12 @@ void x86Int3(x86emu_t* emu)
|
||||
snprintf(buff, 255, "%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) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
|
||||
} else if(strstr(s, "puts")==s) {
|
||||
snprintf(buff, 255, "%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(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} else if(strstr(s, "fprintf")==s) {
|
||||
pu32 = *(uint32_t**)(R_ESP+8);
|
||||
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
|
||||
@@ -191,6 +221,10 @@ void x86Int3(x86emu_t* emu)
|
||||
snprintf(buff, 255, "%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) {
|
||||
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
|
||||
} 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));
|
||||
} 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));
|
||||
} 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));
|
||||
} else if(strstr(s, "XCreateWindow")==s) {
|
||||
@@ -229,11 +263,7 @@ void x86Int3(x86emu_t* emu)
|
||||
break;
|
||||
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
|
||||
break;
|
||||
#ifdef USE_FLOAT
|
||||
case 4: snprintf(buff2, 63, " (%f)", ST0.f);
|
||||
#else
|
||||
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
|
||||
#endif
|
||||
break;
|
||||
case 5: {
|
||||
uint32_t* p = (uint32_t*)R_EAX;
|
||||
|
||||
+2
-2
@@ -891,7 +891,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
|
||||
CLEAR_FLAG(F_OF);
|
||||
}
|
||||
} else {
|
||||
res = (fill << (cnt)) | (fill >> (16 - cnt));
|
||||
res = (fill << (cnt)) | (d >> (16 - cnt));
|
||||
if(s==16)
|
||||
cf = d & 1;
|
||||
else
|
||||
@@ -965,7 +965,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
|
||||
}
|
||||
} else {
|
||||
cf = fill & (1 << (cnt - 1));
|
||||
res = (fill >> cnt) | (fill << (16 - cnt));
|
||||
res = (fill >> cnt) | (d << (16 - cnt));
|
||||
CONDITIONAL_SET_FLAG(cf, F_CF);
|
||||
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
|
||||
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
|
||||
|
||||
+98
-53
@@ -19,6 +19,10 @@
|
||||
#include "x87emu_private.h"
|
||||
#include "box86context.h"
|
||||
#include "my_cpuid.h"
|
||||
#include "bridge.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
int my_setcontext(x86emu_t* emu, void* ucp);
|
||||
|
||||
@@ -39,7 +43,7 @@ int Run(x86emu_t *emu, int step)
|
||||
double d;
|
||||
float f;
|
||||
int64_t ll;
|
||||
sse_regs_t *opex, eax1, *opx2;
|
||||
sse_regs_t *opex, eax1;
|
||||
mmx_regs_t *opem, eam1;
|
||||
|
||||
if(emu->quit)
|
||||
@@ -72,7 +76,7 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_0x48, &&_0x49, &&_0x4A, &&_0x4B, &&_0x4C, &&_0x4D, &&_0x4E, &&_0x4F,
|
||||
&&_0x50, &&_0x51, &&_0x52, &&_0x53, &&_0x54, &&_0x55, &&_0x56, &&_0x57,
|
||||
&&_0x58, &&_0x59, &&_0x5A, &&_0x5B, &&_0x5C, &&_0x5D, &&_0x5E, &&_0x5F,
|
||||
&&_0x60, &&_0x61, &&_0x62, &&_default, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
|
||||
&&_0x60, &&_0x61, &&_0x62, &&_0x63, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
|
||||
&&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_0x6E, &&_0x6F, //0x68-0x6F
|
||||
&&_0x70_0, &&_0x70_1, &&_0x70_2, &&_0x70_3, &&_0x70_4, &&_0x70_5, &&_0x70_6, &&_0x70_7, //0x70-0x77
|
||||
&&_0x70_8, &&_0x70_9, &&_0x70_A, &&_0x70_B, &&_0x70_C, &&_0x70_D, &&_0x70_E, &&_0x70_F, //0x78-0x7F
|
||||
@@ -84,9 +88,9 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_0xA8, &&_0xA9, &&_0xAA, &&_0xAB, &&_0xAC, &&_0xAD, &&_0xAE, &&_0xAF,
|
||||
&&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7,
|
||||
&&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF,
|
||||
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_default, &&_default, &&_0xC6, &&_0xC7,
|
||||
&&_0xC8, &&_0xC9, &&_default, &&_default, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF
|
||||
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_default, &&_0xD7,
|
||||
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7,
|
||||
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_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,
|
||||
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default,
|
||||
@@ -95,10 +99,10 @@ int Run(x86emu_t *emu, int step)
|
||||
};
|
||||
|
||||
static const void* opcodes0f[256] = {
|
||||
&&_0f_0x00, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
|
||||
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
|
||||
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
|
||||
&&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17
|
||||
&&_0f_0x18, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
|
||||
&&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_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
|
||||
@@ -119,10 +123,10 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_0f_0xA8, &&_0f_0xA9, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF,
|
||||
&&_0f_0xB0, &&_0f_0xB1, &&_default, &&_0f_0xB3, &&_default, &&_default, &&_0f_0xB6, &&_0f_0xB7,
|
||||
&&_default, &&_default, &&_0f_0xBA, &&_0f_0xBB, &&_0f_0xBC, &&_0f_0xBD, &&_0f_0xBE, &&_0f_0xBF,
|
||||
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_default, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
|
||||
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_0f_0xC3, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
|
||||
&&_0f_0xC8, &&_0f_0xC9, &&_0f_0xCA, &&_0f_0xCB, &&_0f_0xCC, &&_0f_0xCD, &&_0f_0xCE, &&_0f_0xCF, //0xC8-0xCF
|
||||
&&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7
|
||||
&&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF
|
||||
&&_0f_0xD8, &&_0f_0xD9, &&_0f_0xDA, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_0f_0xDE, &&_0f_0xDF, //0xD8-0xDF
|
||||
&&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_0f_0xE7, //0xE0-0xE7
|
||||
&&_0f_0xE8, &&_0f_0xE9, &&_0f_0xEA, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_0f_0xEE, &&_0f_0xEF, //0xE8-0xEF
|
||||
&&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_0f_0xF7, //0xF0-0xF7
|
||||
@@ -164,41 +168,6 @@ int Run(x86emu_t *emu, int step)
|
||||
&&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
|
||||
};
|
||||
|
||||
static const void* opcodes660f[256] = {
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
|
||||
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
|
||||
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
|
||||
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
|
||||
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
|
||||
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
|
||||
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
|
||||
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
|
||||
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
|
||||
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
|
||||
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
|
||||
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
|
||||
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
|
||||
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_default,
|
||||
&&_default, &&_default, &&_6f_0xBA, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
|
||||
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF
|
||||
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
|
||||
&&_6f_0xD8, &&_6f_0xD9, &&_default, &&_6f_0xDB, &&_6f_0xDC, &&_default, &&_6f_0xDE, &&_6f_0xDF,
|
||||
&&_6f_0xE0, &&_6f_0xE1, &&_6f_0xE2, &&_6f_0xE3, &&_default, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
|
||||
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
|
||||
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
|
||||
&&_6f_0xF8, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
|
||||
};
|
||||
|
||||
x86emurun:
|
||||
ip = R_EIP;
|
||||
// UnpackFlags(emu);
|
||||
@@ -418,6 +387,12 @@ _trace:
|
||||
GET_ED;
|
||||
// ignoring the test for now
|
||||
NEXT;
|
||||
_0x63: /* ARPL Ew, Gw */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
// faking to always happy...
|
||||
SET_FLAG(F_ZF);
|
||||
NEXT;
|
||||
_0x64: /* FS: */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip-1;
|
||||
@@ -629,6 +604,20 @@ _trace:
|
||||
NEXT;
|
||||
_0x86: /* XCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
GET_EB;
|
||||
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
} else {
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
} while(arm_lock_write_b(EB, GB));
|
||||
GB = tmp8u;
|
||||
}
|
||||
// dynarec use need it's own mecanism
|
||||
#else
|
||||
GET_EB;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
@@ -637,9 +626,31 @@ _trace:
|
||||
EB->byte[0] = tmp8u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
NEXT;
|
||||
_0x87: /* XCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
#ifdef DYNAREC
|
||||
GET_ED;
|
||||
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];
|
||||
} else {
|
||||
// XCHG is supposed to automaticaly LOCK memory bus
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
} while(arm_lock_write_d(ED, GD.dword[0]));
|
||||
}
|
||||
GD.dword[0] = tmp32u;
|
||||
}
|
||||
#else
|
||||
GET_ED;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
|
||||
@@ -648,6 +659,7 @@ _trace:
|
||||
ED->dword[0] = tmp32u;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
NEXT;
|
||||
_0x88: /* MOV Eb,Gb */
|
||||
nextop = F8;
|
||||
@@ -684,6 +696,8 @@ _trace:
|
||||
GET_EW;
|
||||
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
|
||||
emu->segs_clean[((nextop&0x38)>>3)] = 0;
|
||||
if(((nextop&0x38)>>3)==_FS)
|
||||
default_fs = EW->word[0];
|
||||
NEXT;
|
||||
_0x8F: /* POP Ed */
|
||||
nextop = F8;
|
||||
@@ -878,7 +892,20 @@ _trace:
|
||||
ip = Pop(emu);
|
||||
STEP
|
||||
NEXT;
|
||||
|
||||
_0xC4: /* LES Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
emu->segs[_ES] = ED->word[0];
|
||||
emu->segs_clean[_ES] = 0;
|
||||
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
|
||||
NEXT;
|
||||
_0xC5: /* LDS Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
emu->segs[_DS] = ED->word[0];
|
||||
emu->segs_clean[_DS] = 0;
|
||||
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
|
||||
NEXT;
|
||||
_0xC6: /* MOV Eb,Ib */
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
@@ -911,6 +938,13 @@ _trace:
|
||||
R_EBP = Pop(emu);
|
||||
NEXT;
|
||||
|
||||
_0xCB: /* FAR RET */
|
||||
ip = Pop(emu);
|
||||
emu->segs[_CS] = Pop(emu); // no check, no use....
|
||||
emu->segs_clean[_CS] = 0;
|
||||
// need to check status of CS register!
|
||||
STEP
|
||||
NEXT;
|
||||
_0xCC: /* INT 3 */
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
@@ -983,7 +1017,10 @@ _trace:
|
||||
_0xD5: /* AAD Ib */
|
||||
R_AX = aad16(emu, R_AX, F8);
|
||||
NEXT;
|
||||
|
||||
_0xD6:
|
||||
CHECK_FLAGS(emu);
|
||||
R_AL = ACCESS_FLAG(F_CF)?0xFF:0x00;
|
||||
NEXT;
|
||||
_0xD7: /* XLAT */
|
||||
R_AL = *(uint8_t*)(R_EBX + R_AL);
|
||||
NEXT;
|
||||
@@ -1185,6 +1222,7 @@ _trace:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x25:
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
@@ -1217,15 +1255,20 @@ _trace:
|
||||
case 0x7D:
|
||||
case 0x7E:
|
||||
case 0x7F: /* BND / NOP */
|
||||
case 0x86: /* XACQUIRE/XRELEASE XCHG */
|
||||
case 0x87: /* XACQUIRE/XRELEASE XCHG */
|
||||
case 0x88: /* XRELEASE MOV... */
|
||||
case 0x89: /* XRELEASE MOV... ignoring acquire thingy */
|
||||
case 0x9C:
|
||||
case 0xC3: /* yup, repz ret is valid */
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
case 0xF0: /* XACQUIRE/XRELEASE LOCK ... ignoring acquire thingy */
|
||||
--ip;
|
||||
NEXT;
|
||||
case 0x90: /* PAUSE */
|
||||
NEXT;
|
||||
case 0xC3: /* REPZ RET... yup */
|
||||
ip = Pop(emu);
|
||||
NEXT;
|
||||
case 0xA4: /* REP MOVSB */
|
||||
while(tmp32u) {
|
||||
--tmp32u;
|
||||
@@ -1488,8 +1531,9 @@ _trace:
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
tmp32u = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
Push(emu, ip);
|
||||
ip = ED->dword[0]; // should get value in temp var. in case ED use ESP?
|
||||
ip = tmp32u;
|
||||
STEP
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
@@ -1509,7 +1553,7 @@ _trace:
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
ip = ED->dword[0];
|
||||
ip = (uintptr_t)getAlternate((void*)ED->dword[0]);
|
||||
STEP
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
@@ -1527,12 +1571,13 @@ _trace:
|
||||
}
|
||||
break;
|
||||
case 6: /* Push Ed */
|
||||
Push(emu, ED->dword[0]);
|
||||
tmp32u = ED->dword[0];
|
||||
Push(emu, tmp32u); // avoid potential issue with push [esp+...]
|
||||
break;
|
||||
default:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
|
||||
printf_log(LOG_NONE, "Illegal Opcode %02X %02X %02X %02X %02X %02X\n", opcode, nextop, PK(2), PK(3), PK(4), PK(5));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
goto fini;
|
||||
|
||||
+394
-67
@@ -11,6 +11,9 @@
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
#ifdef DYNAREC
|
||||
#include "../dynarec/arm_lock_helper.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define F8 *(uint8_t*)(ip++)
|
||||
@@ -28,14 +31,13 @@ void Run6766(x86emu_t *emu)
|
||||
uintptr_t ip = R_EIP+2; //skip 67 66
|
||||
uint8_t opcode = F8;
|
||||
uint8_t nextop;
|
||||
reg32_t *op1, *op2;
|
||||
reg32_t *oped;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x8D: /* LEA Gw,Ew */
|
||||
nextop = F8;
|
||||
op1=GetEw16(emu, nextop);
|
||||
op2=GetG(emu, nextop);
|
||||
op2->word[0] = (uint16_t)(uintptr_t)op1;
|
||||
GET_EW16;
|
||||
GW.word[0] = (uint16_t)(uintptr_t)ED;
|
||||
break;
|
||||
|
||||
|
||||
@@ -52,11 +54,63 @@ void Run67(x86emu_t *emu)
|
||||
uint8_t opcode = F8;
|
||||
int8_t tmp8s;
|
||||
int32_t tmp32s;
|
||||
uint32_t tmp32u;
|
||||
uintptr_t tlsdata;
|
||||
reg32_t *oped;
|
||||
uint8_t nextop;
|
||||
switch(opcode) {
|
||||
|
||||
case 0x64:
|
||||
opcode = F8;
|
||||
tlsdata = GetFSBaseEmu(emu);
|
||||
switch(opcode) {
|
||||
case 0x89: /* MOV ED16,Gd */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = GD.dword[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed16 */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8F: /* POP FS:Ed */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = Pop(emu);
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Ov16 */
|
||||
tmp32u = F16;
|
||||
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
|
||||
break;
|
||||
case 0xA3: /* MOV Ov16,EAX */
|
||||
tmp32u = F16;
|
||||
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: /* Push Ed */
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
Push(emu, ED->dword[0]);
|
||||
break;
|
||||
default:
|
||||
ip-=2;
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ip-=2;
|
||||
UnimpOpcode(emu);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x66: /* MoooRE opcodes */
|
||||
Run6766(emu);
|
||||
break;
|
||||
return;
|
||||
|
||||
case 0x6C: /* INSB */
|
||||
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
|
||||
@@ -71,31 +125,31 @@ void Run67(x86emu_t *emu)
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX && !ACCESS_FLAG(F_ZF))
|
||||
R_EIP += tmp8s;
|
||||
ip += tmp8s;
|
||||
break;
|
||||
case 0xE1: /* LOOPZ */
|
||||
CHECK_FLAGS(emu);
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX && ACCESS_FLAG(F_ZF))
|
||||
R_EIP += tmp8s;
|
||||
ip += tmp8s;
|
||||
break;
|
||||
case 0xE2: /* LOOP */
|
||||
tmp8s = F8S;
|
||||
--R_CX; // don't update flags
|
||||
if(R_CX)
|
||||
R_EIP += tmp8s;
|
||||
ip += tmp8s;
|
||||
break;
|
||||
case 0xE3: /* JCXZ */
|
||||
tmp8s = F8S;
|
||||
if(!R_CX)
|
||||
R_EIP += tmp8s;
|
||||
ip += tmp8s;
|
||||
break;
|
||||
|
||||
case 0xE8: /* CALL Id */
|
||||
tmp32s = F32S; // call is relative
|
||||
Push(emu, R_EIP);
|
||||
R_EIP += tmp32s;
|
||||
Push(emu, ip);
|
||||
ip += tmp32s;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -111,20 +165,29 @@ void RunLock(x86emu_t *emu)
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
#ifdef DYNAREC
|
||||
uint8_t tmp8u2;
|
||||
#endif
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int32_t tmp32s;
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
switch(opcode) {
|
||||
#ifdef DYNAREC
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
do { \
|
||||
tmp8u = arm_lock_read_b(EB); \
|
||||
tmp8u = OP##8(emu, tmp8u, GB); \
|
||||
} while (arm_lock_write_b(EB, tmp8u)); \
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
|
||||
do { \
|
||||
tmp32u = arm_lock_read_d(ED); \
|
||||
tmp32u = OP##32(emu, tmp32u, GD.dword[0]); \
|
||||
} while (arm_lock_write_d(ED, tmp32u)); \
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
@@ -142,7 +205,47 @@ void RunLock(x86emu_t *emu)
|
||||
case B+5: \
|
||||
R_EAX = OP##32(emu, R_EAX, F32); \
|
||||
break;
|
||||
|
||||
#else
|
||||
#define GO(B, OP) \
|
||||
case B+0: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+2: \
|
||||
nextop = F8; \
|
||||
GET_EB; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
GB = OP##8(emu, GB, EB->byte[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+3: \
|
||||
nextop = F8; \
|
||||
GET_ED; \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+4: \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
R_AL = OP##8(emu, R_AL, F8); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break; \
|
||||
case B+5: \
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);\
|
||||
R_EAX = OP##32(emu, R_EAX, F32); \
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);\
|
||||
break;
|
||||
#endif
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or) /* OR 0x08 -> 0x0D */
|
||||
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
|
||||
@@ -159,22 +262,52 @@ void RunLock(x86emu_t *emu)
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
cmp8(emu, R_AL, tmp8u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_b(EB, GB);
|
||||
} else {
|
||||
R_AL = tmp8u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp8(emu, R_AL, EB->byte[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
EB->byte[0] = GB;
|
||||
} else {
|
||||
R_AL = EB->byte[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xB1: /* CMPXCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
cmp32(emu, R_EAX, tmp32u);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
tmp32s = arm_lock_write_d(ED, GD.dword[0]);
|
||||
} else {
|
||||
R_EAX = tmp32u;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
cmp32(emu, R_EAX, ED->dword[0]);
|
||||
if(ACCESS_FLAG(F_ZF)) {
|
||||
ED->dword[0] = GD.dword[0];
|
||||
} else {
|
||||
R_EAX = ED->dword[0];
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xB3: /* BTR Ed,Gd */
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -186,11 +319,27 @@ void RunLock(x86emu_t *emu)
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm_lock_write_d(ED, tmp32u);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xBA:
|
||||
nextop = F8;
|
||||
@@ -204,10 +353,19 @@ void RunLock(x86emu_t *emu)
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
#ifdef DYNAREC
|
||||
if(arm_lock_read_d(ED) & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 6: /* BTR Ed, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
@@ -218,15 +376,31 @@ void RunLock(x86emu_t *emu)
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
tmp32s = arm_lock_write_d(ED, tmp32u);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
ip -= 3; //unfetch
|
||||
ip -= 2; //unfetchall 0F BA but not F0, continue normal without LOCK
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -240,30 +414,105 @@ void RunLock(x86emu_t *emu)
|
||||
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
|
||||
}
|
||||
tmp8u&=31;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
if(tmp32u & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else {
|
||||
CLEAR_FLAG(F_CF);
|
||||
}
|
||||
tmp32u ^= (1<<tmp8u);
|
||||
} while(arm_lock_write_d(ED, tmp32u));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
if(ED->dword[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
ED->dword[0] ^= (1<<tmp8u);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC0: /* XADD Gb,Eb */
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp8u = arm_lock_read_b(EB);
|
||||
tmp8u2 = add8(emu, tmp8u, GB);
|
||||
} while (arm_lock_write_b(EB, tmp8u2));
|
||||
GB = tmp8u;
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp8u = add8(emu, EB->byte[0], GB);
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC1: /* XADD Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
|
||||
} while(arm_lock_write_d(ED, tmp32u2));
|
||||
GD.dword[0] = tmp32u;
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp32u = add32(emu, ED->dword[0], GD.dword[0]);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0xC7: /* CMPXCHG8B Gq */
|
||||
CHECK_FLAGS(emu);
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
#ifdef DYNAREC
|
||||
if(((uintptr_t)ED)&7) {
|
||||
// unaligned!!!
|
||||
uint64_t ref = R_EDX;
|
||||
ref = ref<<32 | R_EAX;
|
||||
void* p = (void*)(((uintptr_t)ED + 3)&~3);
|
||||
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
|
||||
do {
|
||||
uint64_t m = *(uint64_t*)ED;
|
||||
m&=~((0xffffffffLL)<<d);
|
||||
tmp32u = arm_lock_read_d(p);
|
||||
m|=((uint64_t)tmp32u)<<d;
|
||||
if(ref == m) {
|
||||
SET_FLAG(F_ZF);
|
||||
m = ((uint64_t)R_ECX)<<32 | R_EBX;
|
||||
tmp32u2 = m>>d;
|
||||
tmp32s = arm_lock_write_d(p, tmp32u2);
|
||||
if(!tmp32s)
|
||||
*(uint64_t*)ED = m;
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = m&0xffffffff;
|
||||
R_EDX = m>>32;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
} else
|
||||
do {
|
||||
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
SET_FLAG(F_ZF);
|
||||
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
|
||||
} else {
|
||||
CLEAR_FLAG(F_ZF);
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
tmp32s = 0;
|
||||
}
|
||||
} while(tmp32s);
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
tmp32u = ED->dword[0];
|
||||
tmp32u2= ED->dword[1];
|
||||
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
|
||||
@@ -275,10 +524,12 @@ void RunLock(x86emu_t *emu)
|
||||
R_EAX = tmp32u;
|
||||
R_EDX = tmp32u2;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// trigger invalid lock?
|
||||
ip -= 2; // unfetch
|
||||
ip -= 1; // unfetch 0F but not F0
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -292,6 +543,19 @@ void RunLock(x86emu_t *emu)
|
||||
tmp32u = (uint32_t)tmp32s;
|
||||
} else
|
||||
tmp32u = F32;
|
||||
#ifdef DYNAREC
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, add32(emu, tmp32u2, tmp32u))); break;
|
||||
case 1: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, or32(emu, tmp32u2, tmp32u))); break;
|
||||
case 2: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, adc32(emu, tmp32u2, tmp32u))); break;
|
||||
case 3: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sbb32(emu, tmp32u2, tmp32u))); break;
|
||||
case 4: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, and32(emu, tmp32u2, tmp32u))); break;
|
||||
case 5: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sub32(emu, tmp32u2, tmp32u))); break;
|
||||
case 6: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, xor32(emu, tmp32u2, tmp32u))); break;
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
|
||||
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
|
||||
@@ -302,33 +566,51 @@ void RunLock(x86emu_t *emu)
|
||||
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
|
||||
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
|
||||
}
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 0x86: /* XCHG Eb,Gb */
|
||||
nextop = F8;
|
||||
GET_EB;
|
||||
tmp8u = GB;
|
||||
GB = EB->byte[0];
|
||||
EB->byte[0] = tmp8u;
|
||||
break;
|
||||
case 0x87: /* XCHG Ed,Gd */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
tmp32u = GD.dword[0];
|
||||
GD.dword[0] = ED->dword[0];
|
||||
ED->dword[0] = tmp32u;
|
||||
ip--; // let the normal XCHG execute, it have integrated LOCK
|
||||
break;
|
||||
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
ip--;
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: /* INC Ed */
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
} while(arm_lock_write_d(ED, inc32(emu, tmp32u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = inc32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
case 1: /* DEC Ed */
|
||||
#ifdef DYNAREC
|
||||
do {
|
||||
tmp32u = arm_lock_read_d(ED);
|
||||
} while(arm_lock_write_d(ED, dec32(emu, tmp32u)));
|
||||
#else
|
||||
pthread_mutex_lock(&emu->context->mutex_lock);
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0x%02X 0x%02X\n", opcode, PK(0));
|
||||
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
break;
|
||||
@@ -337,10 +619,9 @@ void RunLock(x86emu_t *emu)
|
||||
default:
|
||||
//UnimpOpcode(emu);
|
||||
// should trigger invalid unlock ?
|
||||
ip--; // "unfetch" to use normal instruction
|
||||
ip--; // unfetch "nextop", discard F0 to use normal instruction
|
||||
}
|
||||
R_EIP = ip;
|
||||
pthread_mutex_unlock(&emu->context->mutex_lock);
|
||||
}
|
||||
|
||||
void RunGS(x86emu_t *emu)
|
||||
@@ -506,6 +787,11 @@ void RunGS(x86emu_t *emu)
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
--ip; // ignore FS: to execute regular opcode
|
||||
break;
|
||||
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -517,8 +803,9 @@ void RunGS(x86emu_t *emu)
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
Push(emu, R_EIP);
|
||||
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
|
||||
R_EIP = ED->dword[0];
|
||||
Push(emu, ip);
|
||||
ip = R_EIP;
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@@ -527,13 +814,13 @@ void RunGS(x86emu_t *emu)
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, R_EIP);
|
||||
R_EIP = ED->dword[0];
|
||||
Push(emu, ip);
|
||||
ip = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
R_EIP = ED->dword[0];
|
||||
ip = ED->dword[0];
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@@ -541,7 +828,7 @@ void RunGS(x86emu_t *emu)
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
} else {
|
||||
R_EIP = ED->dword[0];
|
||||
ip = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
@@ -570,9 +857,31 @@ void RunFS(x86emu_t *emu)
|
||||
uint8_t tmp8u;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
int16_t tmp16s;
|
||||
uintptr_t tlsdata = GetFSBaseEmu(emu);
|
||||
switch(opcode) {
|
||||
case 0x01: /* ADD FS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
|
||||
break;
|
||||
|
||||
case 0x03: /* ADD Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x11: /* ADC FS:Ed, Gd */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
|
||||
|
||||
case 0x2B: /* SUB Gd, FS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x33: /* XOR Gd,Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -584,32 +893,24 @@ void RunFS(x86emu_t *emu)
|
||||
cmp32(emu, GD.dword[0], ED->dword[0]);
|
||||
break;
|
||||
|
||||
case 0x54: /* PUSH ESP */
|
||||
tmp32u = R_ESP;
|
||||
R_ESP -= 4;
|
||||
*((uint32_t*)(R_ESP+tlsdata)) = tmp32u; //Push(emu, tmp32u);
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x50: /* PUSH Reg */
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x54: /* PUSH ESP */
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57: /* PUSH Reg */
|
||||
tmp8u = opcode&7;
|
||||
*((uint32_t*)(R_ESP+tlsdata)) = emu->regs[tmp8u].dword[0]; //Push(emu, emu->regs[tmp8u].dword[0]);
|
||||
break;
|
||||
case 0x58:
|
||||
case 0x57:
|
||||
case 0x58: /* POP Reg */
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C: /* POP ESP */
|
||||
case 0x5C: /* POP ESP */
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F: /* POP Reg */
|
||||
tmp8u = opcode&7;
|
||||
emu->regs[tmp8u].dword[0] = *((uint32_t*)(R_ESP+tlsdata)); // Pop(emu);
|
||||
R_ESP += 4;
|
||||
case 0x5F:
|
||||
// Segment override if for memory loc, no stack segment
|
||||
--ip; // so ignore prefix and continue
|
||||
break;
|
||||
|
||||
case 0x67:
|
||||
@@ -617,27 +918,35 @@ void RunFS(x86emu_t *emu)
|
||||
switch(opcode) {
|
||||
case 0x89: /* MOV ED16,Gd */
|
||||
nextop = F8;
|
||||
oped=GetEw16off(emu, nextop, tlsdata);
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = GD.dword[0];
|
||||
break;
|
||||
|
||||
case 0x8B: /* MOV Gd,Ed16 */
|
||||
nextop = F8;
|
||||
oped=GetEw16off(emu, nextop, tlsdata);
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
break;
|
||||
|
||||
case 0x8F: /* POP FS:Ed */
|
||||
nextop = F8;
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
ED->dword[0] = Pop(emu);
|
||||
break;
|
||||
|
||||
case 0xA1: /* MOV EAX,Ov16 */
|
||||
tmp16s = F16S;
|
||||
R_EAX = *(uint32_t*)((tlsdata) + tmp16s);
|
||||
tmp32u = F16;
|
||||
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
|
||||
break;
|
||||
case 0xA3: /* MOV Ov16,EAX */
|
||||
tmp16s = F16S;
|
||||
*(uint32_t*)((tlsdata) + tmp16s) = R_EAX;
|
||||
tmp32u = F16;
|
||||
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
|
||||
break;
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
case 6: /* Push Ed */
|
||||
oped=GetEw16off(emu, nextop, tlsdata);
|
||||
GET_EW16_OFFS(tlsdata);
|
||||
Push(emu, ED->dword[0]);
|
||||
break;
|
||||
default:
|
||||
@@ -703,6 +1012,18 @@ void RunFS(x86emu_t *emu)
|
||||
GET_ED_OFFS(tlsdata);
|
||||
GD.dword[0] = ED->dword[0];
|
||||
break;
|
||||
case 0x8C: /* MOV FS:Ed, Seg */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
|
||||
break;
|
||||
|
||||
case 0x8E: /* MOV Seg,FS:Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
emu->segs[((nextop&0x38)>>3)] = ED->word[0];
|
||||
emu->segs_clean[((nextop&0x38)>>3)] = 0;
|
||||
break;
|
||||
case 0x8F: /* POP Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -748,6 +1069,11 @@ void RunFS(x86emu_t *emu)
|
||||
ED->dword[0] = F32;
|
||||
break;
|
||||
|
||||
case 0xE9:
|
||||
case 0xEB:
|
||||
--ip; // ignore FS: to execute regular opcode
|
||||
break;
|
||||
|
||||
case 0xFF: /* GRP 5 Ed */
|
||||
nextop = F8;
|
||||
GET_ED_OFFS(tlsdata);
|
||||
@@ -759,8 +1085,9 @@ void RunFS(x86emu_t *emu)
|
||||
ED->dword[0] = dec32(emu, ED->dword[0]);
|
||||
break;
|
||||
case 2: /* CALL NEAR Ed */
|
||||
Push(emu, R_EIP);
|
||||
R_EIP = ED->dword[0]; // should get value in temp var. in case ED use ESP?
|
||||
R_EIP = ED->dword[0];
|
||||
Push(emu, ip);
|
||||
ip = R_EIP;
|
||||
break;
|
||||
case 3: /* CALL FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@@ -769,13 +1096,13 @@ void RunFS(x86emu_t *emu)
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
} else {
|
||||
Push16(emu, R_CS);
|
||||
Push(emu, R_EIP);
|
||||
R_EIP = ED->dword[0];
|
||||
Push(emu, ip);
|
||||
ip = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
case 4: /* JMP NEAR Ed */
|
||||
R_EIP = ED->dword[0];
|
||||
ip = ED->dword[0];
|
||||
break;
|
||||
case 5: /* JMP FAR Ed */
|
||||
if(nextop>0xc0) {
|
||||
@@ -783,7 +1110,7 @@ void RunFS(x86emu_t *emu)
|
||||
emu->quit=1;
|
||||
emu->error |= ERR_ILLEGAL;
|
||||
} else {
|
||||
R_EIP = ED->dword[0];
|
||||
ip = ED->dword[0];
|
||||
R_CS = (ED+1)->word[0];
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,90 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "box86stack.h"
|
||||
#include "x86emu.h"
|
||||
#include "x86run.h"
|
||||
#include "x86emu_private.h"
|
||||
#include "x86run_private.h"
|
||||
#include "x86primop.h"
|
||||
#include "x86trace.h"
|
||||
#include "box86context.h"
|
||||
|
||||
#define F8 *(uint8_t*)(ip++)
|
||||
#define F8S *(int8_t*)(ip++)
|
||||
#define F16 *(uint16_t*)(ip+=2, ip-2)
|
||||
#define F16S *(int16_t*)(ip+=2, ip-2)
|
||||
#define F32 *(uint32_t*)(ip+=4, ip-4)
|
||||
#define F32S *(int32_t*)(ip+=4, ip-4)
|
||||
#define PK(a) *(uint8_t*)(ip+a)
|
||||
|
||||
#include "modrm.h"
|
||||
|
||||
void Run660F(x86emu_t *emu)
|
||||
{
|
||||
uintptr_t ip = R_EIP+2; //skip 66 0F
|
||||
uint8_t opcode;
|
||||
uint8_t nextop;
|
||||
reg32_t *oped;
|
||||
uint8_t tmp8u;
|
||||
int8_t tmp8s;
|
||||
uint16_t tmp16u;
|
||||
int16_t tmp16s;
|
||||
uint32_t tmp32u;
|
||||
int32_t tmp32s;
|
||||
sse_regs_t *opex, eax1, *opx2;
|
||||
mmx_regs_t *opem;
|
||||
|
||||
static const void* opcodes660f[256] = {
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
|
||||
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
|
||||
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
|
||||
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
|
||||
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
|
||||
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
|
||||
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
|
||||
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
|
||||
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
|
||||
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
|
||||
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
|
||||
&&_default, &&_default, &&_default, &&_default, &&_6f_0x7C, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
|
||||
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
|
||||
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
|
||||
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
|
||||
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_6f_0xB7,
|
||||
&&_default, &&_default, &&_6f_0xBA, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
|
||||
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
|
||||
&&_6f_0xC8, &&_6f_0xC9, &&_6f_0xCA, &&_6f_0xCB, &&_6f_0xCC ,&&_6f_0xCD, &&_6f_0xCE, &&_6f_0xCF, //0xC8-0xCF
|
||||
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
|
||||
&&_6f_0xD8, &&_6f_0xD9, &&_6f_0xDA, &&_6f_0xDB, &&_6f_0xDC, &&_6f_0xDD, &&_6f_0xDE, &&_6f_0xDF,
|
||||
&&_6f_0xE0, &&_6f_0xE1, &&_6f_0xE2, &&_6f_0xE3, &&_6f_0xE4, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
|
||||
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
|
||||
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
|
||||
&&_6f_0xF8, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
|
||||
};
|
||||
|
||||
#define NEXT goto _fini
|
||||
|
||||
opcode = F8;
|
||||
goto *opcodes660f[opcode];
|
||||
|
||||
_default:
|
||||
emu->old_ip = R_EIP;
|
||||
R_EIP = ip;
|
||||
UnimpOpcode(emu);
|
||||
goto _fini;
|
||||
|
||||
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
|
||||
_6f_##BASE##_0: \
|
||||
PREFIX \
|
||||
@@ -211,21 +295,123 @@
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
eax1 = GX;
|
||||
for (int i=0; i<15; ++i) {
|
||||
for (int i=0; i<16; ++i) {
|
||||
if(EX->ub[i]&128)
|
||||
GX.ub[i] = 0;
|
||||
else
|
||||
GX.ub[i] = eax1.ub[EX->ub[i]&15];
|
||||
}
|
||||
break;
|
||||
case 0x01: /* PHADDW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sw[i] = GX.sw[i*2+0]+GX.sw[i*2+1];
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
|
||||
}
|
||||
break;
|
||||
case 0x02: /* PHADDD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.sd[0] += GX.sd[1];
|
||||
GX.sd[1] = GX.sd[2] + GX.sd[3];
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
GX.sd[2] = EX->sd[0] + EX->sd[1];
|
||||
GX.sd[3] = EX->sd[2] + EX->sd[3];
|
||||
}
|
||||
break;
|
||||
case 0x03: /* PHADDSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = GX.sw[i*2+0]+GX.sw[i*2+1];
|
||||
GX.sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i) {
|
||||
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
|
||||
GX.sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x04: /* PMADDUBSW Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->ub[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->ub[i*2+1];
|
||||
GX.sw[i] = (tmp32s>32767)?32767:tmp32s; // no negative value to test
|
||||
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->sb[i*2+1];
|
||||
GX.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
|
||||
}
|
||||
break;
|
||||
case 0x05: /* PHSUBW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sw[i] = GX.sw[i*2+0] - GX.sw[i*2+1];
|
||||
if(&GX == EX) {
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: /* PSIGNB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<16; ++i)
|
||||
GX.sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
|
||||
break;
|
||||
case 0x09: /* PSIGNW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<8; ++i)
|
||||
GX.sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
|
||||
break;
|
||||
case 0x0A: /* PSIGND Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
|
||||
break;
|
||||
case 0x0B: /* PMULHRSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
tmp32s = ((((int32_t)(GX.sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
|
||||
GX.uw[i] = tmp32s&0xffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1C: /* PABSB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<16; ++i) {
|
||||
GX.sb[i] = abs(EX->sb[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1D: /* PABSW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<8; ++i) {
|
||||
GX.sw[i] = abs(EX->sw[i]);
|
||||
}
|
||||
break;
|
||||
case 0x1E: /* PABSD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<4; ++i) {
|
||||
GX.sd[i] = abs(EX->sd[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
}
|
||||
@@ -234,32 +420,42 @@
|
||||
_6f_0x3A: // these are some SSE3 opcodes
|
||||
opcode = F8;
|
||||
switch(opcode) {
|
||||
case 0x0F: // PALIGNR
|
||||
case 0x0F: // PALIGNR GX, EX, u8
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u = F8;
|
||||
if(tmp8u>31)
|
||||
{EX->q[0] = EX->q[1] = 0;}
|
||||
else if(tmp8u>15) {
|
||||
{GX.q[0] = GX.q[1] = 0;}
|
||||
else
|
||||
#if 0
|
||||
if(tmp8u>15) {
|
||||
tmp8u=(tmp8u-16)*8;
|
||||
if (tmp8u < 64) {
|
||||
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (EX->q[1] >> tmp8u);
|
||||
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (GX.q[1] >> tmp8u);
|
||||
} else {
|
||||
GX.q[0] = EX->q[1] >> (tmp8u - 64);
|
||||
GX.q[0] = GX.q[1] >> (tmp8u - 64);
|
||||
GX.q[1] = 0;
|
||||
}
|
||||
} else {
|
||||
tmp8u*=8;
|
||||
if (tmp8u < 64) {
|
||||
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64-tmp8u));
|
||||
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
|
||||
GX.q[1] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64-tmp8u));
|
||||
} else {
|
||||
tmp8u -= 64;
|
||||
GX.q[0] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64 - tmp8u));
|
||||
GX.q[1] = (EX->q[0] >> tmp8u) | (EX->q[1] >> (64 - tmp8u));
|
||||
GX.q[0] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64 - tmp8u));
|
||||
GX.q[1] = (GX.q[0] >> tmp8u) | (GX.q[1] >> (64 - tmp8u));
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
for (int i=0; i<16; ++i, ++tmp8u)
|
||||
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX.ub[tmp8u-16]):EX->ub[tmp8u];
|
||||
GX.q[0] = eax1.q[0];
|
||||
GX.q[1] = eax1.q[1];
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
goto _default;
|
||||
@@ -363,18 +559,26 @@
|
||||
_6f_0x60: /* PUNPCKLBW Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=7; i>0; --i)
|
||||
for(int i=7; i>0; --i) // 0 is untouched
|
||||
GX.ub[2 * i] = GX.ub[i];
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[2 * i + 1] = EX->ub[i];
|
||||
if(&GX==EX)
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[2 * i + 1] = GX.ub[2 * i];
|
||||
else
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[2 * i + 1] = EX->ub[i];
|
||||
NEXT;
|
||||
_6f_0x61: /* PUNPCKLWD Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=3; i>0; --i)
|
||||
GX.uw[2 * i] = GX.uw[i];
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.uw[2 * i + 1] = EX->uw[i];
|
||||
if(&GX==EX)
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.uw[2 * i + 1] = GX.uw[2 * i];
|
||||
else
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.uw[2 * i + 1] = EX->uw[i];
|
||||
NEXT;
|
||||
_6f_0x62: /* PUNPCKLDQ Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -386,10 +590,16 @@
|
||||
_6f_0x63: /* PACKSSWB Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
|
||||
if(&GX==EX) {
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.sb[i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
|
||||
}
|
||||
NEXT;
|
||||
_6f_0x64: /* PCMPGTB Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -409,13 +619,19 @@
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.ud[i] = (GX.sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
|
||||
NEXT;
|
||||
_6f_0x67: /* PACKUSWB */
|
||||
_6f_0x67: /* PACKUSWB Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
|
||||
if(&GX==EX) {
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
|
||||
}
|
||||
NEXT;
|
||||
_6f_0x68: /* PUNPCKHBW Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -438,20 +654,25 @@
|
||||
_6f_0x6A: /* PUNPCKHDQ Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
|
||||
// no copy needed if &GX==EX
|
||||
GX.ud[0] = GX.ud[2];
|
||||
GX.ud[2] = GX.ud[3];
|
||||
GX.ud[1] = EX->ud[2];
|
||||
GX.ud[2] = GX.ud[3];
|
||||
GX.ud[3] = EX->ud[3];
|
||||
NEXT;
|
||||
_6f_0x6B: /* PACKSSDW Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
|
||||
if(&GX==EX) {
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.sw[i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
|
||||
GX.q[1] = GX.q[0];
|
||||
} else {
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
|
||||
for(int i=0; i<4; ++i)
|
||||
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
|
||||
}
|
||||
NEXT;
|
||||
_6f_0x6C: /* PUNPCKLQDQ Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -607,6 +828,17 @@
|
||||
GX.ud[i] = (GX.ud[i]==EX->ud[i])?0xffffffff:0;
|
||||
NEXT;
|
||||
|
||||
_6f_0x7C: /* HADDPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.d[0] += GX.d[1];
|
||||
if(EX==&GX) {
|
||||
GX.d[1] = GX.d[0];
|
||||
} else {
|
||||
GX.d[1] = EX->d[0] + EX->d[1];
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_6f_0x7E: /* MOVD Ed, Gx */
|
||||
nextop = F8;
|
||||
GET_ED;
|
||||
@@ -632,7 +864,10 @@
|
||||
_6f_0xA5: /* SHLD Ew,Gw,CL */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp8u = (opcode==0xA4)?(F8):R_CL;
|
||||
if(opcode==0xA4)
|
||||
tmp8u = F8;
|
||||
else
|
||||
tmp8u = R_CL;
|
||||
EW->word[0] = shld16(emu, EW->word[0], GW.word[0], tmp8u);
|
||||
NEXT;
|
||||
|
||||
@@ -651,7 +886,10 @@
|
||||
_6f_0xAD: /* SHRD Ew,Gw,CL */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
tmp8u = (opcode==0xAC)?(F8):R_CL;
|
||||
if(opcode==0xAC)
|
||||
tmp8u = F8;
|
||||
else
|
||||
tmp8u = R_CL;
|
||||
EW->word[0] = shrd16(emu, EW->word[0], GW.word[0], tmp8u);
|
||||
NEXT;
|
||||
|
||||
@@ -688,6 +926,11 @@
|
||||
GET_EB;
|
||||
GW.word[0] = EB->byte[0];
|
||||
NEXT;
|
||||
_6f_0xB7: /* MOVZX Gw,Ew */
|
||||
nextop = F8;
|
||||
GET_EW;
|
||||
GW.word[0] = EW->word[0]; // yeah, the ZX is useless here
|
||||
NEXT;
|
||||
|
||||
_6f_0xBA:
|
||||
nextop = F8;
|
||||
@@ -706,6 +949,21 @@
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
break;
|
||||
case 5: /* BTS Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u)) {
|
||||
SET_FLAG(F_CF);
|
||||
} else
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
CLEAR_FLAG(F_CF);
|
||||
break;
|
||||
case 6: /* BTR Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
@@ -721,6 +979,21 @@
|
||||
} else
|
||||
CLEAR_FLAG(F_CF);
|
||||
break;
|
||||
case 7: /* BTC Ew, Ib */
|
||||
CHECK_FLAGS(emu);
|
||||
GET_EW;
|
||||
tmp8u = F8;
|
||||
if((nextop&0xC0)!=0xC0)
|
||||
{
|
||||
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
|
||||
}
|
||||
tmp8u&=15;
|
||||
if(EW->word[0] & (1<<tmp8u))
|
||||
SET_FLAG(F_CF);
|
||||
else
|
||||
CLEAR_FLAG(F_CF);
|
||||
EW->word[0] ^= (1<<tmp8u);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto _default;
|
||||
@@ -819,6 +1092,18 @@
|
||||
GX.q[1] = eax1.q[1];
|
||||
NEXT;
|
||||
|
||||
_6f_0xC8:
|
||||
_6f_0xC9:
|
||||
_6f_0xCA:
|
||||
_6f_0xCB:
|
||||
_6f_0xCC:
|
||||
_6f_0xCD:
|
||||
_6f_0xCE:
|
||||
_6f_0xCF: /* BSWAP reg16 */
|
||||
tmp8s = opcode&7;
|
||||
emu->regs[tmp8s].word[0] = __builtin_bswap16(emu->regs[tmp8s].word[0]);
|
||||
NEXT;
|
||||
|
||||
_6f_0xD1: /* PSRLW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -854,7 +1139,7 @@
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)GX.sw[i] * EX->sw[i];
|
||||
GX.sw[i] = tmp32s;
|
||||
GX.sw[i] = tmp32s&0xffff;
|
||||
}
|
||||
NEXT;
|
||||
_6f_0xD6: /* MOVQ Ex,Gx */
|
||||
@@ -866,18 +1151,21 @@
|
||||
NEXT;
|
||||
_6f_0xD7: /* PMOVMSKB Gd,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<16; ++i)
|
||||
if(EX->ub[i]&0x80)
|
||||
GD.dword[0] |= (1<<i);
|
||||
NEXT;
|
||||
if((nextop&0xC0)==0xC0) {
|
||||
GET_EX;
|
||||
GD.dword[0] = 0;
|
||||
for (int i=0; i<16; ++i)
|
||||
if(EX->ub[i]&0x80)
|
||||
GD.dword[0] |= (1<<i);
|
||||
NEXT;
|
||||
} else
|
||||
goto _default;
|
||||
_6f_0xD8: /* PSUBUSB Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<16; ++i) {
|
||||
tmp16s = (int16_t)GX.ub[i] - EX->ub[i];
|
||||
GX.ub[i] = (tmp16s<0)?0:((tmp16s>255)?255:tmp16s);
|
||||
GX.ub[i] = (tmp16s<0)?0:tmp16s;
|
||||
}
|
||||
NEXT;
|
||||
_6f_0xD9: /* PSUBUSW Gx,Ex */
|
||||
@@ -885,10 +1173,15 @@
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)GX.uw[i] - EX->uw[i];
|
||||
GX.uw[i] = (tmp32s<0)?0:((tmp32s>0xffff)?0xffff:tmp32s);
|
||||
GX.uw[i] = (tmp32s<0)?0:tmp32s;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_6f_0xDA: /* PMINUB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<16; ++i)
|
||||
if(EX->ub[i]<GX.ub[i]) GX.ub[i] = EX->ub[i];
|
||||
NEXT;
|
||||
_6f_0xDB: /* PAND Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -903,7 +1196,14 @@
|
||||
GX.ub[i] = (tmp16s>255)?255:tmp16s;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_6f_0xDD: /* PADDUSW Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32s = (int32_t)GX.uw[i] + EX->uw[i];
|
||||
GX.uw[i] = (tmp32s>65535)?65535:tmp32s;
|
||||
}
|
||||
NEXT;
|
||||
_6f_0xDE: /* PMAXUB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -913,32 +1213,43 @@
|
||||
_6f_0xDF: /* PANDN Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
GX.q[0] = (~GX.q[0]) & EX->q[0];
|
||||
GX.q[1] = (~GX.q[1]) & EX->q[1];
|
||||
GX.q[0] = (~(GX.q[0])) & EX->q[0];
|
||||
GX.q[1] = (~(GX.q[1])) & EX->q[1];
|
||||
NEXT;
|
||||
_6f_0xE0: /* PAVGB Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<16; ++i) GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
|
||||
for (int i=0; i<16; ++i)
|
||||
GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
|
||||
NEXT;
|
||||
_6f_0xE1: /* PSRAW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u=(EX->q[0]>15)?16:EX->ub[0];
|
||||
for (int i=0; i<8; ++i) GX.sw[i] >>= tmp8u;
|
||||
for (int i=0; i<8; ++i)
|
||||
GX.sw[i] >>= tmp8u;
|
||||
NEXT;
|
||||
_6f_0xE2: /* PSRAD Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
|
||||
for (int i=0; i<4; ++i) GX.sd[i] >>= tmp8u;
|
||||
for (int i=0; i<4; ++i)
|
||||
GX.sd[i] >>= tmp8u;
|
||||
NEXT;
|
||||
_6f_0xE3: /* PAVGW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for (int i=0; i<8; ++i) GX.uw[i] = ((uint16_t)GX.uw[i] + EX->uw[i] + 1)>>1;
|
||||
for (int i=0; i<8; ++i)
|
||||
GX.uw[i] = ((uint32_t)GX.uw[i] + EX->uw[i] + 1)>>1;
|
||||
NEXT;
|
||||
_6f_0xE4: /* PMULHUW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i) {
|
||||
tmp32u = (uint32_t)GX.uw[i] * EX->uw[i];
|
||||
GX.uw[i] = (tmp32u>>16)&0xffff;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
_6f_0xE5: /* PMULHW Gx, Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
@@ -954,7 +1265,7 @@
|
||||
GX.sd[1] = EX->d[1];
|
||||
GX.q[1] = 0;
|
||||
NEXT;
|
||||
_6f_0xE7: /* MOVNTDQ Ex, Gx */
|
||||
_6f_0xE7: /* MOVNTDQ Ex, Gx */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
EX->q[0] = GX.q[0];
|
||||
@@ -965,7 +1276,7 @@
|
||||
GET_EX;
|
||||
for(int i=0; i<16; ++i) {
|
||||
tmp16s = (int16_t)GX.sb[i] - EX->sb[i];
|
||||
GX.ub[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
|
||||
GX.sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
|
||||
}
|
||||
NEXT;
|
||||
_6f_0xE9: /* PSUBSW Gx,Ex */
|
||||
@@ -1082,13 +1393,13 @@
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<16; ++i)
|
||||
GX.ub[i] -= EX->ub[i];
|
||||
GX.sb[i] -= EX->sb[i];
|
||||
NEXT;
|
||||
_6f_0xF9: /* PSUBW Gx,Ex */
|
||||
nextop = F8;
|
||||
GET_EX;
|
||||
for(int i=0; i<8; ++i)
|
||||
GX.uw[i] -= EX->uw[i];
|
||||
GX.sw[i] -= EX->sw[i];
|
||||
NEXT;
|
||||
_6f_0xFA: /* PSUBD Gx,Ex */
|
||||
nextop = F8;
|
||||
@@ -1124,5 +1435,8 @@
|
||||
GX.sd[2] += EX->sd[2];
|
||||
GX.sd[3] += EX->sd[3];
|
||||
NEXT;
|
||||
|
||||
|
||||
|
||||
_fini:
|
||||
R_EIP = ip;
|
||||
return;
|
||||
}
|
||||
@@ -57,15 +57,15 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
|
||||
const char* GetNativeName(void* p)
|
||||
{
|
||||
static char unknown[10] = "???";
|
||||
const char *ret = GetNameOffset(my_context->maplib, p);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
static char buff[500] = {0};
|
||||
Dl_info info;
|
||||
if(dladdr(p, &info)==0)
|
||||
if(dladdr(p, &info)==0) {
|
||||
const char *ret = GetNameOffset(my_context->maplib, p);
|
||||
if(ret)
|
||||
return ret;
|
||||
return unknown;
|
||||
else {
|
||||
} else {
|
||||
if(info.dli_sname) {
|
||||
strcpy(buff, info.dli_sname);
|
||||
if(info.dli_fname) {
|
||||
@@ -792,8 +792,8 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
if(!start_cnt && my_context->dec && (
|
||||
(trace_end == 0)
|
||||
|| ((ip >= trace_start) && (ip < trace_end))) ) {
|
||||
pthread_mutex_lock(&my_context->mutex_trace);
|
||||
int tid = syscall(SYS_gettid);
|
||||
pthread_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");
|
||||
@@ -806,6 +806,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
|
||||
my_context->trace_tid = tid;
|
||||
}
|
||||
#endif
|
||||
trace_end = 0;
|
||||
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
|
||||
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
|
||||
uint32_t a = *(uint32_t*)(ip+3);
|
||||
|
||||
@@ -64,6 +64,7 @@ int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void*
|
||||
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
|
||||
#endif
|
||||
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
|
||||
int32_t my_execve(x86emu_t* emu, const char* path, char* const argv[], char* const envp[]);
|
||||
|
||||
// cannot include <fcntl.h>, it conflict with some asm includes...
|
||||
#ifndef O_NONBLOCK
|
||||
@@ -199,6 +200,8 @@ scwrap_t syscallwrap[] = {
|
||||
//{ 221, __NR_fcntl64, 3 },
|
||||
{ 224, __NR_gettid, 0 },
|
||||
{ 240, __NR_futex, 6 },
|
||||
{ 241, __NR_sched_setaffinity, 3 },
|
||||
{ 242, __NR_sched_getaffinity, 3 },
|
||||
{ 252, __NR_exit_group, 1 },
|
||||
#ifdef NOALIGN
|
||||
{ 254, __NR_epoll_create, 1 },
|
||||
@@ -349,7 +352,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
|
||||
char** argv = (char**)R_ECX;
|
||||
char** envv = (char**)R_EDX;
|
||||
printf_log(LOG_DUMP, " => 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 = execve((const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
|
||||
}
|
||||
break;
|
||||
#ifndef __NR_time
|
||||
@@ -627,6 +630,8 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
|
||||
return my_open(emu, p(4), of_convert(u32(8)), u32(12));
|
||||
case 6: // sys_close
|
||||
return (uint32_t)close(i32(4));
|
||||
case 11: // execve
|
||||
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
|
||||
case 123: // SYS_modify_ldt
|
||||
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
|
||||
case 174: // sys_rt_sigaction
|
||||
|
||||
+4
-4
@@ -157,21 +157,21 @@ static tlsdatasize_t* setupTLSData(box86context_t* context)
|
||||
|
||||
void* fillTLSData(box86context_t *context)
|
||||
{
|
||||
pthread_mutex_lock(&context->mutex_lock);
|
||||
pthread_mutex_lock(&context->mutex_tls);
|
||||
tlsdatasize_t *data = setupTLSData(context);
|
||||
pthread_mutex_unlock(&context->mutex_lock);
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
return data;
|
||||
}
|
||||
|
||||
void* resizeTLSData(box86context_t *context, void* oldptr)
|
||||
{
|
||||
pthread_mutex_lock(&context->mutex_lock);
|
||||
pthread_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_lock);
|
||||
pthread_mutex_unlock(&context->mutex_tls);
|
||||
free_tlsdatasize(oldptr);
|
||||
return data;
|
||||
}
|
||||
|
||||
+79
-28
@@ -25,13 +25,8 @@ void fpu_fbst(x86emu_t* emu, uint8_t* d) {
|
||||
// very aproximative... but should not be much used...
|
||||
uint8_t p;
|
||||
uint8_t sign = 0x00;
|
||||
#ifdef USE_FLOAT
|
||||
double tmp, v = ST0.f;
|
||||
if(ST0.f<0.0f)
|
||||
#else
|
||||
double tmp, v = ST0.d;
|
||||
if(ST0.d<0.0)
|
||||
#endif
|
||||
{
|
||||
sign = 0x80;
|
||||
v = -v;
|
||||
@@ -64,38 +59,15 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s) {
|
||||
tmp += m * ((p>>4)&0x0f);
|
||||
m *= 10;
|
||||
}
|
||||
#ifdef USE_FLOAT
|
||||
ST0.f = tmp;
|
||||
p =*(s++);
|
||||
ST0.f += m * (p&0x0f);
|
||||
if(p&0x80)
|
||||
ST0.f = -ST0.f;
|
||||
#else
|
||||
ST0.d = tmp;
|
||||
p =*(s++);
|
||||
ST0.d += m * (p&0x0f);
|
||||
if(p&0x80)
|
||||
ST0.d = -ST0.d;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_FLOAT
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
uint32_t lower;
|
||||
uint32_t upper;
|
||||
} l;
|
||||
struct {
|
||||
float lower;
|
||||
float upper;
|
||||
} f;
|
||||
int64_t ll;
|
||||
} FPU_t;
|
||||
#else
|
||||
#define FPU_t fpu_reg_t
|
||||
#endif
|
||||
#define BIAS80 16383
|
||||
#define BIAS64 1023
|
||||
// long double (80bits) -> double (64bits)
|
||||
@@ -108,9 +80,13 @@ void LD2D(void* ld, void* d)
|
||||
int16_t b;
|
||||
} val;
|
||||
#pragma pack(pop)
|
||||
#if 1
|
||||
memcpy(&val, ld, 10);
|
||||
#else
|
||||
val.f.l.lower = *(uint32_t*)ld;
|
||||
val.f.l.upper = *(uint32_t*)(char*)(ld+4);
|
||||
val.b = *(int16_t*)((char*)ld+8);
|
||||
#endif
|
||||
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
|
||||
int32_t exp64final = exp64&0x7ff;
|
||||
// do specific value first (0, infinite...)
|
||||
@@ -254,3 +230,78 @@ void fpu_savenv(x86emu_t* emu, char* p, int b16)
|
||||
*(uint16_t*)p = tags;
|
||||
// other stuff are not pushed....
|
||||
}
|
||||
|
||||
typedef struct xsave_s {
|
||||
uint16_t ControlWord; /* 000 */
|
||||
uint16_t StatusWord; /* 002 */
|
||||
uint8_t TagWord; /* 004 */
|
||||
uint8_t Reserved1; /* 005 */
|
||||
uint16_t ErrorOpcode; /* 006 */
|
||||
uint32_t ErrorOffset; /* 008 */
|
||||
uint16_t ErrorSelector; /* 00c */
|
||||
uint16_t Reserved2; /* 00e */
|
||||
uint32_t DataOffset; /* 010 */
|
||||
uint16_t DataSelector; /* 014 */
|
||||
uint16_t Reserved3; /* 016 */
|
||||
uint32_t MxCsr; /* 018 */
|
||||
uint32_t MxCsr_Mask; /* 01c */
|
||||
sse_regs_t FloatRegisters[8];/* 020 */ // fpu/mmx are store in 128bits here
|
||||
sse_regs_t XmmRegisters[16]; /* 0a0 */
|
||||
uint8_t Reserved4[96]; /* 1a0 */
|
||||
} xsave_t;
|
||||
|
||||
void fpu_fxsave(x86emu_t* emu, void* ed)
|
||||
{
|
||||
xsave_t *p = (xsave_t*)ed;
|
||||
// should save flags & all
|
||||
emu->sw.f.F87_TOP = emu->top&7;
|
||||
p->ControlWord = emu->cw;
|
||||
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;
|
||||
p->TagWord = tags;
|
||||
p->ErrorOpcode = 0;
|
||||
p->ErrorOffset = 0;
|
||||
p->ErrorSelector = 0;
|
||||
p->DataOffset = 0;
|
||||
p->DataSelector = 0;
|
||||
p->MxCsr = 0;
|
||||
p->MxCsr_Mask = 0;
|
||||
// copy MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx[0], sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
|
||||
// put also FPU regs in a reserved area... on XMM 8-15
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&p->XmmRegisters[8+i].q[0], &emu->fpu[0], sizeof(emu->fpu[0]));
|
||||
// put a magic sign in reserved area, box86 specific
|
||||
((unsigned int *)p->Reserved4)[11] = 0x50515253;
|
||||
}
|
||||
|
||||
void fpu_fxrstor(x86emu_t* emu, void* ed)
|
||||
{
|
||||
xsave_t *p = (xsave_t*)ed;
|
||||
emu->cw = 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;
|
||||
// copy back MMX regs...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx[0]));
|
||||
// copy SSE regs
|
||||
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
|
||||
// check the box86 magic sign in reserved area
|
||||
if(((unsigned int *)p->Reserved4)[11] == 0x50515253) {
|
||||
// also FPU regs where a reserved area... on XMM 8-15?
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->fpu[0], &p->XmmRegisters[8+i].q[0], sizeof(emu->fpu[0]));
|
||||
} else {
|
||||
// copy the mmx to fpu...
|
||||
for(int i=0; i<8; ++i)
|
||||
memcpy(&emu->fpu[0], &emu->mmx[i], sizeof(emu->mmx[0]));
|
||||
}
|
||||
}
|
||||
@@ -66,28 +66,9 @@ static inline void fpu_do_free(x86emu_t* emu, int i)
|
||||
|
||||
void reset_fpu(x86emu_t* emu);
|
||||
|
||||
#ifdef USE_FLOAT
|
||||
static inline void fpu_fcom(x86emu_t* emu, float b)
|
||||
#else
|
||||
static inline void fpu_fcom(x86emu_t* emu, double b)
|
||||
#endif
|
||||
{
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
#ifdef USE_FLOAT
|
||||
if(isnan(ST0.f) || isnan(b)) {
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
} else if (isgreater(ST0.f, b)) {
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
} else if (isless(ST0.f, b)) {
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
}
|
||||
#else
|
||||
if(isnan(ST0.d) || isnan(b)) {
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
@@ -101,7 +82,6 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
emu->sw.f.F87_C0 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
@@ -109,32 +89,13 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_FLOAT
|
||||
static inline void fpu_fcomi(x86emu_t* emu, float b)
|
||||
#else
|
||||
static inline void fpu_fcomi(x86emu_t* emu, double b)
|
||||
#endif
|
||||
{
|
||||
RESET_FLAGS(emu);
|
||||
emu->flags[F_AF] = 0;
|
||||
emu->flags[F_OF] = 0;
|
||||
emu->flags[F_SF] = 0;
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
#ifdef USE_FLOAT
|
||||
if(isnan(ST0.f) || isnan(b)) {
|
||||
emu->flags[F_CF] = 1;
|
||||
emu->flags[F_PF] = 1;
|
||||
emu->flags[F_ZF] = 1;
|
||||
} else if (isgreater(ST0.f, b)) {
|
||||
emu->flags[F_CF] = 0;
|
||||
emu->flags[F_PF] = 0;
|
||||
emu->flags[F_ZF] = 0;
|
||||
} else if (isless(ST0.f, b)) {
|
||||
emu->flags[F_CF] = 1;
|
||||
emu->flags[F_PF] = 0;
|
||||
emu->flags[F_ZF] = 0;
|
||||
}
|
||||
#else
|
||||
if(isnan(ST0.d) || isnan(b)) {
|
||||
emu->flags[F_CF] = 1;
|
||||
emu->flags[F_PF] = 1;
|
||||
@@ -148,7 +109,6 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
|
||||
emu->flags[F_PF] = 0;
|
||||
emu->flags[F_ZF] = 0;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
emu->flags[F_CF] = 0;
|
||||
emu->flags[F_PF] = 0;
|
||||
@@ -156,79 +116,45 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_FLOAT
|
||||
static inline float fpu_round(x86emu_t* emu, float d) {
|
||||
if (!isfinite(d))
|
||||
return d;
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
return floorf(d+0.5);
|
||||
case ROUND_Down:
|
||||
return floorf(d);
|
||||
case ROUND_Up:
|
||||
return ceilf(d);
|
||||
case ROUND_Chop:
|
||||
default:
|
||||
return roundf(d);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline double fpu_round(x86emu_t* emu, double d) {
|
||||
if (!isfinite(d))
|
||||
return d;
|
||||
switch(emu->round) {
|
||||
case ROUND_Nearest:
|
||||
return floor(d+0.5);
|
||||
return nearbyint(d);
|
||||
case ROUND_Down:
|
||||
return floor(d);
|
||||
case ROUND_Up:
|
||||
return ceil(d);
|
||||
case ROUND_Chop:
|
||||
default:
|
||||
return round(d);
|
||||
return trunc(d);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void fpu_fxam(x86emu_t* emu) {
|
||||
#ifdef USE_FLOAT
|
||||
emu->sw.f.F87_C1 = (ST0.ll&0x8000)?1:0;
|
||||
#else
|
||||
emu->sw.f.F87_C1 = (ST0.l.upper&0x80000000)?1:0;
|
||||
#endif
|
||||
if(!emu->fpu_stack) {
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef USE_FLOAT
|
||||
if(isinf(ST0.f))
|
||||
#else
|
||||
if(isinf(ST0.d))
|
||||
#endif
|
||||
{ // TODO: Unsuported and denormal not analysed...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef USE_FLOAT
|
||||
if(isnan(ST0.f))
|
||||
#else
|
||||
if(isnan(ST0.d))
|
||||
#endif
|
||||
{ // TODO: Unsuported and denormal not analysed...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef USE_FLOAT
|
||||
if(ST0.f==0.0f)
|
||||
#else
|
||||
if(ST0.d==0.0)
|
||||
#endif
|
||||
{
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
@@ -244,22 +170,14 @@ static inline void fpu_fxam(x86emu_t* emu) {
|
||||
|
||||
static inline void fpu_ftst(x86emu_t* emu) {
|
||||
emu->sw.f.F87_C1 = 0;
|
||||
#ifdef USE_FLOAT
|
||||
if(isinf(ST0.f) || isnan(ST0.f))
|
||||
#else
|
||||
if(isinf(ST0.d) || isnan(ST0.d))
|
||||
#endif
|
||||
{ // TODO: Unsuported and denormal not analysed...
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 1;
|
||||
emu->sw.f.F87_C0 = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef USE_FLOAT
|
||||
if(ST0.f==0.0f)
|
||||
#else
|
||||
if(ST0.d==0.0)
|
||||
#endif
|
||||
{
|
||||
emu->sw.f.F87_C3 = 1;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
@@ -269,11 +187,7 @@ static inline void fpu_ftst(x86emu_t* emu) {
|
||||
// normal...
|
||||
emu->sw.f.F87_C3 = 0;
|
||||
emu->sw.f.F87_C2 = 0;
|
||||
#ifdef USE_FLOAT
|
||||
emu->sw.f.F87_C0 = (ST0.ll&0x8000)?1:0;
|
||||
#else
|
||||
emu->sw.f.F87_C0 = (ST0.l.upper&0x80000000)?1:0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fpu_fbst(x86emu_t* emu, uint8_t* d);
|
||||
@@ -281,5 +195,7 @@ void fpu_fbld(x86emu_t* emu, uint8_t* s);
|
||||
|
||||
void fpu_loadenv(x86emu_t* emu, char* p, int b16);
|
||||
void fpu_savenv(x86emu_t* emu, char* p, int b16);
|
||||
void fpu_fxsave(x86emu_t* emu, void* ed);
|
||||
void fpu_fxrstor(x86emu_t* emu, void* ed);
|
||||
|
||||
#endif //__X87RUN_PRIVATE_H_
|
||||
@@ -150,12 +150,7 @@ void Run66DD(x86emu_t *emu)
|
||||
char* p =(char*)op1;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
LD2D(p, &d);
|
||||
ST(i).f = d;
|
||||
#else
|
||||
LD2D(p, &ST(i).d);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
@@ -169,12 +164,7 @@ void Run66DD(x86emu_t *emu)
|
||||
char* p =(char*)op1;
|
||||
p += 14;
|
||||
for (int i=0; i<8; ++i) {
|
||||
#ifdef USE_FLOAT
|
||||
d = ST(i).f;
|
||||
D2LD(&d, p);
|
||||
#else
|
||||
D2LD(&ST(i).d, p);
|
||||
#endif
|
||||
p+=10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,12 @@ typedef struct mmaplist_s mmaplist_t;
|
||||
typedef struct dynmap_s {
|
||||
dynablocklist_t* dynablocks; // the dynabockist of the block
|
||||
} dynmap_t;
|
||||
#define DYNAMAP_SIZE (1<<20)
|
||||
#define DYNAMAP_SHIFT 12
|
||||
#endif
|
||||
|
||||
typedef void* (*procaddess_t)(const char* name);
|
||||
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
|
||||
|
||||
#define MAX_SIGNAL 64
|
||||
|
||||
@@ -69,6 +72,7 @@ typedef struct box86context_s {
|
||||
int trace_tid;
|
||||
#ifdef DYNAREC
|
||||
int trace_dynarec;
|
||||
pthread_mutex_t mutex_dyndump;
|
||||
#endif
|
||||
zydis_t *zydis; // dlopen the zydis dissasembler
|
||||
void* box86lib; // dlopen on box86 itself
|
||||
@@ -108,13 +112,19 @@ typedef struct box86context_s {
|
||||
procaddess_t glxprocaddress;
|
||||
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
|
||||
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
|
||||
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
|
||||
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
|
||||
vkprocaddess_t vkprocaddress;
|
||||
|
||||
callbacklist_t *callbacks; // all callbacks
|
||||
|
||||
pthread_mutex_t mutex_once;
|
||||
pthread_mutex_t mutex_once2;
|
||||
pthread_mutex_t mutex_trace;
|
||||
pthread_mutex_t mutex_lock;
|
||||
#ifndef DYNAREC
|
||||
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
|
||||
#endif
|
||||
pthread_mutex_t mutex_tls;
|
||||
pthread_mutex_t mutex_thread;
|
||||
|
||||
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
|
||||
@@ -132,11 +142,19 @@ typedef struct box86context_s {
|
||||
library_t *sdl2ttflib;
|
||||
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;
|
||||
|
||||
int deferedInit;
|
||||
elfheader_t **deferedInitList;
|
||||
@@ -159,7 +177,7 @@ typedef struct box86context_s {
|
||||
dynablocklist_t *dynablocks;
|
||||
mmaplist_t *mmaplist;
|
||||
int mmapsize;
|
||||
dynmap_t* dynmap[65536]; // 4G of memory mapped by 64K block
|
||||
dynmap_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
|
||||
#endif
|
||||
#ifndef NOALIGN
|
||||
kh_fts_t *ftsmap;
|
||||
@@ -176,6 +194,7 @@ typedef struct box86context_s {
|
||||
|
||||
uintptr_t signals[MAX_SIGNAL];
|
||||
uintptr_t restorer[MAX_SIGNAL];
|
||||
int onstack[MAX_SIGNAL];
|
||||
int is_sigaction[MAX_SIGNAL];
|
||||
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
|
||||
int no_sigsegv;
|
||||
@@ -200,7 +219,7 @@ uintptr_t AllocDynarecMap(int size, int nolinker);
|
||||
void FreeDynarecMap(uintptr_t addr, uint32_t size);
|
||||
|
||||
dynablocklist_t* getDBFromAddress(uintptr_t addr);
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
|
||||
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker);
|
||||
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
|
||||
|
||||
void protectDB(uintptr_t addr, uintptr_t size);
|
||||
|
||||
@@ -12,7 +12,13 @@ void FreeBridge(bridge_t** bridge);
|
||||
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
|
||||
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
|
||||
void* GetNativeFnc(uintptr_t fnc);
|
||||
void* GetNativeFncOrFnc(uintptr_t fnc);
|
||||
|
||||
int hasAlternate(void* addr);
|
||||
void* getAlternate(void* addr);
|
||||
void addAlternate(void* addr, void* alt);
|
||||
void cleanAlternate();
|
||||
|
||||
#endif //__BRIDGE_H_
|
||||
@@ -28,6 +28,8 @@ uintptr_t GetCallbackAddress(x86emu_t* emu);
|
||||
int IsCallback(box86context_t* context, x86emu_t* cb);
|
||||
// use thread local emu to run the function (context is unused now)
|
||||
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
|
||||
// use thread local emu to run the function (context is unused now)
|
||||
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, ...);
|
||||
// Find a cb using FNC address and argN as a key
|
||||
|
||||
+4
-1
@@ -13,6 +13,7 @@ extern int box86_dynarec_linker;
|
||||
extern int box86_dynarec_trace;
|
||||
extern int box86_dynarec_forced;
|
||||
extern int box86_dynarec_largest;
|
||||
extern int box86_dynarec_smc;
|
||||
#ifdef ARM
|
||||
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
|
||||
extern int arm_swap;
|
||||
@@ -24,11 +25,13 @@ extern int trace_xmm; // include XMM reg in trace?
|
||||
extern int trace_emm; // include EMM reg in trace?
|
||||
extern int allow_missing_libs;
|
||||
extern int box86_steam;
|
||||
extern int box86_nopulse; // diabling the use of pulseaudio
|
||||
extern uintptr_t trace_start, trace_end;
|
||||
extern box86context_t *my_context; // global context
|
||||
extern char* trace_func;
|
||||
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
|
||||
extern uint16_t default_fs;
|
||||
extern uint32_t default_fs;
|
||||
extern int jit_gdb; // launch gdb when a segfault is trapped
|
||||
#define LOG_NONE 0
|
||||
#define LOG_INFO 1
|
||||
#define LOG_DEBUG 2
|
||||
|
||||
@@ -24,11 +24,11 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr);
|
||||
|
||||
uintptr_t StartDynablockList(dynablocklist_t* db);
|
||||
uintptr_t EndDynablockList(dynablocklist_t* db);
|
||||
void FreeDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
|
||||
|
||||
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
|
||||
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
|
||||
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr);
|
||||
|
||||
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
|
||||
void AddMark(dynablock_t* source, dynablock_t* dest, void** table);
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
typedef struct dynablock_s dynablock_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
void* FillBlock(dynablock_t* block);
|
||||
void* FillBlock(dynablock_t* block, uintptr_t addr);
|
||||
|
||||
#endif //__DYNAREC_ARM_H_
|
||||
+78
-6
@@ -126,6 +126,65 @@ typedef struct my_GtkContainerClass_s
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkContainerClass_t;
|
||||
|
||||
typedef struct my_GtkActionClass_s
|
||||
{
|
||||
my_GObjectClass_t parent_class;
|
||||
void (* activate) (void* action);
|
||||
int menu_item_type;
|
||||
int toolbar_item_type;
|
||||
void* (* create_menu_item) (void* action);
|
||||
void* (* create_tool_item) (void* action);
|
||||
void (* connect_proxy) (void* action, void* proxy);
|
||||
void (* disconnect_proxy) (void* action, void* proxy);
|
||||
void* (* create_menu) (void* action);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkActionClass_t;
|
||||
|
||||
typedef struct my_GtkMiscClass_s
|
||||
{
|
||||
my_GtkWidgetClass_t parent_class;
|
||||
} my_GtkMiscClass_t;
|
||||
|
||||
typedef struct my_GtkLabelClass_s
|
||||
{
|
||||
my_GtkMiscClass_t parent_class;
|
||||
void (* move_cursor) (void* label, int step, int count, int extend_selection);
|
||||
void (* copy_clipboard) (void* label);
|
||||
void (* populate_popup) (void* label, void* menu);
|
||||
int (*activate_link) (void* label, void* uri);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
} my_GtkLabelClass_t;
|
||||
|
||||
typedef struct my_GtkTreeViewClass_s
|
||||
{
|
||||
my_GtkContainerClass_t parent_class;
|
||||
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
|
||||
void (* row_activated) (void* tree_view, void* path, void* column);
|
||||
int (* test_expand_row) (void* tree_view, void* iter, void* path);
|
||||
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
|
||||
void (* row_expanded) (void* tree_view, void* iter, void* path);
|
||||
void (* row_collapsed) (void* tree_view, void* iter, void* path);
|
||||
void (* columns_changed) (void* tree_view);
|
||||
void (* cursor_changed) (void* tree_view);
|
||||
int (* move_cursor) (void* tree_view, int step, int count);
|
||||
int (* select_all) (void* tree_view);
|
||||
int (* unselect_all) (void* tree_view);
|
||||
int (* select_cursor_row) (void* tree_view, int start_editing);
|
||||
int (* toggle_cursor_row) (void* tree_view);
|
||||
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
|
||||
int (* select_cursor_parent) (void* tree_view);
|
||||
int (* start_interactive_search) (void* tree_view);
|
||||
void (*_gtk_reserved0) (void);
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
} my_GtkTreeViewClass_t;
|
||||
|
||||
// GTypeValueTable
|
||||
typedef struct my_GTypeValueTable_s {
|
||||
void (*value_init) (void* value);
|
||||
@@ -180,13 +239,25 @@ my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, int parent);
|
||||
void InitGTKClass(bridge_t *bridge);
|
||||
void FiniGTKClass();
|
||||
|
||||
void SetGObjectID(int id);
|
||||
void SetGTKObjectID(int id);
|
||||
void SetGTKWidgetID(int id);
|
||||
void SetGTKContainerID(int id);
|
||||
void SetGTypeName(void* f);
|
||||
#define GTKCLASSES() \
|
||||
GTKCLASS(GObject) \
|
||||
GTKCLASS(GtkObject) \
|
||||
GTKCLASS(GtkWidget) \
|
||||
GTKCLASS(GtkContainer) \
|
||||
GTKCLASS(GtkAction) \
|
||||
GTKCLASS(GtkLabel) \
|
||||
GTKCLASS(GtkMisc) \
|
||||
GTKCLASS(GtkTreeView) \
|
||||
|
||||
void* wrapCopyGTKClass(void* class, int type);
|
||||
#define GTKCLASS(A) void Set##A##ID(int id);
|
||||
GTKCLASSES()
|
||||
#undef GTKCLASS
|
||||
|
||||
void SetGTypeName(void* f);
|
||||
void AutoBridgeGtk(void*(*ref)(int), void(*unref)(void*));
|
||||
|
||||
void* wrapCopyGTKClass(void* cl, int type);
|
||||
void* unwrapCopyGTKClass(void* klass, int type);
|
||||
|
||||
void my_checkGlobalGdkDisplay();
|
||||
void my_setGlobalGThreadsInit();
|
||||
@@ -205,6 +276,7 @@ typedef struct my_signal_s {
|
||||
|
||||
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
|
||||
void my_signal_delete(my_signal_t* sig);
|
||||
int my_signal_is_valid(void* sig);
|
||||
int my_signal_cb(void* a, void* b, void* c, void* d);
|
||||
|
||||
#endif //__GTKCLASS_H__
|
||||
+5
-5
@@ -558,11 +558,11 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
|
||||
@param kvar Variable to which key will be assigned
|
||||
@param code Block of code to execute
|
||||
*/
|
||||
#define kh_foreach_key(h, kvar, code) { khint_t __i; \
|
||||
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
|
||||
if (!kh_exist(h,__i)) continue; \
|
||||
(kvar) = kh_key(h,__i); \
|
||||
code; \
|
||||
#define kh_foreach_key(h, kvar, code) { khint_t __i; \
|
||||
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
|
||||
if (!kh_exist(h,__i)) continue; \
|
||||
(kvar) = kh_key(h,__i); \
|
||||
code; \
|
||||
} }
|
||||
|
||||
/*! @function
|
||||
|
||||
@@ -102,10 +102,6 @@ typedef enum {
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef union {
|
||||
#ifdef USE_FLOAT
|
||||
float f;
|
||||
uint32_t ll; // same, to avoid more #ifdef...
|
||||
#else
|
||||
double d;
|
||||
struct {
|
||||
uint32_t lower;
|
||||
@@ -116,7 +112,6 @@ typedef union {
|
||||
float upper;
|
||||
} f;
|
||||
int64_t ll;
|
||||
#endif
|
||||
} fpu_reg_t;
|
||||
|
||||
typedef union {
|
||||
|
||||
@@ -34,7 +34,7 @@ int my___sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_si
|
||||
|
||||
int my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize);
|
||||
|
||||
void init_signal_helper();
|
||||
void init_signal_helper(box86context_t* context);
|
||||
void fini_signal_helper();
|
||||
|
||||
#endif //__SIGNALS_H__
|
||||
@@ -2,9 +2,18 @@
|
||||
#define _THREADS_H_
|
||||
|
||||
typedef struct box86context_s box86context_t;
|
||||
typedef struct x86emu_s x86emu_t;
|
||||
|
||||
typedef struct emu_jmpbuf_s {
|
||||
void* jmpbuf;
|
||||
int jmpbuf_ok;
|
||||
x86emu_t* emu;
|
||||
} emu_jmpbuf_t;
|
||||
|
||||
void CleanStackSize(box86context_t* context);
|
||||
|
||||
emu_jmpbuf_t* GetJmpBuf();
|
||||
|
||||
void init_pthread_helper();
|
||||
void fini_pthread_helper();
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
|
||||
}
|
||||
elfheader_t *elf_header = LoadAndCheckElfHeader(f, libname, 0);
|
||||
if(!elf_header) {
|
||||
printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname);
|
||||
printf_log(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming...
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -244,6 +244,12 @@ library_t *NewLibrary(const char* path, box86context_t* context)
|
||||
lib->nbdot = NbDot(lib->name);
|
||||
lib->type = -1;
|
||||
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
|
||||
if(box86_nopulse) {
|
||||
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
|
||||
Free1Library(&lib);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
int notwrapped = FindInCollection(lib->name, &context->box86_emulated_libs);
|
||||
// And now, actually loading a library
|
||||
// look for native(wrapped) libs first
|
||||
|
||||
+20
-1
@@ -44,6 +44,16 @@ GO("libXau.so.6", libxau)
|
||||
GO("libXdmcp.so.6", libxdmcp)
|
||||
GO("libX11-xcb.so.1", libx11xcb)
|
||||
GO("libxcb.so.1", libxcb)
|
||||
GO("libxcb-xfixes.so.0", libxcbxfixes)
|
||||
GO("libxcb-shape.so.0", libxcbshape)
|
||||
GO("libxcb-shm.so.0", libxcbshm)
|
||||
GO("libxcb-randr.so.0", libxcbrandr)
|
||||
GO("libxcb-image.so.0", libxcbimage)
|
||||
GO("libxcb-keysyms.so.1", libxcbkeysyms)
|
||||
GO("libxcb-xtest.so.0", libxcbxtest)
|
||||
GO("libxcb-dri2.so.0", libxcbdri2)
|
||||
GO("libxcb-dri3.so.0", libxcbdri3)
|
||||
GO("libxcb-present.so.0", libxcbpresent)
|
||||
GO("libXtst.so.6", libxtst)
|
||||
GO("libXt.so.6", libxt)
|
||||
GO("libXcomposite.so.1", libxcomposite)
|
||||
@@ -56,7 +66,7 @@ GO("libopenal.so", openal)
|
||||
GO("openal.so", openal)
|
||||
GO("libalut.so.0", alut)
|
||||
GO("libjpeg.so.8", libjpeg)
|
||||
GO("libjpeg.so.62", libjpeg)
|
||||
GO("libjpeg.so.62", libjpeg62)
|
||||
GO("libcurl.so.4", curl)
|
||||
GO("libcurl-gnutls.so.4", curl)
|
||||
GO("libudev.so.0", udev0)
|
||||
@@ -74,6 +84,8 @@ GO("libpulse.so.0", pulse)
|
||||
GO("libsndfile.so.1", libsndfile)
|
||||
GO("libgtk-x11-2.0.so.0", gtkx112)
|
||||
GO("libgdk-x11-2.0.so.0", gdkx112)
|
||||
GO("libgtk-3.so.0", gtk3)
|
||||
GO("libgdk-3.so.0", gdk3)
|
||||
GO("libgdk_pixbuf-2.0.so.0", gdkpixbuf2)
|
||||
GO("libgio-2.0.so.0", gio2)
|
||||
GO("libgmodule-2.0.so.0", gmodule2)
|
||||
@@ -86,7 +98,9 @@ GO("libdbusmenu-gtk.so.4", dbusmenugtk)
|
||||
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("libatk-1.0.so.0", atk)
|
||||
GO("libpangoft2-1.0.so", pangoft2)
|
||||
GO("libpangoft2-1.0.so.0", pangoft2)
|
||||
GO("libpangocairo-1.0.so.0", pangocairo)
|
||||
GO("libcairo.so.2", cairo)
|
||||
@@ -109,5 +123,10 @@ GO("libtinfo.so.6", libtinfo6)
|
||||
GO("libtcmalloc_minimal.so.4", tcmallocminimal)
|
||||
GO("libmpg123.so.0", mpg123)
|
||||
GO("libgnutls.so.30", gnutls)
|
||||
GO("libcups.so.2", libcups)
|
||||
GO("d3dadapter9.so.1", d3dadapter9)
|
||||
GO("libvulkan.so.1", vulkan)
|
||||
GO("libvulkan.so", vulkan)
|
||||
GO("libwayland-client.so.0", waylandclient)
|
||||
|
||||
GO("ld-linux.so.2", ldlinux)
|
||||
Loaded 100 of 213 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user