296 Commits
Author SHA1 Message Date
ptitSeb 41749db028 Bumped version to v0.2.6 2022-04-16 17:15:42 +02:00
ptitSeb e30f302de9 Updated CHANGELOG 2022-04-16 12:26:08 +02:00
ptitSeb d119ed10b9 Added libdl as a dependancy for libXext 2022-04-16 10:37:27 +02:00
ptitSeb 9281289a1b [DYNAREC] Some more -NAN generation handling forwhen not using FASTNAN 2022-04-16 09:02:22 +02:00
ptitSeb 1683c0c679 Fixed interpreted SUBPD opcode 2022-04-16 09:01:46 +02:00
ptitSeb 88a8b9569d Merge pull request #611 from Jai-JAP/master
Fix pkgver in PKGBUILDS
2022-04-16 08:33:56 +02:00
Jai-JAP 18aaa03381 Fix pkgver 2022-04-16 11:35:51 +05:30
ptitSeb aa3474d06e Fixed some callback with 64bits args (help wngstreamer lib, for games like OutCast 1.1) 2022-04-13 11:56:14 +02:00
ptitSeb 0accab638f [DYNAREC] BOX86_DYNAREC_FASTNAN is default now 2022-04-11 10:09:16 +02:00
ptitSeb 29b52bc12e Fined-tune build to get test17 passing on x86 2022-04-10 20:55:57 +02:00
ptitSeb 5840cd3402 Some more NAN bordercase handlin ([DYN?AREC] too, but made FASTNAN default) 2022-04-10 16:20:56 +02:00
ptitSeb 926ff0f4f8 Added better handling of SSE float/double border case ([DYNAREC] too, with BOX86_DYNAREC_FASTNAN) 2022-04-10 15:42:36 +02:00
ptitSeb 13689e7eac Try to fix the flakyness of test11 2022-04-10 14:49:58 +02:00
ptitSeb e4ed4ad3a8 Added 66 0F 38 39/3D and 66 0F 3A 0E opcodes 2022-04-10 10:57:32 +02:00
ptitSeb 1e6037019e Added some libx11 and co. wrapped libs (shoud help #607) 2022-04-07 11:17:26 +02:00
ptitSeb da083aaab4 Merge pull request #605 from Jai-JAP/patch-1
Update PKGBUILDS
2022-04-06 07:47:47 +02:00
Jai A P 7a7853d434 Update PKGBUILD-x86 2022-04-06 10:52:37 +05:30
Jai A P eebe12ca27 Update PKGBUILD-rk3399 2022-04-06 10:52:11 +05:30
Jai A P 7aaade8780 Update PKGBUILD-raspberrypi 2022-04-06 10:51:46 +05:30
Jai A P cb185d4d44 Update PKGBUILD-pyra 2022-04-06 10:51:08 +05:30
Jai A P 3f691dc4f0 Update PKGBUILD-pandora 2022-04-06 10:50:35 +05:30
Jai A P d4c33f71eb Update PKGBUILD-odroid 2022-04-06 10:50:07 +05:30
Jai A P ad106a07ea Update PKGBUILD-gameshell 2022-04-06 10:49:37 +05:30
Jai A P 2ad3a0a7f5 Update PKGBUILD-arm 2022-04-06 10:48:52 +05:30
ptitSeb dc461d4de6 Backported improved and enhanced test17 from box64 2022-03-30 13:19:12 +02:00
ptitSeb d1a9b50dfe Added 66 0F 38 20..25/30..35 opcodes 2022-03-30 13:18:45 +02:00
ptitSeb 9a0da8d011 Added 66 0F 38 14/17 and 66 0F 3A 14/16/20 opcodes 2022-03-30 13:14:26 +02:00
ptitSeb 2d7e3877e7 Added some more wrapped libs, mostly empty for now 2022-03-27 15:33:41 +02:00
ptitSeb 0248ae0a96 [DYNAREC] Added 65 01 and 65 C6 opcodes 2022-03-27 14:39:12 +02:00
ptitSeb 9fd27f3b2c Added BOX86_PREFER_WRAPPED and BOX86_PREFER_EMULATED handling 2022-03-27 11:52:16 +02:00
ptitSeb 4152fcc934 Aded more debug info on SIGILL signal 2022-03-27 11:51:33 +02:00
ptitSeb 53c887a06a [DYNAREC] Fix an issue with neoncache transform when loading a single reg over a quad reg on add position (fixes Garfield Kart) 2022-03-27 11:48:07 +02:00
ptitSeb 316e10baa0 More work around steam and proton/SteamPlay 2022-03-26 13:17:52 +01:00
ptitSeb 8a71c6bc4a Added wrapped libgmp (backported from box64) and libgcrypt (empty for now) 2022-03-20 12:00:04 +01:00
ptitSeb 9b806de7b0 Added some gstreamer-1.0 wrapping (backported from box64) 2022-03-20 11:46:26 +01:00
ptitSeb a14dadc228 And even more work on GTK wrapping 2022-03-19 21:17:03 +01:00
ptitSeb ca850b3d30 Some more gtk wrapping work 2022-03-19 20:33:06 +01:00
ptitSeb c01dbbea0e Better link command 2022-03-19 20:08:04 +01:00
ptitSeb b883307881 Fix Pandora build 2022-03-19 19:40:30 +01:00
ptitSeb ab9bcb1e0b Fixed a warning 2022-03-19 19:40:12 +01:00
ptitSeb 3dc22ff0b8 [DYNAREC] Reworked 0F C6 opcode for better readability 2022-03-19 18:32:20 +01:00
ptitSeb 5e382e12ad More work on GTK wrapping (for #590, but some option dialog still crashes) 2022-03-19 15:10:30 +01:00
ptitSeb 103e55ff97 Fixed some potential issues with LOG=2 trace 2022-03-19 15:09:19 +01:00
ptitSeb 6140b3eee8 Added 66 F5 opcode ([DYNAREC] too) 2022-03-19 15:08:55 +01:00
ptitSeb 09574a69e9 Small fixes to some wrapped X11 functions (should help #591) 2022-03-19 09:08:35 +01:00
ptitSeb c53f961e12 Fixed, again, the mmap block selection (shoudl help #587) 2022-03-18 11:40:08 +01:00
ptitSeb a1d370fc04 Improve findBlockNearHint function, again 2022-03-17 12:18:46 +01:00
ptitSeb 471b679d3f Fixed wrapped mprotect not always working properly (should help #587) 2022-03-17 11:59:29 +01:00
ptitSeb e60caa8648 Fixed a warning 2022-03-17 11:59:29 +01:00
ptitSeb ccfc8a8d30 Merge pull request #589 from wannacu/master
[DYNAREC] Added check of dyn's size
2022-03-17 10:51:49 +01:00
wannacu 6a7b7bec6a [DYNAREC] Added check of dyn's size 2022-03-17 09:30:30 +00:00
ptitSeb 0926c48aea Fixed the new memmap tracking 2022-03-13 17:10:53 +01:00
ptitSeb d10a9e40ed Fixed some LOG=2 improved trace 2022-03-13 17:10:06 +01:00
ptitSeb 4df12ee5ea Fixed some issues with the mapmem tracking (might help #587) 2022-03-13 15:50:37 +01:00
ptitSeb 433294fb40 [DYNAREC] Small cosmetic changes 2022-03-13 15:42:28 +01:00
ptitSeb 298fe50dd1 Merge pull request #585 from wannacu/master
Add some function wrapper of libx11
2022-03-11 16:49:15 +01:00
wannacu 1717fffe8f Add some function wrapper of libx11 2022-03-11 18:19:22 +08:00
ptitSeb 41521913d5 Change method for the mmap free bloc search for a faster one 2022-03-09 11:17:14 +01:00
ptitSeb e75ca5d2ff Change de verbose level of a custommem message 2022-03-08 18:50:22 +01:00
ptitSeb 0d2081ed30 Merge pull request #583 from wannacu/master
Added wrapped libvkd3d
2022-03-08 13:23:04 +01:00
ptitSeb d6abdc2a55 Disabling test14 (conditionalThreads) for now on x86 arch, it's a bit flacky and gives too many false-positive 2022-03-08 11:54:38 +01:00
wannacu 0a0cf77461 Added wrapped libvkd3d 2022-03-08 17:56:29 +08:00
ptitSeb a5c438068c Fix some special case on mmap64 wrapping 2022-03-08 10:18:33 +01:00
ptitSeb d2c8839a69 Added 1 more wrapped function to libx11 2022-03-08 10:18:08 +01:00
ptitSeb 21b560a3b9 Merge pull request #582 from wannacu/master
Added dummy wrapped libharfbuzz and libcairo-gobject
2022-03-07 16:00:27 +01:00
wannacu b1d8de62d4 Added dummy wrapped libharfbuzz and libcairo-gobject 2022-03-07 22:46:05 +08:00
ptitSeb 1e41857d37 Small change is symbol gathering for wrapped libs (help some java versions 2022-03-07 13:42:34 +01:00
ptitSeb 63920e95d3 Improved handling of env. var. for wrapped execve 2022-03-07 11:22:53 +01:00
ptitSeb 7856b2b7ee [TRACE] Better trace for putenv 2022-03-07 11:22:04 +01:00
ptitSeb 5daf34ba29 Added [stack] to the generated maps file (should help #533) 2022-03-07 11:21:36 +01:00
ptitSeb e513cbeaaa Added an option to always show SIGSEGV messages 2022-03-06 19:27:03 +01:00
ptitSeb c782ba2429 Fixed dlinfo (helps wine) 2022-03-06 19:26:52 +01:00
ptitSeb 50dae3f5d8 Added some vulkan extentions 2022-03-06 17:10:01 +01:00
ptitSeb d3e6551b40 Remove a debug trace leftover 2022-03-06 16:44:27 +01:00
ptitSeb 0e1d1a788d Improved speed of mmap changes 2022-03-06 16:27:23 +01:00
ptitSeb dfafce7f05 Change on mmap64 to help some stagging version of wine (for #580) 2022-03-06 15:23:38 +01:00
ptitSeb eb7381457a Detect wine, just in case 2022-03-06 13:54:51 +01:00
ptitSeb 2f8baf9559 Improve a bit when box86 launch program natively or with box64 2022-03-06 11:34:53 +01:00
ptitSeb 34cb03c7df Try to improve the clone syscall (backported from box64) 2022-03-06 11:29:03 +01:00
ptitSeb d76ecb8a38 [ANDROID] Try, again and again, to fix build 2022-03-05 21:48:08 +01:00
ptitSeb 943c2a0bd9 [ANDROID] Try, again, to fix build 2022-03-05 21:28:11 +01:00
ptitSeb a7552c8bb8 [ANDROID] Try to fix build 2022-03-05 21:12:49 +01:00
ptitSeb 8cd78041a2 Improve wrapping of readlinkat function 2022-03-05 20:35:02 +01:00
ptitSeb 3fe3499ec2 Added dladdr1 handling (backported from box64) 2022-03-05 20:30:34 +01:00
ptitSeb 70c49f67c4 [DYNAREC] Fixed GETEBO and GETEDO2 macros 2022-03-05 18:41:38 +01:00
ptitSeb 308c316dbf Backported some improvment on wrapped libx11 from box64 2022-03-05 18:16:53 +01:00
ptitSeb c660b3a9aa Added 1 more wrapped function to libfontconfig (steam BigPicture seems to works now) 2022-03-05 13:39:02 +01:00
ptitSeb 642bb357d3 Put libpangoft2 to the list of gtk wrapped libs 2022-03-04 22:40:31 +01:00
ptitSeb 4978177584 Some wrapped pango / pangocairo / xi functions 2022-03-04 20:14:23 +01:00
ptitSeb ae8a69a840 Improve trace, again, a bit 2022-03-04 16:48:30 +01:00
ptitSeb 383c2be9fc Some work on the basic linux libs 2022-03-03 19:34:10 +01:00
ptitSeb 1cc4653672 [ANDROID] Put back old mutex mothod for android only 2022-03-03 17:25:37 +01:00
ptitSeb 6b6daba17a Some work on gtk wrapped libs 2022-03-03 16:53:09 +01:00
ptitSeb d8eb090a7a [TRACE] Improve trace when symbol there is no symbol name 2022-03-03 16:52:42 +01:00
ptitSeb eb2e96f13b Add possibility to fail loading a lib if a R_386_PC32 reloc fail (help Source engine options menu) 2022-03-03 16:51:57 +01:00
ptitSeb 41201cbb96 Added some more wrapped pulse functions 2022-03-01 11:10:40 +01:00
ptitSeb 151115ed10 Remove special case for hl_linux 2022-03-01 10:02:25 +01:00
ptitSeb 7d4154e0d4 Merge pull request #579 from Mzed3D/patch-1
Update CMakeLists.txt
2022-02-27 14:50:42 +01:00
Mzed3D 7a470daa26 Update CMakeLists.txt
Added Odroid-N2 specific profile
2022-02-27 14:34:07 +01:00
ptitSeb a4e40d06ac Added wrapped (empty) libmimalloc 2022-02-26 18:02:52 +01:00
ptitSeb 875efd2a42 Added 65 39 opcode ([DYNAREC] too) 2022-02-25 21:34:01 +01:00
ptitSeb 9ee0ac92c3 Fixed interpreted 0F 38 00 opcode 2022-02-13 14:40:30 +01:00
ptitSeb c7f554bebb [DYNAREC] Added 0F 3A 0F opcode 2022-02-13 12:50:00 +01:00
ptitSeb 6fe8d71e61 Small fix to 0F 3A 0F opcode 2022-02-13 12:49:37 +01:00
ptitSeb f6f24bce25 [DYNAREC] Added F3 0F D6 opcode 2022-02-13 12:30:33 +01:00
ptitSeb 8b81151ec1 Added wrapped SDL_UpdateWindowSurfaceRects function 2022-02-13 12:29:48 +01:00
ptitSeb 55033ed25e [DYNAREC] Added F2 0F D6 opcode 2022-02-13 12:21:22 +01:00
ptitSeb a829a60341 Undo last commit 2022-02-11 19:14:03 +01:00
ptitSeb 0a25e78964 Fixed wrapped function IMG_SavePNG_RW from SDL2-image 2022-02-11 19:05:46 +01:00
ptitSeb dec1acdfb1 Merge branch 'master' of https://github.com/ptitSeb/box86 2022-02-11 17:45:26 +01:00
ptitSeb 4f0970138b Added 66 0F BF opcode ([DYNAREC] too) 2022-02-11 17:45:15 +01:00
ptitSeb 4707997aec Merge pull request #573 from WheezyE/patch-1
Add note to use box64 to run x86_64 applications
2022-02-10 21:34:50 +01:00
Eric Wiessner (KI7POL) ae5a4b5f4f Add note to use box64 to run x86_64 applications 2022-02-10 13:32:29 -07:00
ptitSeb 5187b55a2e Added wrapped stat64 and lstat64 2022-02-06 20:07:51 +01:00
ptitSeb 60078852bd Merge pull request #564 from MichaIng/imgbot
[ImgBot] Optimize images
2022-02-01 18:53:57 +01:00
ptitSeb 580bacaf93 Merge pull request #563 from MichaIng/patch-1
Make postinst script failsafe
2022-02-01 16:50:30 +01:00
MichaIng eb1ab920cf Make postinst script failsafe
"systemctl restart systemd-binfmt" can only succeed when systemd is the used init system and when the binfmt_misc kernel module is available. The kernel module may not be available right after a kernel upgrade or within a container where it needs to be loaded on the host. 

The common check for whether systemd is used or not is to check for the directory "/run/systemd/system" which is hereby added.

Since modprobe may not be available and within a container always fails (regardless whether the host provides it), the service restart is allowed to fail without failing the postinst script and hence the package install. If the service restart fails, Box86 support in binfmt becomes effective on next system restart, given binfmt_misc is generally available. Furthermore binfmt is a convenience feature while generally Box86 can be used without it. It is hence no reason to hard fail the package install when systemd-binfmt fails for any reason.

Signed-off-by: MichaIng <[email protected]>
2022-02-01 16:30:37 +01:00
ImgBotApp 6c0aabd36e [ImgBot] Optimize images
*Total -- 238.68kb -> 226.88kb (4.94%)

/docs/img/Box86Icon.png -- 67.71kb -> 57.69kb (14.8%)
/docs/img/Box86Logo.png -- 170.97kb -> 169.20kb (1.04%)

Signed-off-by: ImgBotApp <[email protected]>
2022-02-01 15:12:34 +00:00
ptitSeb a3d2443b70 Added 2 wrapped function to gtk3 (for #562) 2022-01-30 14:16:46 +01:00
ptitSeb 313ca172a5 [DYNAREC] Improved potential son detections 2022-01-30 13:14:10 +01:00
ptitSeb ceb4e53f15 [DYNAREC] Added option to force Double for x87 emulation, and added some detection of Crysis to force this option (needed for Crysis physics engine) 2022-01-30 12:28:37 +01:00
ptitSeb 4510b4997a Added 2 wrapped function to libpng12, and 1 to libpng16 (for #560) 2022-01-25 22:48:55 +01:00
ptitSeb 12cc43bd7c Fix(?) of the better wrapping for g_option_context_add_main_entries 2022-01-23 22:11:52 +01:00
ptitSeb 21069c107a Better wrapping for g_option_context_add_main_entries 2022-01-23 20:53:57 +01:00
ptitSeb 93032afe0f More work on symbol versionning of elfloader (for #559, but might help others) 2022-01-23 18:23:20 +01:00
ptitSeb f422fe13f4 Added hl2_linux for the same special case as hl_linux 2022-01-23 18:22:31 +01:00
ptitSeb ed551d1eb3 Don't allow to small stack for native thread 2022-01-23 16:34:58 +01:00
ptitSeb 58cd4119a6 Added a few wrapped function to libnspr4 and libnss3 (but libnspr4 needs more work on special cases) 2022-01-23 16:34:06 +01:00
ptitSeb c8147ce3d4 Added BOX86_ALLOWMISSING_SYMBOLS option, rename BOX86_ALLOWINGLIBS, and added a special case for hl_linux (for #559) 2022-01-23 16:33:00 +01:00
ptitSeb 00df171604 Install i386 libpng12.so.0 with 'make install' along side libstdc++ and libgcc_s 2022-01-23 13:58:01 +01:00
ptitSeb 50ca38d4d0 Added 2 more wrapped function libxcb 2022-01-22 09:27:06 +01:00
ptitSeb e31e5c1a5b Added dprintf and __dprintf_chk wrapped functions (for #558) 2022-01-21 08:47:24 +01:00
ptitSeb c80356a90a Merge pull request #556 from ryanfortner/master
Various packaging improvements
2022-01-18 22:12:22 +01:00
Ryan Fortner 4909b039c0 Update rules 2022-01-18 14:31:07 -05:00
Ryan Fortner dc8ee2718b Update COMPILE.md 2022-01-18 14:09:44 -05:00
Ryan Fortner 8118f4ad18 Update rules 2022-01-18 14:08:14 -05:00
Ryan Fortner de422a0d93 Update rules 2022-01-18 12:58:59 -05:00
Ryan Fortner cbffa01014 Update rules 2022-01-18 12:47:46 -05:00
Ryan Fortner f8688c33a0 test nostrip option 2022-01-18 12:16:32 -05:00
Ryan Fortner 6e0e56b85e add lintian-override 2022-01-18 12:11:34 -05:00
Ryan Fortner 7e81522ed4 Update COMPILE.md 2022-01-18 12:06:58 -05:00
Ryan Fortner 0c8a76fceb fix copyright formatting again (fixes build error) 2022-01-18 12:04:06 -05:00
Ryan Fortner 35273abff7 use quilt instead of native 2022-01-18 11:59:44 -05:00
Ryan Fortner 6c1f3ea4bf Update rules 2022-01-18 11:58:26 -05:00
ptitSeb 5e261e0d7f Merge pull request #555 from ryanfortner/master
Add Debian packaging files
2022-01-18 17:49:49 +01:00
Ryan Fortner 53553ece6f fix formatting in debian/changelog 2022-01-18 11:37:50 -05:00
Ryan Fortner 33d47ff1c8 upload base debianization 2022-01-18 11:35:21 -05:00
ptitSeb 16b8657a47 |DYNAREC] Small optim on cmpxchg opcode 2022-01-16 15:19:09 +01:00
ptitSeb 264c834c2c [DYNAREC] Fixed a typo in previous commit (help steam) 2022-01-16 15:18:16 +01:00
ptitSeb 28b05465ea Too much fun with SHUFPD, fixed '6' part, and fir PSHUFD too (fixed 007 NightFire, maybe others) 2022-01-16 10:43:01 +01:00
ptitSeb b903e57ef9 [DYNAREC] Forgot to also fix the x87 full purge optim 2022-01-15 22:47:56 +01:00
ptitSeb d5ffba47a2 [DYNAREC] Fixed a last bug (again), on x87 purge optim (help nfs3, probably other too) 2022-01-15 22:44:04 +01:00
ptitSeb 34b99bfede Reverted the change on dn_expand / res_query symbol from libresolv 2022-01-15 17:31:44 +01:00
ptitSeb 4f5aac8f50 Fixed issue with dl_vsym internal use (will help #548 and others) 2022-01-15 17:23:32 +01:00
ptitSeb fe53eeb010 Merge pull request #553 from io12/android-ci
Add Android builds to GitHub Actions
2022-01-13 23:02:07 +01:00
Benjamin Levy 67b6f69926 Add Android to CI 2022-01-13 16:10:44 -05:00
ptitSeb 6bf62a3d4e Merge pull request #551 from io12/fix-android
Fix Android build
2022-01-13 07:41:14 +01:00
Benjamin Levy 54b911550f Fix Android build 2022-01-12 21:24:16 -05:00
ptitSeb 31a988877a [DYNAREC] Add one more bug from the x87 optimization squashed (help Freedom Planet) 2022-01-09 23:13:02 +01:00
ptitSeb 88642d81c0 Another attempt to make the function to find versionned symbol more resiliant (should help #548) 2022-01-08 19:12:57 +01:00
ptitSeb 135e8d98e9 [DYNAREC] Fixed a typo in PSHUFD optim (fixes steam, maybe others) 2022-01-08 12:50:38 +01:00
ptitSeb bd5c8fd403 [DYNAREC] Fixed a typo in a x87 optim (for #548 and all windows gog installer in general) 2022-01-08 11:24:07 +01:00
ptitSeb 3b112793aa Added wrapped libselinux with a few functions 2022-01-08 10:23:46 +01:00
ptitSeb 2fc8d9ae4f Move libatk back to the list of exclude libs when using NOGTK (helps steam) 2022-01-07 18:28:28 +01:00
ptitSeb afe63f02fa Merge pull request #547 from Seas0/master
Minor fix in action configuration
2022-01-07 10:16:17 +01:00
Seas0 6aa744dff9 Minor fix in action configuration 2022-01-07 16:45:22 +08:00
ptitSeb 095b04d31c Merge pull request #546 from Seas0/master
Remove temporary test output file
2022-01-07 09:26:08 +01:00
Seas0 6136fe0c8b Fix expansion test case output file 2022-01-07 16:15:38 +08:00
Seas0 e2f3752018 Remove test temporary file 2022-01-07 16:02:08 +08:00
ptitSeb 5d0fdf01f3 Fixed (F0) 0F C7 opcode, only /1 is CMPXCHG8B 2022-01-06 21:46:39 +01:00
ptitSeb cb4b6bc76d Added 66 F0 FF /0 and /1 opcodes ([DYNAREC] too) 2022-01-06 21:14:24 +01:00
ptitSeb bb0f57b5ab Don't abort when try to execute an unsupported syscall 2022-01-06 20:33:54 +01:00
ptitSeb c23981b97f Added one x11 wrapped function (for #545) 2022-01-06 19:27:37 +01:00
ptitSeb c005fc6754 Added deprecated libpng12.so, because it's more and more difficult to have a native version of it 2022-01-06 18:20:04 +01:00
ptitSeb 8d24048c26 [DYNAREC] Improved 66 0F D1/D2 opcodes 2022-01-06 18:20:04 +01:00
ptitSeb ac1ae9f9db [PANDORA] Fix build 2022-01-06 13:18:05 +01:00
ptitSeb 53e8a40e1b (re)Set default log to NONE 2022-01-06 11:53:22 +01:00
ptitSeb a7d803bc82 Made the missing symbol workaround more resiliant 2022-01-05 22:51:53 +01:00
ptitSeb 944ae100fa Added some workaround for program that calls 'uname -m' to get the architecture of the host (also using box64 if present) 2022-01-05 21:20:24 +01:00
ptitSeb b68fd36476 Change default banner and log to be silent if stdout is beeing redirected 2022-01-05 21:20:24 +01:00
ptitSeb 74d530d65e Merge pull request #543 from asppsa/pkgbuild-followup
Update PKGBUILD files to match rk3399 one
2022-01-05 15:03:43 +01:00
Alastair Pharo b5cf71c7af Update other pkgbuild files to match rk3399 one 2022-01-06 00:29:30 +11:00
Alastair Pharo 8d663f80bd Fix package stage of rk3399 pkgbuild 2022-01-05 23:37:34 +11:00
ptitSeb 77257e2532 Merge pull request #541 from asppsa/rk3399-gcc-fix
Don't use cross-compile GCC on 32-bit systems
2022-01-05 08:33:12 +01:00
ptitSeb 44d6719107 Merge pull request #542 from asppsa/pkgbuild-fix
Fix rk3399 PKGBUILD
2022-01-05 08:32:48 +01:00
Alastair Pharo 05ddaa6356 Fix rk3399 PKGBUILD 2022-01-05 17:57:49 +11:00
Alastair Pharo d8a6b6528a Don't use cross-compile GCC on 32-bit systems
If the OS is not aarch64, then use the normal GCC.  This allows
compilation for work on devices like the RK3399 when running in a 32-bit
chroot, instead of using a multilib setup.
2022-01-05 15:53:18 +11:00
ptitSeb 478c781822 [DYNAREC] Detect ARMv8, because VRINT opcodes doesn't exist on ARMv7 2022-01-04 21:55:40 +01:00
ptitSeb 93039252f2 Removed special case for pow10, it's automaticaly handled now) 2022-01-04 20:05:01 +01:00
ptitSeb 3efc3ebe25 Added a warning if launching a binary with a preinit array 2022-01-04 20:04:39 +01:00
ptitSeb 1f5824a55b Added a Workaround when dlsym a native (versionned) symbol without default version fails 2022-01-04 20:04:06 +01:00
ptitSeb d364c2f53e [DYNAREC] Some more various x87 optimizations 2022-01-04 13:20:41 +01:00
ptitSeb 7d0bc98e3e SDmall precision on a x87 opcode 2022-01-04 13:20:18 +01:00
ptitSeb 85e0b26a53 [DYNAREC] Small fixes for some x87 functions 2022-01-04 09:45:42 +01:00
ptitSeb c3f21c8af2 [DYNAREC] Optimized PSHUFD too 2022-01-02 18:26:13 +01:00
ptitSeb 8bd2148ae4 [DYNAREC] Small optim for some case of packssdw opcode 2022-01-02 17:32:27 +01:00
ptitSeb 2c74cef483 [DYNAREC] Remade SHUFPD opcode 2022-01-02 17:26:55 +01:00
ptitSeb 3a1911f5cd [DYNAREC] Fun with shufps 2022-01-02 17:17:40 +01:00
ptitSeb d871886ec5 [DYNAREC] Small improvement to F3 0F 10/11 opcodes 2022-01-02 17:05:29 +01:00
ptitSeb 146a2e8aae Revert most of top8 commit, it seems unstable 2022-01-02 14:15:20 +01:00
ptitSeb 727784d90a More work on x87 handling, using top=8 for empty stack ([DYNAREC] too) 2022-01-01 11:03:26 +01:00
ptitSeb 67647bc51e Merge pull request #539 from Seas0/master
Some improvement on Github Action configuration
2021-12-31 19:15:15 +01:00
Seas0 3ce9d84669 Add test to Github Action 2022-01-01 01:54:30 +08:00
Seas0 af6ed6c296 Add custom build option in Github Action 2022-01-01 01:45:07 +08:00
ptitSeb 3f65c0593f Merge pull request #536 from Seas0/master
Making ctest -j$(nproc) work as intended and fix a typo in github action configuration
2021-12-31 17:22:21 +01:00
Seas0 98e7941371 Fix Github Action event trigger for CMakeLists.txt 2022-01-01 00:15:28 +08:00
Seas0 3fb5eb3ec9 Making ctest -j$(nproc) work as intended
Change the temporary file name of each test in order to prevent the conflict when running ctest with multiple processes enabled
2022-01-01 00:10:05 +08:00
ptitSeb 497c748955 Removed libatk from the NOGTK filter, and added some more libatk wrapped functions 2021-12-31 14:34:32 +01:00
ptitSeb 230247af17 Changed how libresolv is used (for latest libc version) and change 2 symbol bindings 2021-12-31 13:38:17 +01:00
ptitSeb bbea40833b Added one more libgnutls wrapped function (should help steam) 2021-12-31 13:19:53 +01:00
ptitSeb 146ca6a9c9 Added some libgnutls wrapped function (should help steam) 2021-12-31 13:13:41 +01:00
ptitSeb fb7e8c730c Added one libresolv as a dependancy for libglib2 2021-12-31 13:13:19 +01:00
ptitSeb e5135ae67b Added one libc wrapped function (should help steam) 2021-12-31 12:03:44 +01:00
ptitSeb f1b524460e Added 3 x11 wrapped function (should help steam) 2021-12-31 12:03:14 +01:00
ptitSeb 9c9c910fa8 Added a couple of fontconfig wrapped function (should help steam) 2021-12-31 11:58:42 +01:00
ptitSeb 63330cbb84 Added some cairo wrapped function (should help steam) 2021-12-31 11:57:39 +01:00
ptitSeb 5c6816f8ab Small change to the handling of some x87 opcodes 2021-12-30 17:20:46 +01:00
ptitSeb 4c0366e340 [DYNAREC] Improve exchange of st regs, plus some fixes on x87 optim, again (help linux Witcher2 intro video) 2021-12-30 14:27:44 +01:00
ptitSeb 38e2e4e16a [DYNAREC] Added BOX86_DYNAREC_BIGBLOCK=2 option 2021-12-30 11:47:29 +01:00
ptitSeb 430b24c0f3 Added a comment on PREFETCHW opcode 2021-12-28 15:07:16 +01:00
ptitSeb b22b187ce0 Small change on bridge memory protection handling 2021-12-28 15:06:49 +01:00
ptitSeb cc32d6cb98 Added 0F 0D /1 (faked) opcode (for #533) 2021-12-27 11:12:01 +01:00
ptitSeb 66332ae9e2 [DYNAREC] Fixed (again, for the last time?) the x87 load/unload cache optim (should help Witcher2, maybe more) 2021-12-25 12:15:21 +01:00
ptitSeb b6dd3acfea Added 16bits PUSH DS ocpode ([DYNAREC] too) (for #529) 2021-12-23 20:46:03 +01:00
ptitSeb b655e89af0 [DYNAREC] Fixed idiv optimisation, and added a new test about idiv opcode 2021-12-22 11:44:11 +01:00
ptitSeb 2879cf51cd Merge pull request #526 from Seas0/master
Move all _GNU_SOURCE defination to the file head
2021-12-22 11:22:38 +01:00
Seas0 725dabea88 Move all _GNU_SOURCE defination to the file head
Accroding to man 7 feature_test_macros' guide line
2021-12-22 17:23:58 +08:00
ptitSeb 35f133cacd [DYNAREC] Fixed one last issue with x87 optimizations 2021-12-19 16:14:44 +01:00
ptitSeb b0e4f2c696 [DYNAREC] Fixed another issue with x87 optimizations 2021-12-19 15:47:32 +01:00
ptitSeb 65c423917e [DYNAREC] Fixed an incorect assert in fillPredecessors 2021-12-19 14:53:19 +01:00
ptitSeb f128af26ec [DYNAREC] Fixed some issue with x87 optimizations 2021-12-19 13:57:02 +01:00
ptitSeb 1bf955baa8 [TRACE] Changed a bit x87 trace 2021-12-19 13:56:36 +01:00
ptitSeb cee2ff2641 Changed a bit the behavior of elfloader with local symbol on global binding (to fix Unreal loading) 2021-12-19 11:43:23 +01:00
ptitSeb 819cd6c3e2 Don't resolve program name if not needed 2021-12-18 20:55:56 +01:00
ptitSeb 67da32857a [DYNAREC] Disable some IDIV optimisatin, there are some precision issue it seems (helps X3Reunion) 2021-12-18 17:41:40 +01:00
ptitSeb 6796145fa9 Added special case for X3Reunion to use emulated libjpeg.so.62 2021-12-18 15:07:13 +01:00
ptitSeb fea1bcc123 Added some special wrapper for pow10f and pow10 2021-12-18 14:57:10 +01:00
ptitSeb b6125b8063 Added a few gtk wrapped function (for X3R_config) 2021-12-18 14:23:18 +01:00
ptitSeb ad397bb1b6 [DYNAREC@ Fixed some regression with previous commit (like with Icconoclast) 2021-12-16 20:46:14 +01:00
ptitSeb dc333f052d [DYNAREC] Fixed 2 warnings 2021-12-16 08:40:54 +01:00
ptitSeb a77e120fc2 [DYNAREC] Fixed a warning 2021-12-16 08:38:41 +01:00
ptitSeb 07166e591e [DYNAREC] Improve jump internal to a dynablock (should also fix the regression introduced with cc69471576) 2021-12-15 20:44:02 +01:00
ptitSeb a1aac43a4e [DYNAREC] Cleaner flag tracking 2021-12-11 18:27:52 +01:00
ptitSeb cc69471576 [DYNAREC] Improved neon and flag tracking and fixed regression with barrier introduced with commit 5a8a4bb25b 2021-12-11 12:27:52 +01:00
ptitSeb ed8e01ea0c Merge pull request #517 from Seas0/master
Chores: Chinese doc refine and some code refine
2021-12-09 11:52:13 +01:00
Seas0 4fb847196c Minor Chinese doc refine 2021-12-09 18:37:31 +08:00
Seas0 40ee2cb868 Minor readability fix 2021-12-09 17:54:44 +08:00
ptitSeb 8d0b2edba2 Added wprintw to all wrapped ncurses libs (for #215) 2021-12-09 08:05:00 +01:00
ptitSeb 3b6e10a1f9 Added a couple of function to wrapped libc (for #215) 2021-12-09 08:01:38 +01:00
ptitSeb 4d4a849c9b Small change in fcntl, mainly for clarity 2021-12-09 08:00:22 +01:00
ptitSeb 58f94fe9ec [DYNAREC] Added noion of next and predecessor, for later use 2021-12-08 20:31:17 +01:00
ptitSeb ebff6f995a Added better trace for read 2021-12-08 20:11:47 +01:00
ptitSeb 5a8a4bb25b [DYNAREC] Cleaner BARRIER macro and handling 2021-12-08 19:15:08 +01:00
ptitSeb 6d8e781c72 [DYNAREC] Small change on how add_next/get_closest_next works 2021-12-05 17:31:13 +01:00
ptitSeb 834374d0f2 [DYNAREC] Changed NOP emiter and added VSTL_64_W for later use 2021-12-05 17:23:11 +01:00
ptitSeb f0d17b1f86 [DYNAREC] Fixed a rare possible segfault 2021-12-04 16:42:26 +01:00
ptitSeb 5478879a37 Fixed some issue with Find386CopyRel in elfloader 2021-11-30 22:39:17 +01:00
ptitSeb 4e2f50eee7 Backported some of box64 elfloader improvments 2021-11-30 18:48:34 +01:00
ptitSeb c47e25bef3 Changed how wrapped ldlinux, libc, libm and libpthread are load to help with newer glibc version (also should help static build of box86) 2021-11-30 11:40:48 +01:00
ptitSeb b5203b97bb [DYNAREC] Fixed XADD 16bits opcode 2021-11-29 11:58:30 +01:00
ptitSeb a7ac9a0aa8 [DYNAREC] Fixed CMPPD opcode 2021-11-29 11:26:41 +01:00
ptitSeb 0540efa171 [DYNAREC] Fixed and refined SQRTPS, RSRQTPS, RCPPS and DIVPS opcodes 2021-11-29 10:59:21 +01:00
ptitSeb b3b274acf7 [DYNAREC] Small fix on rcr defered flags calculation 2021-11-29 00:31:17 +01:00
ptitSeb 944ffcb788 [DYNAREC] Added missing defered flags functions 2021-11-29 00:27:03 +01:00
ptitSeb 865baf0d5f [DYNAREC] Fixed RCR Ed, 1 opcode 2021-11-29 00:25:21 +01:00
ptitSeb 8b555503c1 Fixed warning on wrapped libdbus 2021-11-29 00:16:44 +01:00
ptitSeb 11bb6bb2aa Fixed warning on wrapped libsdl2 2021-11-29 00:14:10 +01:00
ptitSeb 63864adbda [DYNAREC] Fixed remaining issue for SOFTFP build (for Pandora) 2021-11-29 00:13:52 +01:00
ptitSeb 0d89989c20 Fixed a warning 2021-11-28 23:37:57 +01:00
ptitSeb 59d4821bdc [DYNAREC] More tweaks to SOFTFP build for Pandora 2021-11-28 23:37:42 +01:00
ptitSeb 24ecba3e9e [DYNAREC] Fixed potential issue with FISTP64 and issue with SOFTFP (so Pandora mainly) 2021-11-28 23:32:11 +01:00
ptitSeb d9f9b86996 [DYNAREC] Fixed shld32 opcode 2021-11-28 19:37:26 +01:00
ptitSeb c27febf172 [DYNAREC] Fixed some warning 2021-11-28 18:14:44 +01:00
ptitSeb d18af9daf8 [DYNAREC] Fixed 66 F7 /6 DIV opcode 2021-11-28 17:09:15 +01:00
ptitSeb 4813a35eec [DYNAREC] Fixed an old issue with (quite rare) 66 AF STOSW opcode 2021-11-25 19:55:24 +01:00
ptitSeb 5bd33084dd Improved test17 a bit 2021-11-25 19:54:52 +01:00
ptitSeb 939c54792f Small optim on test8 that need PF 2021-11-24 22:37:41 +01:00
ptitSeb 28f6f58dd7 [DYNAREC] Small optim on FNCLEX opcode 2021-11-24 22:37:22 +01:00
ptitSeb 27fd1d11b8 Update COMPILE.md 2021-11-23 12:49:43 +01:00
ptitSeb 39355d3bd6 Merge pull request #508 from ryanfortner/improve-readme
Improve readme
2021-11-23 01:03:40 +01:00
Ryan Fortner 1582b486db Update readme.md 2021-11-22 18:45:57 -05:00
Ryan Fortner e4d58dd9cb Update README.md 2021-11-22 13:39:50 -05:00
Ryan Fortner f417d640e0 Improve readme 2021-11-22 13:35:42 -05:00
ptitSeb f79e16f48d [DYNAREC] Small changes, mostly cosmetics, on Barriers 2021-11-21 21:04:29 +01:00
ptitSeb 365daab33c [DYNAREC] Improved D9 FC FRNDINT and DF /7 FISTP opcodes 2021-11-21 18:37:00 +01:00
ptitSeb 62fceaaa3c Improve test19 2021-11-21 18:35:38 +01:00
ptitSeb 5af78fb18a [DYNAREC] Optimised D1 /3 RCR Ed, 1 opcode 2021-11-21 14:09:14 +01:00
ptitSeb 2dae632d24 [DYNAREC] Optimized shld32 2021-11-21 13:56:48 +01:00
ptitSeb 680e460ecd [DYNAREC] Small optim for DIV opcode 2021-11-21 11:21:35 +01:00
ptitSeb 07e715bb6d Fixed a warning 2021-11-21 11:21:10 +01:00
ptitSeb e255bc0874 Merge pull request #505 from Moldytzu/master
Fix broken link in pkgbuilds
2021-11-20 17:42:43 +01:00
Alex 0d0129e7c3 fix broken link 2021-11-20 18:40:32 +02:00
ptitSeb 3ca24bd45c Merge pull request #504 from Seas0/master
[DOC] Chinese doc and some typo fix
2021-11-20 10:45:43 +01:00
ptitSeb a627363afa Start of a new dev. cycle 2021-11-20 10:45:27 +01:00
Seas0 bcf6ca9e52 [DOC] Adding Chinese doc, partially referenced box64's
Reference: https://github.com/ptitSeb/box64/blob/main/docs/README_CN.md
2021-11-20 17:39:20 +08:00
Seas0 561579a7d6 [DOC] minor typo fix 2021-11-20 17:39:08 +08:00
393 changed files with 15676 additions and 2739 deletions

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
### Manual build Box86 with Github Action
name: Custom build Box86
on:
workflow_dispatch:
inputs:
platform:
description: 'Target platform name'
required: true
default: 'GENERIC_ARM'
type: choice
options:
- I386
- GENERIC_ARM
- A64
- GAMESHELL
- ODROID
- PANDORA
- PHYTIUM
- PYRA
- RK3288
- RK3399
- RPI4
- RPI4ARM64
- SD845
build_type:
description: 'Build type'
required: true
default: 'RelWithDebInfo'
type: choice
options:
- RelWithDebInfo
- Release
- Debug
- MinSizeRel
dynarec:
description: 'Enable dynarec'
required: false
default: 'true'
type: boolean
trace:
description: 'Enable trace'
required: false
default: 'false'
type: boolean
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ github.event.inputs.platform }} != 'I386' && ${{ github.event.inputs.platform }} != 'GENERIC_ARM' ]]; then
echo "BOX86_PLATFORM_MARCRO=-D${{ github.event.inputs.platform }}=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
else
if [[ ${{ github.event.inputs.platform }} == 'I386' ]]; then
echo "BOX86_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=/bin/i686-linux-gnu-gcc-10" >> $GITHUB_ENV
sudo apt-get -y install git libc6-dev-i386-amd64-cross gcc-10-i686-linux-gnu cmake make python3
else
echo "BOX86_PLATFORM_MARCRO=-DCMAKE_C_FLAGS=-marm" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
fi
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX86_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX86_COMPILER }}"
echo "Build type: ${{ github.event.inputs.build_type }}"
echo "Dynarec Enabled: ${{ github.event.inputs.dynarec }}"
echo "Trace Enabled: ${{ github.event.inputs.trace }}"
- name: "Build Box86"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }} ${{ env.BOX86_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }}\
-DARM_DYNAREC:BOOL=${{ github.event.inputs.dynarec }}\
-DHAVE_TRACE:BOOL=${{ github.event.inputs.trace }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ github.event.inputs.platform }}-${{ github.event.inputs.build_type }}
path: build/box86
+31 -14
View File
@@ -1,7 +1,7 @@
### Auto build Box86 and release its binary with Github Action
name: Build and Release Box86
on:
on:
workflow_dispatch:
release:
push:
@@ -10,16 +10,16 @@ on:
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "CMakeLists.txt"
- "**/*.yml"
pull_request:
pull_request:
types: [assigned, opened, synchronize, reopened]
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "CMakeLists.txt"
- "**/*.yml"
jobs:
@@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM]
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
type: [Release, Trace]
runs-on: ubuntu-latest
@@ -40,15 +40,22 @@ jobs:
sudo apt-get update
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
echo "BOX86_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
sudo apt-get -y install git cmake make python3
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DNOLOADADDR=1" >> $GITHUB_ENV
else
sudo apt-get -y install gcc-arm-linux-gnueabihf
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
fi
else
if [[ ${{ matrix.platform }} == 'I386' ]]; then
echo "BOX86_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=/bin/i686-linux-gnu-gcc-10" >> $GITHUB_ENV
sudo apt-get -y install git libc6-dev-i386-amd64-cross gcc-10-i686-linux-gnu cmake make python3
ls /bin/*gcc*
else
echo BOX86_PLATFORM_MARCRO="-DARM_DYNAREC=ON -DCMAKE_C_FLAGS=-marm" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
@@ -63,26 +70,36 @@ jobs:
echo BOX86_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX86_HAVE_TRACE=1 >> $GITHUB_ENV
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX86_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX86_COMPILER }}"
echo "Build type: ${{ env.BOX86_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX86_HAVE_TRACE }}"
- name: "Build Box86"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }} ${{ env.BOX86_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX86_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX86_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }}\
${{ env.BOX86_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX86_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX86_HAVE_TRACE }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Test Box86"
if: ${{ matrix.platform == 'I386' }}
run: |
cd build
ctest -j$(nproc)
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box86
+74 -36
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.4)
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
@@ -9,6 +9,7 @@ option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch a
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
@@ -21,7 +22,7 @@ option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -51,7 +52,13 @@ else()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
if(RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
cmake_host_system_information(RESULT CMAKE_HOST_SYSTEM_PROCESSOR QUERY OS_PLATFORM)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
if(_aarch64 AND (RK3399 OR ODROIDN2 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64))
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)
@@ -123,10 +130,16 @@ elseif(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ODROIDN2)
add_definitions(-DODROIDN2)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard")
elseif(PHYTIUM)
add_definitions(-DPHYTIUM)
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ANDROID)
add_definitions(-DANDROID)
elseif(ARM_DYNAREC)
#if DYNAREC is selected alone, without any arch
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
@@ -157,6 +170,7 @@ endif()
if(NOALIGN)
add_definitions(-DNOALIGN)
add_definitions(-pipe -march=core2 -msse2)
endif()
if(HAVE_TRACE)
@@ -358,6 +372,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibpanel.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX86_ROOT}/src/wrapped/wrappedgmp.c"
"${BOX86_ROOT}/src/wrapped/wrappedgcrypt.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtk3.c"
@@ -370,6 +386,12 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgconf2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstaudio.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstvideo.c"
"${BOX86_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
@@ -409,8 +431,17 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX86_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX86_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX86_ROOT}/src/wrapped/wrappedsoftokn3.c"
"${BOX86_ROOT}/src/wrapped/wrappedfreebl3.c"
"${BOX86_ROOT}/src/wrapped/wrappedsecret1.c"
"${BOX86_ROOT}/src/wrapped/wrappedtbbmalloc.c"
"${BOX86_ROOT}/src/wrapped/wrappedmimalloc.c"
"${BOX86_ROOT}/src/wrapped/wrappedselinux.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibharfbuzz.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibcairogobject.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibvkd3d.c"
"${BOX86_ROOT}/src/wrapped/wrappedgomp.c"
"${BOX86_ROOT}/src/wrapped/wrappedcap.c"
)
if(ANDROID)
list(APPEND WRAPPEDS
@@ -495,6 +526,7 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/dynarec_arm_df.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f0.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_660f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_66f0.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f20f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f30f.c"
)
@@ -552,7 +584,7 @@ if(ARM_DYNAREC)
if(ANDROID)
target_link_libraries(${BOX86} dynarec m dl)
else()
target_link_libraries(${BOX86} dynarec m dl rt pthread)
target_link_libraries(${BOX86} dynarec m dl rt pthread resolv)
endif()
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
@@ -572,9 +604,10 @@ add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
if(ANDROID)
target_link_libraries(${BOX86} m dl)
target_link_libraries(${BOX86} c m dl)
else()
target_link_libraries(${BOX86} m dl rt pthread)
#target_link_libraries(${BOX86} c m dl rt pthread resolv)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
@@ -593,11 +626,6 @@ else()
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
@@ -606,6 +634,7 @@ if(NOT _x86 AND NOT _x86_64)
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/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
endif()
if(NOT TARGET uninstall)
@@ -649,105 +678,114 @@ set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVIS
INCLUDE(CPack)
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME bootSyscallC COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME printf COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME args COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME maths1 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME threadsStart COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile06.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME trig COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME pi COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fork COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME cppThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME tlsData COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fpu COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME contexts COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile13.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME conditionalThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT LD80BITS)
add_test(NAME conditionalThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile14.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
add_test(NAME linkingIndirectNoversion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME linkingIndirectVersion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME ucomiss COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile.txt
add_test(NAME sse COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile17.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0")
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile.txt
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile19.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref19.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test20 -D TEST_OUTPUT=tmpfile20.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
+23
View File
@@ -0,0 +1,23 @@
box86 (0.2.6) unstable; urgency=low
* Added an option to get generated -NAN on SSE2 operation
* Many small fixes and improvement to get steam and SteamPlay working (along with box64)
* Added some workaround for program calling uname to mimic x86 system
* Added some more Vulkan extensions
* Added some granularity to mmap64, and generic memory protection tracking improvment, to mimic x86 system (for wine stagging and proton)
* Better clone syscall and libc implementation
* Improved wrapping of GTK libs
* More wrapped libs (more gtk libs, like gstreamer-1.0 among other non-gtk libs too)
* More wrapped functions(with some tricky one, like dladdr1)
* Some fixes and improvment to some wrapped functions
* Refactor Dynarec:
* - better handling of SSE/x87 registers
* - optimisation to limit float/double conversion
* - better handling of "internal" jump inside a dynablock
* Improved elfloader
* Improved some tests
* A few fixes in some Dynarec opcodes
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* A bit more optimisation in some Dynarec opcodes
-- Sebastien Chevalier <[email protected]> Tue, 18 Jan 2022 11:20:33 -0500
+1
View File
@@ -0,0 +1 @@
11
+14
View File
@@ -0,0 +1,14 @@
Source: box86
Section: utils
Priority: optional
Maintainer: Ryan Fortner <[email protected]>
Build-Depends: cmake, debhelper (>=11~)
Standards-Version: 4.1.4
Homepage: https://github.com/ptitSeb/box86
Package: box86
Architecture: any
Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems, like ARM (host system needs to be 32bit little-endian).
+26
View File
@@ -0,0 +1,26 @@
Format-Specification: http://dep.debian.net/deps/dep5/
Files: *
Copyright: © 2022 Sebastien Chevalier
License: MIT
License: MIT
Copyright (c) 2018-2021 Sebastien Chevalier ("ptitSeb")
.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+1
View File
@@ -0,0 +1 @@
box86: no-manual-page
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DARM_DYNAREC=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
+1
View File
@@ -0,0 +1 @@
3.0 (quilt)
+5
View File
@@ -0,0 +1,5 @@
Bug-Database: https://github.com/ptitSeb/box86/issues
Bug-Submit: https://github.com/ptitSeb/box86/issues/new
Repository: https://github.com/ptitSeb/box86.git
Repository-Browse: https://github.com/ptitSeb/box86
Security-Contact: [email protected]
+1
View File
@@ -0,0 +1 @@
version=3
+22
View File
@@ -1,3 +1,25 @@
v0.2.6
======
* Added an option to get generated -NAN on SSE2 operation
* Many small fixes and improvement to get steam and SteamPlay working (along with box64)
* Added some workaround for program calling uname to mimic x86 system
* Added some more Vulkan extensions
* Added some granularity to mmap64, and generic memory protection tracking improvment, to mimic x86 system (for wine stagging and proton)
* Better clone syscall and libc implementation
* Improved wrapping of GTK libs
* More wrapped libs (more gtk libs, like gstreamer-1.0 among other non-gtk libs too)
* More wrapped functions(with some tricky one, like dladdr1)
* Some fixes and improvment to some wrapped functions
* Refactor Dynarec:
* better handling of SSE/x87 registers
* optimisation to limit float/double conversion
* better handling of "internal" jump inside a dynablock
* Improved elfloader
* Improved some tests
* A few fixes in some Dynarec opcodes
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* A bit more optimisation in some Dynarec opcodes
v0.2.4
======
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
+10 -3
View File
@@ -47,7 +47,7 @@ sudo systemctl restart systemd-binfmt
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
#### for Tinker Board (1/1S) or RK3288
@@ -57,7 +57,7 @@ As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environme
`mkdir build; cd build; cmake .. -DA64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
#### for Snapdragon 845
@@ -69,7 +69,7 @@ As most Snapdragon 845 device run AARCH64 OS, in most cases you'll need an `armh
`mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
#### for Other ARM Linux platforms
@@ -118,3 +118,10 @@ They are very basic and don't test much for now.
Note about devices with Tegra X1 and newer.
Nvidia don't provide armhf libraries for their GPU drivers at this moment so there is no special variable to compile it for them as it would be missleading for many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. As instalation of Mesa can break Nvidia driver, safest option is usage of chroot.
----
Debian Packaging
----
Box86 can also be packaged into a .deb file with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`.
+23 -19
View File
@@ -1,22 +1,18 @@
# box86
![Official logo](img/Box86Logo.png "Official Logo")
Linux Userspace x86 Emulator with a twist
[![Build Status](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master)](https://app.travis-ci.com/ptitSeb/box86)
Linux Userspace x86_64 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems, 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 supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environnement).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environment).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
@@ -29,13 +25,21 @@ To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](../src/emu/x86primop.c) for copyright details
Here's 6 videos, the first 2 videos are videos of "Airline Tycoon Deluxe" and "Heretic 2" running on a GigaHertz OpenPandora (the second one is using the dynarec), and the next 2 videos are videos of of "Bit.Trip.Runner" and "Neverwinter Night" running on an ODroid XU4 (without dynarec), and the last 2 videos are on on a Pi4: Shovel Knight (video from @ITotalJustice) and Freedom Planet (video from @djazz), also without dynarec.
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
----
Here are 6 videos, the first 2 videos are videos of "Airline Tycoon Deluxe" and "Heretic 2" running on a GigaHertz OpenPandora (the second one is using the dynarec), and the next 2 videos are videos of of "Bit.Trip.Runner" and "Neverwinter Night" running on an ODroid XU4 (without dynarec), and the last 2 videos are on on a Pi4: Shovel Knight (video from @ITotalJustice) and Freedom Planet (video from @djazz), also without dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
You can find many more Box86 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
You can find many more Box86 videos on the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube channels.
Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list/issues
Compatibility list is here: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
@@ -87,10 +91,10 @@ Notes about Steam
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works:
- First problem is Steam crashing after the sign-in window, if you encounter this issue, you may need to add libappindicator. To install it on Debian, run `sudo apt install libappindicator1`.
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm intalled. To install it on Debian, run `sudo apt install libnm0`.
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm installed. To install it on Debian, run `sudo apt install libnm0`.
- Once open, Steam will only work on "Small Mode" and in "Big Picture", not in the regular "Large Mode". This is because some Steam components used in the browser view are only 64-bit now. So go in the "View" menu and switch to "Small view", else the list will stay empty. Alternatively, Steam can be started in small mode directly by using `+open steam://open/minigameslist` command line arguments.
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables.
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aformentionned feature, it is safer to add it to your system if you intend to play those game. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aforementioned feature, it is safer to add it to your system if you intend to play those game. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
Steam for Windows installs fine but doesn't work yet.
@@ -107,19 +111,19 @@ Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those mod
Notes about Vulkan
----
Box86 already wrap vulikan. If your system has a 32bits vulkan driver, box86 will use it when needed. Note that vulkan wrapping has not been tested much, due to the limited vulkan support on the hardware I currently own. Profile 1.0 and 1.1, whith some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardxware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Note that Vulkan wrapping has not been tested much, due to the limited Vulkan support on the hardware I currently own. Profile 1.0 and 1.1, with some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
----
Final word
----
I want to thank everyone who has contributed to box86 developpement.
I want to thank everyone who has contributed to box86 development.
There are many ways to contribute: code, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, icecream95, M-HT
* For their major financial contribution: FlyingFathead, stormchaser3000
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* For their continous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
And I also thank the many other people who participated even once in the project.
+135
View File
@@ -0,0 +1,135 @@
![Official logo](img/Box86Logo.png "Official Logo")
Linux用户空间的x86应用模拟器
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
使用Box86可以在ARM或其他非x86架构的Linux操作系统上运行x86 Linux程序(例如游戏),请注意,主机系统需要是**32位小端**的。
你需要一个**32位**的子系统来运行Box86,因为Box86在纯64位系统上无法使用,同时你也需要一个**32位**的Linux编译工具链来编译Box86,例如**arm-linux-gnueabihf-gcc**, 否则你将无法编译Box86 (一般的64位ARM编译工具链如 aarch64-linux-gnu-gcc 不支持"-marm"编译选项,会编译失败并报错)。
因为Box86使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以在很多情况下性能很不错,也可以方便地与其他应用集成使用。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看Benchmark示例。
大多数x86游戏都用到了OpenGL,所以在ARM平台上类似于[gl4es](https://github.com/ptitSeb/gl4es)的解决方案通常是必要的。(许多ARM平台仅提供OpenGL ES支持,又或者他们的OpenGL实现很不可靠(例如Android上的OpenGL)。)
Box86为ARM平台集成了DynaRec(动态重编译器),比仅使用解释器提升5到10倍性能。关于Dynarec如何工作的更多信息,可以在[这里](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)找到。
许多游戏已可在不做多少改动的情况下直接运行,例如:《粘粘世界》(WorldOfGoo)、《航空大亨豪华版》(Airline Tycoon Deluxe)、《超越光速》(FTL)等、基于GameMaker的游戏(《传说之下》(UNDERTALE)等)。
如果你想开发Box86,最好安装ccache,以缓存编译结果。
如果你需要启用Trace跟踪(例如输出寄存器值与各条被执行的x86指令),你也需要安装[Zydis](https://github.com/zyantific/zydis)。
一些x86内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x86primop.c](../src/emu/x86primop.c)了解版权详情
----
编译与安装
----
> [Box86编译指南](COMPILE.md)
>
> [Box86 Wine安装指南](X86WINE.md)
一些示例视频
----
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
在这几个Youtube频道可以找到更多Box86的相关视频
[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
程序兼容性列表: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
感谢制作Logo和图标的grayduck!
注意:
不要把本项目和[86box](https://github.com/86Box/86Box)搞混了,后者是一个"**全量**"的x86 PC模拟器。
----
使用方法
----
有若干环境变量可以设置Box86的行为。
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
请注意:Box86的Dynarec提供了一种包含"内存保护"和段错误信号处理程序的机制来处理JIT代码。简单来说,如果你想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),就会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的命令,来防止在每个段错误时都停止程序运行,如果你想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
----
关于64位平台的注意事项
----
Box86的工作原理是直接将函数调用从x86_转换到主机系统,主机系统(Box86运行的系统)需要有32位的库。Box86并不包括任何64位<->32位的转换。所以如果你需要在64位平台上运行Box86,那么你需要建立一个32位的库环境,并以32位ARM为目标系统编译Box86(例如使用arm-linux-gnueabihf-gcc工具链交叉编译或直接在armhf chroot环境中编译运行)。
如果你需要运行64位应用,请考虑使用[Box64](https://github.com/ptitSeb/box64),它可以在64位平台上运行x86_64程序,但请再一次注意运行x86程序需要Box86与32位库环境(就像在x86_64的Linux上运行x86程序需要x86 multiarch库一样)。
----
关于Unity游戏的注意事项
----
当前对于Unity游戏的模拟仍不完善。Unity使用Mono,但它所使用的信号机制还没有被完美模拟。理论上可以使用原生Mono库(在[这里](https://github.com/Unity-Technologies/mono)可以找到),但Mono的封装比较麻烦,现在还没完成,所以我们使用了模拟的Mono库,目前Mono的JIT动态编译代码已由"内存保护"(Protected memory)机制实现,应该能正常运行。
同时,一些Unity3D游戏需要OpenGL 3+,目前在大部分Arm开发板上提供OpenGL 3+是很困难的。
所以,并不是所有的Unity游戏都能运行,尤其是那些需要提供很高的OpenGL配置(3.2+)的游戏更有可能不行,但除此之外应该问题不大,而且能运行的游戏的性能应该不错。
提示:如果游戏开始后在显示任何东西之前退出,在Raspberry Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
----
关于Steam的注意事项
----
Linux Steam 现在可以在Box86上运行,但还是有点不稳定,而且有些功能可能不正常:
- 如果Steam在显示登录界面后崩溃,你可能需要安装libappindicator库,例如运行`sudo apt install libappindicator1`。
- 如果你选择记住密码,而Steam在下次启动时崩溃,你可能需要安装libnm库,例如运行`sudo apt install libnm0`。
- Steam不能在正常的大界面模式下工作,因为Steam在浏览器模式使用的一些组件只能在64位平台上运行。所以请在查看选项卡中选择"小模式",否则Steam将无法正常显示列表。或者在启动Steam添加`+open steam://open/minigameslist`参数,这样Steam将会直接在小模式下启动。
- 为了避免"libc.so.6 is absent"的错误,请添加环境变量`STEAMOS=1` 与 `STEAM_RUNTIME=1`。
- 一些游戏(例如基于起源引擎的游戏:《传送门》、《半衰期2》)使用了libtcmalloc库,Box86会尝试检测它们并通过LD_PRELOAD预加载它们来获得更好的兼容性,虽然应该可以在没有上述功能的情况下工作,但保险起见,我们还是建议你安装它,例如运行`sudo apt install libtcmalloc-minimal4`。
Windows Steam 可以安装但目前不能运行。
----
关于Wine的注意事项
----
Box86现在已经支持Wine。Wine的内建程序全部能运行,许多Windows 程序和游戏也运行良好。但是不要忘记大多数 Windows 游戏都使用 Direct3D,这可能需要完整的 OpenGL 驱动程序和尽可能高的配置文件(基于 ES2 后端的 gl4es 现在不能运行 Wine 的Direct3D组件)。
注意:如果你想在 Raspberry Pi 3 或更早版本上用 Box86 运行 Wine,由于这些设备的内核默认使用 2G/2G 虚拟内存分配(2G 空间用于用户态程序,2G 空间用于内核),与需要访问内存地址 > 2G 的 Wine 程序不兼容。 因此,你需要重新配置内核以使用 3G/1G 的内存分配方式。
----
关于Vulkan的注意事项
----
Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序,Box86会在需要时使用它。但请注意,由于作者目前拥有的硬件上的Vulkan支持有限,因此Vulkan封装库尚未经过太多测试。 Vulkan 1.0、1.1与一些扩展应该能工作。 但Vulkan 1.2还没有被实现。已经有一些在树莓派4上的Vulkan演示 (Sascha Willems 的演示中,为x86构建的demo与与直接为armhf构建的demo工作均正常)。但请注意,Pi4的Vulkan驱动程序目前不支持 dxvk(wine DirectX->Vulkan 兼容层),这不是Box86的问题,而是由于缺少扩展(硬件支持)与一些其他驱动问题。而在Panfrost上,PanVK尚不成熟,暂时没有用它测试dxvk。
----
结语
----
我要感谢所有为 box86 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, icecream95, M-HT
* 财务帮助:FlyingFathead, stormchaser3000
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box86,请不要忘记提及!)
+29 -3
View File
@@ -119,6 +119,7 @@ Forbid dynablock creation in the interval specified (helpfull for debugging beha
Enables/Disables Box86's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps)
#### BOX86_DYNAREC_STRONGMEM
Enable/Disable simulation of Strong Memory model
@@ -126,6 +127,16 @@ Enable/Disable simulation of Strong Memory model
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX86_DYNAREC_X87DOUBLE
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (faster)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
#### BOX86_DYNAREC_FASTNAN
Enable/Disable generation of -NAN
* 0 : Generate -NAN like on x86 (slower, more x86 accurate)
* 1 : Don't do anything special with NAN, to go as fast as possible (Default)
#### BOX86_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -140,11 +151,26 @@ Enable/Disable simulation of Strong Memory model
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSINGLIBS
Allow Box86 to continue even if a library is missing.
#### BOX86_ALLOWMISSING_LIBS
Allow Box86 to continue even if a library is missing (renamed from BOX86_ALLOWMISSINGLIBS).
* 0 : Box86 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_ALLOWMISSING_SYMBOLS
Allow dlopen with RTLD_NOW flag to not resolve all symbols.
* 0 : Box86 will stop if a library have unresolved symbols. (Default.)
* 1 : Continue even if a needed library have unresolved symbols (like symbols not yet wrapped).
#### BOX86_PREFER_WRAPPED
Box86 will use wrapped libs even if the lib is specified with absolute path
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
* 1 : Use Wrapped native libs even if path is absolute
#### BOX86_PREFER_EMULATED
Box86 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
#### BOX86_NOPULSE
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
@@ -153,7 +179,7 @@ Disables the load of pulseaudio libraries.
#### BOX86_NOGTK
Disables the loading of wrapped GTK libraries.
* 0 : Load wrapped GTK libraries if found. (Default.)
* 1 : Disables loading wrapped GTK libraries (can be used with Steam, along with STEAM_RUNTIME=1 to use the i386 version of GTK).
* 1 : Disables loading wrapped GTK libraries.
#### BOX86_NOVULKAN
Disables the load of vulkan libraries.
+1 -1
View File
@@ -3,7 +3,7 @@ _TwisterOS users: Wine, winetricks, and Box86 are already installed in TwisterOS
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 already has a 3G/1G split kernel and works with Wine, but **the Pi 3B+ and earlier models have a 2G/2G kernel and require a custom-compiled 3G/1G kernel to get Wine working.**_
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (x64 is not yet implemented).
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
See installation steps below (in the [Examples](#examples) section).
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM devices other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 169 KiB

+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-arm-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-arm-git}" -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-gameshell-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-gameshell-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-gameshell-git}" -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-odroid-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-odroid-git}" -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pandora-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pandora-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pandora-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-pandora-git}" -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pyra-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pyra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-pyra-git}" -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+6 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rpi-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -20,8 +20,7 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
build() {
# Check for Pi version number
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
_piversion=4
@@ -36,24 +35,11 @@ prepare() {
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%-rpi-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-rpi-git}" -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-rk3399-git}" -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
@@ -18,26 +18,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x86-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-x86-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-x86-git}" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-x86-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+1 -1
View File
@@ -12,7 +12,7 @@ This will copy the PKGBUILD for your platform (where you type your platform name
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).
All specified in [COMPILE.md](../docs/COMPILE.md).
### 3. Any advantages with that sollution?
This might give you some advantages like those:
+3 -1
View File
@@ -1,2 +1,4 @@
#!/bin/sh
systemctl restart systemd-binfmt
if [ -d '/run/systemd/system' ]; then
systemctl restart systemd-binfmt || :
fi
+4 -1
View File
@@ -748,9 +748,12 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("sdl1ttf", "sdl2ttf") \
or match("smpeg", "smpeg2") \
or match("udev0", "udev1") \
or match("gstinterfaces010","gstvideo")\
or match("gstinterfaces010","gstaudio")\
or match("gstreamer010","gstreamer") \
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
or match("libc", "ldlinux") \
:
# libc and ldlinux have some "__libc_" data symbols in common... TODO check if ok
continue
+5
View File
@@ -52,5 +52,10 @@ if( TEST_RESULT )
message( FATAL_ERROR "Failed: The output of ${TEST_PROGRAM} did not match ${TEST_REFERENCE}")
endif( TEST_RESULT )
# remove the temporary files if they exist
if( EXISTS ${TEST_OUTPUT} )
file(REMOVE "${TEST_OUTPUT}")
endif()
# everything went fine...
message( "Passed: The output of ${TEST_PROGRAM} matches ${TEST_REFERENCE}" )
+5
View File
@@ -176,6 +176,7 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->defver = NewDefaultVersion();
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
@@ -283,6 +284,9 @@ void FreeBox86Context(box86context_t** context)
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
if(ctx->stack_clone)
free(ctx->stack_clone);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
@@ -304,6 +308,7 @@ void FreeBox86Context(box86context_t** context)
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->defver);
finiAllHelpers(ctx);
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 2
#define BOX86_REVISION 4
#define BOX86_REVISION 6
#endif //__BOX86_VERSION_H_
+182 -1
View File
@@ -44,6 +44,13 @@ static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
static int inited = 0;
typedef struct mapmem_s {
uintptr_t begin, end;
struct mapmem_s *next;
} mapmem_t;
static mapmem_t *mapmem = NULL;
typedef struct blocklist_s {
void* block;
int maxfree;
@@ -348,7 +355,7 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
for(int i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
mmaplist[i].locked = 1;
int rsize = 0;
size_t rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
@@ -674,8 +681,99 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
#endif
void printMapMem()
{
mapmem_t* m = mapmem;
while(m) {
printf_log(LOG_INFO, " %p-%p\n", (void*)m->begin, (void*)m->end);
m = m->next;
}
}
void addMapMem(uintptr_t begin, uintptr_t end)
{
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
// find attach point (cannot be the 1st one by construction)
mapmem_t* m = mapmem;
while(m->next && begin>m->next->begin) {
m = m->next;
}
// attach at the end of m
mapmem_t* newm;
if(m->end>=begin-1) {
if(end<=m->end)
return; // zone completly inside current block, nothing to do
m->end = end; // enlarge block
newm = m;
} else {
// create a new block
newm = (mapmem_t*)calloc(1, sizeof(mapmem_t));
newm->next = m->next;
newm->begin = begin;
newm->end = end;
m->next = newm;
}
while(newm && newm->next && (newm->next->begin-1)<=newm->end) {
// fuse with next
if(newm->next->end>newm->end)
newm->end = newm->next->end;
mapmem_t* tmp = newm->next;
newm->next = tmp->next;
free(tmp);
}
// all done!
}
void removeMapMem(uintptr_t begin, uintptr_t end)
{
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
mapmem_t* m = mapmem, *prev = NULL;
while(m) {
// check if block is beyond the zone to free
if(m->begin > end)
return;
// check if the block is completly inside the zone to free
if(m->begin>=begin && m->end<=end) {
// just free the block
mapmem_t *tmp = m;
if(prev) {
prev->next = m->next;
m = prev;
} else {
mapmem = m->next; // change attach, but should never happens
m = mapmem;
prev = NULL;
}
free(tmp);
} else if(begin>m->begin && end<m->end) { // the zone is totaly inside the block => split it!
mapmem_t* newm = (mapmem_t*)calloc(1, sizeof(mapmem_t)); // create a new "next"
newm->end = m->end;
m->end = begin - 1;
newm->begin = end + 1;
newm->next = m->next;
m->next = newm;
// nothing more to free
return;
} else if(begin>m->begin && begin<m->end) { // free the tail of the block
m->end = begin - 1;
} else if(end>m->begin && end<m->end) { // free the head of the block
m->begin = end + 1;
}
prev = m;
m = m->next;
}
}
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
@@ -688,6 +786,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
@@ -698,6 +797,7 @@ void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
@@ -705,6 +805,16 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
}
}
void freeProtection(uintptr_t addr, uintptr_t size)
{
removeMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i] = 0;
}
}
uint32_t getProtection(uintptr_t addr)
{
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
@@ -712,6 +822,67 @@ uint32_t getProtection(uintptr_t addr)
return ret;
}
void allocProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!memprot[i])
memprot[i] = prot;
}
}
void loadProtectionFromMap()
{
if(box86_mapclean)
return;
char buf[500];
FILE *f = fopen("/proc/self/maps", "r");
uintptr_t current = 0x0;
if(!f)
return;
while(!feof(f)) {
char* ret = fgets(buf, sizeof(buf), f);
(void)ret;
char r, w, x;
uintptr_t s, e;
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
if(current<s) {
removeMapMem(current, s-1);
current = e;
}
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
}
}
fclose(f);
box86_mapclean = 1;
}
#define LOWEST (void*)0x10000
void* findBlockNearHint(void* hint, size_t size)
{
mapmem_t* m = mapmem;
uintptr_t h = (uintptr_t)hint;
while(m) {
// granularity 0x10000
uintptr_t addr = (m->end+1+0xffff)&~0xffff;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
// check hint and available size
if(addr<=h && end>=h && end-h+1>=size)
return hint;
if(addr>=h && end-addr+1>=size)
return (void*)addr;
m = m->next;
}
return hint;
}
void* find32bitBlock(size_t size)
{
return findBlockNearHint(LOWEST, size);
}
int unlockCustommemMutex()
{
int ret = 0;
@@ -769,6 +940,11 @@ void init_custommem_helper(box86context_t* ctx)
#endif
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
// init mapmem list
mapmem = (mapmem_t*)calloc(1, sizeof(mapmem_t));
mapmem->begin = 0x0;
mapmem->end = (uintptr_t)LOWEST - 1;
loadProtectionFromMap();
}
void fini_custommem_helper(box86context_t *ctx)
@@ -821,4 +997,9 @@ void fini_custommem_helper(box86context_t *ctx)
#endif
free(p_blocks);
pthread_mutex_destroy(&mutex_blocks);
while(mapmem) {
mapmem_t *tmp = mapmem;
mapmem = mapmem->next;
free(tmp);
}
}
+97 -12
View File
@@ -66,7 +66,7 @@ Op is 20-27
#define c__ (0b1110<<28) // means all
// nop
#define NOP EMIT(0xe1a00000)
#define NOP EMIT(0xe320f000)
// mov dst, src
#define MOV_REG(dst, src) EMIT(0xe1a00000 | ((dst) << 12) | (src) )
@@ -213,6 +213,9 @@ Op is 20-27
// add dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.c dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT((cond) | 0x00800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.s dst, src1, src2, lsl #imm
#define ADDS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -242,9 +245,12 @@ Op is 20-27
// cmp.s dst, src, #imm
#define CMPS_IMM8(src, imm8) \
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmn.s dst, src, #imm
// cmn.s.cond dst, src, #imm
#define CMNS_IMM8_COND(cond, src, imm8) \
EMIT((cond) | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmn.s dst, src, #imm
#define CMNS_IMM8(src, imm8) \
EMIT(c__ | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// tst.s dst, src1, src2, lsl #imm
#define TSTS_REG_LSL_IMM5(src1, src2, imm5) \
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -254,21 +260,33 @@ Op is 20-27
// tst.s dst, src1, #imm ror rot*2
#define TSTS_IMM8_ROR(src, imm8, rot) \
EMIT(0xe3100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// tst.s.cond dst, src1, #imm ror rot*2
#define TSTS_IMM8_ROR_COND(cond, src, imm8, rot) \
EMIT((cond) | 0x03100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// orr dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr.cond dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT(cond | 0x01800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr.s dst, src1, src2, lsl #imm
#define ORRS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.cond dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT(cond | 0x01800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.s dst, src1, src2, lsr #imm
#define ORRS_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.s dst, src1, src2, lsl rs
#define ORRS_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// orr.s dst, src1, src2, lsr rs
#define ORRS_REG_LSR_REG(dst, src1, src2, rs) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brRLSR(rs, src2) )
// orr dst, src1, #imm8
#define ORR_IMM8(dst, src, imm8, rot) \
EMIT(0xe3800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
@@ -281,6 +299,9 @@ Op is 20-27
// orr dst, src1, src2, lsl rs
#define ORR_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// orr dst, src1, src2, lsr rs
#define ORR_REG_LSR_REG(dst, src1, src2, rs) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brRLSR(rs, src2) )
// xor dst, src1, src2, lsl #imm
#define XOR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0200000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -466,6 +487,7 @@ Op is 20-27
// Mul and MulA
#define MULMULA(Cond, A, S, Rd, Rn, Rs, Rm) (Cond | 0b000000<<22 | (A)<<21 | (S)<<20 | (Rd)<<16 | (Rn)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
#define MUL(Rd, Rm, Rn) EMIT(MULMULA(c__, 0, 0, (Rd), 0, (Rm), (Rn)))
#define MLA(Rd, Rn, Rm, Ra) EMIT(MULMULA(c__, 1, 0, (Rd), (Ra), (Rm), (Rn)))
#define MLS_gen(Cond, Rd, Ra, Rm, Rn) (Cond | 0b00000110<<20 | (Rd)<<16 | (Ra)<<12 | (Rm)<<8 | 0b1001<<4 | (Rn))
//MLS : Rd = Ra - Rm*Rn
@@ -486,6 +508,8 @@ Op is 20-27
// UBFX: Unsigned Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define UBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111111<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
// UBFX: Unsigned Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define UBFX_COND(cond, rd, rn, lsb, width) EMIT(cond | (0b0111111<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
// SBFX: Signed Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define SBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111101<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
@@ -554,6 +578,16 @@ Op is 20-27
#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))
#define LDREXH_gen(cond, Rn, Rt) (cond | 0b0001111<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Half-Word Rt from Rn (tagging the memory)
#define LDREXH(Rt, Rn) EMIT(LDREXH_gen(c__, Rn, Rt))
#define LDREXH_COND(cond, Rt, Rn) EMIT(LDREXH_gen(cond, Rn, Rt))
#define STREXH_gen(cond, Rd, Rn, Rt) (cond | 0b0001111<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Half-Word Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREXH(Rd, Rt, Rn) EMIT(STREXH_gen(c__, Rd, Rn, Rt))
#define STREXH_COND(cond, Rd, Rt, Rn) EMIT(STREXH_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))
// Reverse bits of Rm, store result in Rd
@@ -654,6 +688,10 @@ Op is 20-27
// Store to memory to single VSTR Sd, [Rn, #+/-imm8], imm8&3 ignored!
#define VSTR_32(Sd, Rn, Imm8) EMIT(c__ | (0b1101<<24) | (((Imm8)<0)?0:1)<<23 | (((Sd)&1)<<22) | (0<<20) | ((Rn)<<16) | ((((Sd)>>1)&15)<<12) | (0b1010<<8) | ((abs(Imm8)>>2)&255))
#define VSTM_64_gen(cond, P, U, D, W, Rn, Vd, imm8) (cond | 0b110<<25 | (P)<<24 | (U)<<23 | (D)<<22 | (W)<<21 | (Rn)<<16 | (Vd)<<12 | 0b1011<<8 | (imm8))
// Store a sery of Dx, post imcrementing Rn
#define VSTM_64_W(Dd, Rn) EMIT(VSTM_64_gen(c__, 0, 1, ((Dd)>>4)&1, 1, Rn, (Dd)&15, 2))
// Convert from single Sm to double Dd
#define VCVT_F64_F32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0111<<16) | (((Dd)&15)<<12) | (0b101<<9) | (0<<8) | (0b11<<6) | (((Sm)&1)<<5) | (0<<4) | (((Sm)>>1)&15))
// Convert from double Dm to single Sd
@@ -680,6 +718,42 @@ Op is 20-27
// Inplace convert from F64 to S16. Rounding is not selectable
#define VCVT_S16_F64(Dd) EMIT(VCVT_FP_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
#define VRINT_FP_gen(D, RM, Vd, size, M, Vm) (0b111111101<<23 | (D)<<22 | 0b111<<19 | (RM)<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<4 | (Vm))
// Round floating-point to integer to Nearest with Ties to Away
#define VRINTA_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b00, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer to Nearest with Ties to Away
#define VRINTA_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer towards -Infinity
#define VRINTM_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b11, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards -Infinity
#define VRINTM_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b11, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer to Nearest
#define VRINTN_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b01, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer to Nearest
#define VRINTN_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer towards +Infinity
#define VRINTP_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b10, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards +Infinity
#define VRINTP_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTR_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b110<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR
#define VRINTR_F32(Sd, Sm) EMIT(VRINTR_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR
#define VRINTR_F64(Dd, Dm) EMIT(VRINTR_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTX_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b111<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR with eXecptions if inexact
#define VRINTX_F32(Sd, Sm) EMIT(VRINTX_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR with eXecptions if inexact
#define VRINTX_F64(Dd, Dm) EMIT(VRINTX_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTZ_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b110<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<7 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer towards Zero
#define VRINTZ_F32(Sd, Sm) EMIT(VRINTZ_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards Zero
#define VRINTZ_F64(Dd, Dm) EMIT(VRINTZ_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&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) )
@@ -814,19 +888,19 @@ Op is 20-27
#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))
#define VLD1LANE_16(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, (index)<<2, 15))
#define VLD1LANE_32(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, (index)<<3, 15))
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 0, (index)<<1, 15))
#define VLD1LANE_16(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, (index)<<2, 15))
#define VLD1LANE_32(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, (index)<<3, 15))
#define VLD1ALL_gen(D, Rn, Vd, size, T, a, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | 0b11<<10| (size)<<6 | (T)<<5 | (a)<<4 | (Rm))
#define VLD1ALL_16(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, 0, 0, 15))
#define VLD1ALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, 0, 0, 15))
#define VLD1QALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, 1, 0, 15))
#define VLD1ALL_16(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, 0, 0, 15))
#define VLD1ALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, 0, 0, 15))
#define VLD1QALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, 1, 0, 15))
#define VST1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b00<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
#define VST1LANE_8(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
#define VST1LANE_16(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, (index)<<2, 15))
#define VST1LANE_32(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, (index)<<3, 15))
#define VST1LANE_8(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 0, (index)<<1, 15))
#define VST1LANE_16(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, (index)<<2, 15))
#define VST1LANE_32(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, (index)<<3, 15))
#define VADD_gen(size, D, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1000<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#define VADD_8(Dd, Dn, Dm) EMIT(VADD_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -870,7 +944,7 @@ Op is 20-27
#define VCEQQ_16(Dd, Dn, Dm) EMIT(VCEQ_I_gen(1, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_32(Dd, Dn, Dm) EMIT(VCEQ_I_gen(2, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_32(Dd, Dn, Dm) EMIT(VCEQ_I_gen(2, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
//#define VCEQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15)) // doesn't exist
#define VCEQQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_F_gen(sz, D, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | (sz)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1110<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#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))
@@ -883,6 +957,7 @@ Op is 20-27
#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 VCEQQ_0_F32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 1, 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))
@@ -1288,7 +1363,17 @@ Op is 20-27
#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_8(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<1)|0b1), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_8(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<1)|0b1), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_16(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<2)|0b10), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_16(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<2)|0b10), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_64(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<4)|0b1000), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VREV64_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | (Q)<<6 | (M)<<5 | (Vm))
#define VREV64_32(Dd, Dm) EMIT(VREV64_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VREV64Q_32(Dd, Dm) EMIT(VREV64_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, ((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))
+1 -1
View File
@@ -179,7 +179,7 @@ INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d64 &g&g param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
+1 -1
View File
@@ -1164,7 +1164,7 @@ const char* arm_print(uint32_t opcode) {
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
int param = (opcode >> 7) & 0x3;
sprintf(ret, "VREV%d.%d %s, %s", 16 << param, 8 << size, vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VREV%d.%d %s, %s", 64 >> param, 8 << size, vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m]);
} else if ((opcode & 0xFFB30F10) == 0xF3B00200) {
int u = (opcode >> 7) & 1;
int size = (opcode >> 18) & 0x3;
+1 -1
View File
@@ -314,7 +314,7 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
if(current && current->done) {
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
+4 -1
View File
@@ -30,6 +30,7 @@ void arm_epilog_fast() EXPORTDYN;
#ifdef DYNAREC
#ifdef HAVE_TRACE
#include "elfloader.h"
uintptr_t getX86Address(dynablock_t* db, uintptr_t arm_addr);
#endif
void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
@@ -38,7 +39,9 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
if(!addr) {
x2-=8; // actual PC is 2 instructions ahead
dynablock_t* db = FindDynablockFromNativeAddress(x2);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
void* x86addr = db?(void*)getX86Address(db, (uintptr_t)x2):NULL;
const char* pcname = getAddrFunctionName((uintptr_t)x86addr);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
}
#endif
dynablock_t* current = NULL;
+156 -66
View File
@@ -3,6 +3,7 @@
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include "debug.h"
#include "box86context.h"
@@ -60,9 +61,17 @@ void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const cha
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(!box86_dynarec_bigblock)
return;
// exist?
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
// put in a free slot
for(int i=0; i<dyn->next_sz; ++i)
if(!dyn->next[i]) {
dyn->next[i] = addr;
return;
}
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
@@ -75,13 +84,12 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
++i;
}
return best;
}
@@ -206,7 +214,7 @@ int next_instruction(dynarec_arm_t *dyn, uintptr_t addr)
nextop = PK(1);
switch((nextop>>3)&7) {
case 0: // INC Ed
case 1: //DEC Ed
case 1: // DEC Ed
case 2: // CALL Ed
case 4: // JMP Ed
case 6: // Push Ed
@@ -231,7 +239,7 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
return (i==n)?1:0;
}
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
{
// x86 instruction is <16 bytes
int toadd;
@@ -260,6 +268,98 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size,
return insts;
}
static void fillPredecessors(dynarec_arm_t* dyn)
{
int pred_sz = 0;
// compute total size of predecessor to alocate the array
// first compute the jumps
for(int i=0; i<dyn->size; ++i) {
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1) {
++pred_sz;
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
}
}
// second the "has_next"
for(int i=0; i<dyn->size; ++i) {
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz)) {
++pred_sz;
++dyn->insts[i+1].pred_sz;
}
}
dyn->predecessor = (int*)malloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
dyn->insts[i].pred = p;
p += dyn->insts[i].pred_sz;
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
assert(p==dyn->predecessor+pred_sz);
// fill pred
for(int i=0; i<dyn->size; ++i) {
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz))
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
dyn->insts[dyn->insts[i].x86.jmp_insts].pred[dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz++] = i;
}
}
static void updateNeed(dynarec_arm_t* dyn, int ninst, uint32_t need) {
uint32_t old_need = dyn->insts[ninst].x86.need_flags;
uint32_t new_need = old_need | need;
uint32_t new_use = dyn->insts[ninst].x86.use_flags;
uint32_t old_use = dyn->insts[ninst].x86.old_use;
if((new_need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET) {
new_need &=~X_PEND;
new_need |= X_ALL;
}
uint32_t new_set = 0;
if(dyn->insts[ninst].x86.state_flags & SF_SET)
new_set = dyn->insts[ninst].x86.set_flags;
if(dyn->insts[ninst].x86.state_flags & SF_PENDING)
new_set |= X_PEND;
if((new_need&X_PEND) && (
dyn->insts[ninst].x86.state_flags==SF_SET || dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
new_need &=~X_PEND;
new_need |=X_ALL;
}
dyn->insts[ninst].x86.need_flags = new_need;
dyn->insts[ninst].x86.old_use = new_use;
if(dyn->insts[ninst].x86.jmp_insts==-1)
new_need |= X_PEND;
// a Flag Barrier will change all need to "Pending", as it clear all flags optimisation
if(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)
new_need = X_PEND;
if((new_need == old_need) && (new_use == old_use)) // no changes, bye
return;
if(!(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)) {
new_need &=~new_set; // clean needed flag that were suplied
new_need |= new_use; // new need
}
if((new_need == (X_ALL|X_PEND)) && (dyn->insts[ninst].x86.state_flags & SF_SET))
new_need = X_ALL;
//update need to new need on predecessor
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
updateNeed(dyn, dyn->insts[ninst].pred[i], new_need);
}
static void resetNeed(dynarec_arm_t* dyn) {
for(int i = dyn->size; i-- > 0;) {
dyn->insts[i].x86.old_use = 0;
dyn->insts[i].x86.need_flags = dyn->insts[i].x86.default_need;
}
}
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
@@ -275,6 +375,7 @@ void CancelBlock()
return;
free(helper->next);
free(helper->insts);
free(helper->predecessor);
free(helper->sons_x86);
free(helper->sons_arm);
if(helper->dynablock && helper->dynablock->block)
@@ -314,30 +415,17 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
// already protect the block and compute hash signature
protectDB(addr, end-addr); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// Compute flag_need, without taking into account any barriers
uint32_t last_need = X_PEND;
for(int i = helper.size; i-- > 0;) {
last_need |= helper.insts[i].x86.use_flags;
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
if (last_need == (X_PEND | X_ALL)) {
last_need = X_ALL;
}
helper.insts[i].x86.need_flags = last_need;
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
if (last_need & X_PEND) {
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
} else {
last_need &= ~helper.insts[i].x86.set_flags;
}
}
}
// Compute flag_need, without with current barriers
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end) {
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.use_flags |= X_PEND;
} else {
// find jump address instruction
int k=-1;
@@ -345,76 +433,76 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(helper.insts[i2].x86.addr==j)
k=i2;
}
if(k!=-1) // -1 if not found, mmm, probably wrong, exit anyway
helper.insts[k].x86.barrier = 1;
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
}
}
// fill predecessors with the jump address
fillPredecessors(&helper);
// check for the optionnal barriers now
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].x86.barrier==3)
if(helper.insts[i].barrier_maybe) {
// out-of-block jump
if(helper.insts[i].x86.jmp_insts == -1) {
if(i==helper.size-1 || helper.insts[i+1].x86.barrier)
helper.insts[i].x86.barrier=2; // nope, end of block or barrier just after
else
helper.insts[i].x86.barrier=0; // ok, no need for a barrier here after all
} else
helper.insts[i].x86.barrier=2;
// nothing for now
} else {
// inside block jump
int k = helper.insts[i].x86.jmp_insts;
if(k>i) {
// jump in the future
if(helper.insts[k].pred_sz>1) {
// with multiple flow, put a barrier
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
} else {
// jump back
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
}
}
}
// check to remove useless barrier, in case of jump when destination doesn't needs flags
for(int i=helper.size-1; i>=0; --i) {
/*for(int i=helper.size-1; i>=0; --i) {
int k;
if(helper.insts[i].x86.jmp
&& helper.insts[i].x86.jmp_insts>=0
&& helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1) {
int k = helper.insts[i].x86.jmp_insts;
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
&& helper.insts[k].x86.barrier&BARRIER_FLAGS) {
//TODO: optimize FPU barrier too
if((!helper.insts[k].x86.need_flags)
||(helper.insts[k].x86.set_flags==X_ALL
&& helper.insts[k].x86.state_flags==SF_SET)
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
helper.insts[k].x86.barrier = 4; // remove barrier (keep FPU barrier, and still reset state flag)
helper.insts[k].x86.barrier &= ~BARRIER_FLAGS; // remove flag barrier
}
}
}
}*/
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
for(int i = helper.size; i-- > 0;) {
if(helper.insts[i].x86.barrier==1)
// immediate barrier
helper.insts[i].x86.use_flags |= X_PEND;
else if(helper.insts[i].x86.jmp
&& helper.insts[i].x86.jmp_insts>=0
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
) {
if(helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1)
if(helper.insts[k].x86.barrier&BARRIER_FLAGS)
// jumpto barrier
helper.insts[i].x86.use_flags |= X_PEND;
if(helper.insts[i].x86.barrier&BARRIER_FLAGS && (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags))
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
else
helper.insts[i].x86.use_flags |= helper.insts[helper.insts[i].x86.jmp_insts].x86.need_flags;
helper.insts[i].x86.use_flags |= (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags);
}
if(helper.insts[i].x86.barrier&BARRIER_FLAGS)
// immediate barrier
helper.insts[i].x86.use_flags |= X_PEND;
}
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
helper.insts[i].x86.need_flags = 0;
last_need = X_PEND;
for(int i = helper.size; i-- > 0;) {
helper.insts[i].x86.need_flags = last_need;
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
if (last_need & X_PEND) {
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
} else {
last_need &= ~helper.insts[i].x86.set_flags;
}
}
last_need |= helper.insts[i].x86.use_flags;
if (last_need == (X_PEND | X_ALL)) {
last_need = X_ALL;
}
}
updateNeed(&helper, i, 0);
// pass 1, float optimisations
// pass 1, float optimisations, first pass for flags
arm_pass1(&helper, addr);
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
@@ -510,6 +598,8 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
} else
free(sons);
}
free(helper.predecessor);
helper.predecessor = NULL;
free(helper.sons_x86);
helper.sons_x86 = NULL;
free(helper.sons_arm);
@@ -517,4 +607,4 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
current_helper = NULL;
block->done = 1;
return (void*)block;
}
}
+132 -98
View File
@@ -340,7 +340,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x27:
INST_NAME("DAA");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DAA\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTB(x1, xEAX, 0);
@@ -402,7 +402,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x2F:
INST_NAME("DAS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DAS\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTB(x1, xEAX, 0);
@@ -464,7 +464,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x37:
INST_NAME("AAA");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization AAA\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTH(x1, xEAX, 0);
@@ -532,7 +532,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x3F:
INST_NAME("AAS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization AAS\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTH(x1, xEAX, 0);
@@ -548,7 +548,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x46:
case 0x47:
INST_NAME("INC reg");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&0x07);
emit_inc32(dyn, ninst, gd, x3, x14);
break;
@@ -561,7 +561,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x4E:
case 0x4F:
INST_NAME("DEC reg");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&0x07);
emit_dec32(dyn, ninst, gd, x3, x14);
break;
@@ -691,24 +691,29 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F|(dyn->insts[ninst].x86.barrier?0:X_PEND)); \
READFLAGS(F); \
i8 = F8S; \
BARRIER(3); \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8);\
Bcond(NO, i32); \
if(!dyn->insts[ninst].x86.barrier) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0x70:
@@ -1377,7 +1382,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Eb, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
u8 = F8;
emit_rol8c(dyn, ninst, x1, u8&0x1f, x2, x14);
@@ -1385,7 +1390,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("ROR Eb, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
u8 = F8;
emit_ror8c(dyn, ninst, x1, u8&0x1f, x2, x14);
@@ -1393,7 +1398,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
@@ -1404,7 +1409,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("RCR Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
@@ -1467,7 +1472,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
u8 = (F8)&0x1f;
emit_rol32c(dyn, ninst, ed, u8, x3, x14);
@@ -1475,7 +1480,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
u8 = (F8)&0x1f;
emit_ror32c(dyn, ninst, ed, u8, x3, x14);
@@ -1483,7 +1488,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEDW(x14, x1);
@@ -1498,7 +1503,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDW(x14, x1);
u8 = F8&0x1f;
if(u8==1) {
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
MOVW(x3, u8);
@@ -1523,7 +1528,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
WBACK;
} else if(u8>1) {
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, u8);
CALL_(rcr32, ed, (1<<x14));
@@ -1565,7 +1570,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RETN");
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
READFLAGS(X_PEND); // lets play safe here too
BARRIER(2);
BARRIER(BARRIER_FLOAT);
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
*need_epilog = 0;
@@ -1576,7 +1581,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// 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);
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -1624,7 +1629,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
if(PK(0)=='S' && PK(1)=='C') {
addr+=2;
BARRIER(2);
BARRIER(BARRIER_FLOAT);
INST_NAME("Special Box86 instruction");
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
{
@@ -1684,7 +1689,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(PK(0)==0x80) {
INST_NAME("Syscall");
u8 = F8;
BARRIER(2);
BARRIER(BARRIER_FLOAT);
MOV32(xEIP, ip+2);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
CALL_S(x86Syscall, -1, 0);
@@ -1706,7 +1711,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); // Not a hack, EFLAGS are restored
BARRIER(2);
BARRIER(BARRIER_FLOAT);
iret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -1718,14 +1723,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
if(opcode==0xD0) {
INST_NAME("ROL Eb, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
} else {
INST_NAME("ROL Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization ROL 8b\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
CALL_(rol8, x1, (1<<x3));
@@ -1736,7 +1741,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0xD0) {
INST_NAME("ROR Eb, 1");
MOVW(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
@@ -1744,7 +1749,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ROR Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
SETFLAGS(X_OF|X_CF, SF_SET);
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization ROR 8b\n");
GETEB(x1);
CALL_(ror8, x1, (1<<x3));
EBBACK;
@@ -1752,7 +1757,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
if(opcode==0xD0) {INST_NAME("RCL Eb, 1");} else {INST_NAME("RCL Eb, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
@@ -1762,7 +1767,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
if(opcode==0xD0) {INST_NAME("RCR Eb, 1");} else {INST_NAME("RCR Eb, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
@@ -1826,21 +1831,21 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
@@ -1850,12 +1855,31 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
GETEDW(x14, x1);
CALL_(rcr32, ed, (1<<x14));
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
MOVW(x3, 1);
STR_IMM9(x3, xEmu, offsetof(x86emu_t, op2));
SET_DF(x3, d_rcr32);
} else IFX(X_ALL) {
SET_DFNONE(x3);
}
IFX(X_OF) {
XOR_REG_LSR_IMM8(x3, xFlags, ed, 31);
BFI(xFlags, x3, F_OF, 1);
}
MOVS_REG_LSR_IMM5(x3, xFlags, 1); // load CC (F_CF==0) into ARM CF
MOVS_REG_RRX(ed, ed);
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1, 0);
BFC_COND(cCC, xFlags, F_CF, 1);
}
WBACK;
break;
case 4:
@@ -1931,7 +1955,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
@@ -1941,7 +1965,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
@@ -2035,20 +2059,27 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
addr = dynarecDF(dyn, addr, ip, ninst, ok, need_epilog);
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8, 1); \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!dyn->insts[ninst].x86.barrier) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ");
@@ -2120,8 +2151,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// disabling this to avoid fetching data outside current block (in case this part changed, this block will not been marck as dirty)
/*case 3:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(1);
BARRIER_NEXT(1);
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
MOV32(x2, addr);
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
@@ -2162,15 +2193,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(ninst && dyn->insts[ninst-1].x86.set_flags) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
// regular call
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst==dyn->size-1) {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
if(u32==0) { // self modifying code maybe? so use indirect address fetching
@@ -2184,7 +2213,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE9:
case 0xEB:
BARRIER(1);
BARRIER(BARRIER_MAYBE);
if(opcode==0xE9) {
INST_NAME("JMP Id");
i32 = F32S;
@@ -2193,18 +2222,18 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F8S;
}
JUMP(addr+i32, 0);
if(dyn->insts) {
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
if(dyn->insts[ninst].x86.jmp_insts==-1) {
// out of the block
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
fpuCacheTransform(dyn, ninst, x1, x2, x3);
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
if(tmp==-4) {
NOP;
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
if(tmp==-4) {
NOP;
} else {
Bcond(c__, tmp);
}
Bcond(c__, tmp);
}
}
*need_epilog = 0;
@@ -2315,7 +2344,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC3:
INST_NAME("(REPZ) RET");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(2);
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -2537,7 +2566,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("IMUL AL, Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization IMUL 8b\n");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2546,7 +2575,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("DIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2555,7 +2584,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("IDIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization IDIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2612,7 +2641,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
if(arm_div && ninst && dyn->insts
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
SET_DFNONE(x2); // flags are undefined
@@ -2655,9 +2685,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETEDH(x1);
if(arm_div) {
// check if a 32bits division is enough
CMPS_IMM8(xEDX, 0); // compare to 0
CMNS_IMM8_COND(cNE, xEDX, 1); // compare to FFFFFFFF if not 0
TSTS_IMM8_ROR_COND(cEQ, xEAX, 0b10, 1); // also test that xEAX is not signed!
B_MARK(cEQ);
CMNS_IMM8(xEDX, 1); // compare to FFFFFFFF if not 0
B_MARK2(cNE);
TSTS_IMM8_ROR(xEAX, 0b10, 1); // also test that xEAX is signed!
B_MARK(cNE);
MARK2;
}
if(ed!=x1) {MOV_REG(x1, ed);}
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
@@ -2711,14 +2747,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_inc8(dyn, ninst, x1, x2, x14);
EBBACK;
break;
case 1:
INST_NAME("DEC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_dec8(dyn, ninst, x1, x2, x14);
EBBACK;
@@ -2733,14 +2769,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETED;
emit_inc32(dyn, ninst, ed, x3, x14);
WBACK;
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETED;
emit_dec32(dyn, ninst, ed, x3, x14);
WBACK;
@@ -2750,22 +2786,20 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
//SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
GETEDH(xEIP);
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst==dyn->size-1) {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
jump_to_next(dyn, 0, ed, ninst);
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
BARRIER(1);
BARRIER(BARRIER_FULL);
GETEDH(xEIP);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
+277 -123
View File
@@ -87,6 +87,20 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
//CALL(arm_ud, -1, 0);
UDF(0);
break;
case 0x0D:
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("PREFETCHW");
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = fakeed(dyn,addr, ninst, nextop);
// should use PLDW, but it's not available on cortex-a8 for example
break;
default:
DEFAULT;
}
break;
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
@@ -433,6 +447,29 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0x3A: // these are some more SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F:
INST_NAME("PALIGNR Gm, Em, Ib");
nextop = F8;
GETGM(q0);
GETEM(q1);
u8 = F8;
if(u8>15) {
VEOR(q0, q0, q0);
} else if(u8>7) {
d0 = fpu_get_scratch_quad(dyn);
VEOR(d0, d0, d0);
VEXT_8(q0, q0, d0, u8-8);
} else {
VEXT_8(q0, q1, q0, u8);
}
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
@@ -577,23 +614,37 @@ 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
v1 = fpu_get_scratch_quad(dyn);
// Newton-Raphson: Xn+1 = Xn*(3-d*Xn²)/2 converge to 1/sqrt(d) with X0 = result of VSQRTE
// and VSQRTS is (3-A*B)/2
// so VSQRTE(d) -> X is initial step
// VSQRTS(d,X*X)*X -> X loop
// than d*X -> SQRT(d) (because X ~ 1/sqrt(d))
VRSQRTEQ_F32(v2, q0); // v2 = X0 (=X), q0 = d
VMULQ_F32(v1, v2, v2); // v1 = X0²
VRSQRTSQ_F32(v1, v1, q0); // v1 = (3-d*X0²)/2
VMULQ_F32(v2, v2, v1); // v2 = X0*(3-d*X0²)/2 = X1
VMULQ_F32(v1, v2, v2); // v1 = x1²
VRSQRTSQ_F32(v1, v1, q0); // v1 = (3-d*X1²)/2
VMULQ_F32(v2, v2, v1); // v2 = X1*(3-d*X1²)/2 = X2
if(!box86_dynarec_fastnan) {
// need to preserve v0, in case it's == q0
VMULQ_F32(v1, v2, q0); // v1 = X2*d ~ SQRT(d)
if(v0<dyn->n.fpu_scratch || v0!=q0)
q1 = v0; // v0 is a scratch register
else
q1 = fpu_get_scratch_quad(dyn); // need a new scratch
VCEQQ_0_F32(q1, q0); // prepare mask, 111 when == 0.0
VMOVQ_H32(v2, 0xff); // prepare +inf
VSHRQ_U32(v2, v2, 1); // 0xff000000 -> 0x7f800000 == +inf
VCEQQ_32(v2, v2, q0); // v2 mask: 111 when == +inf
VORRQ(q1, q1, v2); // q1 mask: 111 when ==0 || == +inf
VBICQ(v1, v1, q1); // mask value in result
VANDQ(q1, q0, q1); // keep original value that are 0 or +inf
VORRQ(v0, v1, q1); // copy over
} else {
VMULQ_F32(v0, v2, q0); // v0 = X2*d ~ SQRT(d)
}
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
@@ -601,21 +652,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0, 0);
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");
@@ -623,14 +660,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(q0 == v0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
v2 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v2, q0);
VRECPSQ_F32(v1, v2, q0);
VMULQ_F32(v0, v2, v1);
VRECPEQ_F32(v0, q0);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
@@ -719,16 +749,19 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x5E:
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX(v0, 1);
q0 = fpu_get_scratch_quad(dyn);
q1 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(q0, v1);
VRECPSQ_F32(q1, q0, v1);
VMULQ_F32(q0, q0, q1);
VRECPSQ_F32(q1, q0, v1);
VMULQ_F32(q0, q0, q1);
VMULQ_F32(v0, v0, q0);
GETEX(q0, 0);
GETGX(q1, 1);
// use Gx * 1/Ex, using RECP
// Newton-Raphson: Xn+1 = Xn*(2-d*Xn) converge to 1/d if X0 if result of VRECPE(d)
// VRECPE is 2-A*B
v1 = fpu_get_scratch_quad(dyn);
v2 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v2, q0); // v2 = X0, q0 = d
VRECPSQ_F32(v1, q0, v2); // v1 = 2-d*X0
VMULQ_F32(v2, v2, v1); // v2 = X0*(2-d*X0) = X1
VRECPSQ_F32(v1, q0, v2); // v1 = 2-d*X1
VMULQ_F32(v2, v2, v1); // v2 = X1*(2-d*X1) = X2 ~ 1/d
VMULQ_F32(q1, q1, v2);
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
@@ -857,9 +890,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(v0);
GETEM(v1);
q0 = fpu_get_scratch_quad(dyn);
VMOVD(q0+0, v0);
VMOVD(q0+1, v1);
if(!(v0&1) && (v1==(v0+1))) {
q0 = v0; // no need to move the regs...
} else {
q0 = fpu_get_scratch_quad(dyn);
VMOVD(q0+0, v0);
VMOVD(q0+1, v1);
}
VQMOVN_S32(v0, q0);
break;
@@ -1130,24 +1167,29 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F|(dyn->insts[ninst].x86.barrier?0:X_PEND)); \
i32_ = F32S; \
BARRIER(3); \
JUMP(addr+i32_, 1); \
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8);\
Bcond(NO, i32); \
READFLAGS(F); \
i32_ = F32S; \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i32_, 1); \
GETFLAGS; \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!dyn->insts[ninst].x86.barrier) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0x80:
@@ -1396,13 +1438,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET_PENDING);
UXTB(x3, xECX, 0);
GETEDW(x14, x1);
SETFLAGS(X_ALL, SF_SET);
AND_IMM8(x3, xECX, 0x1f);
GETED;
GETGD;
MOV_REG(x2, gd);
CALL(shld32, ed, (wback?(1<<wback):0));
emit_shld32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
@@ -1971,68 +2011,182 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
i32 = -1;
j32 = 0;
GETGX(v0, 1);
q0 = fpu_get_scratch_quad(dyn); // temporary storage
// use stack as temporary storage
SUB_IMM8(xSP, xSP, 4);
if((nextop&0xC0)!=0xC0)
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
u8 = F8;
// first two elements from Gx
for (int i=0; i<2; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
VST1LANE_32(v0+(idx/2), xSP, idx&1);
i32 = idx;
v2 = fpu_get_scratch_double(dyn);
if((nextop&0xC0)!=0xC0) {
// from memory
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
u8 = F8;
q0 = v0;
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v0, 0); break;
case 0b0001: VREV64_32(q0, v0); break; // reverse low part
case 0b0010: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0011: VEXT_8(q0, v0+1, v0, 4); break;
case 0b0100: break; // same
case 0b0101: VDUP_32(q0, v0, 1); break;
case 0b0110: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0111: VREV64_32(v2, v0);
VEXT_8(q0, v0+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v0);
VEXT_8(q0, v2, v0+1, 4); break;
case 0b1001: VEXT_8(q0, v0, v0+1, 4); break;
case 0b1010: VDUP_32(q0, v0+1, 0); break;
case 0b1011: VREV64_32(q0, v0+1); break;
case 0b1100: VEXT_8(q0, v0+1, v0, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(v2, v0+1);
VEXT_8(q0, v0, v2, 4); break;
case 0b1110: VMOVD(q0, v0+1); break;
case 0b1111: VDUP_32(q0, v0+1, 1); break;
}
VLD1LANE_32(q0+(i/2), xSP, i&1);
}
i32 = -1;
// next two from Ex
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
for (int i=2; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
VST1LANE_32(v1+(idx/2), xSP, idx&1);
i32 = idx;
// High part
if(((u8>>4)&3) == ((u8>>6)&3)) {
if((u8>>4)&3) {
ADD_IMM8(x3, wback, ((u8>>4)&3)*4);
}
VLD1LANE_32(q0+(i/2), xSP, i&1);
VLD1ALL_32(q0+1, ((u8>>4)&3)?x3:wback);
} else {
if((u8>>4)&3) {
ADD_IMM8(x3, wback, ((u8>>4)&3)*4);
}
VLD1LANE_32(q0+1, ((u8>>4)&3)?x3:wback, 0);
if((u8>>6)&3) {
ADD_IMM8(x3, wback, ((u8>>6)&3)*4);
}
VLD1LANE_32(q0+1, ((u8>>6)&3)?x3:wback, 1);
}
} else {
for (int i=2; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
ADD_IMM8(x2, ed, idx*4);
i32 = idx;
// from register
wback = 0; ed = nextop&7;
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
u8 = F8;
if((v0==v1) && ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111))) {
// same value duplicated all along
q0 = v0;
VDUPQ_32(v0, v0+((u8>>1)&1), u8&1);
} else if ((v0==v1) && (u8==0b01000100)) {
q0 = v0;
VMOVD(v0+1, v0);
} else if ((v0==v1) && (u8==0b11101110)) {
q0 = v0;
VMOVD(v0, v0+1);
} else if ((v0==v1) && (u8==0b10110001)) {
q0 = v0;
VREV64Q_32(v0, v0);
} else if ((v0==v1) && (u8==0b01001110)) {
q0 = v0;
VSWP(v0, v0+1);
} else if ((v0==v1) && (u8==0b11011000)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0, v0+1);
} else if ((v0==v1) && (u8==0b00100111)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0+1, v0);
} else if ((v0==v1) && (u8==0b01110010)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0, v0+1);
VREV64Q_32(v0, v0);
} else if ((v0==v1) && (u8==0b10001101)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0+1, v0);
VREV64Q_32(v0, v0);
} else {
if(v1!=v0)
q0 = v0; // no need for temp storage
else if((u8&0b10100000)==0b10100000)
q0 = v0; // no need for temp if only low/low and high/high are shuffled
else
q0 = fpu_get_scratch_quad(dyn); // temporary storage
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v0, 0); break;
case 0b0001: VREV64_32(q0, v0); break; // reverse low part
case 0b0010: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0011: VEXT_8(q0, v0+1, v0, 4); break;
case 0b0100: VMOVD(q0, v0); break; // same
case 0b0101: VDUP_32(q0, v0, 1); break;
case 0b0110: VEXT_8(q0, v0, v0+1, 4);
VREV64_32(q0, q0); break;
case 0b0111: VREV64_32(v2, v0);
VEXT_8(q0, v0+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v0);
VEXT_8(q0, v2, v0+1, 4); break;
case 0b1001: VEXT_8(q0, v0, v0+1, 4); break;
case 0b1010: VDUP_32(q0, v0+1, 0); break;
case 0b1011: VREV64_32(q0, v0+1); break;
case 0b1100: VEXT_8(q0, v0+1, v0, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(v2, v0+1);
VEXT_8(q0, v0, v2, 4); break;
case 0b1110: VMOVD(q0, v0+1); break;
case 0b1111: VDUP_32(q0, v0+1, 1); break;
}
// High part
switch ((u8>>4)&0xf) {
case 0b0000: VDUP_32(q0+1, v1, 0); break;
case 0b0001: VREV64_32(q0+1, v1); break; // reverse low part
case 0b0010: VREV64_32(v2, v1+1);
VEXT_8(q0+1, v2, v1, 4); break;
case 0b0011: VEXT_8(q0+1, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0+1, v1); break; // same
case 0b0101: VDUP_32(q0+1, v1, 1); break;
case 0b0110: VEXT_8(q0+1, v1, v1+1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b0111: VREV64_32(v2, v1);
VEXT_8(q0+1, v1+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v1);
VEXT_8(q0+1, v2, v1+1, 4); break;
case 0b1001: VEXT_8(q0+1, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0+1, v1+1, 0); break;
case 0b1011: VREV64_32(q0+1, v1+1); break;
case 0b1100: VEXT_8(q0+1, v1+1, v1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b1101: VREV64_32(v2, v1+1);
VEXT_8(q0+1, v1, v2, 4); break;
case 0b1110: VMOVD(q0+1, v1+1); break;
case 0b1111: VDUP_32(q0+1, v1+1, 1); break;
}
VLD1LANE_32(q0+(i/2), x2, i&1);
}
}
ADD_IMM8(xSP, xSP, 4);
VMOVQ(v0, q0);
break;
case 0xC7:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x1, wback, fixedaddress+0);
LDR_IMM9(x2, wback, fixedaddress+4);
CMPS_REG_LSL_IMM5(xEAX, x1, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x2, 0);
B_MARK(cNE); // EDX != Ed[1]
STR_IMM9(xEBX, wback, fixedaddress+0);
STR_IMM9(xECX, wback, fixedaddress+4);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x1);
MOV_REG(xEDX, x2);
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
switch((nextop>>3)&7) {
case 1:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x1, wback, fixedaddress+0);
LDR_IMM9(x2, wback, fixedaddress+4);
CMPS_REG_LSL_IMM5(xEAX, x1, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x2, 0);
B_MARK(cNE); // EDX != Ed[1]
STR_IMM9(xEBX, wback, fixedaddress+0);
STR_IMM9(xECX, wback, fixedaddress+4);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x1);
MOV_REG(xEDX, x2);
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
break;
default:
DEFAULT;
}
break;
case 0xC8:
case 0xC9:
+4 -7
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -299,13 +300,9 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
}
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst!=dyn->size-1) {
} else {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
jump_to_next(dyn, 0, xEIP, ninst);
+46 -3
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -28,16 +29,30 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2, wb;
uint8_t wback, wb1, wb2, wb, eb1, eb2;
uint8_t u8;
int fixedaddress;
MAYUSE(j32);
MAYUSE(wback);
MAYUSE(wb2);
MAYUSE(wb);
MAYUSE(eb1);
MAYUSE(eb2);
switch(opcode) {
case 0x01:
INST_NAME("ADD GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO2(x14);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -137,6 +152,16 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_xor32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x39:
INST_NAME("CMP GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x14);
emit_cmp32(dyn, ninst, ed, gd, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -400,6 +425,24 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(xEAX, x2, 0);
break;
case 0xC6:
INST_NAME("MOV GS:Eb, Ib");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= u8
u8 = F8;
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
MOVW(x3, u8);
BFI(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
u8 = F8;
MOVW(x3, u8);
STRB_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
case 0xC7:
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x14);
@@ -422,14 +465,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
+24 -6
View File
@@ -175,6 +175,12 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x1E:
INST_NAME("PUSH DS");
MOVW(x1, offsetof(x86emu_t, segs[_DS]));
LDRH_REG(x2, xEmu, x1);
PUSH16(x2, xESP);
break;
case 0x21:
INST_NAME("AND Ew, Gw");
@@ -295,7 +301,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x46:
case 0x47:
INST_NAME("INC Reg16");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_inc16(dyn, ninst, x1, x3, x14);
@@ -310,7 +316,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg16");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_dec16(dyn, ninst, x1, x3, x14);
@@ -681,6 +687,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xAF:
INST_NAME("SCASW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, 2);
UXTH(x1, xEAX, 0);
LDRHAI_REG_LSL_IMM5(x2, xEDI, x3);
@@ -898,6 +905,10 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xF0:
return dynarec66F0(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0xF2:
case 0xF3:
nextop = F8;
@@ -991,6 +1002,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xF5:
INST_NAME("CMC");
READFLAGS(X_CF);
SETFLAGS(X_CF, SF_SUBSET);
XOR_IMM8(xFlags, xFlags, 1<<F_CF);
break;
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
@@ -1045,8 +1063,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_REG_LSL_IMM5(x2, x2, xEDX, 16);
UDIV(x3, x2, ed);
MLS(x14, x3, ed, x2); // x14 = x2 mod ed (i.e. x2 - x3*ed)
BFI(xEAX, x3, 1, 16);
BFI(xEDX, x14, 1, 16);
BFI(xEAX, x3, 0, 16);
BFI(xEDX, x14, 0, 16);
} else {
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
@@ -1086,14 +1104,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1);
emit_inc16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1);
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
+216 -82
View File
@@ -619,17 +619,55 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("ADDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VADD_F64(v0, v0, q0);
VADD_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
}
break;
case 0x59:
INST_NAME("MULPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VMUL_F64(v0, v0, q0);
VMUL_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
}
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
@@ -656,9 +694,28 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("SUBPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VSUB_F64(v0, v0, q0);
VSUB_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
}
break;
case 0x5D:
INST_NAME("MINPD Gx, Ex");
@@ -677,9 +734,28 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("DIVPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VDIV_F64(v0, v0, q0);
VDIV_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
}
break;
case 0x5F:
INST_NAME("MAXPD Gx, Ex");
@@ -866,51 +942,113 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(u8==0x4E) {
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
VDUPQ_32(v0, v1+((u8>>1)&1), u8&1);
} else if (u8==0b01000100) {
VMOVD(v0+1, v1);
VMOVD(v0, v1);
} else if (u8==0b11101110) {
VMOVD(v0, v1+1);
VMOVD(v0+1, v1+1);
} else if (u8==0b10110001) {
VREV64Q_32(v0, v1);
} else if (u8==0b00011011) {
VREV64Q_32(v0, v1);
VSWP(v0, v0+1);
} else if (u8==0b01001110) {
if(v0==v1) {
VSWP(v0, v0+1);
} else {
VMOVD(v0, v1+1);
VMOVD(v0+1, v1);
}
} else if (u8==0b11011000) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VMOVQ(v0, v1);
VTRN_32(v0, v0+1);
} else if (u8==0b00100111) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VMOVQ(v0, v1);
VTRN_32(v0+1, v0);
} else if (u8==0b10001101) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VREV64Q_32(v0, v1); // 10 11 00 01
VTRN_32(v0, v0+1); // 10 00 11 01
} else if (u8==0b01110010) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VREV64Q_32(v0, v1); // 10 11 00 01
VTRN_32(v0+1, v0); // 01 11 00 10
} else {
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)
};
q0 = fpu_get_scratch_quad(dyn); // temporary storage
d0 = fpu_get_scratch_double(dyn);
if(v0==v1) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
uint32_t a1, a2, a3, a4;
a1 = swp[(u8>>(0*2))&3];
a2 = swp[(u8>>(1*2))&3];
MOV32(x2, a1);
if(a1==a2) {MOV_REG(x3, x2);} else {MOV32(x3, a2);}
VMOVtoV_D(d0, x2, x3);
VTBL2_8(v0+0, q1, d0);
a3 = swp[(u8>>(2*2))&3];
a4 = swp[(u8>>(3*2))&3];
if(a3!=a1 || a4!=a2) {
if(a3!=a1) {
if(a3==a2) {MOV_REG(x2, x3);} else {MOV32(x2, a3);}
}
if(a4!=a2) {
if(a4==a3) {MOV_REG(x3, x2);} else {MOV32(x3, a4);}
}
VMOVtoV_D(d0, x2, x3);
if(v1!=v0)
q0 = v0; // no need for temp storage
else if((u8&0xf)==((u8>>4)&0xf))
q0 = v0;
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v1, 0); break;
case 0b0001: VREV64_32(q0, v1); break; // reverse low part
case 0b0010: VREV64_32(d0, v1+1);
VEXT_8(q0, d0, v1, 4); break;
case 0b0011: VEXT_8(q0, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0, v1); break; // same
case 0b0101: VDUP_32(q0, v1, 1); break;
case 0b0110: VEXT_8(q0, v1, v1+1, 4);
VREV64_32(q0, q0); break;
case 0b0111: VREV64_32(d0, v1);
VEXT_8(q0, v1+1, d0, 4); break;
case 0b1000: VREV64_32(d0, v1);
VEXT_8(q0, d0, v1+1, 4); break;
case 0b1001: VEXT_8(q0, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0, v1+1, 0); break;
case 0b1011: VREV64_32(q0, v1+1); break;
case 0b1100: VEXT_8(q0, v1+1, v1, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(d0, v1+1);
VEXT_8(q0, v1, d0, 4); break;
case 0b1110: VMOVD(q0, v1+1); break;
case 0b1111: VDUP_32(q0, v1+1, 1); break;
}
VTBL2_8(v0+1, q1, d0);
// High part
if((u8&0xf)==((u8>>4)&0xf)) {
VMOVD(q0+1, q0);
} else switch ((u8>>4)&0xf) {
case 0b0000: VDUP_32(q0+1, v1, 0); break;
case 0b0001: VREV64_32(q0+1, v1); break; // reverse low part
case 0b0010: VREV64_32(d0, v1+1);
VEXT_8(q0+1, d0, v1, 4); break;
case 0b0011: VEXT_8(q0+1, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0+1, v1); break; // same
case 0b0101: VDUP_32(q0+1, v1, 1); break;
case 0b0110: VEXT_8(q0+1, v1, v1+1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b0111: VREV64_32(d0, v1);
VEXT_8(q0+1, v1+1, d0, 4); break;
case 0b1000: VREV64_32(d0, v1);
VEXT_8(q0+1, d0, v1+1, 4); break;
case 0b1001: VEXT_8(q0+1, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0+1, v1+1, 0); break;
case 0b1011: VREV64_32(q0+1, v1+1); break;
case 0b1100: VEXT_8(q0+1, v1+1, v1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b1101: VREV64_32(d0, v1+1);
VEXT_8(q0+1, v1, d0, 4); break;
case 0b1110: VMOVD(q0+1, v1+1); break;
case 0b1111: VDUP_32(q0+1, v1+1, 1); break;
}
VMOVQ(v0, q0);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
u8 = F8;
if (u8) {
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
if(u8&3) {
ADD_IMM8(x3, ed, (u8&3)*4);
}
VLD1QALL_32(v0, (u8&3)?x3:ed);
} else {
for (int i=0; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
@@ -919,8 +1057,6 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VLD1LANE_32(v0+(i/2), x2, i&1);
}
} else {
VLD1QALL_32(v0, ed);
}
}
break;
@@ -1554,6 +1690,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
BFI(gd, x1, 0, 16);
break;
case 0xBF:
INST_NAME("MOVSX Gw, Ew");
nextop = F8;
GETGD;
GETEW(x1);
BFI(gd, x1, 0, 16);
break;
case 0xC1:
INST_NAME("XADD Gw, Ew");
@@ -1562,7 +1705,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGW(x1);
GETEW(x2);
BFI((xEAX+((nextop&0x38)>>3)), x2, 0, 16); // GW <- EW
emit_add16(dyn, ninst, x1, x2, x14, x3, 1);
emit_add16(dyn, ninst, x2, x1, x14, x3, 1);
EWBACK;
break;
case 0xC2:
@@ -1571,42 +1714,34 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
u8 = F8;
u8 = F8&7;
// 0
if((u8&7)==6){
VCMP_F64(d0, v0);
} else {
VCMP_F64(v0, d0);
}
VCMP_F64(v0, d0);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0, x2, x2);
// 1
if((u8&7)==6){
VCMP_F64(d0+1, v0+1);
} else {
VCMP_F64(v0+1, d0+1);
}
VCMP_F64(v0+1, d0+1);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0+1, x2, x2);
@@ -1646,17 +1781,21 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(v0, 1);
GETEX(v1, 0);
u8 = F8;
if(v0==v1 && u8==0) {
VMOVD(v0+1, v0);
if(v0==v1) {
switch (u8&3) {
case 0b00: VMOVD(v0+1, v0); break;
case 0b01: VSWP(v0, v0+1); break;
case 0b10: break;
case 0b11: VMOVD(v0, v0+1); break;
}
} 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));
if(v0==v1) {
VMOVQ(v0, q0);
switch(u8&1) {
case 0: break;
case 1: VMOVD(v0, v0+1); break;
}
switch((u8>>1)&1) {
case 0: VMOVD(v0+1, v1); break;
case 1: VMOVD(v0+1, v1+1); break;
}
}
break;
@@ -1688,13 +1827,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VNEGN_16(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VDUPQ_16(v0, q1, 0);
VNEGNQ_16(v0, v0); // because we want SHR and not SHL
VSHLQ_U16(q0, q0, v0);
break;
case 0xD2:
+133
View File
@@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
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 0xFF:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7)
{
case 0: // INC Ew
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
GETEW(x1);
emit_inc16(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
if(!fixedaddress) {
TSTS_IMM8(wback, 1);
B_MARK(cNE); // unaligned
}
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
MARKLOCK;
LDREXH(x1, wback);
emit_inc16(dyn, ninst, x1, x3, x14);
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
MARK;
LDRH_IMM8(x1, wback, 0);
LDREXB(x3, wback);
BFI(x1, x3, 0, 8);
emit_inc16(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
}
}
break;
case 1: //DEC Ew
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
GETEW(x1);
emit_dec32(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
if(!fixedaddress) {
TSTS_IMM8(wback, 1);
B_MARK(cNE); // unaligned
}
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
MARKLOCK;
LDREXH(x1, wback);
emit_dec16(dyn, ninst, x1, x3, x14);
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
MARK;
LDRH_IMM8(x1, wback, 0);
LDREXB(x3, wback);
BFI(x1, x3, 0, 8);
emit_dec16(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
}
}
break;
default:
// default to NO LOCK
addr-=2;
}
DMB_ISH();
break;
default:
DEFAULT;
}
return addr;
}
+22 -14
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#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)
@@ -132,20 +133,27 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8, 1); \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!dyn->insts[ninst].x86.barrier) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
+168 -58
View File
@@ -34,11 +34,15 @@ static const float f_pi = PI;
static const float f_lg2 = LG2;
static const float f_ln2 = LN2;
extern int arm_v8;
static const void* round_map[4] = {nearbyint, floor, ceil, trunc};
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int fixedaddress;
int v1, v2;
int s0;
@@ -50,6 +54,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
(void)u8;
switch(nextop) {
@@ -69,9 +74,12 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_64(v2, v1);
}
// should set C1 to 0
break;
case 0xC8:
INST_NAME("FXCH ST0");
break;
case 0xC9:
case 0xCA:
case 0xCB:
@@ -81,17 +89,8 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
i1 = x87_get_cache(dyn, ninst, 1, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
// swap those too
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
i3 = dyn->n.neoncache[i1].v;
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
dyn->n.neoncache[i2].v = i3;
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
// should set C1 to 0
break;
case 0xD0:
@@ -106,6 +105,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VNEG_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE1:
INST_NAME("FABS");
@@ -115,6 +115,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VABS_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE4:
@@ -136,7 +137,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// not in cache, so check Empty status and load it
// x14 will be the actual top
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
i2 = -dyn->x87stack;
i2 = -dyn->n.x87stack;
if(i2) {
if(i2<0) {
SUB_IMM8(x14, x14, -i2);
@@ -154,7 +155,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK3(cEQ);
} else {
// simply move from cache reg to r2/r3
v1 = dyn->x87reg[i1];
v1 = dyn->n.x87reg[i1];
VMOVfrV_D(x2, x3, v1);
}
// get exponant in r1
@@ -199,6 +200,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_i_64(v1, 0b01110000);
}
// should set C1 to 0
break;
case 0xE9:
INST_NAME("FLDL2T");
@@ -210,6 +212,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_l2t));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEA:
INST_NAME("FLDL2E");
@@ -221,6 +224,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_l2e));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEB:
INST_NAME("FLDPI");
@@ -232,6 +236,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_pi));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEC:
INST_NAME("FLDLG2");
@@ -243,6 +248,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_lg2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xED:
INST_NAME("FLDLN2");
@@ -254,6 +260,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_ln2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEE:
INST_NAME("FLDZ");
@@ -263,41 +270,32 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_8(v1, 0); // cannot use VMOV_i_F64
}
// should set C1 to 0
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VSQRT_F32(v1, v1);
} else {
VSQRT_F64(v1, v1);
}
break;
case 0xFC:
INST_NAME("FRNDINT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1, 0);
/*
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
u8 = x87_setround(dyn, ninst, x1, x2, x3);
VCVT_S32_F64(x1, v1); // limit to 32bits....
VCVT_F64_S32(v1, x1);
x87_restoreround(dyn, ninst, u8);
*/
break;
case 0xF0:
INST_NAME("F2XM1");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
//if(ST0.d!=0.0)
// ST0.d = exp2(ST0.d)-1.0;
VMOV_64(0, v1);
CALL_1D(exp2, 0); // return is d0
if((PK(0)==0xD9 && PK(1)==0xE8) && // next inst is FLD1
(PK(2)==0xDE && PK(3)==0xC1)) {
MESSAGE(LOG_DUMP, "Hack for fld1 / faddp st1, st0\n");
VMOV_64(v1, 0);
addr+=4;
} else {
VMOV_i_64(v1, 0b01110000); // 1.0
VSUB_F64(v1, 0, v1);
}
#endif
// should set C1 to 0
break;
case 0xF1:
INST_NAME("FYL2X");
@@ -307,24 +305,30 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d)*ST(1).d
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF2:
INST_NAME("FTAN");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
INST_NAME("FPTAN");
v2 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_64(0, v1); // prepare call to tan
CALL_1D(tan, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C1 = 0;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C1 C2 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
VMOV_i_64(v2, 0b01110000);
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
} else {
VMOV_i_64(v2, 0b01110000);
}
break;
case 0xF3:
INST_NAME("FPATAN");
@@ -335,6 +339,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_2D(atan2, 0);
VMOV_64(v2, 0); //ST(1).d = atan2(ST1.d, ST0.d);
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF4:
INST_NAME("FXTRACT");
@@ -342,13 +347,48 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1, 0);
// C1 set only if stack under/overflow occurs
break;
case 0xF5:
INST_NAME("FPREM1");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem1, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_double(dyn);
VDIV_F64(s0, v1, v2);
// set rounding to Nearest
MOVW(x2, 1); // Nearest
VMRS(x1); // get fpscr
MOV_REG(x14, x1);
BFI(x1, x2, 22, 2); // inject new round
VMSR(x1); // put new fpscr
VCVTR_S32_F64(s0*2, s0); // => Q
// set back rounding
VMSR(x14);
// get Q
VMOVfrV(x14, s0*2);
// Put back Q in a double
VCVT_F64_S32(s0, s0*2);
VMUL_F64(s0, s0, v2);
VSUB_F64(v1, v1, s0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
// set C2 = 0
BFC(x1, 10, 1);
// set C1 = Q0
BFI(x1, x14, 9, 1);
// set C3 = Q1
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 14, 1);
// Set C0 = Q2
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 8, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
#endif
break;
case 0xF6:
INST_NAME("FDECSTP");
@@ -357,6 +397,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SUB_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// should set C1 to 0
break;
case 0xF7:
INST_NAME("FINCSTP");
@@ -365,13 +406,40 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// should set C1 to 0
break;
case 0xF8:
INST_NAME("FPREM");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_double(dyn);
VDIV_F64(s0, v1, v2);
VCVT_S32_F64(s0*2, s0); // => Q
// get Q
VMOVfrV(x14, s0*2);
// Put back Q in a double
VCVT_F64_S32(s0, s0*2);
VMUL_F64(s0, s0, v2);
VSUB_F64(v1, v1, s0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
// set C2 = 0
BFC(x1, 10, 1);
// set C1 = Q0
BFI(x1, x14, 9, 1);
// set C3 = Q1
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 14, 1);
// Set C0 = Q2
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 8, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
#endif
break;
case 0xF9:
INST_NAME("FYL2XP1");
@@ -382,21 +450,56 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VSQRT_F32(v1, v1);
} else {
VSQRT_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xFB:
INST_NAME("FSINCOS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_64(0, v1);
CALL_1D(sin, 0);
VSWP(v1, 0);
CALL_1D(cos, 0);
CALL_1D(cos, 0); // would it be faster to do sqrt(1-sin()²) ???
VMOV_64(v2, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
case 0xFC:
INST_NAME("FRNDINT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
if(!arm_v8) {
// check if finite first
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
// load round mode
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x2, x1, 10, 2); // extract round...
MOV32(x1, round_map);
LDR_REG_LSL_IMM5(x2, x1, x2, 2);
VMOV_64(0, v1); // prepare call to fpu_round
CALL_1DR(x2, x3, 0);
VMOV_64(v1, 0);
} else {
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VRINTR_F64(v1, v1);
x87_restoreround(dyn, ninst, u8);
}
// should set C1 to 0
break;
case 0xFD:
INST_NAME("FSCALE");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
@@ -406,9 +509,15 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cEQ);
VMOV_64(0, v2);
CALL_1DD(trunc, exp2, 0);
if(!arm_v8) {
VMOV_64(0, v2);
CALL_1DD(trunc, exp2, 0);
} else {
VRINTZ_F64(0, v2);
CALL_1D(exp2, 0);
}
VMUL_F64(v1, v1, 0);
// should set C1 to 0
break;
case 0xFE:
INST_NAME("FSIN");
@@ -416,9 +525,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOV_64(0, v1); // prepare call to sin
CALL_1D(sin, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
case 0xFF:
@@ -427,9 +536,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOV_64(0, v1); // prepare call to cos
CALL_1D(cos, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
@@ -459,7 +568,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else
@@ -476,6 +585,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(!ST_IS_F(0)) {
VCVT_F64_F32(v1, s0);
}
// should set C1 to 0
break;
case 2:
INST_NAME("FST float[ED], ST0");
+85 -4
View File
@@ -122,9 +122,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE2:
INST_NAME("FNCLEX");
LDRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
MOVW(x1, 0);
BFI(x2, x1, 0, 8); // IE .. PE, SF, ES
BFI(x2, x1, 15, 1); // B
BFC(x2, 0, 8); // IE .. PE, SF, ES
BFC(x2, 15, 1); // B
STRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
break;
case 0xE3:
@@ -230,7 +229,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
ed = x1;
ed = x1; // will not be writen immediatly, so x1 is safe for now
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
@@ -289,16 +288,49 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x3, ed, 4);
STRH_IMM8(x14, ed, 8);
} else {
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
#endif
}
break;
case 7:
INST_NAME("FSTP tbyte");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
@@ -306,6 +338,55 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
x87_do_pop(dyn, ninst, x3);
break;
default:
+5 -15
View File
@@ -80,17 +80,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
INST_NAME("FSTP ST0, STx");
// copy the cache value for st0 to stx
i1 = x87_get_cache(dyn, ninst, 0, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
// swap those too
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
i3 = dyn->n.neoncache[i1].v;
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
dyn->n.neoncache[i2].v = i3;
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
@@ -231,12 +221,12 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
if(dyn->x87stack) {
if(dyn->n.x87stack) {
// update top
if(dyn->x87stack>0) {
SUB_IMM8(x2, x2, dyn->x87stack);
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->x87stack);
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
+60 -26
View File
@@ -23,7 +23,7 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static const void* round_map[4] = {arm_fist64_0, arm_fist64_1, arm_fist64_2, arm_fist64_3};
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
@@ -31,7 +31,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t j32;
uint8_t wback;
uint8_t ed;
int v0, v1, v2;
int /*v0, */v1, v2;
int s0;
int fixedaddress;
int parity;
@@ -39,7 +39,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(v0);
//MAYUSE(v0);
MAYUSE(j32);
switch(nextop) {
@@ -60,12 +60,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FNSTSW AX");
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
if(dyn->x87stack) {
if(dyn->n.x87stack) {
// update top
if(dyn->x87stack>0) {
SUB_IMM8(x2, x2, dyn->x87stack);
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->x87stack);
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
@@ -281,41 +281,39 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
MESSAGE(LOG_DUMP, "Hack for FILD/FISTP i64");
} else {
// Save xFlags to use it as scratch...
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
// set STll(0).ll=i64 and ref=ST(0).q later (emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top])
// get TOP
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->x87stack;
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(xFlags, xFlags, -a);
AND_IMM8(xFlags, xFlags, 7);
SUB_IMM8(x1, x1, -a);
AND_IMM8(x1, x1, 7);
} else if(a>0) {
ADD_IMM8(xFlags, xFlags, a);
AND_IMM8(xFlags, xFlags, 7);
ADD_IMM8(x1, x1, a);
AND_IMM8(x1, x1, 7);
}
ADD_REG_LSL_IMM5(xFlags, xEmu, xFlags, 4); // each fpu_ll is 2 int64: ref than ll
ADD_IMM8_ROR(xFlags, xFlags, offsetof(x86emu_t, fpu_ll)>>2, 15);
STRD_IMM8(x2, xFlags, 8); // save ll
// ed (and so x1) is not use anymore.
ADD_REG_LSL_IMM5(x1, xEmu, x1, 4); // each fpu_ll is 2 int64: ref than ll
ADD_IMM8_ROR(x1, x1, offsetof(x86emu_t, fpu_ll)>>2, 15);
STRD_IMM8(x2, x1, 8); // save ll
// continue with conversion
MOVS_REG_LSR_IMM5(x14, x3, 31); // x14 is sign bit
B_MARK(cEQ); // no NEG is no sign bit
RSBS_IMM8(x2, x2, 0);
RSC_IMM8(x3, x3, 0);
MARK;
VMOVtoV(s0, x3);
VMOVtoV(s0, x3); // last time x3 is used
VCVT_F64_U32(v1, s0);
VEOR(v2, v2, v2);
MOVW(x1, 0x41F0);
VMOVtoDx_16(v2, 3, x1);
MOVW(x3, 0x41F0);
VMOVtoDx_16(v2, 3, x3);
VMUL_F64(v1, v1, v2); // v1 = double high part of i64
VMOVtoV(s0, x2);
VCVT_F64_U32(v2, s0);
VADD_F64(v1, v1, v2);
TSTS_IMM8(x14, 1);
VNEG_F64_cond(cNE, v1, v1);
VST1_64(v1, xFlags); // Store STll(0).ref
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
VST1_64(v1, x1); // Store STll(0).ref
}
break;
case 6:
@@ -343,16 +341,51 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x3, ed, 4);
}
} else {
#if 0
v1 = x87_get_st(dyn, ninst, x2, x3, 0);
#if 1
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
fpu_get_scratch_double(dyn); // to alocate v0
v2 = fpu_get_scratch_double(dyn);
#if 1
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
} else if(a>0) {
ADD_IMM8(x14, x14, a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x14, xEmu, x14, 4); // each fpu_ll is 2 int64: ref than ll
MOVW(x2, offsetof(x86emu_t, fpu_ll)); //can be optimized?
ADD_REG_LSL_IMM5(x14, x14, x2, offsetof(fpu_ll_t, sref));
VLDR_64(v2, x14, 0);
VCEQ_32(v2, v2, v1); // compare
VMOVfrV_D(x2, x3, v2);
ANDS_REG_LSL_IMM5(x2, x2, x3, 0); // if NE then values are the same!
B_MARK(cEQ); // do the i64 conversion
// memcpy(ed, &STll(0).ll, sizeof(int64_t));
LDRD_IMM8(x2, x14, offsetof(fpu_ll_t, sq)); // load ll
B_MARK3(c__);
MARK;
// load round mode
LDRH_IMM8(x14, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x2, x14, 10, 2); // extract round...
MOV32(x14, round_map);
LDR_REG_LSL_IMM5(x2, x14, x2, 2);
VMOV_64(0, v1); // prepare call to log2
CALL_1DR_U64(x2, x2, x3, x14, (1<<x1));
MARK3;
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
#else
v0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
// check STll(0).ref==ST(0).q so emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top]
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->x87stack;
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
@@ -407,6 +440,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK3;
STR_IMM9(x2, x1, 0);
STR_IMM9(x3, x1, 4);
#endif
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x2, x3, 0);
+64
View File
@@ -469,6 +469,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
int j32;
MAYUSE(j32);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
@@ -521,6 +522,69 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SHLD32 instruction, from s1, fill s2 , shift s3, store result in s1 using s4 and s3 as scratch
void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
int j32;
MAYUSE(j32);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shl32
SET_DF(s4, d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
CMPS_IMM8(s3, 0);
IFX(F_OF) {
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PEND) {
STR_IMM9_COND(cEQ, s1, xEmu, offsetof(x86emu_t, res));
}
B_NEXT(cEQ);
IFX(X_CF) {
RSB_IMM8(s4, s3, 32);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
MOVS_REG_LSL_REG(s1, s1, s3);
} else {
MOV_REG_LSL_REG(s1, s1, s3);
}
IFX(X_OF) {
MOVW_COND(cCS, s4, 1);
MOVW_COND(cCC, s4, 0);
CMPS_IMM8(s3, 1);
ORR_REG_LSR_IMM5_COND(cEQ, s4, s4, s1, 30);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
//else
BFC_COND(cNE, xFlags, F_OF, 1);
}
RSB_IMM8(s3, s3, 32);
IFX(X_ZF) {
ORRS_REG_LSR_REG(s1, s1, s2, s3);
} else {
ORR_REG_LSR_REG(s1, s1, s2, s3);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ROL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
+3 -4
View File
@@ -374,7 +374,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch. May destroy s2 also
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX_PENDOR0 {
@@ -401,10 +401,9 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
AND_IMM8(s2, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
LDR_REG_LSR_IMM5(s4, s4, s2, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
+57 -46
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
@@ -351,6 +352,10 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
DMB_ISH();
break;
case 0x66:
return dynarec66F0(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x81:
case 0x83:
@@ -637,7 +642,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK3;
DMB_ISH();
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
UFLAG_IF {emit_cmp8(dyn, ninst, x1, x2, x3, x14);}
break;
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
@@ -678,16 +683,16 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_IMM8(wback, 3); // anoying, all those test
STR_IMM9_COND(cNE, gd, wback, 0);
}
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);}
} else {
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);}
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, x14);
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);}
MOV_REG(xEAX, ed);
MARK3
DMB_ISH();
@@ -936,48 +941,54 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC7:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDREX_COND(cNE, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
} else {
LDREXD(x2, wback);
switch((nextop>>3)&7) {
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
LDREX_COND(cNE, x2, wback);
} else {
LDREXD(x2, wback);
}
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);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x14, x2, wback);
STREX_COND(cNE, x14, x2, wback);
} else {
STREXD(x14, x2, wback);
}
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
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;
DMB_ISH();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
DEFAULT;
}
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);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x14, x2, wback);
STREX_COND(cNE, x14, x2, wback);
} else {
STREXD(x14, x2, wback);
}
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
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;
DMB_ISH();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
@@ -993,7 +1004,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x14);
@@ -1030,7 +1041,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x14);
+67
View File
@@ -40,6 +40,10 @@
} \
}
#define GETGM(a) \
gd = (nextop&0x38)>>3; \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
@@ -159,7 +163,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSQRT_F64(v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
}
break;
case 0x58:
@@ -168,7 +183,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
}
break;
case 0x59:
INST_NAME("MULSD Gx, Ex");
@@ -176,7 +202,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
}
break;
case 0x5A:
INST_NAME("CVTSD2SS Gx, Ex");
@@ -200,7 +237,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
}
break;
case 0x5D:
INST_NAME("MINSD Gx, Ex");
@@ -219,7 +267,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
}
break;
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
@@ -311,6 +370,14 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoV_D(v0, x2, x2);
break;
case 0xD6:
INST_NAME("MOVDQ2Q Gm, Ex");
nextop = F8;
GETGM(v0);
GETEX(v1, 0);
VMOV_64(v0, v1);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
+45 -7
View File
@@ -50,6 +50,9 @@
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETGX_empty(a) gd = ((nextop&0x38)>>3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
@@ -98,10 +101,17 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
VEORQ(v0, v0, v0);
VMOVtoDx_32(v0, 0, x2);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity && (v0<16)) {
VEORQ(v0, v0, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0);
VLDR_32(v0*2, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
VEORQ(v0, v0, v0);
VMOVtoDx_32(v0, 0, x2);
}
}
break;
case 0x11:
@@ -128,9 +138,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(q0, d1);
}
} else {
VMOVfrDx_32(x2, v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
STR_IMM9(x2, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity && (v0<16)) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0);
VSTR_32(v0*2, ed, fixedaddress);
} else {
VMOVfrDx_32(x2, v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
STR_IMM9(x2, ed, fixedaddress);
}
}
break;
case 0x12:
@@ -614,6 +630,28 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoDx_32(v0, 0, x2);
break;
case 0xD6:
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX_empty(v0);
if((nextop&0xC0)==0xC0) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VEORQ(v0, v0, v0); // usefull?
VMOV_64(v0, v1);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
}
}
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
+351 -93
View File
@@ -8,6 +8,7 @@
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include "debug.h"
#include "box86context.h"
@@ -66,12 +67,12 @@ void arm_fxtract(x86emu_t* emu)
}
void arm_fprem(x86emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
int64_t tmp64s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp64s;
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);
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
}
void arm_frndint(x86emu_t* emu)
{
@@ -116,6 +117,43 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
}
}
int64_t arm_fist64_0(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = nearbyint(d);
return tmp;
}
int64_t arm_fist64_1(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = floor(d);
return tmp;
}
int64_t arm_fist64_2(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = ceil(d);
return tmp;
}
int64_t arm_fist64_3(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = trunc(d);
return tmp;
}
void arm_fistt64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
@@ -126,7 +164,7 @@ void arm_fistt64(x86emu_t* emu, int64_t* ed)
void arm_fld(x86emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
}
@@ -142,7 +180,7 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
D2LD(&ST(i).d, p);
p+=10;
}
}
@@ -153,7 +191,7 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
LD2D(p, &ST(i).d);
p+=10;
}
@@ -162,48 +200,48 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
int64_t tmp64s = lrint(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp64s;
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);
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
{
return dyn->fpu_scratch++; // return an Sx
return dyn->n.fpu_scratch++; // return an Sx
}
// Get a FPU double scratch reg
int fpu_get_scratch_double(dynarec_arm_t* dyn)
{
int i = (dyn->fpu_scratch+1)&(~1);
dyn->fpu_scratch = i+2;
int i = (dyn->n.fpu_scratch+1)&(~1);
dyn->n.fpu_scratch = i+2;
return i/2; // return a Dx
}
// 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) {
if(dyn->n.fpu_scratch>4) {
if(dyn->n.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, NEON_CACHE_SCR, 0);
return dyn->fpu_extra_qscratch;
dyn->n.fpu_extra_qscratch = fpu_get_reg_quad(dyn, NEON_CACHE_SCR, 0);
return dyn->n.fpu_extra_qscratch;
}
int i = (dyn->fpu_scratch+3)&(~3);
dyn->fpu_scratch = i+4;
int i = (dyn->n.fpu_scratch+3)&(~3);
dyn->n.fpu_scratch = i+4;
return i/2; // Return a Dx, not a Qx
}
// Reset scratch regs counter
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;
dyn->n.fpu_scratch = 0;
if(dyn->n.fpu_extra_qscratch) {
fpu_free_reg_quad(dyn, dyn->n.fpu_extra_qscratch);
dyn->n.fpu_extra_qscratch = 0;
}
}
// Get a FPU double reg
@@ -211,10 +249,13 @@ int fpu_get_reg_double(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
{
// TODO: check upper limit?
int i=0;
while (dyn->fpuused[i]) ++i;
dyn->fpuused[i] = 1;
while (dyn->n.fpuused[i] && (i<24)) ++i;
assert(i<24);
dyn->n.fpuused[i] = 1;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i].t = t;
dyn->n.news |= (1<<i);
return i+FPUFIRST; // return a Dx
}
// Free a FPU double reg
@@ -222,7 +263,7 @@ void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
int i=reg-FPUFIRST;
dyn->fpuused[i] = 0;
dyn->n.fpuused[i] = 0;
if(dyn->n.neoncache[i].t!=NEON_CACHE_ST_F && dyn->n.neoncache[i].t!=NEON_CACHE_ST_D)
dyn->n.neoncache[i].v = 0;
}
@@ -230,36 +271,42 @@ void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
int fpu_get_reg_quad(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
{
int i=0;
while (dyn->fpuused[i] || dyn->fpuused[i+1]) i+=2;
dyn->fpuused[i] = dyn->fpuused[i+1] = 1;
while ((dyn->n.fpuused[i] || dyn->n.fpuused[i+1]) && (i<24)) i+=2;
assert(i<24);
dyn->n.fpuused[i] = dyn->n.fpuused[i+1] = 1;
dyn->n.neoncache[i].t = t;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i+1].t = t;
dyn->n.neoncache[i+1].n = n;
dyn->n.news |= (3<<i);
return i+FPUFIRST; // Return a Dx, not a Qx
}
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
{
int i=reg-FPUFIRST;
dyn->fpuused[i] = dyn->fpuused[i+1] = 0;
dyn->n.fpuused[i] = dyn->n.fpuused[i+1] = 0;
dyn->n.neoncache[i].v = 0;
dyn->n.neoncache[i+1].v = 0;
}
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->fpu_reg = 0;
dyn->n.fpu_reg = 0;
for (int i=0; i<24; ++i) {
dyn->fpuused[i]=0;
dyn->n.fpuused[i]=0;
dyn->n.neoncache[i].v = 0;
}
}
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
{
if(!dyn->insts)
return NEON_CACHE_ST_D;
if (dyn->insts[ninst].n.swapped) {
if(dyn->insts[ninst].n.combined1 == a)
a = dyn->insts[ninst].n.combined2;
else if(dyn->insts[ninst].n.combined2 == a)
a = dyn->insts[ninst].n.combined1;
}
for(int i=0; i<24; ++i)
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
@@ -283,114 +330,141 @@ int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a)
return NEON_CACHE_ST_D;
}
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st)
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
{
if(a+dyn->insts[ninst].n.stack_next-st<0)
/*if(a+dyn->insts[ninst].n.stack_next-st<0)
// The STx has been pushed at the end of instructon, so stop going back
return -1;
return -1;*/
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a, int st)
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
{
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a, int st)
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
{
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->n.neoncache[i].n==a+dyn->n.stack-st)
&& dyn->n.neoncache[i].n==a)
return i;
return -1;
}
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
if(a == dyn->insts[ninst].n.combined1) {
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined2, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined2 %d i=%d\n", ninst, dyn->insts[ninst].n.combined2 ,i);
if(a == dyn->insts[ninst].n.combined1 || a == dyn->insts[ninst].n.combined2) {
if(a == dyn->insts[ninst].n.combined1) {
a = dyn->insts[ninst].n.combined2;
} else
a = dyn->insts[ninst].n.combined1;
int i = neoncache_get_st_f_noback(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_combined, ninst=%d combined%c %d i=%d (stack:%d/%d)\n", ninst, (a == dyn->insts[ninst].n.combined2)?'2':'1', a ,i, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined2, st);
if(!dyn->insts[ninst].n.barrier)
neoncache_promote_double_internal(dyn, ninst-1, maxinst, a-dyn->insts[ninst].n.stack_push);
// go forward is combined is not pop'd
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined2)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined2, st);
}
} else if(a == dyn->insts[ninst].n.combined2) {
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined1, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined1 %d i=%d\n", ninst, dyn->insts[ninst].n.combined1 ,i);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined1, st);
// go forward is combined is not pop'd
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined1)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined1, st);
if(a-dyn->insts[ninst].n.stack_pop>=0)
if(!dyn->insts[ninst+1].n.barrier)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, a-dyn->insts[ninst].n.stack_pop);
}
}
}
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
if(dyn->insts[ninst+1].n.barrier)
return;
while(ninst>=0) {
int i = neoncache_get_st_f(dyn, ninst, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
a+=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: add pop'd ST (going backward)
int i = neoncache_get_st_f(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d, i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->insts[ninst].n.stack-st; // adjust STx
st = dyn->insts[ninst].n.stack; // new stack depth
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
if(dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
} else {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
}
a-=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: remove push'd ST (going backward)
--ninst;
if(ninst<0 || a<0 || dyn->insts[ninst].n.barrier)
return;
}
}
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
while(ninst<maxinst) {
int i = neoncache_get_st_f_noback(dyn, ninst, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
while((ninst!=-1) && (ninst<maxinst) && (a>=0)) {
a+=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: add push'd ST (going forward)
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
}
int i = neoncache_get_st_f_noback(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d(%d/%d), i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->insts[ninst].n.stack-st; // adjust STx
st = dyn->insts[ninst].n.stack; // new stack depth
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && !dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
++ninst;
a-=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: remove pop'd ST (going forward)
if(dyn->insts[ninst].x86.has_next && !dyn->insts[ninst].n.barrier)
++ninst;
else
ninst=-1;
}
neoncache_promote_double(dyn, ninst, a, st);
if(ninst==maxinst)
neoncache_promote_double(dyn, ninst, a);
}
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st)
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a)
{
int i = neoncache_get_current_st_f(dyn, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d/%d i=%d\n", ninst, a, st, dyn->n.stack, i);
int i = neoncache_get_current_st_f(dyn, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d i=%d\n", ninst, a, dyn->n.stack, i);
if(i<0) return;
dyn->n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->n.stack-st;
st = dyn->n.stack;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if(dyn->n.combined1 || dyn->n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined2, st);
else if(dyn->n.combined2 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined1, st);
if(dyn->n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d swapped! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
a = dyn->n.combined2;
else if(dyn->n.combined2 == a)
a = dyn->n.combined1;
} else {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined2);
else if(dyn->n.combined2 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined1);
}
}
if(!ninst) return;
neoncache_promote_double_internal(dyn, ninst-1, ninst, a, st);
a-=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: remove push'd ST (going backward)
if(!ninst || a<0) return;
neoncache_promote_double_internal(dyn, ninst-1, ninst, a);
}
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
@@ -403,6 +477,158 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
return NEON_CACHE_ST_D;
}
int isPred(dynarec_arm_t* dyn, int ninst, int pred) {
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
if(dyn->insts[ninst].pred[i]==pred)
return pred;
return -1;
}
int getNominalPred(dynarec_arm_t* dyn, int ninst) {
if((ninst<=0) || !dyn->insts[ninst].pred_sz)
return -1;
if(isPred(dyn, ninst, ninst-1)!=-1)
return ninst-1;
return dyn->insts[ninst].pred[0];
}
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int i2 = dyn->insts[ninst].x86.jmp_insts;
if(i2<0)
return 1;
if((dyn->insts[i2].x86.barrier&BARRIER_FLOAT))
return ((dyn->insts[ninst].x86.barrier&BARRIER_FLOAT))?0:1; // if the barrier as already been apply, no transform needed
int ret = 0;
if(!i2) { // just purge
if(dyn->insts[ninst].n.stack_next) {
return 1;
}
for(int i=0; i<24 && !ret; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
ret = 1;
}
return ret;
}
// Check if ninst can be compatible to i2
if(dyn->insts[ninst].n.stack_next != dyn->insts[i2].n.stack-dyn->insts[i2].n.stack_push) {
return 1;
}
neoncache_t cache_i2 = dyn->insts[i2].n;
neoncacheUnwind(&cache_i2);
for(int i=0; i<24; ++i) {
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!cache_i2.neoncache[i].v) { // but there is nothing at i2 for i
ret = 1;
} else if(dyn->insts[ninst].n.neoncache[i].v!=cache_i2.neoncache[i].v) { // there is something different
if(dyn->insts[ninst].n.neoncache[i].n!=cache_i2.neoncache[i].n) { // not the same x86 reg
ret = 1;
}
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_XMMR && cache_i2.neoncache[i].t == NEON_CACHE_XMMW)
{/* nothing */ }
else
ret = 1;
}
} else if(cache_i2.neoncache[i].v)
ret = 1;
}
return ret;
}
void neoncacheUnwind(neoncache_t* cache)
{
if(cache->swapped) {
// unswap
int a = -1;
int b = -1;
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if(cache->neoncache[j].n == cache->combined1)
a = j;
else if(cache->neoncache[j].n == cache->combined2)
b = j;
}
if(a!=-1 && b!=-1) {
int tmp = cache->neoncache[a].n;
cache->neoncache[a].n = cache->neoncache[b].n;
cache->neoncache[b].n = tmp;
}
cache->swapped = 0;
cache->combined1 = cache->combined2 = 0;
}
if(cache->news) {
// reove the newly created neoncache
for(int i=0; i<24; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
cache->news = 0;
}
if(cache->stack_push) {
// unpush
for(int j=0; j<24; ++j) {
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if(cache->neoncache[j].n<cache->stack_push)
cache->neoncache[j].v = 0;
else
cache->neoncache[j].n-=cache->stack_push;
}
}
cache->x87stack-=cache->stack_push;
cache->stack-=cache->stack_push;
cache->stack_push = 0;
}
cache->x87stack+=cache->stack_pop;
cache->stack_next = cache->stack;
cache->stack_pop = 0;
cache->barrier = 0;
// And now, rebuild the x87cache info with neoncache
cache->mmxcount = 0;
cache->fpu_scratch = 0;
cache->fpu_extra_qscratch = 0;
cache->fpu_reg = 0;
for(int i=0; i<8; ++i) {
cache->x87cache[i] = -1;
cache->mmxcache[i] = -1;
cache->ssecache[i].v = -1;
cache->x87reg[i] = 0;
}
int x87reg = 0;
for(int i=0; i<24; ++i) {
if(cache->neoncache[i].v) {
cache->fpuused[i] = 1;
switch (cache->neoncache[i].t) {
case NEON_CACHE_MM:
cache->mmxcache[cache->neoncache[i].n] = i+FPUFIRST;
++cache->mmxcount;
++cache->fpu_reg;
break;
case NEON_CACHE_XMMR:
case NEON_CACHE_XMMW:
cache->ssecache[cache->neoncache[i].n].reg = i+FPUFIRST;
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
++cache->fpu_reg;
++i; // next next
break;
case NEON_CACHE_ST_F:
case NEON_CACHE_ST_D:
cache->x87cache[x87reg] = cache->neoncache[i].n;
cache->x87reg[x87reg] = i+FPUFIRST;
++x87reg;
++cache->fpu_reg;
break;
case NEON_CACHE_SCR:
cache->fpuused[i] = 0;
cache->neoncache[i].v = 0;
break;
}
} else {
cache->fpuused[i] = 0;
}
}
}
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
@@ -496,3 +722,35 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
#undef PK
}
const char* getCacheName(int t, int n)
{
static char buff[20];
switch(t) {
case NEON_CACHE_ST_D: sprintf(buff, "ST%d", n); break;
case NEON_CACHE_ST_F: sprintf(buff, "st%d", n); break;
case NEON_CACHE_MM: sprintf(buff, "MM%d", n); break;
case NEON_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case NEON_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
case NEON_CACHE_SCR: sprintf(buff, "Scratch"); break;
case NEON_CACHE_NONE: buff[0]='\0'; break;
}
return buff;
}
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst)
{
// check flags cache
if(dyn->insts[ninst].f_entry.dfnone || dyn->insts[ninst].f_entry.pending)
return 0;
if(dyn->insts[ninst].x86.state_flags)
return 0;
// check neoncache
neoncache_t* n = &dyn->insts[ninst].n;
if(n->news || n->stack || n->stack_next)
return 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].v)
return 0;
return 1;
}
+25 -2
View File
@@ -23,6 +23,11 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
int64_t arm_fist64_0(double d);
int64_t arm_fist64_1(double d);
int64_t arm_fist64_2(double d);
int64_t arm_fist64_3(double d);
void arm_ud(x86emu_t* emu);
#define FPUFIRST 8
@@ -50,13 +55,29 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
// Get type for STx
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a);
// Get if STx is FLOAT or DOUBLE
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st);
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a);
// Get actual type for STx
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a);
// Get actual STx is FLOAT or DOUBLE
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a);
// Back-propagate a change float->double
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st);
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
// Combine and propagate if needed (pass 1 only)
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
// FPU Cache transformation (for loops)
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int i1);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_arm_t* dyn, int ninst, int pred);
int getNominalPred(dynarec_arm_t* dyn, int ninst);
// 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);
// Do the GETED, but don't emit anything...
@@ -65,4 +86,6 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// 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);
const char* getCacheName(int t, int n);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
File diff suppressed because it is too large. Load diff
+60 -23
View File
@@ -76,7 +76,8 @@
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, O, 0);\
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
ed = x1; \
}
@@ -153,8 +154,9 @@
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
if(wback!=x3) wback = x3; \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
@@ -211,6 +213,12 @@
#define CALL_2D(F, M) call_d(dyn, ninst, F, NULL, 2, x3, -1, M, 0)
// CALL_1DD will use x3 for the call address. Return value in D0, 1 ARG in D0, cals 2 functions in a row
#define CALL_1DD(F, F2, M) call_d(dyn, ninst, F, F2, 1, x3, -1, M, 0)
// CALL_1D_U64 will use S as scratch. Return value in ret/ret2, 1 ARG in D0
#define CALL_1DR_U64(R, ret, ret2, S, M) call_dr(dyn, ninst, R, 1, S, ret, ret2, M, 1)
// CALL_1D will use S as scratch. Return value in D0, 1 ARG in D0
#define CALL_1DR(R, S, M) call_dr(dyn, ninst, R, 1, S, -1, -1, M, 0)
// CALL_1RD will use S as scratch. Return value in D0, 1 ARG in R
#define CALL_1RD(F, R, S, M) call_rd(dyn, ninst, F, R, S, M, 0);
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
@@ -239,7 +247,7 @@
Bcond(cond, j32)
// Branch to next instruction if cond (use j32)
#define B_NEXT(cond) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
j32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
@@ -284,15 +292,16 @@
} \
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->dfnone = 0
#define SET_DFOK() dyn->dfnone = 1
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
if(dyn->state_flags!=SF_PENDING) { \
if((dyn->f.pending!=SF_SET) \
&& (dyn->f.pending!=SF_SET_PENDING)) { \
if(dyn->f.pending!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
j32 = (GETMARKF)-(dyn->arm_size+8); \
@@ -300,16 +309,28 @@
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
dyn->f.pending = SF_SET; \
SET_DFOK(); \
}
#endif
// SF_MAYSET doesn't change the flags status cache
// it also doesn't consume any needed flags
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)/*|X_PEND*/)))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
((B==SF_SET_PENDING && !(dyn->insts[ninst].x86.need_flags&X_PEND)?SF_SET:B))
#define SETFLAGS(A, B) \
if(dyn->f.pending!=SF_SET \
&& (B==SF_SUBSET || B==SF_SUBSET_PENDING) \
&& (dyn->insts[ninst].x86.need_flags&(~((A)|((B==SF_SUBSET_PENDING)?X_PEND:0))))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
if(dyn->insts[ninst].x86.need_flags) switch(B) { \
case SF_SUBSET: \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SUBSET_PENDING: \
case SF_SET_PENDING: \
dyn->f.pending = (dyn->insts[ninst].x86.need_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
break; \
case SF_MAYSET: break; \
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
@@ -327,10 +348,7 @@
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x86.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
#ifndef NEW_BARRIER_INST
#define NEW_BARRIER_INST
#define DEFAULT *ok = -1; BARRIER(BARRIER_NOFLAGS)
#endif
#if STEP < 2
@@ -368,6 +386,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define dynarecDF STEPNAME(dynarecDF)
#define dynarecF0 STEPNAME(dynarecF0)
#define dynarec660F STEPNAME(dynarec660F)
#define dynarec66F0 STEPNAME(dynarec66F0)
#define dynarecF20F STEPNAME(dynarecF20F)
#define dynarecF30F STEPNAME(dynarecF30F)
@@ -380,6 +399,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define call_d STEPNAME(call_d_)
#define call_dr STEPNAME(call_dr_)
#define call_rd STEPNAME(call_rd_)
#define grab_fsdata STEPNAME(grab_fsdata_)
#define grab_tlsdata STEPNAME(grab_tlsdata_)
#define emit_cmp8 STEPNAME(emit_cmp8)
@@ -454,6 +475,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
#define emit_shld32 STEPNAME(emit_shld32)
#define emit_pf STEPNAME(emit_pf)
@@ -471,6 +493,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_restoreround STEPNAME(x87_restoreround)
#define x87_swapreg STEPNAME(x87_swapreg)
#define sse_setround STEPNAME(sse_setround)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
@@ -492,6 +515,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
// put back (if needed) the single reg in place
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
#define fpuCacheTransform STEPNAME(fpuCacheTransform)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly);
@@ -507,10 +532,10 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
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, int saveflags);
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags);
void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int ret2, uint32_t mask, int saveflags);
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags);
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);
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);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
@@ -583,6 +608,7 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
@@ -615,9 +641,19 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// swap 2 x87 regs
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#if STEP < 2
#define CHECK_CACHE() 0
#else
#define CHECK_CACHE() fpuCacheNeedsTransform(dyn, ninst)
#endif
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
@@ -656,7 +692,7 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn, int ninst);
void fpu_reset(dynarec_arm_t* dyn);
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
@@ -688,6 +724,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
+116 -19
View File
@@ -36,15 +36,71 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
dyn->dfnone = 0;
fpu_reset(dyn, ninst);
dyn->f.pending = 0;
dyn->f.dfnone = 0;
fpu_reset(dyn);
int reset_n = -1;
// ok, go now
INIT;
while(ok) {
ip = addr;
if((dyn->insts[ninst].x86.barrier==1)) {
NEW_BARRIER_INST;
if (reset_n!=-1) {
if(reset_n==-2) {
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
} else {
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
#if STEP > 1
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
dyn->n = dyn->insts[ninst].n;
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
if(box86_dynarec_dump)
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
for(int i=0; i<24; ++i)
if(dyn->insts[reset_n].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
MESSAGE(LOG_DEBUG, " ==> ");
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
MESSAGE(LOG_DEBUG, " -> ");
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
if(dyn->n.combined1 || dyn->n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
if(dyn->n.stack_push || dyn->n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
dyn->f = dyn->insts[reset_n].f_exit;
if(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT) {
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
fpu_reset(dyn);
}
if(dyn->insts[ninst].x86.barrier&BARRIER_FLAGS) {
MESSAGE(LOG_DEBUG, "Apply Barrier Flags\n");
dyn->f.dfnone = 0;
dyn->f.pending = 0;
}
}
reset_n = -1;
}
// propagate ST stack state, especial stack pop that are defered
if(dyn->n.stack_pop) {
@@ -58,6 +114,9 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->n.stack_pop = 0;
}
dyn->n.stack = dyn->n.stack_next;
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
NEW_INST;
fpu_reset_scratch(dyn);
#ifdef HAVE_TRACE
@@ -80,43 +139,81 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INST_EPILOG;
if(dyn->insts[ninst+1].x86.barrier) {
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if(dyn->insts[ninst+1].x86.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
int next = ninst+1;
#if STEP > 0
if(!dyn->insts[ninst].x86.has_next && dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts!=-1)
next = dyn->insts[ninst].x86.jmp_insts;
#endif
if(dyn->insts[ninst].x86.has_next && dyn->insts[next].x86.barrier) {
if(dyn->insts[next].x86.barrier&BARRIER_FLOAT)
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if(dyn->insts[next].x86.barrier&BARRIER_FLAGS) {
dyn->f.pending = 0;
dyn->f.dfnone = 0;
}
}
#if STEP != 0
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
++ii;
if((dyn->insts[ii].x86.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are availble
if(reset_n==-1) {
reset_n = -2;
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
}
}
}
#if STEP == 0
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3))
#else
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM)
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
reset_n = -2;
for(int ii=0; ii<ninst; ++ii)
if(dyn->insts[ii].x86.jmp == next) {
reset_n = ii;
ii=ninst;
}
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
} else if(next && (next-addr)<30) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
if(ok && !isJumpTableDefault((void*)addr))
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
(ok && dyn->size >= 2000))
#else
if(ok && (ninst==dyn->size))
#endif
{
#if STEP == 3
dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
--ninst;
if(!dyn->insts[ninst].x86.barrier) {
BARRIER(BARRIER_FLOAT);
}
#if STEP == 0
if(dyn->insts[ninst].x86.set_flags)
dyn->insts[ninst].x86.default_need |= X_PEND;
else
dyn->insts[ninst].x86.use_flags |= X_PEND;
#endif
BARRIER(2);
++ninst;
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
+21 -7
View File
@@ -5,12 +5,20 @@
dyn->insts[ninst].x86.addr = addr;\
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
#define MESSAGE(A, ...)
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
#define READFLAGS(A) \
dyn->insts[ninst].x86.use_flags = A; dyn->f.dfnone = 1;\
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x86.set_flags = A; \
if(B!=SF_MAYSET) { \
dyn->insts[ninst].x86.state_flags = B; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0; \
}
#define EMIT(A)
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)(A)); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
@@ -19,14 +27,20 @@
dyn->cap *= 2; \
} \
dyn->insts[ninst].x86.addr = ip; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0; \
dyn->insts[ninst].f_entry = dyn->f; \
if(ninst) {dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;}
#define INST_EPILOG
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].x86.has_next = ok;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO) {\
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
+7 -4
View File
@@ -2,11 +2,14 @@
#define FINI
#define MESSAGE(A, ...)
#define EMIT(A)
#define READFLAGS(A)
#define SETFLAGS(A,B)
#define NEW_INST dyn->n.combined1 = dyn->n.combined2 = 0
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0
#define INST_EPILOG dyn->insts[ninst].n = dyn->n
#define INST_EPILOG \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].f_exit = dyn->f
#define INST_NAME(name)
+6 -2
View File
@@ -3,7 +3,11 @@
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
#define NEW_INST if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
if(ninst && isInstClean(dyn, ninst)) \
++dyn->sons_size; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
+31 -22
View File
@@ -7,46 +7,55 @@
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
#define NEW_INST \
if(ninst && isInstClean(dyn, ninst)) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block); \
++dyn->sons_size; \
}
#define INST_EPILOG
#define INST_NAME(name) \
if(box86_dynarec_dump) {\
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d, set=%X, use=%X, need=%X", \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), set=%X, use=%X, need=%X", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
ninst, \
dyn->insts[ninst].x86.barrier, \
dyn->insts[ninst].x86.state_flags, \
dyn->state_flags, \
dyn->f.pending, \
dyn->f.dfnone, \
dyn->insts[ninst].x86.set_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_flags); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);\
} \
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)\
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);\
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)\
dynarec_log(LOG_NONE, ", jmp=out");\
for(int ii=0; ii<24; ++ii) { \
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:ST%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:st%d", (ii+8)*2, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:MM%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:XMM%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:xmm%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:Scratch", ii+8); break; \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_NONE: \
default: break; \
} \
} \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next) \
printf_log(LOG_NONE, " X87:%d/%d", dyn->n.stack, dyn->insts[ninst].n.stack_next);\
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
printf_log(LOG_NONE, " CMB:%d/%d", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
}
#define NEW_BARRIER_INST \
if(ninst) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here\n");\
++dyn->sons_size; \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) \
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack); \
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
}
+55 -37
View File
@@ -6,6 +6,8 @@
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
#define BARRIER_MAYBE 8
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
#define NEON_CACHE_ST_F 2
@@ -20,31 +22,6 @@ typedef union neon_cache_s {
unsigned int n:4; // reg number
};
} neon_cache_t;
typedef struct neoncache_s {
neon_cache_t neoncache[24];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
uint8_t combined1;
uint8_t combined2;
} neoncache_t;
typedef struct instruction_arm_s {
instruction_x86_t x86;
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;
neoncache_t n;
} instruction_arm_t;
typedef union sse_cache_s {
int v;
struct {
@@ -52,6 +29,57 @@ typedef union sse_cache_s {
uint8_t write;
};
} sse_cache_t;
typedef struct neoncache_s {
// Neon cache
neon_cache_t neoncache[24];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
int8_t stack_push;
uint8_t combined1;
uint8_t combined2;
uint8_t swapped; // the combined reg were swapped
uint8_t barrier; // is there a barrier at instruction epilog?
uint32_t news; // bitmask, wich neoncache are new for this opcode
// fpu cache
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int8_t x87reg[8]; // reg used for x87cache entry
int8_t mmxcache[8];// cache status for the 8 MMX registers
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
int8_t fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
int8_t x87stack; // cache stack counter
int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
int8_t fpu_scratch;// scratch counter
int8_t fpu_extra_qscratch; // some opcode need an extra quad scratch register
int8_t fpu_reg; // x87/sse/mmx reg counter
} neoncache_t;
typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
int dfnone; // if defered flags is already set to df_none
} flagcache_t;
typedef struct instruction_arm_s {
instruction_x86_t x86;
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
int pred_sz; // size of predecessor list
int *pred; // predecessor array
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;
int barrier_maybe;
flagcache_t f_exit; // flags status at end of intruction
neoncache_t n; // neoncache at end of intruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin
} instruction_arm_t;
typedef struct dynarec_arm_s {
instruction_arm_t *insts;
@@ -62,25 +90,15 @@ typedef struct dynarec_arm_s {
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
int state_flags;// actual state for on-demand flags
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int x87reg[8]; // reg used for x87cache entry
int mmxcache[8];// cache status for the 8 MMX registers
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
flagcache_t f;
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
int x87stack; // cache stack counter
int mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
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 dfnone; // if defered flags is already set to df_none
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
} dynarec_arm_t;
+20 -10
View File
@@ -1,6 +1,11 @@
#ifndef __DYNAREC_PRIVATE_H_
#define __DYNAREC_PRIVATE_H_
#define BARRIER_NONE 0
#define BARRIER_FLAGS 1
#define BARRIER_FLOAT 2
#define BARRIER_FULL 3
// all flags for the use_flags field
#define X_CF (1<<0)
#define X_PF (1<<1)
@@ -9,27 +14,32 @@
#define X_SF (1<<4)
#define X_OF (1<<5)
#define X_ALL ((1<<6)-1)
#define X_PEND (0x1000)
#define X_PEND (0x80)
// all state flags
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_SET_PENDING 3
#define SF_MAYSET 4
#define SF_SUBSET 5
#define SF_SET_PENDING (SF_SET|SF_PENDING)
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
#define SF_MAYSET 8
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
int barrier; // next instruction is a jump point, so no optim allowed
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_cond; // 1 of conditionnal jump
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint32_t use_flags; // 0 or combination of X_?F
uint32_t set_flags; // 0 or combination of X_?F
uint32_t need_flags; // calculated
int state_flags; // One of SF_XXX state
uint8_t jmp_cond; // 1 of conditionnal jump
uint8_t has_next; // does this opcode can continue to the next?
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
uint8_t default_need;// 0 or X_PEND basically
uint8_t need_flags; // calculated
uint8_t old_use; // calculated
} instruction_x86_t;
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
+1 -1
View File
@@ -83,7 +83,7 @@ INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d64 &g&g param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
+558 -232
View File
File diff suppressed because it is too large. Load diff
+5
View File
@@ -241,6 +241,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->initarray_sz = val / sizeof(Elf32_Addr);
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
@@ -350,6 +354,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
const char* GetSymbolVersion(elfheader_t* h, int version)
{
version&=0x7fff; // remove bit15 that switch between hidden/public
if(!h->VerNeed || (version<2))
return NULL;
/*if(version==1)
+47 -17
View File
@@ -60,6 +60,18 @@
if(emu->quit) goto fini;
STEP;
NEXT;
_0f_0x0D: /* PREFETCH group */
nextop = F8;
switch((nextop>>3)&7) {
case 1: /* PREFETCHW */
GET_ED; //nothing for now. Could maybe use some builtin prefetch instruction
break;
default:
goto _default;
}
NEXT;
_0f_0x10: /* MOVUPS Gx,Ex */
nextop = F8;
GET_EX;
@@ -227,7 +239,7 @@
if(EM->ub[i]&128)
GM.ub[i] = 0;
else
GM.ub[i] = eax1.ub[EM->ub[i]&7];
GM.ub[i] = eam1.ub[EM->ub[i]&7];
}
break;
case 0x04: /* PMADDUBSW Gm,Em */
@@ -288,7 +300,7 @@
_0f_0x3A:
opcode = F8;
switch(opcode) {
case 0xF: /* palignr */
case 0x0F: /* palignr */
nextop = F8;
GET_EM;
tmp8u = F8;
@@ -297,8 +309,10 @@
} else if (tmp8u > 8) {
tmp8u -= 8;
GM.q >>= tmp8u*8;
} else if (tmp8u == 8 || tmp8u == 0) {
} else if (tmp8u == 8) {
// nothing
} else if (tmp8u == 0) {
GM.q = EM->q;
} else {
GM.q <<= (8-tmp8u)*8;
GM.q |= (EM->q >> tmp8u*8);
@@ -435,8 +449,18 @@
_0f_0x52: /* RSQRTPS Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
GX.f[i] = 1.0f/sqrtf(EX->f[i]);
for(int i=0; i<4; ++i) {
if(EX->f[i]==0)
GX.f[i] = 1.0f/EX->f[i];
else if (EX->f[i]<0)
GX.f[i] = NAN;
else if (isnan(EX->f[i]))
GX.f[i] = EX->f[i];
else if (isinf(EX->f[i]))
GX.f[i] = 0.0;
else
GX.f[i] = 1.0f/sqrtf(EX->f[i]);
}
NEXT;
_0f_0x53: /* RCPPS Gx, Ex */
nextop = F8;
@@ -1093,19 +1117,25 @@
GX.q[1] = eax1.q[1];
NEXT;
_0f_0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
switch((nextop>>3)&7) {
case 1:
CHECK_FLAGS(emu);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
break;
default:
goto _default;
}
NEXT;
_0f_0xC8:
+8
View File
@@ -55,6 +55,9 @@
STEP
NEXT;
_66_0x1E: /* PUSH DS */
Push16(emu, emu->segs[_DS]);
NEXT;
_66_0x1F: /* POP DS */
emu->segs[_DS] = Pop16(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
@@ -482,6 +485,11 @@
R_ECX = tmp32u;
NEXT;
_66_0xF5: /* CMC */
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
NEXT;
_66_0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
GET_EW;
+15
View File
@@ -23,6 +23,7 @@
ll = ST(nextop&7).sq;
ST(nextop&7).sq = ST0.sq;
ST0.sq = ll;
emu->sw.f.F87_C1 = 0;
break;
case 0xD0: /* FNOP */
@@ -30,9 +31,11 @@
case 0xE0: /* FCHS */
ST0.d = -ST0.d;
emu->sw.f.F87_C1 = 0;
break;
case 0xE1: /* FABS */
ST0.d = fabs(ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xE4: /* FTST */
@@ -73,25 +76,30 @@
case 0xF0: /* F2XM1 */
ST0.d = exp2(ST0.d) - 1.0;
emu->sw.f.F87_C1 = 0;
break;
case 0xF1: /* FYL2X */
ST(1).d *= log2(ST0.d);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xF2: /* FPTAN */
ST0.d = tan(ST0.d);
fpu_do_push(emu);
ST0.d = 1.0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xF3: /* FPATAN */
ST1.d = atan2(ST1.d, ST0.d);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xF4: /* FXTRACT */
ST0.d = frexp(ST0.d, &tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
// C1 set only if stack under/overflow occurs
break;
case 0xF8: /* FPREM */
@@ -146,30 +154,37 @@
case 0xF9: /* FYL2XP1 */
ST(1).d *= log2(ST0.d + 1.0);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xFA: /* FSQRT */
ST0.d = sqrt(ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xFC: /* FRNDINT */
ST0.d = fpu_round(emu, ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
emu->sw.f.F87_C1 = 0;
break;
case 0xFE: /* FSIN */
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xFF: /* FCOS */
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
+1 -1
View File
@@ -132,7 +132,7 @@
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
LD2D(&STld(0), &ST(0).d);
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
break;
case 7: /* FSTP tbyte */
+30 -2
View File
@@ -53,17 +53,32 @@
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] = sqrt(EX->d[0]);
if(EX->d[0]<0.0 )
GX.d[0] = -NAN;
else
GX.d[0] = sqrt(EX->d[0]);
break;
case 0x58: /* ADDSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// add generate a -NAN only if doing inf + -inf
if((isinf(GX.d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)!=(GX.q[0]&0x8000000000000000LL)))
GX.d[0] = -NAN;
else
#endif
GX.d[0] += EX->d[0];
break;
case 0x59: /* MULSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
if((isinf(GX.d[0]) && EX->d[0]==0.0) || (isinf(EX->d[0]) && GX.d[0]==0.0))
GX.d[0] = -NAN;
else
#endif
GX.d[0] *= EX->d[0];
break;
case 0x5A: /* CVTSD2SS Gx, Ex */
@@ -75,18 +90,31 @@
case 0x5C: /* SUBSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// sub generate a -NAN only if doing inf - inf
if((isinf(GX.d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)==(GX.q[0]&0x8000000000000000LL)))
GX.d[0] = -NAN;
else
#endif
GX.d[0] -= EX->d[0];
break;
case 0x5D: /* MINSD Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isless(EX->d[0], GX.d[0]))
if (isnan(GX.d[0]) || isnan(EX->d[0]) || (EX->d[0]<=GX.d[0]))
GX.d[0] = EX->d[0];
break;
case 0x5E: /* DIVSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
is_nan = isnan(GX.d[0]) || isnan(EX->d[0]);
#endif
GX.d[0] /= EX->d[0];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[0]))
GX.d[0] = -NAN;
#endif
break;
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
+2 -2
View File
@@ -323,14 +323,14 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
}
// start with FPU regs...
if(emu->fpu_stack) {
if(emu->fpu_stack<8)
if(emu->fpu_stack<9)
for (int i=0; i<emu->fpu_stack; i++) {
//if(i==4) strcat(buff, "\n");
sprintf(tmp, "ST%d=%f", i, emu->x87[(emu->top+i)&7].d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
else {
sprintf(tmp, "Warning, incoherent fpu_stack=%d", emu->fpu_stack);
+37 -24
View File
@@ -119,16 +119,20 @@ 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, "shm_open")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
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;
perr = 2;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
perr = 2;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
@@ -138,9 +142,14 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "putenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(!strcmp(s, "read")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
@@ -150,13 +159,13 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "my___xstat64")==s) {
} 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, "my___xstat")==0) {
} 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, "my___lxstat64")==s) {
} 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;
} else if(strstr(s, "sem_timedwait")==s) {
@@ -174,10 +183,10 @@ void x86Int3(x86emu_t* emu)
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "my_mmap64")) {
} else if(!strcmp(s, "mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 3;
} else if(!strcmp(s, "my_mmap")) {
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
@@ -190,54 +199,58 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "my_vsnprintf")==s) {
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_vsprintf")==s) {
} else if(strstr(s, "vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my___vsprintf_chk")==s) {
} else if(strstr(s, "__vsprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my___snprintf_chk")==s) {
} else if(strstr(s, "__snprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_snprintf")==s) {
} else if(strstr(s, "snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_sprintf")==s) {
} else if(strstr(s, "sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_printf")==s) {
} else if(strstr(s, "printf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "my_wprintf")==s) {
} else if(strstr(s, "wprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
} else if(strstr(s, "my___vswprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
} else if(strstr(s, "__vswprintf")==s) {
if(*(size_t*)(R_ESP+12)<2) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
}
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "my_fprintf")==s) {
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "my_vfprintf")==s) {
} else if(strstr(s, "vfprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+12);
@@ -246,9 +259,9 @@ void x86Int3(x86emu_t* emu)
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, "my_glXGetProcAddress")==s) {
} else if(strstr(s, "glXGetProcAddress")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "my_sscanf")==s) {
} 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(!strcmp(s, "vsscanf")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
@@ -270,7 +283,7 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "my_syscall")) {
} else if(!strcmp(s, "syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else {
+6 -3
View File
@@ -46,6 +46,9 @@ int Run(x86emu_t *emu, int step)
int64_t ll;
sse_regs_t *opex, eax1;
mmx87_regs_t *opem, eam1;
#ifndef NOALIGN
int is_nan;
#endif
if(emu->quit)
return 0;
@@ -101,7 +104,7 @@ int Run(x86emu_t *emu, int step)
static const void* opcodes0f[256] = {
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_0f_0x0D, &&_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, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
@@ -138,7 +141,7 @@ int Run(x86emu_t *emu, int step)
&&_66_0x00_0, &&_66_0x00_1, &&_66_0x00_2, &&_66_0x00_3, &&_66_0x00_4 ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07
&&_66_0x08_0, &&_66_0x08_1, &&_66_0x08_2, &&_66_0x08_3, &&_66_0x08_4 ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F
&&_66_0x10_0, &&_66_0x10_1, &&_66_0x10_2, &&_66_0x10_3, &&_66_0x10_4 ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17
&&_66_0x18_0, &&_66_0x18_1, &&_66_0x18_2, &&_66_0x18_3, &&_66_0x18_4 ,&&_66_0x18_5, &&_default, &&_66_0x1F, //0x18-0x1F
&&_66_0x18_0, &&_66_0x18_1, &&_66_0x18_2, &&_66_0x18_3, &&_66_0x18_4 ,&&_66_0x18_5, &&_66_0x1E, &&_66_0x1F, //0x18-0x1F
&&_66_0x20_0, &&_66_0x20_1, &&_66_0x20_2, &&_66_0x20_3, &&_66_0x20_4 ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27
&&_66_0x28_0, &&_66_0x28_1, &&_66_0x28_2, &&_66_0x28_3, &&_66_0x28_4 ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F
&&_66_0x30_0, &&_66_0x30_1, &&_66_0x30_2, &&_66_0x30_3, &&_66_0x30_4 ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37
@@ -165,7 +168,7 @@ int Run(x86emu_t *emu, int step)
&&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_66_0xF5, &&_default, &&_66_0xF7,
&&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
};
+124 -49
View File
@@ -536,63 +536,73 @@ void RunLock(x86emu_t *emu)
#endif
break;
case 0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
switch((nextop>>3)&7) {
case 1:
CHECK_FLAGS(emu);
#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) {
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) {
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;
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = m&0xffffffff;
R_EDX = m>>32;
tmp32s = 0;
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
} 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) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
ip = R_EIP;
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xC7 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
break;
}
break;
default:
// trigger invalid lock?
@@ -798,6 +808,59 @@ void RunLock66(x86emu_t *emu)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xFF:
nextop = F8;
GET_EW;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#ifdef DYNAREC
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = inc16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, inc16(emu, tmp16u)));
#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
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = dec16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, dec16(emu, tmp16u)));
#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:
ip=R_EIP;
UnimpOpcode(emu);
break;
}
break;
default:
ip-=3; // unfetch nextop, F0 & 66
UnimpOpcode(emu);
@@ -889,6 +952,18 @@ void RunGS(x86emu_t *emu)
GET_ED_OFFS(tlsdata);
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x39: /* CMP Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x3B: /* CMP Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x40:
case 0x41:
+209 -11
View File
@@ -38,6 +38,9 @@ void Run660F(x86emu_t *emu)
int32_t tmp32s;
sse_regs_t *opex, eax1, *opx2;
mmx87_regs_t *opem;
#ifndef NOALIGN
int is_nan;
#endif
opcode = F8;
@@ -366,6 +369,23 @@ void Run660F(x86emu_t *emu)
}
break;
case 0x14: /* BLENDVPS Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
if(emu->xmm[0].ud[i]&0x80000000)
GX.ud[i] = EX->ud[i];
}
break;
case 0x17: // PTEST GX, EX
nextop = F8;
GET_EX;
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!((GX.q[0]&EX->q[0])|(GX.q[1]&EX->q[1])), F_ZF);
CONDITIONAL_SET_FLAG(!(((~GX.q[0])&EX->q[0])|((~GX.q[1])&EX->q[1])), F_CF);
break;
case 0x1C: /* PABSB Gx, Ex */
nextop = F8;
GET_EX;
@@ -388,6 +408,96 @@ void Run660F(x86emu_t *emu)
}
break;
case 0x20: /* PMOVSXBW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=7; i>=0; --i)
GX.sw[i] = EX->sb[i];
break;
case 0x21: /* PMOVSXBD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.sd[i] = EX->sb[i];
break;
case 0x22: /* PMOVSXBQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sb[i];
break;
case 0x23: /* PMOVSXWD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.sd[i] = EX->sw[i];
break;
case 0x24: /* PMOVSXWQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sw[i];
break;
case 0x25: /* PMOVSXDQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sd[i];
break;
case 0x30: /* PMOVZXBW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=7; i>=0; --i)
GX.uw[i] = EX->ub[i];
break;
case 0x31: /* PMOVZXBD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.ud[i] = EX->ub[i];
break;
case 0x32: /* PMOVZXBQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->ub[i];
break;
case 0x33: /* PMOVZXWD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.ud[i] = EX->uw[i];
break;
case 0x34: /* PMOVZXWQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->uw[i];
break;
case 0x35: /* PMOVZXDQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->ud[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.sd[i]>EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
case 0x3D: /* PMAXSD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.sd[i]<EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
@@ -397,6 +507,15 @@ void Run660F(x86emu_t *emu)
case 0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0E: /* PBLENDW Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
for (int i=0; i<8; ++i) {
if(tmp8u&(1<<i))
GX.uw[i] = EX->uw[i];
}
break;
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GET_EX;
@@ -434,6 +553,31 @@ void Run660F(x86emu_t *emu)
}
#endif
break;
case 0x16: // PEXTRD ED, GX, u8
nextop = F8;
GET_ED;
tmp8u = F8;
ED->dword[0] = GX.ud[tmp8u&3];
break;
case 0x21: // INSERTPS GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
if((nextop&0xC0)==0xC0) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
GX.ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
for(int i=0; i<4; ++i)
if(tmp8u&(1<<i))
GX.ud[i] = 0;
break;
case 0x22: // PINSRD GX, ED, u8
nextop = F8;
GET_ED;
tmp8u = F8;
GX.ud[tmp8u&0x3] = ED->dword[0];
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
@@ -450,8 +594,14 @@ void Run660F(x86emu_t *emu)
case 0x51: /* SQRTPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] = sqrt(EX->d[0]);
GX.d[1] = sqrt(EX->d[1]);
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
if(EX->d[i]<0.0) // on x86, default nan are negative
GX.d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
else
#endif
GX.d[i] = sqrt(EX->d[i]);
}
break;
case 0x54: /* ANDPD Gx, Ex */
@@ -481,14 +631,28 @@ void Run660F(x86emu_t *emu)
case 0x58: /* ADDPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] += EX->d[0];
GX.d[1] += EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// add generate a -NAN only if doing inf + -inf
if((isinf(GX.d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)!=(GX.q[i]&0x8000000000000000LL)))
GX.d[i] = -NAN;
else
#endif
GX.d[i] += EX->d[i];
}
break;
case 0x59: /* MULPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] *= EX->d[0];
GX.d[1] *= EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
if((isinf(GX.d[i]) && EX->d[i]==0.0) || (isinf(EX->d[i]) && GX.d[i]==0.0))
GX.d[i] = -NAN;
else
#endif
GX.d[i] *= EX->d[i];
}
break;
case 0x5A: /* CVTPD2PS Gx, Ex */
nextop = F8;
@@ -530,8 +694,15 @@ void Run660F(x86emu_t *emu)
case 0x5C: /* SUBPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] -= EX->d[0];
GX.d[1] -= EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// sub generate a -NAN only if doing inf - inf
if((isinf(GX.d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)==(GX.q[i]&0x8000000000000000LL)))
GX.d[i] = -NAN;
else
#endif
GX.d[i] -= EX->d[i];
}
break;
case 0x5D: /* MINPD Gx, Ex */
nextop = F8;
@@ -544,8 +715,16 @@ void Run660F(x86emu_t *emu)
case 0x5E: /* DIVPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] /= EX->d[0];
GX.d[1] /= EX->d[1];
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
is_nan = isnan(GX.d[i]) || isnan(EX->d[i]);
#endif
GX.d[i] /= EX->d[i];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[i]))
GX.d[i] = -NAN;
#endif
}
break;
case 0x5F: /* MAXPD Gx, Ex */
nextop = F8;
@@ -834,11 +1013,25 @@ void Run660F(x86emu_t *emu)
case 0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
is_nan = isnan(GX.d[0]) || isnan(GX.d[1]);
#endif
GX.d[0] += GX.d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[0]))
GX.d[0] = -NAN;
#endif
if(EX==&GX) {
GX.d[1] = GX.d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX.d[1] = EX->d[0] + EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[1]))
GX.d[1] = -NAN;
#endif
}
break;
@@ -1059,6 +1252,11 @@ void Run660F(x86emu_t *emu)
GET_EB;
GW.sword[0] = EB->sbyte[0];
break;
case 0xBF: /* MOVSX Gw,Ew */
nextop = F8;
GET_EW;
GW.sword[0] = EW->sword[0];
break;
case 0xC1: /* XADD Gw,Ew */ // Xchange and Add
nextop = F8;
@@ -1467,4 +1665,4 @@ void Run660F(x86emu_t *emu)
R_EIP = ip;
return;
}
}
+62 -9
View File
@@ -19,6 +19,7 @@
#include "x86run.h"
#include "librarian.h"
#include "elfloader.h"
#include "bridge.h"
#ifdef HAVE_TRACE
#include "x86trace.h"
#endif
@@ -339,6 +340,51 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_rcl8:
cc = (emu->op1 >> (8 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 6) & 0x2)), F_OF);
break;
case d_rcl16:
cc = (emu->op1 >> (16 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 14) & 0x2)), F_OF);
break;
case d_rcl32:
cc = (emu->op1 >> (32 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 30) & 0x2)), F_OF);
break;
case d_rcr8:
cnt = emu->op2 % 9;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 6) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_rcr16:
cnt = emu->op2 % 17;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 14) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_rcr32:
cnt = emu->op2 % 33;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 30) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_shl8:
if (emu->op2 < 8) {
cnt = emu->op2 % 8;
@@ -512,7 +558,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -521,7 +567,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -530,7 +576,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -727,14 +773,21 @@ const char* getAddrFunctionName(uintptr_t addr)
static char ret[1000];
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
elfheader_t* elf = FindElfAddress(my_context, addr);
const char* symbname = FindNearestSymbolName(elf, (void*)addr, &start, &sz);
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
if(addr==start)
sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
if(symbname[0]=='\0')
sprintf(ret, "%s + 0x%x", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));
else if(addr==start)
sprintf(ret, "%s/%s", ElfName(elf), symbname);
else
sprintf(ret, "%s/%s + %d", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
} else
sprintf(ret, "???");
sprintf(ret, "%s/%s + %d", ElfName(elf), symbname, addr - start);
} else {
if(elf) {
sprintf(ret, "%s + 0x%x", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));
} else
sprintf(ret, "???");
}
return ret;
}
+81 -26
View File
@@ -246,6 +246,9 @@ scwrap_t syscallwrap[] = {
#ifdef __NR_memfd_create
{ 356, __NR_memfd_create, 2},
#endif
#ifdef __NR_futex_waitv
{ 449, __NR_futex_waitv, 5},
#endif
};
struct mmap_arg_struct {
@@ -317,6 +320,7 @@ int clone_fn(void* arg)
DynaRun(emu);
int ret = R_EAX;
FreeX86Emu(&emu);
my_context->stack_clone_used = 0;
return ret;
}
@@ -481,42 +485,46 @@ void EXPORT x86Syscall(x86emu_t *emu)
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
break;
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
// so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, tls=R_ESI, child_tid=R_EDI
if(R_ECX)
{
// should wrap that using a thread...
//struct x86_pt_regs *regs = (struct x86_pt_regs *)R_EDI;
// lets duplicate the emu
void* stack_base = (void*)R_ECX;
int stack_size = 0;
if(!R_ECX) {
// allocate a new stack...
stack_size = 1024*1024;
//stack_base = malloc(stack_size); // why not 1M... (normal operation do copy on write, simpler to just copy)
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base-size_to_copy, (void*)R_ESP, size_to_copy);
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
SetESP(newemu, (uintptr_t)stack_base);
// setup registers
/*if(regs) {
SetEAX(newemu, regs->eax);
SetEBX(newemu, regs->ebx);
SetECX(newemu, regs->ecx);
SetEDX(newemu, regs->edx);
SetEDI(newemu, regs->edi);
SetESI(newemu, regs->esi);
SetEBP(newemu, regs->ebp);
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);*/
void* mystack = (R_EBX&CLONE_VM)?malloc(1024*1024):NULL; // stack for own process... memory leak, but no practical way to remove it
int ret = clone(clone_fn, (void*)((R_EBX&CLONE_VM)?((uintptr_t)mystack+1024*1024):0), R_EBX, newemu, R_ESI, R_EDI, R_EBP);
//int r = syscall(__NR_clone, R_EBX, (R_EBX&CLONE_VM)?((uintptr_t)mystack):0, R_EDX, R_ESI, NULL); // cannot use that syscall in C: how to setup the stack?!
R_EAX = ret;
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
R_EAX = (uint32_t)ret;
}
else
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
break;
case 122: // uname
{
@@ -639,6 +647,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
uint32_t EXPORT my_syscall(x86emu_t *emu)
{
static uint32_t warned = 0;
uint32_t s = u32(0);
printf_log(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
// check wrapper first
@@ -677,6 +686,49 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
case 91: // munmap
return (uint32_t)my_munmap(emu, p(4), u32(8));
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
// so flags=u(4), stack=p(8), parent_tid=p(12), tls=p(16), child_tid=p(20)
if(p(8))
{
void* stack_base = p(8);
int stack_size = 0;
if(!stack_base) {
// allocate a new stack...
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (p(8))?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
// x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), u32(4), newemu, p(12), p(16), p(20));
return (uint32_t)ret;
}
else
return (uint32_t)syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
break;
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 125: // mprotect
@@ -718,9 +770,12 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
if(!(warned&(1<<s))) {
printf_log(LOG_INFO, "Warning: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
warned|=(1<<s);
}
errno = ENOSYS;
return -1;
}
return 0;
}
+7 -2
View File
@@ -34,7 +34,12 @@ static inline void fpu_do_push(x86emu_t* emu)
return;
}*/
if(emu->fpu_stack<8)
++emu->fpu_stack;
++emu->fpu_stack;
else {
emu->sw.f.F87_C1 = 1;
return;
}
emu->sw.f.F87_C1 = 0;
emu->p_regs[newtop].tag = 0; // full
emu->top = newtop;
}
@@ -136,7 +141,7 @@ void fpu_fxam(x86emu_t* emu);
static inline void fpu_ftst(x86emu_t* emu) {
emu->sw.f.F87_C1 = 0;
if(isinf(ST0.d) || isnan(ST0.d))
if(isnan(ST0.d))
{ // TODO: Unsuported and denormal not analysed...
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 1;
+1 -1
View File
@@ -4,7 +4,7 @@
typedef struct x86emu_s x86emu_t;
#ifndef BUILD_LIB
int init_auxval(int argc, const char **argv, const char **env);
int init_auxval(int argc, const char **argv, char **env);
#endif
unsigned long real_getauxval(unsigned long type);
+6 -3
View File
@@ -13,7 +13,9 @@ typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct kh_defaultversion_s kh_defaultversion_t;
typedef struct library_s library_t;
typedef struct linkmap_s linkmap_t;
typedef struct kh_fts_s kh_fts_t;
typedef struct kh_threadstack_s kh_threadstack_t;
typedef struct zydis_dec_s zydis_dec_t;
@@ -111,6 +113,7 @@ typedef struct box86context_s {
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
kh_defaultversion_t *defver; // the default version for symbols (the XXX@@vvvv of symbols)
vkprocaddess_t vkprocaddress;
pthread_mutex_t mutex_once;
@@ -150,6 +153,7 @@ typedef struct box86context_s {
library_t *asound;
library_t *pulse;
library_t *d3dadapter9;
linkmap_t *linkmap;
int deferedInit;
elfheader_t **deferedInitList;
@@ -186,9 +190,8 @@ typedef struct box86context_s {
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
int no_sigsegv;
int no_sigill;
#ifdef BUILD_DYNAMIC
int count; // number of instances
#endif
void* stack_clone;
int stack_clone_used;
} box86context_t;
extern box86context_t *my_context; // global context
+6
View File
@@ -35,14 +35,20 @@ uintptr_t getJumpTableAddress(uintptr_t addr);
#endif
#define PROT_DYNAREC 0x80
#define PROT_CUSTOM (PROT_DYNAREC)
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
uint32_t getProtection(uintptr_t addr);
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void freeProtection(uintptr_t addr, uintptr_t size);
void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
int unlockCustommemMutex();
+8
View File
@@ -15,7 +15,9 @@ extern int box86_dynarec_forced;
extern int box86_dynarec_largest;
extern int box86_dynarec_bigblock;
extern int box86_dynarec_strongmem;
extern int box86_dynarec_x87double;
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
extern int box86_dynarec_fastnan;
#ifdef ARM
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
@@ -26,10 +28,16 @@ extern int dlsym_error; // log dlsym error
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int allow_missing_libs;
extern int box86_prefer_wrapped;
extern int box86_prefer_emulated;
extern int box86_steam;
extern int box86_wine;
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
extern int box86_nogtk; // disabling the use of wrapped gtk
extern int box86_novulkan; // disabling the use of wrapped vulkan
extern int box86_mapclean;
extern int box86_showsegv;
extern int allow_missing_symbols;
extern uintptr_t trace_start, trace_end;
extern char* trace_func;
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
+1 -4
View File
@@ -2,7 +2,7 @@
#define __DICTIONNARY_H_
#include <stdint.h>
typedef struct dic_s dic_t;
typedef void dic_t;
dic_t *NewDictionnary();
void FreeDictionnary(dic_t **dic);
@@ -10,7 +10,4 @@ void FreeDictionnary(dic_t **dic);
const char* AddDictionnary(dic_t* dic, const char* s);
int ExistDictionnary(dic_t* dic, const char* s);
const char* AddDefault(dic_t* dic, const char* s, const char** vername);
const char* ExistDefault(dic_t* dic, const char* s);
#endif //__DICTIONNARY_H_
+8 -3
View File
@@ -24,13 +24,13 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
void FreeElfMemory(elfheader_t* head);
int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int RelocateElf(lib_t* maplib, lib_t* local_maplib, elfheader_t* head);
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, elfheader_t* head);
int RelocateElf(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, box86context_t* box86, x86emu_t* emu);
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RunElfInit(elfheader_t* h, x86emu_t* emu);
@@ -52,6 +52,7 @@ dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
#endif
void ResetSpecialCaseMainElf(elfheader_t* h);
void CreateMemorymapFile(box86context_t* context, int fd);
void* GetDynamicSection(elfheader_t* h);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
@@ -60,4 +61,8 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index);
const char* VersionnedName(const char* name, int ver, const char* vername);
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
void* GetNativeSymbolUnversionned(void* lib, const char* name);
void AddMainElfToLinkmap(elfheader_t* lib);
#endif //__ELF_LOADER_H_
+128
View File
@@ -210,6 +210,123 @@ typedef struct my_GtkWindowClass_s {
void (*_gtk_reserved4) (void);
} my_GtkWindowClass_t;
typedef struct my_GtkButtonClass_s {
my_GtkBinClass_t parent_class;
void (* pressed) (void *button);
void (* released) (void *button);
void (* clicked) (void *button);
void (* enter) (void *button);
void (* leave) (void *button);
void (* activate) (void *button);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkButtonClass_t;
typedef struct my_GtkToggleButtonClass_s {
my_GtkButtonClass_t parent_class;
void (* toggled) (void* toggle_button);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkToggleButtonClass_t;
typedef struct my_GtkCheckButtonClass_s {
my_GtkToggleButtonClass_t parent_class;
void (* draw_indicator) (void* check_button, void* area);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkCheckButtonClass_t;
typedef struct my_GtkComboBoxClass_s {
my_GtkBinClass_t parent_class;
void (* changed) (void* combo_box);
void*(* get_active_text)(void* combo_box);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkComboBoxClass_t;
typedef struct my_GtkEntryClass_s {
my_GtkWidgetClass_t parent_class;
void (* populate_popup) (void* entry, void* menu);
void (* activate) (void* entry);
void (* move_cursor) (void* entry, int step, int count, int extend_selection);
void (* insert_at_cursor) (void* entry, void* str);
void (* delete_from_cursor) (void* entry, int type, int count);
void (* backspace) (void* entry);
void (* cut_clipboard) (void* entry);
void (* copy_clipboard) (void* entry);
void (* paste_clipboard) (void* entry);
void (* toggle_overwrite) (void* entry);
void (* get_text_area_size) (void* entry, void* x, void* y, void* width, void* height);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkEntryClass_t;
typedef struct my_GtkSpinButtonClass_s {
my_GtkEntryClass_t parent_class;
int (*input) (void* spin_button, void* new_value);
int (*output) (void* spin_button);
void (*value_changed) (void* spin_button);
void (*change_value) (void* spin_button, int scroll);
void (*wrapped) (void* spin_button);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkSpinButtonClass_t;
typedef struct my_GtkProgressClass_s {
my_GtkWidgetClass_t parent_class;
void (* paint) (void* progress);
void (* update) (void* progress);
void (* act_mode_enter) (void* progress);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkProgressClass_t;
typedef struct my_GtkProgressBarClass_s {
my_GtkProgressClass_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkProgressBarClass_t;
typedef struct my_GtkFrameClass_s {
my_GtkBinClass_t parent_class;
void (*compute_child_allocation) (void* frame, void* allocation);
} my_GtkFrameClass_t;
typedef struct my_GtkMenuShellClass_s {
my_GtkContainerClass_t parent_class;
void (*deactivate) (void* menu_shell);
void (*selection_done) (void* menu_shell);
void (*move_current) (void* menu_shell, int direction);
void (*activate_current) (void* menu_shell, int force_hide);
void (*cancel) (void* menu_shell);
void (*select_item) (void* menu_shell, void* menu_item);
void (*insert) (void* menu_shell, void* child, int position);
int (*get_popup_delay) (void* menu_shell);
int (*move_selected) (void* menu_shell, int distance);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkMenuShellClass_t;
typedef struct my_GtkMenuBarClass_s {
my_GtkMenuShellClass_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkMenuBarClass_t;
typedef struct my_MetaFramesClass_s
{
my_GtkWindowClass_t parent_class;
@@ -302,6 +419,17 @@ GTKCLASS(GtkBin) \
GTKCLASS(GtkWindow) \
GTKCLASS(GtkTable) \
GTKCLASS(GtkFixed) \
GTKCLASS(GtkButton) \
GTKCLASS(GtkComboBox) \
GTKCLASS(GtkToggleButton)\
GTKCLASS(GtkCheckButton)\
GTKCLASS(GtkEntry) \
GTKCLASS(GtkSpinButton) \
GTKCLASS(GtkProgress) \
GTKCLASS(GtkProgressBar)\
GTKCLASS(GtkFrame) \
GTKCLASS(GtkMenuShell) \
GTKCLASS(GtkMenuBar) \
GTKCLASS(MetaFrames) \
GTKCLASS(GDBusObjectManagerClient) \
+2 -4
View File
@@ -25,20 +25,18 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char** paths, int npath, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername);
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib);
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
const char* GetNameOffset(lib_t *maplib, void* offs);
+1 -1
View File
@@ -12,7 +12,7 @@ typedef struct needed_libs_s needed_libs_t;
library_t *NewLibrary(const char* path, box86context_t* box86);
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x86emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x86emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t* emu);
int ReloadLibrary(library_t* lib, x86emu_t* emu);
void InactiveLibrary(library_t* lib);
void Free1Library(library_t **lib, x86emu_t* emu);
+16
View File
@@ -329,3 +329,19 @@ void AlignFlock64(void* dest, void* source); // x86 -> Arm
// defined in wrapperlibc.c
int of_convert(int); // x86->arm
int of_unconvert(int); // arm->x86
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;
void alignNGValue(my_GValue_t* v, void* value, int n);
void unalignNGValue(void* value, my_GValue_t* v, int n);
+8 -1
View File
@@ -16,9 +16,16 @@ void FreeMapSymbols(kh_mapsymbols_t** map);
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local);
// don't add if already there
#define MAX_STEP 3
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local);
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
// default version handling
KHASH_MAP_DECLARE_STR(defaultversion, const char*)
kh_defaultversion_t* NewDefaultVersion();
void FreeDefaultVersion(kh_defaultversion_t** def);
void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername);
const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname);
#endif //__SYMBOLS_PRIVATE_H_
+15 -58
View File
@@ -6,20 +6,11 @@
#include "custommem.h"
#include "khash.h"
KHASH_SET_INIT_STR(store);
KHASH_MAP_INIT_STR(default, const char*);
typedef struct dic_s {
kh_store_t *dic;
kh_default_t *def;
} dic_t;
KHASH_SET_INIT_STR(dic);
dic_t *NewDictionnary()
{
dic_t *dic = (dic_t*)calloc(1, sizeof(dic_t));
dic->dic = kh_init(store);
dic->def = kh_init(default);
dic_t *dic = kh_init(dic);
return dic;
}
@@ -27,65 +18,31 @@ void FreeDictionnary(dic_t **d)
{
if(!d || !*d)
return;
dic_t* dic = *d;
kh_dic_t* dic = (kh_dic_t*)*d;
const char* k;
kh_foreach_value(dic->def, k, free((void*)k));
kh_destroy(default, dic->def);
kh_foreach_key(dic->dic, k, free((void*)k));
kh_destroy(store, dic->dic);
free(dic);
kh_foreach_key(dic, k, free((void*)k));
kh_destroy(dic, dic);
*d = NULL;
}
const char* AddDictionnary(dic_t* dic, const char* s)
const char* AddDictionnary(dic_t* d, const char* s)
{
khint_t k = kh_get(store, dic->dic, s);
if(k!=kh_end(dic->dic))
return kh_key(dic->dic, k);
kh_dic_t* dic = (kh_dic_t*)d;
khint_t k = kh_get(dic, dic, s);
if(k!=kh_end(dic))
return kh_key(dic, k);
char* n = strdup(s);
int ret;
k = kh_put(store, dic->dic, n, &ret);
k = kh_put(dic, dic, n, &ret);
return n;
}
int ExistDictionnary(dic_t* dic, const char* s)
int ExistDictionnary(dic_t* d, const char* s)
{
khint_t k = kh_get(store, dic->dic, s);
if(k!=kh_end(dic->dic))
kh_dic_t* dic = (kh_dic_t*)d;
khint_t k = kh_get(dic, dic, s);
if(k!=kh_end(dic))
return 1;
return 0;
}
const char* AddDefault(dic_t* dic, const char* s, const char** vername)
{
char name[strlen(s)+1];
strcpy(name, s);
char* p = strchr(name, '@');
if(!p) {
printf_log(LOG_NONE, "Warning, Added Default symbol without version mark %s\n", s);
return NULL;
}
*p=0;
const char* key = AddDictionnary(dic, name);
char* def_ver = strdup(p+2);
*vername = def_ver;
int ret;
khint_t k = kh_put(default, dic->def, key, &ret);
if(!ret) {
free(def_ver);
*vername = kh_value(dic->def, k);
return key;
}
kh_value(dic->def, k) = def_ver;
return key;
}
const char* ExistDefault(dic_t* dic, const char* s)
{
khint_t k = kh_get(default, dic->def, s);
if(k!=kh_end(dic->def))
return kh_value(dic->def, k);
return NULL;
}
+66 -66
View File
@@ -37,9 +37,9 @@ lib_t *NewLibrarian(box86context_t* context, int ownlibs)
static void freeLibraryRecurse(lib_t *maplib, x86emu_t *emu, int idx, char *freed, library_t* owner) {
if (freed[idx]) return; // Already freed
freed[idx] = 1; // Avoid infinite loops
library_t *lib = maplib->libraries[idx];
if(lib==owner) return; // don't free owner of maplib
freed[idx] = 1; // Avoid infinite loops
printf_log(LOG_DEBUG, "Unloading %s\n", lib->name);
for (int i = lib->dependedby.size - 1; i >= 0; --i) {
int j;
@@ -47,8 +47,8 @@ static void freeLibraryRecurse(lib_t *maplib, x86emu_t *emu, int idx, char *free
if (lib->dependedby.libs[i] == maplib->libraries[j]) break;
}
if (j == maplib->libsz) {
// We cannot access the 'name' field, since we can't be sure it hasn't been freed somewhere else...
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->dependedby.libs[i]);
// dependant lib already freed
// library as been freed already
continue;
}
if (freed[j] == 1) {
@@ -298,10 +298,23 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
}
if (lib->type == 1) {
// Need to add library to the linkmap (put here so the link is ordered)
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
// Crashed already
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
return 1;
}
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->priv.n.elf_index]);
lm->l_name = lib->name;
lm->l_ld = GetDynamicSection(my_context->elfs[lib->priv.n.elf_index]);
}
return 0;
}
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, library_t* lib, box86context_t* box86, x86emu_t* emu)
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box86context_t* box86, x86emu_t* emu)
{
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
@@ -313,22 +326,22 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
} else {
// it's an emulated lib,
// load dependancies and launch init sequence
if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, lib, local, box86, emu)) {
if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box86, emu)) {
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
const char* libs[] = {"libGL.so.1"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box86, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box86, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box86, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box86, emu);
}
// finalize the lib
if(FinalizeLibrary(lib, local?maplib:NULL, emu)) {
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
return 1;
}
@@ -340,8 +353,9 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
}
EXPORTDYN
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char** paths, int npath, box86context_t* box86, x86emu_t* emu)
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu)
{
box86_mapclean = 0;
if(!neededlibs) {
neededlibs = alloca(sizeof(needed_libs_t));
memset(neededlibs, 0, sizeof(needed_libs_t));
@@ -357,7 +371,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
int idx_end = neededlibs->size;
// add dependant libs and init them
for (int i=idx; i<idx_end; ++i)
if(AddNeededLib_init(maplib, neededlibs, deplib, local, neededlibs->libs[i], box86, emu)) {
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box86, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
if(!allow_missing_libs) return 1;
}
@@ -481,25 +495,6 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
}
return 1;
}
if(version==0) { //check if a default version has been defined
const char* default_ver = ExistDefault(my_context->versym, name);
if(default_ver) {
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, 2, default_ver)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, 2, default_ver)) {
if(end2>*end && start2==end2)
*end = end2;
}
free(buff);
}
return 1;
}
}
}
// some special case symbol, defined inside box86 itself
if(!strcmp(name, "gdk_display")) {
*start = (uintptr_t)my_GetGTKDisplay();
@@ -513,6 +508,10 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
// not found...
return 0;
}
@@ -535,6 +534,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
return maplib->context->elfs[idx];
}
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalSymbolElf(maplib, name, 2, defver);
// nope, not found
return NULL;
}
@@ -548,6 +551,10 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalNoWeakSymbolStartEnd(maplib, name, start, end, 2, defver);
// nope, not found
return 0;
}
@@ -560,6 +567,10 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1))
if(start || end)
return 1;
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return IsGlobalNoWeakSymbolInNative(maplib, name, 2, defver);
// nope, not found
return 0;
@@ -583,45 +594,15 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
return 0;
}
}
return 0;
}
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
{
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
}
}
return 0;
}
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
{
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
}
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetLocalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
return 0;
}
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base)
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib)
{
// first, search in self...
const char* ret = NULL;
@@ -630,8 +611,7 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)p);
if(h) {
ret = FindNearestSymbolName(h, p, &offs, &size);
}
if(h) {
if(start)
*start = (void*)offs;
if(sz)
@@ -640,6 +620,26 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
*libname = ElfName(h);
if(base)
*base = GetBaseAddress(h);
if(lib) {
if(h == my_context->elfs[0])
*lib = NULL; // main elf
else {
for(int i=0; i<my_context->maplib->libsz; ++i) {
int idx = GetElfIndex(my_context->maplib->libraries[i]);
if((idx!=-1) && (my_context->elfs[idx]==h)) {
*lib = my_context->maplib->libraries[i];
return ret;
}
}
for(int i=0; i<my_context->local_maplib->libsz; ++i) {
int idx = GetElfIndex(my_context->local_maplib->libraries[i]);
if((idx!=-1) && (my_context->elfs[idx]==h)) {
*lib = my_context->local_maplib->libraries[i];
return ret;
}
}
}
}
return ret;
}
// TODO: find if cyclic references exists (should also fix MapLibAddMapLib)
+132 -11
View File
@@ -9,6 +9,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <link.h>
#include "debug.h"
#include "library.h"
@@ -197,7 +198,9 @@ static void initNativeLib(library_t *lib, box86context_t* context) {
if(strcmp(lib->name, wrappedlibs[i].name)==0) {
if(wrappedlibs[i].init(lib, context)) {
// error!
printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, dlerror());
const char* error_str = dlerror();
if(error_str) // don't print the message if there is no error string from last error
printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, error_str);
return; // non blocker...
}
printf_log(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
@@ -209,10 +212,31 @@ static void initNativeLib(library_t *lib, box86context_t* context) {
lib->getlocal = NativeLib_GetLocal;
lib->type = 0;
// Call librarian to load all dependant elf
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, NULL)) { // probably all native, not emulated, so that's fine
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, NULL)) { // probably all native, not emulated, so that's fine
printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name);
return;
}
#ifdef ANDROID
printf_log(LOG_DEBUG, "No dlinfo on Android %s\n", lib->name);
#else
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
// Crashed already
printf_log(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name);
break;
}
struct link_map real_lm;
#ifndef RTLD_DI_LINKMAP
#define RTLD_DI_LINKMAP 2
#endif
if(dlinfo(lib->priv.w.lib, RTLD_DI_LINKMAP, &real_lm)) {
printf_log(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name);
}
lm->l_addr = real_lm.l_addr;
lm->l_name = real_lm.l_name;
lm->l_ld = real_lm.l_ld;
#endif
break;
}
}
@@ -299,6 +323,24 @@ static void initEmulatedLib(const char* path, library_t *lib, box86context_t* co
}
}
static const char* essential_libs[] = {
"libc.so.6", "libpthread.so.0", "librt.so.1", "libGL.so.1", "libGL.so", "libX11.so.6",
"libasound.so.2", "libdl.so.2", "libm.so.6",
"libXxf86vm.so.1", "libXinerama.so.1", "libXrandr.so.2", "libXext.so.6", "libXfixes.so.3", "libXcursor.so.1",
"libXrender.so.1", "libXft.so.2", "libXi.so.6", "libXss.so.1", "libXpm.so.4", "libXau.so.6", "libXdmcp.so.6",
"libX11-xcb.so.1", "libxcb.so.1", "libxcb-xfixes.so.0", "libxcb-shape.so.0", "libxcb-shm.so.0", "libxcb-randr.so.0",
"libxcb-image.so.0", "libxcb-keysyms.so.1", "libxcb-xtest.so.0", "libxcb-glx.so.0", "libxcb-dri2.so.0", "libxcb-dri3.so.0",
"libXtst.so.6", "libXt.so.6", "libXcomposite.so.1", "libXdamage.so.1", "libXmu.so.6", "libxkbcommon.so.0",
"libxkbcommon-x11.so.0", "libpulse-simple.so.0", "libpulse.so.0", "libvulkan.so.1", "libvulkan.so",
"ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4"
};
static int isEssentialLib(const char* name) {
for (int i=0; i<sizeof(essential_libs)/sizeof(essential_libs[0]); ++i)
if(!strcmp(name, essential_libs[i]))
return 1;
return 0;
}
extern char* libGL;
library_t *NewLibrary(const char* path, box86context_t* context)
{
@@ -330,12 +372,18 @@ library_t *NewLibrary(const char* path, box86context_t* context)
}
}
int notwrapped = FindInCollection(lib->name, &context->box86_emulated_libs);
int essential = isEssentialLib(lib->name);
if(!notwrapped && box86_prefer_emulated && !essential)
notwrapped = 1;
int precise = (!box86_prefer_wrapped && !essential && path && path[0]=='/')?1:0;
if(!notwrapped && precise && strstr(path, "libtcmalloc_minimal.so"))
precise = 0; // allow native version for tcmalloc_minimum
// check if name is libSDL_sound-1.0.so.1 but with SDL2 loaded, then try emulated first...
if(!notwrapped && !strcmp(lib->name, "libSDL_sound-1.0.so.1") && my_context->sdl2lib)
notwrapped = 1;
// And now, actually loading a library
// look for native(wrapped) libs first
if(!notwrapped)
if(!notwrapped && !precise)
initNativeLib(lib, context);
// then look for a native one
if(lib->type==-1)
@@ -366,7 +414,7 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x86emu_t* emu)
}
return 0;
}
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x86emu_t* emu)
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t* emu)
{
if(!lib)
return 0;
@@ -376,11 +424,11 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x86emu_t* emu)
lib->priv.n.finalized = 1;
elfheader_t *elf_header = my_context->elfs[lib->priv.n.elf_index];
// finalize relocations
if(RelocateElf(my_context->maplib, local_maplib, elf_header)) {
if(RelocateElf(my_context->maplib, local_maplib, bindnow, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
return 1;
}
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
RelocateElfPlt(my_context->maplib, local_maplib, bindnow, elf_header);
#ifdef HAVE_TRACE
if(trace_func) {
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
@@ -434,11 +482,11 @@ int ReloadLibrary(library_t* lib, x86emu_t* emu)
}
// can close the file now
fclose(f);
if(RelocateElf(lib->context->maplib, lib->maplib, elf_header)) {
if(RelocateElf(lib->context->maplib, lib->maplib, 0, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
return 1;
}
RelocateElfPlt(lib->context->maplib, lib->maplib, elf_header);
RelocateElfPlt(lib->context->maplib, lib->maplib, 0, elf_header);
// init (will use PltRelocator... because some other libs are not yet resolved)
RunElfInit(elf_header, emu);
}
@@ -448,6 +496,13 @@ int ReloadLibrary(library_t* lib, x86emu_t* emu)
void InactiveLibrary(library_t* lib)
{
lib->active = 0;
#ifdef DYNAREC
// free Dynablocks associated with this lib
if(lib->type==1) {
elfheader_t *elf_header = lib->context->elfs[lib->priv.n.elf_index];
cleanDBFromAddressRange((uintptr_t)GetBaseAddress(elf_header), GetBaseSize(elf_header), 1);
}
#endif
}
void Free1Library(library_t **lib, x86emu_t* emu)
@@ -528,7 +583,7 @@ int IsSameLib(library_t* lib, const char* path)
}
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
{
if(!name[0] || !lib->active)
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// check first if already in the map
@@ -554,7 +609,7 @@ int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uin
}
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
{
if(!name[0] || !lib->active)
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// get a new symbol
@@ -580,7 +635,7 @@ int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
}
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local)
{
if(!name[0] || !lib->active)
if(!name[0] || !lib || !lib->active)
return 0;
khint_t k;
// check first if already in the map
@@ -707,6 +762,14 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
strcat(newname, name);
symbol = dlsym(lib->priv.w.lib, newname);
}
if(!symbol)
symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, name);
if(!symbol && lib->priv.w.altprefix) {
char newname[200];
strcpy(newname, lib->priv.w.altprefix);
strcat(newname, name);
symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, newname);
}
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
return 0;
@@ -760,6 +823,14 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
strcat(newname, name);
symbol = dlsym(lib->priv.w.lib, newname);
}
if(!symbol)
symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, name);
if(!symbol && lib->priv.w.altprefix) {
char newname[200];
strcpy(newname, lib->priv.w.altprefix);
strcat(newname, name);
symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, newname);
}
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
return 0;
@@ -778,6 +849,8 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
symbol = dlsym(lib->priv.w.lib, kh_value(lib->symbol2map, k).name);
if(!symbol)
symbol = dlsym(RTLD_DEFAULT, kh_value(lib->symbol2map, k).name); // search globaly maybe
if(!symbol)
symbol = GetNativeSymbolUnversionned(lib->priv.w.lib, kh_value(lib->symbol2map, k).name);
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->symbol2map, k).name, lib->name);
return 0;
@@ -795,6 +868,8 @@ int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr
{
if(!lib->active)
return 0;
if(version==-2) // don't send global native symbol for a version==-2 search
return 0;
// check in datamaps (but no version, it's not handled there)
if(getSymbolInDataMaps(lib, name, noweak, addr, size))
return 1;
@@ -838,6 +913,52 @@ lib_t* GetMaplib(library_t* lib)
return lib->maplib;
}
linkmap_t* getLinkMapLib(library_t* lib)
{
linkmap_t* lm = my_context->linkmap;
while(lm) {
if(lm->l_lib == lib)
return lm;
lm = lm->l_next;
}
return NULL;
}
linkmap_t* addLinkMapLib(library_t* lib)
{
if(!my_context->linkmap) {
my_context->linkmap = (linkmap_t*)calloc(1, sizeof(linkmap_t));
my_context->linkmap->l_lib = lib;
return my_context->linkmap;
}
linkmap_t* lm = my_context->linkmap;
while(lm->l_next)
lm = lm->l_next;
lm->l_next = (linkmap_t*)calloc(1, sizeof(linkmap_t));
lm->l_next->l_lib = lib;
lm->l_next->l_prev = lm;
return lm->l_next;
}
void removeLinkMapLib(library_t* lib)
{
linkmap_t* lm = getLinkMapLib(lib);
if(!lm) return;
if(lm->l_next)
lm->l_next->l_prev = lm->l_prev;
if(lm->l_prev)
lm->l_prev->l_next = lm->l_next;
free(lm);
}
void AddMainElfToLinkmap(elfheader_t* elf)
{
linkmap_t* lm = addLinkMapLib(NULL); // main elf will have a null lib link
lm->l_addr = (Elf32_Addr)GetElfDelta(elf);
lm->l_name = my_context->fullpath;
lm->l_ld = GetDynamicSection(elf);
}
static int is_neededlib_present(needed_libs_t* needed, library_t* lib)
{
if(!needed || !lib)
+16
View File
@@ -1,6 +1,7 @@
#ifndef __LIBRARY_PRIVATE_H_
#define __LIBRARY_PRIVATE_H_
#include <stdint.h>
#include <elf.h>
#include "custommem.h"
#include "khash.h"
@@ -105,4 +106,19 @@ typedef struct map_onedata_s {
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int version, const char* vername, int local); // Add bridges to functions
typedef struct linkmap_s {
// actual struct link_map
Elf32_Addr l_addr;
char* l_name;
Elf32_Dyn* l_ld;
struct linkmap_s *l_next, *l_prev;
// custom
library_t* l_lib;
} linkmap_t;
linkmap_t* getLinkMapLib(library_t* lib);
linkmap_t* addLinkMapLib(library_t* lib);
void removeLinkMapLib(library_t* lib);
#endif //__LIBRARY_PRIVATE_H_
Loaded 100 of 393 files, more files were not shown because too many files have changed in this diff. Show more