660 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
ptitSeb 5368285be0 Bumped version to v0.2.4 2021-11-19 21:57:50 +01:00
ptitSeb 096ff18ee8 Update CHANGELOG.md 2021-11-19 21:41:31 +01:00
ptitSeb 2cde569916 [DYNAREC] Small cosmetic change 2021-11-19 21:41:15 +01:00
ptitSeb f0afcb2e62 [DOC] Small change to COMPILE.md, especially for i386 build 2021-11-19 15:39:12 +01:00
ptitSeb 5b606a785d [DYNAREC] Added an option to simulate Strong Memory Model, and auto activate it when libmonobdgcw-2.0.so is detected 2021-11-19 15:34:57 +01:00
ptitSeb 6bfa4a390c [DYNAREC] Disable BigBlock when libmonobdwgc-2.0.so is loaded 2021-11-19 13:48:53 +01:00
ptitSeb 1b91e9d614 [TRACE] Fixed trace on function from a dlopen library not triggering properly 2021-11-19 13:46:30 +01:00
ptitSeb bff458d636 [DYNAREC] Change mutex locks a bit on Dynablock / Memorymap handling (backported from box64) 2021-11-19 13:44:40 +01:00
ptitSeb 8814b73eb3 [DYNAREC] Improved cancelling of FillBlock (backported from box64) 2021-11-19 13:02:23 +01:00
ptitSeb d116855eb8 [DYNAREC] Added an option to disable BigBlock building (backported from box64) 2021-11-19 12:10:47 +01:00
ptitSeb 5dd4a31f17 Merge pull request #501 from Seas0/tokitori2+fix
Adding missing macro for Tokitori 2+ patch to fix compile error …
2021-11-19 10:39:52 +01:00
ptitSeb a32bf25289 Update CMakeLists.txt 2021-11-19 10:38:02 +01:00
Seas0 eac21c4f59 Adding missing macro for Tokitori 2+ patch to fix compile error for RK3288 and etc. 2021-11-19 17:23:52 +08:00
ptitSeb f4f5cb2e80 Merge pull request #500 from Seas0/master
chores: adding auto build via Github Action and some typo fix
2021-11-19 10:16:59 +01:00
Seas0 f559a75353 fix typo (GAMEHELL -> GAMESHELL) 2021-11-19 17:04:30 +08:00
Seas0 aff26ce1c0 Adding Github Action auto build 2021-11-19 16:59:25 +08:00
ptitSeb 49717bf706 Added tokitori2+ patch to Oyra/Pandora/RK3288 and GO Advanced clones 2021-11-15 17:44:52 +01:00
ptitSeb 283eecadd6 Added some missing Vulkan wrapped function (now dxvk 1.9.2 works with wine on Radeon mesa driver) 2021-11-14 14:08:12 +01:00
ptitSeb 9069f56a9d [TRACE] Improve symbol name in LOG=2 (backported for box64) 2021-11-14 12:08:00 +01:00
ptitSeb 422c095ebf [TRACE] reduce code under mutex for x86int3 trace 2021-11-14 11:33:03 +01:00
ptitSeb 8373bee595 Fixed ResolveFile, so execvp doesn't sefgfault when executale is not found (help Wine when ntl_auth is not found) 2021-11-14 10:42:20 +01:00
ptitSeb a474c66e26 [DYNAREC] Optimzed ROR Eb, 1 and ROL Eb, 1 opcodes 2021-11-09 18:45:58 +01:00
ptitSeb b933efedd1 [DYNAREC] Fixed shrd32 optimization 2021-11-09 18:38:33 +01:00
ptitSeb 8719e9a857 [DYNAREC] Fixed SUBSET flags handling again (fixes sound in zsnes) 2021-11-08 18:38:06 +01:00
ptitSeb 2995c5312e [DYNAREC] Optimized shrd32 opcode 2021-11-07 20:36:07 +01:00
ptitSeb 0bed0d5b9c [DYNAREC] Fixed rare case or ROR and ROL with u8=0 2021-11-07 18:41:28 +01:00
ptitSeb 4e4d4515d0 [DYNAREC] Optimized RCR Ed, 1 opcode 2021-11-07 18:35:29 +01:00
ptitSeb 6b46117211 [DYNAREC] Optimized 66 F7/6 DIV opcode 2021-11-07 18:00:10 +01:00
ptitSeb 679dbafc9e Fixed some borderline cases with CMPSS opcode ([DYNAREC] too) 2021-11-07 09:15:05 +01:00
ptitSeb f6415a746c Added a few more gtk3 and co wrapped functions 2021-11-06 16:54:05 +01:00
ptitSeb b5623128b2 Merge pull request #494 from rajdakin/printerfix
Fixed some ARM instructions in the printer
2021-11-04 11:38:50 +01:00
rajdakin cdcf85bdfa Fixed some issues 2021-11-04 11:31:51 +01:00
rajdakin 41f301c3c4 Fixed some ARM instructions in the printer 2021-11-04 11:18:11 +01:00
ptitSeb 2641c5b274 Fixed RK3288 profile (for #493) 2021-11-03 21:28:58 +01:00
ptitSeb 9f4c37104a [DYNAREC] Optimized fxam 2021-11-02 21:19:42 +01:00
ptitSeb 428d59a1b0 [DYNAREC] More changes to flags optimisations 2021-11-01 17:52:49 +01:00
ptitSeb f3532ccb99 [DYNAREC] Math on ESP don't needs X_PEND or X_ALL flags 2021-11-01 14:08:06 +01:00
ptitSeb 64f7ff5880 [DYNAREC] Fixed LOCK prefix with Memory Barrier (speedup Wine D3D games) 2021-10-31 12:20:47 +01:00
ptitSeb 79fd8562bf [DYNAREC] Added DMB emitter 2021-10-31 11:10:18 +01:00
ptitSeb b2aab80ef0 [DYNAREC] Simplified Flag propagation 2021-10-31 11:02:34 +01:00
ptitSeb cb9698a5b0 Added wrapped libtbbmalloc 2021-10-30 22:50:37 +02:00
ptitSeb 3c0ac75fc7 Merge pull request #490 from Moldytzu/master
compiling instructions for Tinker Board 1/1S
2021-10-30 22:46:40 +02:00
ptitSeb 00c7e88da0 Added procision on building with ARM_DYNAREC without hardware profile (for #489 and #487) 2021-10-30 22:45:18 +02:00
Alex e26d7981b0 compiling instructions for Tinker Board 1/1S 2021-10-30 23:45:13 +03:00
ptitSeb 2d184211bf Merge pull request #488 from Danct12/a64
Add A64 profile
2021-10-30 19:39:52 +02:00
Danct12 1d7072bf86 Add A64 to docs/COMPILE.md 2021-10-30 22:35:53 +07:00
Danct12 33401074e7 Add A64 profile 2021-10-30 22:33:59 +07:00
ptitSeb 35fcd0b269 Added DATAVM macro for wrapped functions 2021-10-30 16:48:03 +02:00
ptitSeb 6ce9ba83df [DYNAREC] Added FPU in some CFLAGS and ASMFLAGS (to help #487) 2021-10-30 15:33:19 +02:00
ptitSeb 0ee881cf0d Added Phytium paragraph to COMPILE.md 2021-10-30 12:11:56 +02:00
ptitSeb 9bf5db778b Better wrapping for xmlParseChunk (should help #486) 2021-10-30 12:09:08 +02:00
ptitSeb bcdeff5217 [DYNAREC] Force architecture to armv7 if using DYNAREC without any hardware profile (may help #487) 2021-10-30 10:11:19 +02:00
ptitSeb 4a7c16c336 Fixed wrapped __pthread_mutex_destroy that was exported 2021-10-28 19:28:38 +02:00
ptitSeb fa4b5fe75a Aligned one more Vk structure 2021-10-27 22:23:41 +02:00
ptitSeb 7cf983f765 Updated the CHANGELOG 2021-10-27 19:43:30 +02:00
ptitSeb 102e0a8ab3 Added a comment, internal note of a todo 2021-10-27 19:43:30 +02:00
ptitSeb 754d7fc8a6 Detect box64 and export 64bits system if present 2021-10-24 19:08:58 +02:00
ptitSeb 79d355668f Optimized (and small fixes) to custom allocator ([DYNAREC] Speedup long launch time) 2021-10-24 19:06:36 +02:00
ptitSeb 189cd84c41 Wrapped libtcmalloc.so.0 the same as libtcmalloc_minimum.so.4 2021-10-23 17:16:45 +02:00
ptitSeb a5b13f592b Better wrpaping for g_initable_new 2021-10-23 10:29:46 +02:00
ptitSeb 987c87595a Fixed a warning 2021-10-23 10:26:29 +02:00
ptitSeb dc26964fd2 Added libdl as a dependancy for libX11 2021-10-22 19:56:38 +02:00
ptitSeb 5a94979c69 Added one more cairo function (for steam) 2021-10-22 10:29:11 +02:00
ptitSeb 028f700093 Merge pull request #484 from Heasterian/patch-4
Update CMakeLists.txt
2021-10-21 20:19:43 +02:00
Heasterian e782ffc98d Update CMakeLists.txt
Fix SD845 building without dynarec.
2021-10-21 21:06:24 +03:00
ptitSeb 6675da0661 Added a few symbol in wrapped libcairo 2021-10-21 10:43:26 +02:00
ptitSeb ba965fce28 Proper fix for link issue on glibc 2.34+ (for #479) 2021-10-20 23:51:42 +02:00
ptitSeb aeca17a36f Merge pull request #480 from Heasterian/patch-3
Add Snapdragon 845 compilation
2021-10-17 22:18:27 +02:00
Heasterian 0e64848623 Update COMPILE.md
Changes about compilation on Snapdragon 845 devices
2021-10-17 21:42:59 +03:00
Heasterian 52bf1907c5 Update CMakeLists.txt
Adding configuration for Snapdragon 845 devices.
2021-10-17 21:39:47 +03:00
ptitSeb 40a2e18034 [TRAVIS] Change to use graviton2 for arm build 2021-10-14 21:15:50 +02:00
ptitSeb 535db78525 Improved ucomiss test17 with minss and maxss testing 2021-10-10 20:11:01 +02:00
ptitSeb aee4ee9430 [DYNAREC] Changed trace a bit to be more explicit for ST as float 2021-10-10 17:03:57 +02:00
ptitSeb 20fd7e5b23 [DYNAREC] Another small optim for FSTP STx, ST0 opcode 2021-10-10 16:48:50 +02:00
ptitSeb 1cf3dd1cb1 [DYNAREC] Small optim for UCOMI-typed opcodes 2021-10-10 16:19:38 +02:00
ptitSeb a9a88c2f6e [DYNAREC] Small fix to FNSTSW AX and optim to FNSTSW mem opcodes 2021-10-10 16:01:06 +02:00
ptitSeb 1b8dd6fa19 [DYNAREC] Optim: don't insert a barrier for conditionnal jump that goes out of the block 2021-10-10 15:09:37 +02:00
ptitSeb cffafe8b65 [DYNAREC] Now that pass0 create insts on the fly, remove all insts existance tests 2021-10-10 10:44:58 +02:00
ptitSeb 1d2752a0be [DYNAREC] Small optim on FSTP Stx, ST0 opccode 2021-10-10 10:27:31 +02:00
ptitSeb 6151667c84 [DYNAREC] Small cosmetic change 2021-10-10 10:18:21 +02:00
ptitSeb d87c72298f [DYNAREC] x87 use float when possible 2021-10-10 10:14:45 +02:00
ptitSeb 2e1b3d23dc [DYNAREC] Pass0 now doing jump/barrier instead of pass 1 2021-10-08 09:07:40 +02:00
ptitSeb 1955c22501 [DYNAREC] Added a few more F32 emiters 2021-10-07 20:08:13 +02:00
ptitSeb 6378359fd8 [DYNAREC] Track of neon cache per intruction block now 2021-10-07 17:48:11 +02:00
ptitSeb fe83210938 [DYNAREC] Fixed some VCTV printer 2021-10-07 17:47:22 +02:00
ptitSeb aae0a76d2b Added a few more libc wraped functions (for #472, but still some symbols missing) 2021-10-07 17:46:42 +02:00
ptitSeb 34d7177768 [DYNAREC] New tracking of neon regs cache (1st step: improve trace) 2021-10-07 08:14:01 +02:00
ptitSeb 28131360b2 Added a new x87 test 2021-10-07 08:11:59 +02:00
ptitSeb 7e0f3af5a0 Small fix to elfloader (fixed ut99 4.51 that was broken for a long time, didn't broke CMR) 2021-10-04 23:44:04 +02:00
ptitSeb cb6c9e8ceb Added a few more vkalign structs 2021-10-04 22:08:23 +02:00
ptitSeb b30a071783 Fixed a warning 2021-10-02 22:35:15 +02:00
ptitSeb 0e8ab73e49 Added some hack so d3dadapter9 is loaded automaticaly when asked 2021-10-02 15:30:51 +02:00
ptitSeb 7475e7f68d More work on Vulkan alignment 2021-10-02 14:23:37 +02:00
ptitSeb 25902550fa Added VK_EXT_tooling_info to vulkan 2021-10-02 12:42:09 +02:00
ptitSeb 883b7bf054 Added VK_NV_coverage_reduction_mode to vulkan 2021-10-02 12:40:00 +02:00
ptitSeb b3077791b2 Added VK_KHR_fragment_shading_rate to vulkan 2021-10-02 12:37:36 +02:00
ptitSeb 46fbe2a9a8 Added VK_NV_cooperative_matrix to vulkan 2021-10-02 12:34:29 +02:00
ptitSeb d5fab7c7b1 More changes to how vkInstanceGetProcAddr is handled 2021-10-02 12:31:37 +02:00
ptitSeb 860a404cb1 Better debug info for vulkan wrapper 2021-10-02 11:53:06 +02:00
ptitSeb 0fa9c01549 One more vulkan extension 2021-10-02 11:51:12 +02:00
ptitSeb b34652d862 Added 2 more wrapped Vulkan functions 2021-10-02 11:06:47 +02:00
ptitSeb fcd7578b9a Added Phytium profile 2021-10-02 09:58:25 +02:00
ptitSeb f5e0c61d12 Do not enable box64 in box86 yet 2021-09-29 19:21:48 +02:00
ptitSeb 92d2d2c638 Added more gtk3 wrapped functions 2021-09-29 19:07:33 +02:00
ptitSeb 79a1dc0564 Improved gtk3 wrapping(ePSXe runs now 2021-09-28 21:53:19 +02:00
ptitSeb a22c0d3343 Small fix to GSourceFuncs wrapping 2021-09-28 20:03:33 +02:00
ptitSeb 46114235f9 Added handling of GDBusObjectManagerClientClass wrapping 2021-09-26 18:26:22 +02:00
ptitSeb 2bb62e419d More work on gtk wrapping 2021-09-25 13:33:18 +02:00
ptitSeb ac6f71b188 Added wrapping of GtkTable and GtkFixed structures 2021-09-25 13:17:55 +02:00
ptitSeb a438985c8c Added minimum wrapped libsecret-1 2021-09-25 13:08:08 +02:00
ptitSeb 9f310e6be2 More simplifation of some wrapped files 2021-09-25 11:27:45 +02:00
ptitSeb edfb61a452 Simplifed wrappedglibc2 2021-09-25 10:41:27 +02:00
ptitSeb 3b30a559b6 Added wrapped g_signal_connect_object and simplified wrappedgobject2 2021-09-25 10:37:20 +02:00
ptitSeb 497d4dc804 Fixed SDL_vsnprintf signature (for #469) 2021-09-24 18:41:12 +02:00
ptitSeb 631856ae54 Added tantative 0F 00 /1 STR opcode (for #406) 2021-09-23 19:58:32 +02:00
ptitSeb 8b887c7714 Improved elfload and mmap (should help #467) 2021-09-22 08:53:11 +02:00
ptitSeb 852f6af362 Added more wrapped function and wrapped libs to nss3+friends (for #466, but still unstable) 2021-09-21 20:58:50 +02:00
ptitSeb cd6cb2352f This should help for alternate handling 2021-09-21 20:56:21 +02:00
ptitSeb 5bc7a1bf4f Small cosmetic change 2021-09-21 20:54:10 +02:00
ptitSeb 844566a78a Added empty wrapped libgconf-2 2021-09-20 21:53:14 +02:00
ptitSeb 2320c0de77 Fixed a small bug with gtk wrapping 2021-09-20 21:52:30 +02:00
ptitSeb 6afddae6d8 [DYNAREC] Improved 0F 0B UD2 opcode handling 2021-09-18 18:35:50 +02:00
ptitSeb 5de22d4ce1 Fixed execvp wrapping 2021-09-18 17:58:52 +02:00
ptitSeb 3162ae83b4 Added wrapped libnspr4, libsmime3, libnssutil3 and libnss3 2021-09-18 16:19:53 +02:00
ptitSeb e5bcae6e43 Forgot to export my_modify_ldt 2021-09-18 12:51:20 +02:00
ptitSeb a110b60a2a Try to use mmap first when loading elf file into memory 2021-09-18 08:36:46 +02:00
ptitSeb 9190a20ca1 Added better vsyscall support, and fixed some issues with alternate address handling 2021-09-12 13:40:00 +02:00
ptitSeb 7a7f746782 Fixed a warning in a wrapped libc function 2021-09-12 10:04:09 +02:00
ptitSeb 6c148b77a1 Small adjustment in one SDL2 function signature 2021-09-12 09:54:14 +02:00
ptitSeb e30eae7652 [README] Added a precision on 64bis build and box64 existance (for #459) 2021-09-11 15:44:52 +02:00
ptitSeb 811ffe83f8 Merge pull request #458 from Heasterian/patch-2
Note for Tegra users
2021-09-11 12:26:54 +02:00
Heasterian ae8d61c3a3 Note for Tegra users 2021-09-11 13:23:22 +03:00
ptitSeb 0e54aaf70f Merge pull request #455 from JohnnyonFlame/goa_clone_pr
General fixes and definitions for GO Advance clones
2021-09-05 15:52:26 +02:00
ptitSeb 4498f216a0 [TRAVIS] Remove ctest for armhf 2021-09-05 15:50:13 +02:00
ptitSeb 3b4a1e6861 [TRAVIS] nope, adding armhf arch using dpkg didn't changed anything 2021-09-05 15:40:21 +02:00
ptitSeb 83a9f96f20 [TRAVIS] try to add 32bits archs 2021-09-05 15:30:29 +02:00
JohnnyonFlame dad2601f0d Provide a fake passwd struct on getpwuid failure.
Fixes Chowdren games dereferencing an offset of a NULL pointer on 351ELEC when getpwuid fails and Chowdren fails to gracefully recover.
2021-09-05 10:27:28 -03:00
JohnnyonFlame fb79a9eb22 Added variable BOX86_FORCE_ES to force a specific OpenGL ES Context version on SDL_CreateWindow calls. 2021-09-05 10:27:28 -03:00
JohnnyonFlame 5fded645fb Added SDL_DYNAPI_entry wrapper. 2021-09-05 10:27:28 -03:00
ptitSeb 84f16804bb [TRAVIS] and added libgcc1-i386-cross on amd64 platform 2021-09-05 15:19:11 +02:00
ptitSeb e6969267e9 [TRAVIS] Added build badge on README 2021-09-05 15:13:52 +02:00
ptitSeb 1655a98997 [TRAVIS] and added some gcc-multilib on amd64 platform 2021-09-05 15:11:28 +02:00
ptitSeb 4444bd2286 [TRAVIS] disable ctest on arm build, arm64 VM doesn't seems capable of running armhf code 2021-09-05 15:07:44 +02:00
ptitSeb fe402954f8 [TRAVIS] Try to add i386 multi arch for amd64 build 2021-09-05 14:58:59 +02:00
ptitSeb 9ae3543879 [TRAVIS] Yet another fix for script syntax 2021-09-05 14:56:17 +02:00
ptitSeb e88fa9ab45 [TRAVIS] Another fix for script syntax 2021-09-05 14:52:41 +02:00
ptitSeb c707150666 [TRAVIS] Fix script syntax 2021-09-05 14:49:41 +02:00
ptitSeb c2e5f60526 [TRAVIS] Try some travis build (arm and x86) 2021-09-05 14:46:00 +02:00
JohnnyonFlame 395629f678 Added GOA_CLONE definitions.
Sets compilation definitions for GO Advance clones, such as the RG351p/v, Gameforce Chi, RGB10 and other such devices.
2021-09-05 08:32:27 -03:00
ptitSeb f77b80899d Added major contributor list in README 2021-09-05 11:28:31 +02:00
ptitSeb 5720619bd2 [DYNAREC] Fixed (again) 16bits and 32bits BTR/BTS/BTC with imm8==0 (help steam) 2021-09-04 12:12:21 +02:00
ptitSeb e33ac88379 Merge pull request #454 from ye-yeshun/master
fix LDS and LES
2021-09-02 08:05:30 +02:00
ye-yeshun 96c9bf168e Merge branch 'ptitSeb:master' into master 2021-09-02 13:24:15 +08:00
Yeshun Ye 3711622f66 fix: fix errors of 'LDS' and 'LES'.
Signed-off-by: Yeshun Ye <[email protected]>
2021-09-02 13:06:05 +08:00
ptitSeb a3cd9f7de7 Added 64 39 opcode ([DYNAREC] too) 2021-09-01 20:22:48 +02:00
ptitSeb 389927dc1d Added 65 31 opcode ([DYNAREC] too) (for #425) 2021-08-29 18:18:38 +02:00
ptitSeb ff63fa7437 [DYNAREC] Small fix for 8bits ror/rol when imm8!=0 and imm8&7==0 2021-08-29 16:02:22 +02:00
ptitSeb b480d6856b [DYNAREC] Fixed 16bits BTS/BTR/BTC with imm8==0 (helps EWJ SE Win95, probably other too) 2021-08-29 15:15:19 +02:00
ptitSeb 76786e9e43 [DYNAREC] Fixed BTS/BTR/BTC with imm8==0 (helps EWJ SE Win95, probably other too) 2021-08-29 14:50:46 +02:00
ptitSeb aa9ff80137 [DYNAREC] Small optim on flag for BTC/BTR/BTS/BSF/BSR opcodes 2021-08-29 10:38:26 +02:00
ptitSeb 2e60a6b6e7 [DYNAREC] Added a YIELD opcode for F3 90 PAUSE opocde (instead of nothing) 2021-08-29 09:01:23 +02:00
ptitSeb f24684f478 [DYNAREC] Small optim for LOCK opcodes with fixed addresses 2021-08-28 19:12:50 +02:00
ptitSeb f43a507e91 Allow older version of python to be used 2021-08-27 16:02:42 +02:00
ptitSeb 25f7283af9 Redone some of the wrapping of freetype to be consistant with other wrapping 2021-08-27 10:01:21 +02:00
ptitSeb ea29d3f6df Merge pull request #451 from ye-yeshun/master
add 'palignr' 'psignw' 'lzcnt' instructions.
2021-08-27 08:52:19 +02:00
ptitSeb 1592f9246b Merge pull request #450 from wannacu/master
use GOM to wrap FT_Outline_Decompose (libfreetype)
2021-08-27 08:45:02 +02:00
ptitSeb b481c25ee5 Merge branch 'master' into master 2021-08-27 08:44:54 +02:00
ptitSeb e6fa77b3c0 Fix build on ARM platform 2021-08-27 08:39:01 +02:00
ptitSeb 3da5f56257 Merge pull request #449 from rajdakin/rebuild_wrappers
Upgrade of the rebuild_wrappers script (and a bit more)
2021-08-27 07:55:54 +02:00
Yeshun Ye d97dfa768a Add 'LZCNT' instruction.
Signed-off-by: Yeshun Ye <[email protected]>
2021-08-27 11:41:58 +08:00
Yeshun Ye 1d671b104b Add 'PSIGNW' instruction.
Signed-off-by: Yeshun Ye <[email protected]>
2021-08-27 11:40:33 +08:00
Yeshun Ye d7cb28a66b Add 'palignr' instruction.
Signed-off-by: Yeshun Ye <[email protected]>
2021-08-27 11:38:28 +08:00
rajdakin d153456653 Bug fixes and version bump 2021-08-27 01:12:12 +02:00
rajdakin ad77202a05 Last step in upgrading the rebuild_wrappers script 2021-08-27 00:39:29 +02:00
rajdakin 20ffd3681e Fixed the same minor issue as in box64 2021-08-27 00:30:41 +02:00
rajdakin d66c1f4510 Added GOWM, GOWS, GOW2 support 2021-08-27 00:29:42 +02:00
rajdakin fcdd6f7947 Fixed bz2's stream unwrapping 2021-08-27 00:01:19 +02:00
rajdakin 1b54190c15 First step at upgrading the script 2021-08-26 23:23:49 +02:00
rajdakin 7550203dc9 Fixed some wrapper headers 2021-08-26 23:20:08 +02:00
wannacu 380e9fa09e use GOM to wrap FT_Outline_Decompose (libfreetype) 2021-08-26 23:03:11 +08:00
ptitSeb c04aeec3e5 Fixed wine/vulkan paragraph in README (for #445) 2021-08-23 10:28:04 +02:00
ptitSeb b758d842c4 Added some precisions to Vulkan support in README 2021-08-22 09:20:07 +02:00
ptitSeb ff9da0c850 Merge pull request #444 from chunky-milk/master
move LICENSE back to root
2021-08-22 09:11:44 +02:00
Ryan Fortner 87681ffcaa move LICENSE back to root 2021-08-21 14:04:53 -04:00
ptitSeb 47c33cd5a9 cancelFillBlock is DYNAREC only (for #443) 2021-08-21 17:44:49 +02:00
ptitSeb ea9e9da829 Improved handling of default version symbol (HalfLife, and probably other, works now) 2021-08-12 17:22:40 +02:00
ptitSeb 0ffcfcb0c0 Added a few more gnutls wrapped functions 2021-08-12 10:11:14 +02:00
ptitSeb 132d2dc3fc Added one gnutls function 2021-08-12 09:33:17 +02:00
ptitSeb de61c33093 Fixed BOX86_JITGDB=2 not working 2021-08-11 17:06:12 +02:00
ptitSeb 38b12c9773 Small fixes to some thread wrapped functions 2021-08-11 12:09:26 +02:00
ptitSeb 2734536fa7 [DYNAREC] Added handling of Segfault triggered while FillBlock is running, to just cancel the dynablock and use interpretor there 2021-08-11 10:46:08 +02:00
ptitSeb d4e7852598 Small adjustment with vorbisfile wrapping 2021-08-10 10:17:46 +02:00
ptitSeb fd3da6af08 Change lock order in relock function, just in case 2021-08-10 10:15:45 +02:00
ptitSeb de3ec8e7af Small fix to longjump inside signal handling 2021-08-09 13:55:21 +02:00
ptitSeb 2256560985 Some more work on signal handling to try avoid deadlock 2021-08-09 12:00:53 +02:00
ptitSeb 342ee45558 Added 65 D0/D2 opcodes 2021-08-07 20:04:03 +02:00
ptitSeb c207597409 Some more small changes to signal handling, again 2021-08-07 19:49:40 +02:00
ptitSeb 2f5198eb9f Check protection status before recomputing a hask of a block (not sure it's really usefull) 2021-08-07 19:49:19 +02:00
ptitSeb 96fb201246 Added test about longjmp in singal handling 2021-08-05 07:49:57 +02:00
ptitSeb ff36508548 Change Signal handling to always use sigaction, and improve longjmp in signal handler handling 2021-08-04 18:07:36 +02:00
ptitSeb 02612749c8 Merge pull request #434 from piz-ewing/master
Fixed INC/DEC (for lazy flags)
2021-08-04 08:33:14 +02:00
piz-ewing 7648cd9a56 Fixed INC/DEC (for lazy flags) 2021-08-04 14:28:23 +08:00
ptitSeb 95feb02d97 Add a precision for PI4 on 64bits OS in COMPILE.md 2021-08-03 15:00:09 +02:00
ptitSeb 36a49e135e Merge pull request #432 from wannacu/master
[DYNAREC] Added 66 0F 38 06 opcode
2021-08-03 08:28:37 +02:00
Zhipeng Zhao 8fe7b90daa [DYNAREC] Added 66 0F 38 06 opcode 2021-08-03 14:09:13 +08:00
ptitSeb 238103a5e0 Added wrapped modify_ldt to libc (for #424) 2021-08-01 08:24:55 +02:00
ptitSeb 72e0d80af9 Merge pull request #427 from lifning/master
Add a couple stubs for SDL 2.0.14 & Fix ld-linux.so wrapper for ppcle
2021-07-29 23:26:48 +02:00
lifning 21b61f07da Add SDL_GameControllerHasLED and SDL_GameControllerHasSensor stubs from SDL 2.0.14 (used by recent versions of FNA) 2021-07-29 12:29:13 -07:00
lifning 1d67fb050c Use proper ld-linux.so ALTNAME2 on little-endian PowerPC 2021-07-29 12:28:04 -07:00
ptitSeb 40eaacc33b Added /lib/box86 and /usr/lib/box86 to default BOX86_LD_LIBRARY_PATH 2021-07-28 21:51:06 +02:00
ptitSeb 4b47e699f5 Added many libGL extension (from box64) 2021-07-28 21:49:40 +02:00
ptitSeb d845f048ea Added 65 29 opcode ([DYNAREC] too) (for #425) 2021-07-28 14:27:24 +02:00
ptitSeb e70dc0af56 Added 65 D1/D3 opcodes ([DYNAREC] too) (for #425) 2021-07-28 14:16:40 +02:00
ptitSeb 3c3c64f3c7 [DYNAREC] Fixed 65 0F AF opcode (for #425) 2021-07-28 12:11:34 +02:00
ptitSeb 87a9ce334a Added 65 0F AF opcode ([DYNAREC] too) (for #425) 2021-07-28 11:36:38 +02:00
ptitSeb ace58063e4 Added 65 21 opcode ([DYNAREC] too) (for #425) 2021-07-28 11:18:58 +02:00
ptitSeb 33ef14cd5d Added 65 23 opcode ([DYNAREC] too) (for #425) 2021-07-27 13:35:54 +02:00
ptitSeb 4f6196b330 Merge pull request #422 from icecream95/vtable_internal
Set the internal vtable for D3D9 structs
2021-07-23 09:58:42 +02:00
Icecream95 fbe1ff93e9 Set the internal vtable for D3D9 structs 2021-07-23 10:23:01 +12:00
ptitSeb b2581fccaa Merge pull request #420 from Jai-JAP/aur
Update archlinux/*
2021-07-22 14:40:37 +02:00
Jai-JAP 056e29c9a8 Rename archlinux/ to pkgbuilds/ 2021-07-22 17:44:53 +05:30
Jai A P 0bf409fc10 Update archlinux/* 2021-07-22 17:38:22 +05:30
ptitSeb 6d2a3883ac Change email address in PKGBUILD header 2021-07-22 13:30:39 +02:00
ptitSeb d7dcb56105 Fixed status of C2 x87 flags after sin, cos, sincos and tan function ([DYNCAREC] too) (for #158, thnk @icecream95 for the debugging) 2021-07-21 12:04:18 +02:00
ptitSeb a62a9f6c75 Added wrapped function gtk_input_add_full to gtk2 2021-07-17 15:40:53 +02:00
ptitSeb b4c32dd56b Added a few more gtk2 progress wrapped functions 2021-07-17 14:43:03 +02:00
ptitSeb 3a323abc9a [DYNAREC] Fix potential deadlock (for #417, thx for the hint) 2021-07-16 10:49:17 +02:00
ptitSeb 1fefd5c82c Change COMPILE.md to remove the '-j4' on Pi build instruction, as it can fail depending the amount of memory available, but added a comment for those who wants to use it 2021-07-13 21:57:09 +02:00
ptitSeb e470a28bda Small changes on MOV Ed, Seg and CALL FAR opcodes 2021-07-13 16:45:39 +02:00
ptitSeb 435f1c2a16 Small change to not try to fetch bock at new thread if dynarec is disabled 2021-07-13 16:45:39 +02:00
ptitSeb e9f72c1e33 Merge pull request #411 from WheezyE/patch-1
Update COMPILE.md
2021-07-13 07:35:26 +02:00
Eric Wiessner (KI7POL) f8d8c6c7a4 Update COMPILE.md
just wanted to clarify the info about which flags to use for aarch64 builds a little bit
2021-07-12 17:44:22 -06:00
ptitSeb 0c7022a756 Fixed ELF Signature detection 2021-07-12 22:18:52 +02:00
ptitSeb 7254e5558b Fixed some memory issue when launching box64 from box86 main 2021-07-12 14:29:32 -05:00
ptitSeb 17cdb30ab1 Use box64 to launch x64 binary (if box64 is present in same folder as box86) 2021-07-12 12:38:08 -05:00
ptitSeb db743b1226 Name Trace build as box86 (remove the trailing t) 2021-07-12 11:39:27 -05:00
ptitSeb e9cc8d43a9 Re-splitted mmx and x87 regs (not sure why, but this fixes the Shaking Cam issue in The Witcher 2 for windows) 2021-07-11 16:12:31 +02:00
ptitSeb 4dd9bf74d9 Fixed BOX86_LOG=2 for mmap 2021-07-10 18:33:51 +02:00
ptitSeb 722909a9cf Fixed an issue with memory protection introduced on 1/1/21... 2021-07-10 16:59:14 +02:00
ptitSeb 13287a114c Refined .deb build script with arch naming and postinst 2021-07-10 10:08:15 +02:00
ptitSeb 1a6659d577 Fixed small issue in 66 0F BA opcode 2021-07-10 10:08:15 +02:00
ptitSeb 3a7cc57fde Merge pull request #409 from wannacu/master
Added wrapped libv4l2.so.0
2021-07-09 16:22:42 +02:00
wannacu c093f18d20 Added wrapped libv4l2.so.0 2021-07-09 22:10:54 +08:00
ptitSeb f2ebd77ace First try at building .deb package using cmake CPack 2021-07-09 14:31:54 +02:00
ptitSeb ad55a85b89 Refined handling od flag 0x4 for wrapped dlopen 2021-07-09 11:24:06 +02:00
ptitSeb 779e0bdc50 Handling flag 0x4 for wrapped dlopen 2021-07-09 10:29:05 +02:00
ptitSeb 80c4d80952 Fix non-dynarec build 2021-07-08 09:35:02 +02:00
ptitSeb 42e54c0241 Improved Handling of some TLS Reloc 2021-07-06 19:29:43 +02:00
ptitSeb b393356b4b Removed mutex per bridge and use a global one (remove chance of freeze on fork) 2021-07-06 19:08:04 +02:00
ptitSeb f65555c810 Try to speedup a bit FindR386COPYRel 2021-07-06 18:49:39 +02:00
ptitSeb 174bf29f28 [DYNAREC] Improved CMPSS and CMPSD ocpodes (backported from box64) 2021-07-06 18:42:14 +02:00
ptitSeb 1776027e63 Fixed some potential crash with emulated RW on SDL1 2021-07-06 18:34:32 +02:00
ptitSeb 4018df12cd Try to fix compilation on old libc 2021-07-06 18:33:15 +02:00
ptitSeb c400cd5f61 Added some wrapped function to libXext 2021-07-05 17:50:27 +02:00
ptitSeb 4710c4777e Update README.md 2021-07-03 10:58:21 +02:00
ptitSeb a872136418 [DYNAREC] Improved FILD/FISTP i64 hack 2021-07-03 10:54:00 +02:00
ptitSeb da15c9619a [DYNAREC] Improved PSHUFD opcode 2021-07-03 10:53:11 +02:00
ptitSeb a67b510cae Improved README 2021-07-03 10:52:21 +02:00
ptitSeb c84d1a827e Small changes around wine, wine64 and box86 exitting process 2021-07-03 10:52:05 +02:00
ptitSeb 0e2cac5505 Added pthread_mutexattr_getprotocol wrapped function 2021-07-03 10:51:04 +02:00
ptitSeb aa4f39a51b [DYNAREC] Added some small optim for SSE XOR on same reg 2021-06-29 15:14:41 +02:00
ptitSeb 3c0b7830de Added ucomiss test 2021-06-29 14:35:16 +02:00
ptitSeb 25f43108fe [DYNAREC] Fixed DF /5 FILD opcode, and optimized FILD/FISTP i64 sequence (fixes #404) 2021-06-29 11:46:08 +02:00
ptitSeb da64e491bb Added 66 0F 01 /4 dummy opcode (always 0), for #404 2021-06-28 09:52:09 +02:00
ptitSeb 23fe11278c Merge pull request #403 from WheezyE/patch-2
Update X86WINE.md with cosmetic edits
2021-06-26 22:30:24 +02:00
Eric Wiessner (KI7POL) f27361bf17 Update X86WINE.md with cosmetic edits
Just trying to rearrange and consolidate some info for clarity & brevity.  I added some notes that we will assume users are using the default wine 5.13 version unless otherwise specified.  I also wanted to put the Twister OS FAQ Wine install as the top example since I think it looks more approachable to beginners users and will install a more standard version of wine for bug reports.
2021-06-26 14:12:50 -06:00
ptitSeb 91e0120780 Merge pull request #402 from JinShil/patch-1
Fix typo in README
2021-06-26 08:21:32 +02:00
Mike e4f2af21c3 Fix typo in README 2021-06-26 13:54:45 +09:00
ptitSeb 2edb0ed1e3 [DYNAREC] Another fix for D9 F3 opcode (fixing Neverwinter Night issue #401) 2021-06-23 20:53:39 +02:00
ptitSeb e317c61084 [DYNAREC] Fix D9 F3 opcode (fixing Neverwinter Night issue #401) 2021-06-23 16:24:14 +02:00
ptitSeb 5506dbbc77 Added wrapping of MetaFrames in gtkclasses 2021-06-23 09:45:47 +02:00
ptitSeb 2ed175ee3b Fixed signature for a libXi function 2021-06-23 09:45:19 +02:00
ptitSeb 2a2631075e Try to add some workaround for libs with embedded libtccmalloc (for #400) 2021-06-23 08:35:59 +02:00
ptitSeb 406226bd2b More improvement to elfloader (fixing hlds for #385 and Unreal linux that was broken since elfloader last changes) 2021-06-22 18:40:05 +02:00
ptitSeb 6f105f0720 Added some more detailled trace for 2 wprintf functions 2021-06-22 17:40:39 +02:00
ptitSeb e30430be48 [DYNAREC] Added an inline version of FISTP i64, but disabled for now: it's awfully complex, not sure it's really worth it 2021-06-21 14:43:29 +02:00
ptitSeb 3a52af11bd [DYNAREC] Added optimized MUL 8bits opcode 2021-06-21 11:22:07 +02:00
ptitSeb c73b427d42 Added a few more gtk3 wrapped function (for #398) 2021-06-21 11:16:24 +02:00
ptitSeb 85f5a619ab Added syscall 328 (for #398) 2021-06-20 14:52:51 +02:00
ptitSeb a6d94027db Added some symbol to wrapped gtk3 (for #398) 2021-06-20 14:50:23 +02:00
ptitSeb 45a3044a61 [DYNAREC] Small optim on Purge SSE Cache 2021-06-20 14:48:14 +02:00
ptitSeb d25b3a307e Minor cosmetic chnge to wrapped libc 2021-06-20 14:47:28 +02:00
ptitSeb d5e3bc9ceb [ANDROID] Fixed build (still for #395) 2021-06-18 14:23:39 +02:00
ptitSeb cd8f2997ca [ANDROID] Added wrapped of libandroid-shmem.so (and added some libX11 .so synonym), for #395 2021-06-18 11:03:54 +02:00
ptitSeb df65e97491 Remove Discord link, use github discussion istead 2021-06-17 08:21:22 +02:00
ptitSeb abbb60a4fa Fixed and added a wrapped function to libc 2021-06-17 08:18:51 +02:00
ptitSeb ff05035bc0 Added some more libcrypto wrapped functions 2021-06-16 17:57:05 +02:00
ptitSeb 71d9d78ed5 Added a wrapped function to libSSL 2021-06-16 17:27:35 +02:00
ptitSeb d8b2e96552 Disabled, this is not ready yet 2021-06-16 15:19:41 +02:00
ptitSeb c974ce057e Improved emulated library loader, to not stop at first binary found even if not at the correct architecture 2021-06-16 15:18:30 +02:00
ptitSeb ddbe50c5ef Better wrapping for __snprintf_chk function 2021-06-16 15:08:22 +02:00
ptitSeb 2aaf87bbcf Fixed SDL_HasIntersection signature (fixing To The Moon blank screen) 2021-06-16 15:07:56 +02:00
ptitSeb 8c74fde404 Added some hack to try detect SDL_sound custom build for SDL2 and use emulated one first (fixing some sound in To The Moon) 2021-06-16 15:07:44 +02:00
ptitSeb dbe5afeaba Better trace for soem snprintf functions 2021-06-16 15:06:41 +02:00
ptitSeb 9bf035539b Added even more libcrypto wrapped functions 2021-06-15 16:10:10 +02:00
ptitSeb 5cb73d58cd Added some more libcrypto wrapped functions 2021-06-15 16:07:57 +02:00
ptitSeb 1e3eba1b5b More help for building on old system 2021-06-15 15:35:04 +02:00
ptitSeb 87af935494 Various small warning fixes 2021-06-15 14:52:33 +02:00
ptitSeb 86cc204693 [DYNAREC] Fixed softfp build 2021-06-15 13:40:03 +02:00
ptitSeb d1e6d744ae Minor adjustment to some wrapped libc functions signature 2021-06-15 13:36:39 +02:00
ptitSeb cea3dcea67 [DYNAREC] Fixed detection of softfp float-abi 2021-06-15 13:35:42 +02:00
ptitSeb 72a896a95a Forced BOX86_NOGTK=1 when detecting steam 2021-06-15 08:44:28 +02:00
ptitSeb 9ca0c429bf [DYNAREC] Small fix to shld32c emiter 2021-06-15 08:44:09 +02:00
ptitSeb 681e06ce73 [DYNAREC] Added (U/S)DIV printer 2021-06-12 20:27:36 +02:00
ptitSeb 3a3e393d20 [DYNAREC] Added ror8c emiter, and fixed rol8c 2021-06-12 17:06:36 +02:00
ptitSeb 6b86cb7d1e [DYNAREC] Added rol8c emiter 2021-06-12 16:44:58 +02:00
ptitSeb 4a772f1bb6 [DYNAREC] Remove Need Optim mark for IMUL 16bits 2021-06-12 16:21:33 +02:00
ptitSeb d8309595cf [DYNAREC] Fix previous commit 2021-06-12 16:08:17 +02:00
ptitSeb 6000f4f25c [DYNAREC] Added inline version of FILD i64 opcode 2021-06-12 16:00:49 +02:00
ptitSeb 3cabeb4f27 [DYNAREC] Marked opcode that can use optimizion in DUMP 2021-06-12 14:02:13 +02:00
ptitSeb 53b525d758 [DYNAREC] Added more IDIV handling for ARM DIV (when available) 2021-06-12 13:25:53 +02:00
ptitSeb 06ebc4cb03 [DYNAREC] Fixed detection for DIV / IDIV opcode to alow ARM DIV use (if present) 2021-06-12 12:22:08 +02:00
ptitSeb 25245e2a46 [DYNAREC] More changes on Flags handling, fixing some border cases (like with CLC or other opcode that only do SUBSET of flags) 2021-06-12 11:46:28 +02:00
ptitSeb 4d8adae071 [DYNAREC] Saved xFlags when doing a direct math call in x87 opcodes 2021-06-11 18:50:27 +02:00
ptitSeb d65216df76 Added special opcode handling on signal to regular signal 2021-06-11 18:49:47 +02:00
ptitSeb 155c4ba1f9 [DYNAREC] Fixed XCHG 16bits version opcode 2021-06-11 18:49:12 +02:00
ptitSeb f6ff832e51 [DYNAREC] Added Special case opcode detection for signal, when occur in speiciific palces to adjust registers value (REP MOVS/D/B) and REP(Z/NZ) CMPS(B/D) for now) 2021-06-11 15:36:00 +02:00
ptitSeb 0b4045ffb1 [DYNAREC] Potential fix for rare case of opcode with SUBSET Flags and need for PEND 2021-06-11 15:34:40 +02:00
ptitSeb 677d9feb87 Added a bit more function to wrapped gtk2 2021-06-10 21:16:01 +02:00
ptitSeb 043ac1fdab [DYNAREC] Try to optimize some of the complex x87 opcodes 2021-06-10 17:16:00 +02:00
ptitSeb dacd75ca7e [DYNAREC] Small optim on Native function call (and small fix on stack alignment) 2021-06-10 11:44:18 +02:00
ptitSeb 3e5352f79c [DYNAREC] Try to use IDIV when available 2021-06-09 16:23:15 +02:00
ptitSeb 2f56a667f3 Cpuid now also export HT extension 2021-06-09 16:10:51 +02:00
ptitSeb cefa19ec6a [DYNAREC] Added another special case for SIGSEGV du to heavy multitasking issue with memory protection mapping 2021-06-09 14:27:21 +02:00
ptitSeb ab2ab88581 [DYNAREC] Use ARM 32bits DIV when possible 2021-06-09 12:35:00 +02:00
ptitSeb a5c28c6020 Flags are undefined after a div operation 2021-06-09 12:34:25 +02:00
ptitSeb ac3ddc134e [DYNAREC] Added unsupported 0F AE /5 opcode, to avoid dynablock break 2021-06-09 11:09:27 +02:00
ptitSeb 86659b40bd Some small improvments in signal handling 2021-06-06 17:48:45 +02:00
ptitSeb fd7c7e356c [DYNAREC] Fixed end handling in dynablock construction 2021-06-06 17:48:45 +02:00
ptitSeb 10c4e0323a [DYNAREC] Fixed potential issue with longjmp native function call 2021-06-06 17:48:45 +02:00
ptitSeb 53a647af56 Merge pull request #391 from WheezyE/patch-1
Fix bolded 'Notes about Wine' section in readme
2021-06-05 19:10:16 +02:00
Eric Wiessner (KI7POL) 026185da74 Fix bolded 'Notes about Wine' section in readme 2021-06-05 09:52:10 -06:00
ptitSeb 951a85d3b7 Improved getopt handling 2021-06-05 15:05:15 +02:00
ptitSeb d6db825ec3 [DYNAREC] Various small fixes to flags handling 2021-06-05 10:23:20 +02:00
ptitSeb d9ab158b97 Fixed BT/BTC/BTR/BTS opcodes ([DYNAREC] too) (helped KaM Rmake, probably other) 2021-06-04 21:51:53 +02:00
ptitSeb f9305d58e8 [DYNAREC] Fixed DD C0..C7 FFREE opcode 2021-06-04 16:47:15 +02:00
ptitSeb 8da827d06f Added an option to use stderr for logs 2021-06-04 16:46:43 +02:00
ptitSeb 4ee29a6d57 Improve trace when fpu_stack is incoherent 2021-06-04 16:42:54 +02:00
ptitSeb e060e060af Fixed SDL_JoystickGetGUIDString function signature 2021-06-04 13:14:44 +02:00
ptitSeb 81a63edcbc Improved unloading of libs (helps wine) 2021-06-04 11:06:24 +02:00
ptitSeb 8b1ca1330f Added EE opcode 2021-06-03 23:03:29 +02:00
ptitSeb 7bc1a6d7c7 [DYNAREC] Improve handling of SMC (should help autoextractible/encrypted programs) 2021-06-03 18:04:50 +02:00
ptitSeb 9e24a71225 [DYNAREC] Fixed C0 ROL/ROR opcode (help some versions of WeChat) 2021-06-03 18:03:52 +02:00
ptitSeb 8d89e7efdb Some fine-tunning on wrapped lubncurses and friends 2021-06-03 16:15:13 +02:00
ptitSeb 4ca4e84878 Improved elfloader with COPY and GLOBAL reloc with version 2021-06-03 16:15:06 +02:00
ptitSeb 9461f7d24e Added Global symbol workaround for libtinfo/libncurses 2021-06-03 14:51:22 +02:00
ptitSeb e29ba9e43e Improved PltResolver to search a no version symbol if ver=0 one is not found 2021-06-03 14:50:50 +02:00
ptitSeb a875a16c92 Fixed special case for FSCALE opcode, thx to PCem developper ([DYNAREC] too) 2021-06-03 13:08:20 +02:00
ptitSeb de92a8a41b Added wrapped libpanel and mvprintw function to libncurses 2021-06-02 17:38:10 +02:00
ptitSeb d719809440 Added some more wrapped libGL functions (help apitrace) 2021-06-01 11:06:45 +02:00
ptitSeb 656e7552b5 Improved custom named libGL handling 2021-06-01 11:02:52 +02:00
ptitSeb 9715a2fef6 Added dummy SGDT 0F 01 /0 opcode 2021-05-31 19:04:52 +02:00
ptitSeb 268166b20a Added dummy SLDT 0F 00 /0 opcode 2021-05-31 18:39:08 +02:00
ptitSeb f03fb651c2 Added dummy 0F 01 /1 SIDT opcode 2021-05-31 18:22:51 +02:00
ptitSeb 6b05e42582 Some adjustements to elfloader needed libs loading 2021-05-31 17:49:46 +02:00
ptitSeb 0d42b42459 Added alternate name for libSDL2_image, libSDL2_ttf and libexpat 2021-05-30 20:35:08 +02:00
ptitSeb 2159d407ee Improve handling of freetype FTC_Manager (help wine dwrite font manager) 2021-05-30 10:32:44 +02:00
ptitSeb 2b9645e3a6 Small fixes after big elfloader rework 2021-05-29 18:23:20 +02:00
ptitSeb 5d0d1e4eb2 Fixed some old issue with env. var. parsing, and a bit more help on new BOX86_DUMP one 2021-05-28 11:57:10 +02:00
ptitSeb 0d82e52aa6 Updated docs with the elfloader rework 2021-05-28 11:25:10 +02:00
ptitSeb 28cfc17bb6 Added 2 more wrapped function to pthread 2021-05-28 08:04:39 +02:00
ptitSeb 5c8d387c27 Large refactoring of elfloader 2021-05-27 19:55:17 +02:00
ptitSeb 213f51c14b Wrapped GLX_NV_vertex_array_range functions 2021-05-27 18:45:18 +02:00
ptitSeb d2e5f715a9 Started a new dev. cycle 2021-05-27 18:44:16 +02:00
914 changed files with 41209 additions and 11135 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
+105
View File
@@ -0,0 +1,105 @@
### Auto build Box86 and release its binary with Github Action
name: Build and Release Box86
on:
workflow_dispatch:
release:
push:
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeLists.txt"
- "**/*.yml"
pull_request:
types: [assigned, opened, synchronize, reopened]
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeLists.txt"
- "**/*.yml"
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
type: [Release, Trace]
runs-on: ubuntu-latest
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
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
else
echo BOX86_PLATFORM_MARCRO="-DARM_DYNAREC=ON -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
if [[ ${{ matrix.type }} == 'Release' ]]; then
echo BOX86_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX86_HAVE_TRACE=0 >> $GITHUB_ENV
else
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
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
Executable
+26
View File
@@ -0,0 +1,26 @@
language: c
arch:
- arm64-graviton2
- amd64
os: linux
dist: focal
addons:
apt:
packages:
- python3
compiler:
- gcc
#Build steps
before_script:
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then sudo dpkg --add-architecture armhf ; else sudo dpkg --add-architecture i386 ; fi
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then sudo apt-get -y install gcc-arm-linux-gnueabihf ; else sudo apt-get -y install gcc-multilib libc6-dev:i386 libgcc1:i386 ; fi
- mkdir build
- cd build
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; else CFLAGS="-m32" cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; fi
script:
- make
- if [ "$TRAVIS_CPU_ARCH" != "arm64" ]; then ctest --output-on-failure ; fi
+181 -58
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})
@@ -6,17 +6,23 @@ option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(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})
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR RK3399 OR RPI4ARM64)
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 "")
@@ -46,7 +52,13 @@ else()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
if(RK3399 OR RPI4ARM64)
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)
@@ -66,50 +78,71 @@ endif()
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
endif()
if(GAMESHELL)
add_definitions(-DGAMEHELL)
elseif(GAMESHELL)
add_definitions(-DGAMESHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
endif()
if(PYRA)
elseif(PYRA)
add_definitions(-DPYRA)
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
endif()
if(RPI2)
elseif(RPI2)
add_definitions(-DRPI)
add_definitions(-DRPI2)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
endif()
if(RPI3)
elseif(RPI3)
add_definitions(-DRPI)
add_definitions(-DRPI3)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
endif()
if(RPI4)
elseif(RPI4)
add_definitions(-DRPI)
add_definitions(-DRPI4)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
endif()
if(RPI4ARM64)
elseif(RPI4ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI4ARM64)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
endif()
if(ODROID)
elseif(ODROID)
add_definitions(-DODROID)
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
endif()
if(RK3399)
elseif(RK3288)
add_definitions(-DRK3288)
add_definitions(-mcpu=cortex-a17 -mfpu=neon -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a17 -mfpu=neon -mfloat-abi=hard")
elseif(SD845)
add_definitions(-DSD845)
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(A64)
add_definitions(-DA64)
add_definitions(-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(GOA_CLONE)
add_definitions(-DGOA_CLONE)
add_definitions(-marm -mcpu=cortex-a35 -mfpu=neon-vfpv3 -march=armv8-a+crc+simd+crypto -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a35 -mfpu=neon-vfpv3 -march=armv8-a+crc+simd+crypto -mfloat-abi=hard")
elseif(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+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")
endif()
if(POWER9)
@@ -123,7 +156,7 @@ endif()
if(BOX86LIB)
set(BOX86 box86)
elseif(HAVE_TRACE)
set(BOX86 box86t)
set(BOX86 box86)
else()
set(BOX86 box86)
endif()
@@ -137,6 +170,7 @@ endif()
if(NOALIGN)
add_definitions(-DNOALIGN)
add_definitions(-pipe -march=core2 -msse2)
endif()
if(HAVE_TRACE)
@@ -216,6 +250,9 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/elfs/elfload_dump.c"
"${BOX86_ROOT}/src/librarian/library.c"
"${BOX86_ROOT}/src/librarian/librarian.c"
"${BOX86_ROOT}/src/librarian/dictionnary.c"
"${BOX86_ROOT}/src/librarian/symbols.c"
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
@@ -332,8 +369,11 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${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"
@@ -343,8 +383,15 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgobject2.c"
"${BOX86_ROOT}/src/wrapped/wrappedglib2.c"
"${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"
@@ -376,8 +423,31 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibtiff.c"
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX86_ROOT}/src/wrapped/wrappedcrashhandler.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibv4l2.c"
"${BOX86_ROOT}/src/wrapped/wrappednspr4.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmime3.c"
"${BOX86_ROOT}/src/wrapped/wrappednssutil3.c"
"${BOX86_ROOT}/src/wrapped/wrappednss3.c"
"${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(NOT ANDROID)
if(ANDROID)
list(APPEND WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedandroidshmem.c"
)
else()
list(APPEND WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
@@ -387,7 +457,7 @@ endif()
# If BOX86_ROOT contains a ".c", the build breaks...
string(REPLACE ".c" "_private.h" MODROOT ${BOX86_ROOT})
set(WRAPPEDS_HEAD "")
set(WRAPPEDS_HEAD "${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9_genvate.h")
foreach(A ${WRAPPEDS})
string(REPLACE ".c" "_private.h" C ${A})
string(REPLACE "${MODROOT}" "${BOX86_ROOT}" B ${C})
@@ -456,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"
)
@@ -513,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")
@@ -533,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)
@@ -554,9 +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)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
@@ -565,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)
@@ -577,92 +647,145 @@ if(NOT TARGET uninstall)
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION "Box86 - Linux Userspace x86 Emulator with a twist")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MAJOR\\s*")
string(REGEX REPLACE "BOX86_MAJOR" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX86_MAJOR ${TEMP_STRING})
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MINOR\\s*")
string(REGEX REPLACE "BOX86_MINOR" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX86_MINOR ${TEMP_STRING})
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_REVISION\\s*")
string(REGEX REPLACE "BOX86_REVISION" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX86_REVISION ${TEMP_STRING})
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX86_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${BOX86_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${BOX86_REVISION})
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
if(_aarch64 OR _armhf)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
elseif(_x86_64 OR _x86)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
else()
#probably wrong...
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
endif()
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
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
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=tmpfile15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# WIP
#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_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_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.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=tmpfile16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
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=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=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()
View File
File renamed without changes.
-44
View File
@@ -1,44 +0,0 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${_pkgname%-arm-git}-git" "${_pkgname%-arm-git}")
conflicts=("${pkgname%-git}" "${_pkgname%-arm-git}-git" "${_pkgname%-arm-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm-git}"
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)
}
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
}
-44
View File
@@ -1,44 +0,0 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${_pkgname%-odroid-git}-git" "${_pkgname%-odroid-git}")
conflicts=("${pkgname%-git}" "${_pkgname%-odroid-git}-git" "${_pkgname%-odroid-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-odroid-git}"
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)
}
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
}
-44
View File
@@ -1,44 +0,0 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
url="https://github.com/ptitSeb/box86"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-x86-git}")
conflicts=("${pkgname%-x86-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x86-git}"
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)
}
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
}
+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
+44
View File
@@ -1,3 +1,47 @@
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)
* Introduce BOX86_DYNAREC_STRONGMEM, like with box64 (not found any program that needs that yet)
* More vulkan wrapped function (so dkvk works, at least with RX550)
* Reworked Elfloader part, with better handling of versionned symbols
* Improve speed for x87 code (by avoiding many float<->double conversion)
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
* Added a detection of box64 in uname call, to expose an x86_64 system instead of i386 one
* Added a fix for linking box86 on system using glibc 2.34+
* A few more wrapped libs
* More ARM hardware option in CMake (Phytium, SD845)
* Changed a bit struture of Dynarec, switching some operations from Pass1 to Pass0
* Small fixes to elfloader
* Some fixes and improvments on wrapped libs (mainly gtk2, gtk3 and d3dadpter)
* Better VSyscall implementation
* Fixed the "Alternate" handling (address shadowing on x86 side)
* A few opcodes border case fixes
* Improved wrapper helpers (from rajdakin)
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
* Improvment to the handling of longjmp inside signal handlers
v0.2.2
======
* Reworked some elfloader relocation mecanism
+54 -8
View File
@@ -20,30 +20,64 @@ Compiling
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
make
sudo make install
sudo systemctl restart systemd-binfmt
```
Note that you can use `make -j2` or more to speed up 1st build, but beware of the memory requirement if you go to high.
_For Pi4. Change to RPI2 or RPI3 for other models. Change to RPI4ARM64 for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
#### for Raspberry Pi on 64bits OS
_For Pi4. Change to RPI2 or RPI3 for other models. Change `-DRPI4=1` to `-DRPI4ARM64=1` for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
```
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j2
sudo make install
sudo systemctl restart systemd-binfmt
```
#### for ODROID
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### for RK3399
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
`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
`mkdir build; cd build; cmake .. -DRK3288=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### for Allwinner A64
`mkdir build; cd build; cmake .. -DA64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
#### for Snapdragon 845
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Snapdragon 845 device run AARCH64 OS, in most cases you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Phytium
`mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
#### for Other ARM Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### for x86 Linux
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### use ccmake
@@ -65,7 +99,7 @@ To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` b
*to have ARM Dynarec*
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode). Note that compiling with `ARM_DYNAREC` but without hardware profile is not advise. If you get error building that "target CPU does not support ARM mode", then try to pick hardware profile (like ODROID for armv7 or PI4 for armv8). Also, if you are using a 64bits with armhf multiarch, it's much easier to pick one of the hardware profile like `RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
*not building from a git clone*
@@ -79,3 +113,15 @@ A few tests are included.
They can be launched with `ctest`
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`.
+45 -29
View File
@@ -1,24 +1,22 @@
# box86
![Official logo](img/Box86Logo.png "Official Logo")
Linux Userspace x86 Emulator with a twist
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 some cases.
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 an solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Many games already work without much tweaking, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine. (there's a long list, among them are UNDERTALE, A Risk of Rain, and Cook Serve Delicious)
@@ -27,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 [Pi Labs Channel](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman Channel](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
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">
@@ -43,13 +49,6 @@ Note that this project is not to be mistaken with [86box](https://github.com/86B
----
Discord
----
If you want to discuss (or have any problems) about box86, feel free to join the [Pi Labs Discord Server](https://discord.gg/Fh8sjmu)!
----
Usage
----
@@ -73,11 +72,11 @@ Notes about 64-bit platforms
Because Box86 works by directly translating function calls from x86 to host system, the host system (the one Box86 is running on) needs to have 32-bit libraries. Box86 doesn't include any 32-bit <-> 64-bit translation. So basically, to run Box86 on, for example, an ARM64 platform, you will need to build Box86 for ARM 32-bit, and also need to have a chroot with 32-bit libraries.
Also note that, even if, on day, there is a Box86_64, this one will only be able to run x86_64 binaries on 64-bit platforms. You will still need Box86 (and a 32-bit chroot) to run x86 binaries (in fact, the same is the case on actual x86_64 Linux).
If you look at a 64bits version of box86, look at [Box64](https://github.com/ptitSeb/box64): this one is able to run x86_64 binaries on 64-bit platforms. But note that you still need Box86 (and a 32-bit chroot) to run x86 binaries (as it also happens on actual x86_64 Linux that need x86 libs and binary on multiarch to run).
----
A note about Unity game emulation
Notes about Unity game emulation
----
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with the new "protected memory" mechanism implemented it should be running with correct performance now.
@@ -92,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.
@@ -104,11 +103,28 @@ Steam for Windows installs fine but doesn't work yet.
Notes about Wine
----
Wine is now partly supported. Wine integrated program all runs, and some windows programs and games now runs fine. Don't forget most Windows games use Direct3D, this may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
Wine is now supported. Wine integrated program all runs, and many windows programs and games also runs fine. Don't forget most Windows games use Direct3D, this may require a complete OpenGL driver and a as high profile as possible (and gl4es with ES2 backend have issue with Wine for now).
Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those models use a default OS that have a kernel with a 2/2 Split (meaning 2G of space for user program, and 2G of space for the Kernel). This is not compatible with Wine programs that needs to access memory > 2Gb address. So you'll need to reconfigure your kernel for a 3G/1G split.
----
Final words
Notes about Vulkan
----
(If you use Box86 in your project, please don't forget to mention Box86!)
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 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 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.
(If you use Box86 in your project, please don't forget to mention it!)
+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,请不要忘记提及!)
+47 -4
View File
@@ -9,7 +9,12 @@ Controls the Verbosity level of the logs
* 0: NONE : No message (except some fatal error). (Default.)
* 1: INFO : Show some minimum log (Example: librairies not found)
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3: DUMP : All DEBUG plus DUMP of all ELF Info.
* 3: DUMP : All DEBUG plus DUMP of all ELF Info (so same as `BOX86_LOG=2 BOX86_DUMP=1`)
#### BOX86_DUMP
Controls the Dump of elf content
* 0: No dump of elf information (Default)
* 1: Dump elf sections and relocations and other information (also active if using `BOX86_LOG=3`)
#### BOX86_NOBANNER
Disables Box86 printing its version and build
@@ -31,6 +36,7 @@ Enables/Disables the logging of `dlsym` errors.
#### BOX86_TRACE_FILE
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box86 instance
Use `stderr` to use this instead of default `stdout`
#### BOX86_TRACE
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
@@ -109,6 +115,28 @@ Enables/Disables trace for generated code.
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX86_DYNAREC_BIGBLOCK
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
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX86_DYNAREC_X87DOUBLE
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
@@ -123,11 +151,26 @@ Forbid dynablock creation in the interval specified (helpfull for debugging beha
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.)
@@ -136,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.
+49 -55
View File
@@ -1,14 +1,14 @@
# Installing Wine (and winetricks)
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (x64 is not yet implemented).
_TwisterOS users: Wine, winetricks, and Box86 are already installed in TwisterOS. You do not have to install anything._
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 already has a 3G/1G split kernel and works with Wine, but **the Pi 3B+ and earlier models have a 2G/2G kernel and require a custom-compiled 3G/1G kernel to get Wine working.**_
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
See installation steps below (in the [Examples](#examples) section).
_TwisterOS users, take note: Wine, winetricks, and Box86 are pre-installed in TwisterOS. TwisterOS users do not have to install anything._
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.
Box86 actually 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 Windows and Wine i386 libraries (`.so` or `.dll` files) so that they will work with your ARM device's libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) versions of Wine install files (even though we are installing it on an ARM processor). Box86 "wraps" many of Wine's core Linux i386 libraries so that their calls are interpretable by Linux ARM libraries. Below are examples of how to install Wine from each of those places.
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 has a 3G/1G split kernel, but **the Pi 3 and earlier models have a 2G/2G kernel by default and will need you to install a custom-compiled 3G/1G kernel to get Wine to work.**
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) version of Wine even though we are installing it on an ARM processor.
## Overview
The general procedure for installing Wine for Box86 is to...
@@ -20,10 +20,40 @@ The general procedure for installing Wine for Box86 is to...
- Download winetricks (which is simply a very complicated bash script), make it executable, then copy it to `/usr/local/bin`.
## Examples
_These examples were all tested on Raspberry Pi 4. Note the similarities between the different install methods._
### Installing Wine for Box86 on Raspberry Pi OS from Twister OS FAQ .tgz files
_Links from the [TwisterOS FAQ](https://twisteros.com/faq.html)_
### Installing wine-devel, wine-stable, or wine-staging for Raspberry Pi OS Buster from WineHQ deb files
This installs Wine v5.13 (which is the version of Wine that comes pre-installed in TwisterOS). When submitting bug reports, other Box86 users may assume you are using this version of Wine unless you specify otherwise.
```
# Backup any old wine installations
sudo mv ~/wine ~/wine-old
sudo mv ~/.wine ~/.wine-old
sudo mv /usr/local/bin/wine /usr/local/bin/wine-old
sudo mv /usr/local/bin/wineboot /usr/local/bin/wineboot-old
sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
# Download, extract wine, and install wine (last I checked, the Twister OS FAQ page had Wine 5.13-devel)
wget https://twisteros.com/wine.tgz -O ~/wine.tgz
tar -xzvf ~/wine.tgz
rm ~/wine.tgz # clean up
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
# Boot wine (make fresh wineprefix in ~/.wine )
wine wineboot
```
### Installing Wine for Box86 on Raspberry Pi OS Buster from WineHQ .deb files
_Links from the [WineHQ repo](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/)_
This install method allows you to install different versions of Wine. You may install any version and any branch of Wine that you wish (wine-devel, wine-stable, or wine-staging).
```
# Backup any old wine installations
sudo mv ~/wine ~/wine-old
@@ -66,53 +96,19 @@ rm -rf libfaudio # clean up
wine wineboot
```
### Installing Wine for Raspberry Pi OS from the Twister OS FAQ page
_Links from the [TwisterOS FAQ](https://twisteros.com/faq.html)_
```
# Backup any old wine installations
sudo mv ~/wine ~/wine-old
sudo mv ~/.wine ~/.wine-old
sudo mv /usr/local/bin/wine /usr/local/bin/wine-old
sudo mv /usr/local/bin/wineboot /usr/local/bin/wineboot-old
sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
# Download, extract wine, and install wine (last I checked, the Twister OS FAQ page had Wine 5.13-devel)
wget https://twisteros.com/wine.tgz -O ~/wine.tgz
tar -xzvf ~/wine.tgz
rm ~/wine.tgz # clean up
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
# Boot wine (make fresh wineprefix in ~/.wine )
wine wineboot
```
## Installing winetricks
Winetricks is a script which makes it easier to install & configure any desired Windows core system software packages which may be dependencies for certain Windows programs.
Winetricks is a bash script which makes it easier to install & configure any desired Windows core system software packages which may be dependencies for certain Windows programs. You can either install it with `apt`, or manually using the steps below.
```
# Backup old winetricks
sudo mv /usr/local/bin/winetricks /usr/local/bin/winetricks-old
# Download
cd ~/Downloads
wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
# Install
sudo chmod +x winetricks
sudo mv winetricks /usr/local/bin/
# winetricks needs this installed
sudo apt-get install cabextract -y
sudo apt-get install cabextract -y # winetricks needs this installed
sudo mv /usr/local/bin/winetricks /usr/local/bin/winetricks-old # Backup old winetricks
cd ~/Downloads && wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks # Download
sudo chmod +x winetricks && sudo mv winetricks /usr/local/bin/ # Install
```
If you have a desktop menu itm for wintricks, you may need to edit it to add the nobanner env var. Do so by edition `/usr/share/applications/winetricks.desktop` with your favorite text editor (not that you'll need `sudo` to save the file) and change from `Exec=winetricks --gui` to `Exec=env BOX86_NOBANNER=1 winetricks --gui`
Whenever we run winetricks, we must tell Box86 to supress its info banner, otherwise winetricks will crash. Box86's info banner can be suppressed using the `BOX86_NOBANNER=1` environment variable before invoking winetricks (example: `BOX86_NOBANNER=1 winetricks`).
If `apt` installed a desktop menu shortcut for winetricks (or if you make your own desktop shortcut for winetricks) then you may need to edit that shortcut to include Box86's BOX86_NOBANNER=1 env var. With your favorite text editor, edit `/usr/share/applications/winetricks.desktop` and change `Exec=winetricks --gui` to `Exec=env BOX86_NOBANNER=1 winetricks --gui`.
## Example commands
Here is an example of how we should run a winetricks command with box86:
@@ -126,13 +122,11 @@ For a list of all the different Windows packages & libraries that winetricks can
## Other notes
### Wineprefixes (and Wine initialization)
The first time Wine is run (`wine wineboot`), it will create a fresh wineprefix for you (by default, located in the hidden folder `~/.wine`). Think of a wineprefix as Wine's virtual 'harddrive' where it installs software and saves settings. Wineprefixes are portable and deletable.
When you first run or boot Wine (`wine wineboot`), Wine will create a new user environment within which to install Windows software. This user environment is called a "wineprefix" (or "wine bottle") and is located (by default) in `~/.wine` (note that Linux folders with a `.` in front of them are "hidden" folders). Think of a wineprefix as Wine's virtual 'harddrive' where it installs software and saves settings. Wineprefixes are portable and deletable. For more Wine documentation, see [WineHQ](https://www.winehq.org/documentation).
If you at any point corrupt something inside your default wineprefix, you can start "fresh" by deleting your `~/.wine` directory (with the `rm -rf ~/.wine` command) and boot wine again to create a new default wineprefix.
### Transplanting wineprefixes (side-loading)
When you first run or boot Wine (`wine wineboot`), Wine will create a new user environment within which to install Windows software. This user environment is called a "wineprefix" (or "wine bottle") and is located (by default) in `~/.wine` (note that Linux folders with a `.` in front of them are "hidden" folders). For more Wine documentation, see [WineHQ](https://www.winehq.org/documentation).
If software isn't installing in Wine with Box86, but is installing for you in Wine on a regular x86 Linux computer, you can copy a wineprefix from your x86 Linux computer to the device you're running Box86 on. This is most easily done by tarring the `~/.wine` folder on your x86 Linux computer (`tar -cvf winebottle.tar ~/.wine`), transferring the tar file to your device, then un-tarring the tar file (`tar -xf winebottle.tar`) on your device running Box86 & Wine. Tarring the wineprefix preserves any symlinks that are inside it.
### Swapping out different versions of Wine
@@ -140,4 +134,4 @@ Some versions of Wine work better with certain software. It is best to install a
Your entire Wine installation can reside within a single folder on your Linux computer. TwisterOS assumes that your Wine installation is located inside the `~/wine/` directory. The actual directory where you put your `wine` folder doesn't matter as long as you have symlinks within the `/usr/local/bin/` directory which point to the `wine` folder so that Linux can find Wine when you type `wine` into the terminal).
You can change which version of Wine you are running simply by renaming your old `wine` and `.wine` folders to something else, then putting a new `wine` folder (containing your new version of Wine) in its place. Running `wine wineboot` again will make a fresh wineprefix with your new version of Wine. You can check which version of Wine you're running with the `wine --version` command.
You can change which version of Wine you are running simply by renaming your old `wine` and `.wine` folders to something else, then putting a new `wine` folder (containing your new version of Wine) in its place. Running `wine wineboot` again will migrate a wineprefix from an older version of Wine to be usable by the newer version of Wine you just installed. You can check which version of Wine you're running with the `wine --version` command.
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

+29
View File
@@ -0,0 +1,29 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm-git}-git" "${pkgname%-arm-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm-git}-git" "${pkgname%-arm-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
cmake -B build -S "${pkgname%-arm-git}" -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
@@ -1,7 +1,7 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-gameshell-git
pkgver=r2798.0edc0374
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
}
+29
View File
@@ -0,0 +1,29 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
conflicts=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-odroid-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
cmake -B build -S "${pkgname%-odroid-git}" -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
@@ -1,8 +1,7 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pandora-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -20,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
}
@@ -1,8 +1,7 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pyra-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -20,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
}
@@ -1,8 +1,7 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rpi-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -10,8 +9,8 @@ url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%--rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%--rpi-git}")
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
@@ -21,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
@@ -37,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
}
@@ -1,8 +1,7 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -20,20 +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%-rk3399-git}/build"
make DESTDIR="${pkgdir}/" install
make -C build DESTDIR="${pkgdir}/" install
}
+28
View File
@@ -0,0 +1,28 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
url="https://github.com/ptitSeb/box86"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-x86-git}-git" "${pkgname%-x86-git}")
conflicts=("${pkgname%-git}" "${pkgname%-x86-git}-git" "${pkgname%-x86-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x86-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
cmake -B build -S "${pkgname%-x86-git}" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
+4 -1
View File
@@ -12,10 +12,13 @@ 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:
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
- your `box86` installation is recognized as a package (where it wasn't when installing with `make install`).
### Note: You can use [makedeb](https://github.com/makedeb/makedeb) (or) [pkgbuild2spec](https://github.com/prozum/pkgbuild2spec) to compile box86 to .deb or .rpm installer files.
Executable
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
if [ -d '/run/systemd/system' ]; then
systemctl restart systemd-binfmt || :
fi
+286 -278
View File
@@ -621,7 +621,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
skiprbr = False
if idx % 2:
if text == "c":
if variables["cond"] != -1:
if variables["cond"] >= 0:
append("%s")
printf_args = printf_args + ", cond"
elif text == "Rd":
@@ -1675,297 +1675,305 @@ def main(root, ver, __debug_forceAllDebugging=False):
# Now the files rebuilding part
# File header and guard
header = """/*****************************************************************
* File automatically generated by rebuild_printer.py (v{version})
*****************************************************************/
"""
files_header = {
"arm_printer.c": """#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "arm_printer.h"
// conditions
#define cEQ (0b0000<<28)
#define cNE (0b0001<<28)
#define cCS (0b0010<<28)
#define cCC (0b0011<<28)
#define cMI (0b0100<<28)
#define cPL (0b0101<<28)
#define cVS (0b0110<<28)
#define cVC (0b0111<<28)
#define cHI (0b1000<<28)
#define cLS (0b1001<<28)
#define cGE (0b1010<<28)
#define cLT (0b1011<<28)
#define cGT (0b1100<<28)
#define cLE (0b1101<<28)
#define c__ (0b1110<<28) // means all
static const char* conds[16] = {
"EQ", "NE", "CS", "CC",
"MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT",
"GT", "LE", "", "##"
};
static const char* regname[16] = {
"r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9",
"r10", "r11", "r12", "SP", "LR", "PC"
};
// Single precision are V_:_
// Double and quad precision are _:V_
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
static const char* vecname[96] = {
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
};
static const char* dts[16] = {
"S8", "S16", "S32", "S64",
"U8", "U16", "U32", "U64",
"I8", "I16", "I32", "I64",
"F8", "F16", "F32", "F64"
};
static const char* shift_type[4] = {
"lsl ", "lsr ", "asr ", "ror "
};
const char* print_shift(int shift, int comma) {
static __thread char ret[20];
ret[0] = '\\0';
int sh_op = (shift >> 1) & 3;
if(shift & 1) {
int rs = shift >> 4;
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
} else {
uint8_t amount = shift >> 3;
if (!amount) {
switch (sh_op) {
case 0b00:
break;
case 0b01:
case 0b10:
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
break;
case 0b11:
sprintf(ret, "%srrx", (comma ? ", " : ""));
break;
}
} else {
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
}
}
return ret;
}
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
const char* print_register_list(int list, int size) {
int last = -2;
int cnt = 0;
static __thread char ret[68];
ret[0] = '{';
ret[1] = '\\0';
for (int i = 0; i < size; ++i) {
if (list & (1 << i)) {
if (last >= 0) {
++cnt;
"arm_printer.c": """
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "arm_printer.h"
// conditions
#define cEQ (0b0000<<28)
#define cNE (0b0001<<28)
#define cCS (0b0010<<28)
#define cCC (0b0011<<28)
#define cMI (0b0100<<28)
#define cPL (0b0101<<28)
#define cVS (0b0110<<28)
#define cVC (0b0111<<28)
#define cHI (0b1000<<28)
#define cLS (0b1001<<28)
#define cGE (0b1010<<28)
#define cLT (0b1011<<28)
#define cGT (0b1100<<28)
#define cLE (0b1101<<28)
#define c__ (0b1110<<28) // means all
static const char* conds[16] = {
"EQ", "NE", "CS", "CC",
"MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT",
"GT", "LE", "", "##"
};
static const char* regname[16] = {
"r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9",
"r10", "r11", "r12", "SP", "LR", "PC"
};
// Single precision are V_:_
// Double and quad precision are _:V_
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
static const char* vecname[96] = {
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
};
static const char* dts[16] = {
"S8", "S16", "S32", "S64",
"U8", "U16", "U32", "U64",
"I8", "I16", "I32", "I64",
"F8", "F16", "F32", "F64"
};
static const char* shift_type[4] = {
"lsl ", "lsr ", "asr ", "ror "
};
const char* print_shift(int shift, int comma) {
static __thread char ret[20];
ret[0] = '\\0';
int sh_op = (shift >> 1) & 3;
if(shift & 1) {
int rs = shift >> 4;
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
} else {
if (last == -1)
strcat(ret, ", ");
strcat(ret, regname[i]);
last = i;
uint8_t amount = shift >> 3;
if (!amount) {
switch (sh_op) {
case 0b00:
break;
case 0b01:
case 0b10:
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
break;
case 0b11:
sprintf(ret, "%srrx", (comma ? ", " : ""));
break;
}
} else {
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
}
}
return ret;
}
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
const char* print_register_list(int list, int size) {
int last = -2;
int cnt = 0;
static __thread char ret[68];
ret[0] = '{';
ret[1] = '\\0';
for (int i = 0; i < size; ++i) {
if (list & (1 << i)) {
if (last >= 0) {
++cnt;
} else {
if (last == -1)
strcat(ret, ", ");
strcat(ret, regname[i]);
last = i;
}
} else {
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[i - 1]);
}
if (last != -2) last = -1;
cnt = 0;
}
}
} else {
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[i - 1]);
strcat(ret, regname[size - 1]);
}
if (last != -2) last = -1;
cnt = 0;
strcat(ret, "}");
return ret;
}
}
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[size - 1]);
}
strcat(ret, "}");
return ret;
}
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
static __thread char ret[68];
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
if (start + (double_prec + 1) * size > 32) {
return "!!!";
}
if (size == 0) {
return "!!!";
}
if (double_prec && (size % 2 == 1)) {
strcpy(ret, "!! {");
} else {
ret[0] = '{';
ret[1] = '\\0';
}
char regChr;
if (double_prec) {
regChr = 'D';
size /= 2;
} else {
regChr = 'S';
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
}
sprintf(tmp, "%c%d}", regChr, start + size - 1);
strcat(ret, tmp);
return ret;
}
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
const char* print_modified_imm_NEON(int op_cmode, int imm) {
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
strcpy(&ret[4], "UNPREDICTABLE");
switch (op_cmode) {
case 0b00000: // VMOV.I32
case 0b00001: // VORR.I32
case 0b10000: // VMVN.I32
case 0b10001: // VBIC.I32
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b00010: // VMOV.I32
case 0b00011: // VORR.I32
case 0b10010: // VMVN.I32
case 0b10011: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X00", imm);
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
static __thread char ret[68];
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
if (start + (double_prec + 1) * size > 32) {
return "!!!";
}
if (size == 0) {
return "!!!";
}
if (double_prec && (size % 2 == 1)) {
strcpy(ret, "!! {");
} else {
ret[0] = '{';
ret[1] = '\\0';
}
char regChr;
if (double_prec) {
regChr = 'D';
size /= 2;
} else {
regChr = 'S';
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
}
sprintf(tmp, "%c%d}", regChr, start + size - 1);
strcat(ret, tmp);
return ret;
}
break;
case 0b00100: // VMOV.I32
case 0b00101: // VORR.I32
case 0b10100: // VMVN.I32
case 0b10101: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X0000", imm);
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
const char* print_modified_imm_NEON(int op_cmode, int imm) {
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
strcpy(&ret[4], "UNPREDICTABLE");
switch (op_cmode) {
case 0b00000: // VMOV.I32
case 0b00001: // VORR.I32
case 0b10000: // VMVN.I32
case 0b10001: // VBIC.I32
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b00010: // VMOV.I32
case 0b00011: // VORR.I32
case 0b10010: // VMVN.I32
case 0b10011: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b00100: // VMOV.I32
case 0b00101: // VORR.I32
case 0b10100: // VMVN.I32
case 0b10101: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X0000", imm);
}
break;
case 0b00110: // VMOV.I32
case 0b00111: // VORR.I32
case 0b10110: // VMVN.I32
case 0b10111: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X000000", imm);
}
break;
case 0b01000: // VMOV.I16
case 0b01001: // VORR.I16
case 0b11000: // VMVN.I16
case 0b11001: // VBIC.I16
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01010: // VMOV.I16
case 0b01011: // VORR.I16
case 0b11010: // VMVN.I16
case 0b11011: // VBIC.I16
if (imm) {
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b01100: // VMOV.I32
case 0b11100: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFF", imm);
}
break;
case 0b01101: // VMOV.I32
case 0b11101: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFFFF", imm);
}
break;
case 0b01110: // VMOV.I8
strcpy(ret, "I8");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01111: // VMOV.F32
strcpy(ret, "F32");
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
break;
case 0b11110: // VMOV.I64
{
strcpy(ret, "I64");
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
}
break;
case 0b11111: // V???.-
default:
strcpy(ret, "-");
strcpy(&ret[4], "UNDEFINED");
break;
}
return ret;
}
break;
case 0b00110: // VMOV.I32
case 0b00111: // VORR.I32
case 0b10110: // VMVN.I32
case 0b10111: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X000000", imm);
}
break;
case 0b01000: // VMOV.I16
case 0b01001: // VORR.I16
case 0b11000: // VMVN.I16
case 0b11001: // VBIC.I16
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01010: // VMOV.I16
case 0b01011: // VORR.I16
case 0b11010: // VMVN.I16
case 0b11011: // VBIC.I16
if (imm) {
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b01100: // VMOV.I32
case 0b11100: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFF", imm);
}
break;
case 0b01101: // VMOV.I32
case 0b11101: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFFFF", imm);
}
break;
case 0b01110: // VMOV.I8
strcpy(ret, "I8");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01111: // VMOV.F32
strcpy(ret, "F32");
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
break;
case 0b11110: // VMOV.I64
const char* arm_print(uint32_t opcode) {
static __thread char ret[100];
memset(ret, 0, sizeof(ret));
"""
}
files_guard = {
"arm_printer.c": """
{
strcpy(ret, "I64");
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
strcpy(ret, "???");
}
return ret;
}
break;
case 0b11111: // V???.-
default:
strcpy(ret, "-");
strcpy(&ret[4], "UNDEFINED");
break;
"""
}
return ret;
}
const char* arm_print(uint32_t opcode) {
static __thread char ret[100];
memset(ret, 0, sizeof(ret));
"""
}
files_guard = {"arm_printer.c": """{
strcpy(ret, "???");
}
return ret;
}
"""}
banner = "/*******************************************************" + ('*'*len(ver)) + "***\n" \
" * File automatically generated by rebuild_printer.py (v" + ver + ") *\n" \
" *******************************************************" + ('*'*len(ver)) + "***/\n"
trim = lambda string: '\n'.join(line[2:] for line in string.splitlines())[1:]
# Yes, the for loops are inverted. This is because both dicts should have the same keys.
for fhdr in files_guard:
files_header[fhdr] = banner + trim(files_header[fhdr])
for fhdr in files_header:
files_guard[fhdr] = trim(files_guard[fhdr])
for f in files_header:
with open(os.path.join(root, "src", "dynarec", f), 'w') as file:
file.write(header.format(version = ver))
file.write(files_header[f])
file.write(output)
file.write(files_guard[f])
@@ -1980,6 +1988,6 @@ if __name__ == '__main__':
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
if main(sys.argv[1], "1.1.0.04") != 0:
if main(sys.argv[1], "1.2.0.05") != 0:
exit(2)
exit(0)
+1273 -611
View File
File diff suppressed because it is too large. Load diff
+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}" )
+31 -17
View File
@@ -21,6 +21,7 @@
#include "signals.h"
#include <sys/mman.h>
#include "custommem.h"
#include "dictionnary.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
@@ -36,6 +37,7 @@ void initAllHelpers(box86context_t* context)
return;
my_context = context;
init_pthread_helper();
init_bridge_helper();
init_signal_helper(context);
inited = 1;
}
@@ -48,7 +50,7 @@ void finiAllHelpers(box86context_t* context)
return;
fini_pthread_helper(context);
fini_signal_helper();
cleanAlternate();
fini_bridge_helper();
fini_custommem_helper(context);
finied = 1;
}
@@ -96,6 +98,7 @@ int unlockMutex()
#endif
GO(my_context->mutex_tls, 9)
GO(my_context->mutex_thread, 10)
GO(my_context->mutex_bridge, 11)
#undef GO
return ret;
@@ -103,7 +106,6 @@ int unlockMutex()
void relockMutex(int locks)
{
relockCustommemMutex(locks);
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
@@ -118,7 +120,9 @@ void relockMutex(int locks)
#endif
GO(my_context->mutex_tls, 9)
GO(my_context->mutex_thread, 10)
GO(my_context->mutex_bridge, 11)
#undef GO
relockCustommemMutex(locks);
}
static void init_mutexes(box86context_t* context)
@@ -129,13 +133,14 @@ static void init_mutexes(box86context_t* context)
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, &attr);
#else
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_dyndump, &attr);
#else
pthread_mutex_init(&context->mutex_lock, &attr);
#endif
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutexattr_destroy(&attr);
}
@@ -169,9 +174,12 @@ box86context_t *NewBox86Context(int argc)
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->defver = NewDefaultVersion();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x86Syscall, 0);
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
#ifdef BUILD_LIB
context->box86lib = RTLD_DEFAULT; // not ideal
#else
@@ -217,6 +225,7 @@ void FreeBox86Context(box86context_t** context)
FreeLibrarian(&ctx->local_maplib, NULL);
if(ctx->maplib)
FreeLibrarian(&ctx->maplib, NULL);
FreeDictionnary(&ctx->versym);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
@@ -275,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);
@@ -292,24 +304,26 @@ void FreeBox86Context(box86context_t** context)
}
}
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifndef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#else
pthread_mutex_destroy(&ctx->mutex_dyndump);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->defver);
finiAllHelpers(ctx);
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_dyndump);
#else
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
free(ctx);
}
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 2
#define BOX86_REVISION 2
#define BOX86_REVISION 6
#endif //__BOX86_VERSION_H_
+377 -146
View File
@@ -32,9 +32,9 @@
// init inside dynablocks.c
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
static dynablocklist_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
static pthread_mutex_t mutex_mmap;
static mmaplist_t *mmaplist;
static int mmapsize;
static mmaplist_t *mmaplist = NULL;
static int mmapsize = 0;
static int mmapcap = 0;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
static uintptr_t *box86_jumptable[JMPTABL_SIZE];
static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
@@ -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;
@@ -58,8 +65,8 @@ static blocklist_t* p_blocks = NULL; // actual blocks for custom mallo
typedef union mark_s {
struct {
unsigned int fill:1;
unsigned int size:31;
unsigned int fill:1;
};
uint32_t x32;
} mark_t;
@@ -68,98 +75,146 @@ typedef struct blockmark_s {
mark_t next;
} blockmark_t;
#define NEXT_BLOCK(b) (blockmark_t*)((uintptr_t)(b) + (b)->next.size + sizeof(blockmark_t))
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
static void printBlock(blockmark_t* b, void* start)
{
printf_log(LOG_INFO, "========== Block is:\n");
do {
printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
b = NEXT_BLOCK(b);
} while(b->next.x32);
printf_log(LOG_INFO, "===================\n");
}
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, int maxsize, int* size)
static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* start)
{
// get start of block
blockmark_t *m = (blockmark_t*)block;
blockmark_t *m = (blockmark_t*)((start)?start:block);
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
*size = m->next.size-sizeof(blockmark_t);
if(!m->next.fill && m->next.size>=maxsize) {
*size = m->next.size;
return m;
}
m = (blockmark_t*)((uintptr_t)m + m->next.size);
m = NEXT_BLOCK(m);
}
return NULL;
}
static int getMaxFreeBlock(void* block, size_t block_size)
static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
{
// get start of block
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
if(start) {
blockmark_t *m = (blockmark_t*)start;
int maxsize = 0;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>maxsize) {
maxsize = m->next.size;
}
m = NEXT_BLOCK(m);
}
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
} else {
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return (maxsize>=sizeof(blockmark_t))?maxsize:0; // no block large enough left...
}
m = PREV_BLOCK(m);
}
return (maxsize>=sizeof(blockmark_t))?maxsize:0;
}
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
}
static void* allocBlock(void* block, void *sub, int size)
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
{
(void)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
s->next.fill = 1;
s->next.size = size+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
// check if a new mark is worth it
if(s->next.size>size+2*sizeof(blockmark_t))
s->next.size = size;
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
// new mark
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = (uintptr_t)n - (uintptr_t)m;
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
n->prev.fill = 0;
n->prev.size = m->next.size;
}
if(pstart && sub==*pstart) {
// get the next free block
m = (blockmark_t*)*pstart;
while(m->next.fill)
m = NEXT_BLOCK(m);
*pstart = (void*)m;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
static void freeBlock(void *block, void* sub)
static size_t freeBlock(void *block, void* sub, void** pstart)
{
blockmark_t *m = (blockmark_t*)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
if(block!=sub)
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
m = PREV_BLOCK(s);
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size;
m->next.size += s->next.size + sizeof(blockmark_t);
n->prev.size = m->next.size;
s = m;
}
// check if merge with next
if(n->next.x32 && !n->next.fill) {
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
blockmark_t *n2 = NEXT_BLOCK(n);
//remove n
s->next.size += n->next.size;
s->next.size += n->next.size + sizeof(blockmark_t);
n2->prev.size = s->next.size;
}
if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) {
*pstart = (void*)s;
}
// return free size at current block (might be bigger)
return s->next.size;
}
// return 1 if block has been expanded to new size, 0 if not
static int expandBlock(void* block, void* sub, int newsize)
static int expandBlock(void* block, void* sub, size_t newsize)
{
(void)block;
newsize = (newsize+3)&~3;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
blockmark_t *n = NEXT_BLOCK(s);
if(s->next.size>=newsize)
// big enough, no shrinking...
return 1;
if(s->next.fill)
return 0; // next block is filled
if(s->next.size + n->next.size < newsize)
// unsigned bitfield of this length gets "promoted" to *signed* int...
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
return 0; // free space too short
// ok, doing the alloc!
s->next.size = newsize+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
s->next.size += n->next.size+sizeof(blockmark_t);
else
s->next.size = newsize+sizeof(blockmark_t);
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
@@ -174,7 +229,7 @@ static int expandBlock(void* block, void* sub, int newsize)
return 1;
}
// return size of block
static int sizeBlock(void* sub)
static size_t sizeBlock(void* sub)
{
blockmark_t *s = (blockmark_t*)sub;
return s->next.size;
@@ -187,12 +242,12 @@ void* customMalloc(size_t size)
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
int rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
size_t rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize, NULL);
if(sub) {
void* ret = allocBlock(p_blocks[i].block, sub, size);
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
if(rsize==p_blocks[i].maxfree)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
@@ -216,14 +271,14 @@ void* customMalloc(size_t size)
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = allocsize-sizeof(blockmark_t);
m = (blockmark_t*)(p+allocsize-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = allocsize-sizeof(blockmark_t);
m->next.size = allocsize-2*sizeof(blockmark_t);
blockmark_t* n = NEXT_BLOCK(m);
n->next.x32 = 0;
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
void* ret = allocBlock(p_blocks[i].block, p, size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
@@ -245,21 +300,20 @@ void* customRealloc(void* p, size_t size)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
if(expandBlock(p_blocks[i].block, sub, size)) {
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
pthread_mutex_unlock(&mutex_blocks);
return p;
}
pthread_mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
pthread_mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
}
}
pthread_mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
return customMalloc(size);
}
void customFree(void* p)
@@ -272,8 +326,8 @@ void customFree(void* p)
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(p_blocks[i].block, sub);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
pthread_mutex_unlock(&mutex_blocks);
return;
}
@@ -290,6 +344,8 @@ typedef struct mmaplist_s {
size_t size;
kh_dynablocks_t* dblist;
uint8_t* helper;
void* first; // first free block, to speed up things
int locked; // don't try to add stuff on locked block
} mmaplist_t;
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
@@ -297,13 +353,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
// look for free space
void* sub = NULL;
for(int i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size) {
int rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
mmaplist[i].locked = 1;
size_t rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
if(rsize==mmaplist[i].maxfree)
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
if(rsize==mmaplist[i].maxfree) {
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
}
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(!blocks) {
blocks = mmaplist[i].dblist = kh_init(dynablocks);
@@ -313,9 +371,17 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
for(int j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
int size255=(size<256)?size:255;
for(size_t j=0; j<size255; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
if(size!=size255)
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
mmaplist[i].locked = 0;
return ret;
} else {
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted mmaplist[%d] info?\n", i);
if(box86_log >= LOG_DEBUG)
printBlock(mmaplist[i].block, mmaplist[i].first);
}
}
}
@@ -325,8 +391,11 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
{
int i = mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
if(mmapsize>mmapcap) {
mmapcap += 32;
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
}
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
@@ -345,21 +414,23 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
#endif
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
mmaplist[i].locked = 1;
mmaplist[i].block = p;
mmaplist[i].size = MMAPSIZE;
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
mmaplist[i].first = p;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = MMAPSIZE-sizeof(blockmark_t);
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
m->next.size = MMAPSIZE-2*sizeof(blockmark_t);
blockmark_t* n = NEXT_BLOCK(m);
n->next.x32 = 0;
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size, &mmaplist[i].first);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
khint_t k;
@@ -368,6 +439,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
kh_value(blocks, k) = db;
for(int j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
mmaplist[i].locked = 0;
return sub;
}
@@ -379,15 +451,18 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(mmaplist[i].block, sub);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
for(int j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
}
if(mmaplist[i].locked) {
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
++mmaplist[i].locked;
}
return;
}
@@ -424,7 +499,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
#ifndef USE_MMAP
pthread_mutex_lock(&mutex_mmap);
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
@@ -448,18 +522,13 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
kh_value(blocks, k) = db;
pthread_mutex_unlock(&mutex_mmap);
return (uintptr_t)p;
}
pthread_mutex_lock(&mutex_mmap);
uintptr_t ret = FindFreeDynarecMap(db, size);
if(!ret)
ret = AddNewDynarecMap(db, size);
pthread_mutex_unlock(&mutex_mmap);
return ret;
}
@@ -468,7 +537,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
if(!addr || !size)
return;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
pthread_mutex_lock(&mutex_mmap);
#ifndef USE_MMAP
free((void*)addr);
#else
@@ -480,12 +548,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
pthread_mutex_unlock(&mutex_mmap);
return;
}
pthread_mutex_lock(&mutex_mmap);
ActuallyFreeDynarecMap(db, addr, size);
pthread_mutex_unlock(&mutex_mmap);
}
dynablocklist_t* getDB(uintptr_t idx)
@@ -588,11 +653,12 @@ void protectDB(uintptr_t addr, uintptr_t size)
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
memprot[i] = prot|PROT_DYNAREC;
if(!(prot&PROT_DYNAREC))
if(!(prot&PROT_DYNAREC)) {
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
memprot[i] = prot|PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
}
}
}
@@ -605,8 +671,8 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
memprot[i] = prot&~PROT_DYNAREC;
if(prot&PROT_DYNAREC) {
memprot[i] = prot&~PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
}
@@ -615,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) {
@@ -627,8 +784,20 @@ 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) {
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
memprot[i] = 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) {
@@ -636,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);
@@ -643,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;
@@ -653,9 +893,6 @@ int unlockCustommemMutex()
ret|=(1<<B); \
}
GO(mutex_blocks, 0)
#ifdef DYNAREC
GO(mutex_mmap, 1)
#endif
#undef GO
return ret;
}
@@ -667,9 +904,6 @@ void relockCustommemMutex(int locks)
pthread_mutex_lock(&A); \
GO(mutex_blocks, 0)
#ifdef DYNAREC
GO(mutex_mmap, 1)
#endif
#undef GO
}
@@ -679,9 +913,6 @@ static void init_mutexes(void)
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
#ifdef DYNAREC
pthread_mutex_init(&mutex_mmap, &attr);
#endif
pthread_mutexattr_destroy(&attr);
}
@@ -709,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)
@@ -717,51 +953,41 @@ void fini_custommem_helper(box86context_t *ctx)
return;
inited = 0;
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<mmapsize; ++i) {
if(mmaplist[i].block)
#ifdef USE_MMAP
munmap(mmaplist[i].block, mmaplist[i].size);
#else
free(mmaplist[i].block);
#endif
if(mmaplist[i].dblist) {
kh_destroy(dynablocks, mmaplist[i].dblist);
mmaplist[i].dblist = NULL;
if(box86_dynarec) {
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<mmapsize; ++i) {
if(mmaplist[i].block)
#ifdef USE_MMAP
munmap(mmaplist[i].block, mmaplist[i].size);
#else
free(mmaplist[i].block);
#endif
if(mmaplist[i].dblist) {
kh_destroy(dynablocks, mmaplist[i].dblist);
mmaplist[i].dblist = NULL;
}
if(mmaplist[i].helper) {
free(mmaplist[i].helper);
mmaplist[i].helper = NULL;
}
}
if(mmaplist[i].helper) {
free(mmaplist[i].helper);
mmaplist[i].helper = NULL;
if(dblist_oversized) {
kh_destroy(dynablocks, dblist_oversized);
dblist_oversized = NULL;
}
mmapsize = 0;
mmapcap = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
uintptr_t idx = 0;
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i)
if(dynmap[i])
FreeDynablockList(&dynmap[i]);
free(mmaplist);
for (int i=0; i<DYNAMAP_SIZE; ++i)
if(box86_jumptable[i]!=box86_jmptbl_default)
free(box86_jumptable[i]);
}
if(dblist_oversized) {
kh_destroy(dynablocks, dblist_oversized);
dblist_oversized = NULL;
}
mmapsize = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
uintptr_t idx = 0;
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynablocklist_t* dblist = dynmap[i];
if(dblist) {
uintptr_t startdb = StartDynablockList(dblist);
uintptr_t enddb = EndDynablockList(dblist);
uintptr_t startaddr = 0;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = 0xFFFFFFFF;
if(endaddr>enddb) endaddr = enddb;
FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
}
}
for (uintptr_t i=idx; i<=end; ++i)
if(dynmap[i])
FreeDynablockList(&dynmap[i]);
pthread_mutex_destroy(&mutex_mmap);
free(mmaplist);
for (int i=0; i<DYNAMAP_SIZE; ++i)
if(box86_jumptable[i]!=box86_jmptbl_default)
free(box86_jumptable[i]);
#endif
for(int i=0; i<n_blocks; ++i)
#ifdef USE_MMAP
@@ -771,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);
}
}
+147 -19
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) )
@@ -107,6 +107,8 @@ Op is 20-27
#define MOV_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
// mov dst, src ror imm5
#define MOV_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
// mov dst, src rrx (1)
#define MOV_REG_RRX(dst, src) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((0)<<7))
// mov.s dst, src lsl imm5
#define MOVS_REG_LSL_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (0<<5) | ((imm5)<<7))
// mov.s dst, src lsr imm5
@@ -115,6 +117,8 @@ Op is 20-27
#define MOVS_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
// mov.s dst, src ror imm5
#define MOVS_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
// mov.s dst, src rrx (1)
#define MOVS_REG_RRX(dst, src) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((0)<<7))
// mov.s dst, src lsl rs
#define MOVS_REG_LSL_REG(dst, src, rs) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (1<<4) | (0<<5) | ((rs)<<8))
@@ -169,6 +173,9 @@ Op is 20-27
// rsb cond dst, src, #(imm8)
#define RSB_COND_IMM8(cond, dst, src, imm8) \
EMIT((cond) | 0x02600000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// rsc dst, src, #(imm8)
#define RSC_IMM8(dst, src, imm8) \
EMIT(0xe2E00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and dst, src1, src2, lsl #imm
#define AND_REG_LSL_IMM5(dst, src1, src2, imm5) \
@@ -182,11 +189,14 @@ Op is 20-27
// and dst, src, #(imm8)
#define AND_IMM8(dst, src, imm8) \
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and dst, src1, #imm ror rot*2
#define AND_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// and.s dst, src, #(imm8)
#define ANDS_IMM8(dst, src, imm8) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and.s dst, src1, #imm ror rot*2
#define ANDS_IMM8_ROR(src, imm8, rot) \
#define ANDS_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// add dst, src, #(imm8)
#define ADD_IMM8(dst, src, imm8) \
@@ -203,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) )
@@ -232,6 +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.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) )
@@ -241,18 +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 )
@@ -265,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) )
@@ -302,6 +339,9 @@ Op is 20-27
// bic.cond dst, src, IMM8
#define BIC_IMM8_COND(cond, dst, src, imm8, rot) \
EMIT((cond) | 0x03c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// bic dst, src1, #imm ror rot*2
#define BIC_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe3c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// bic.s dst, src1, #imm ror rot*2
#define BICS_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe3d00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
@@ -324,9 +364,6 @@ Op is 20-27
#define MVN_COND_REG_LSL_IMM5(cond, dst, rm, imm5) \
EMIT(cond | 0x01e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm5, rm) )
// Single data transfert construction
#define SDT_REG(Cond, P, U, B, W, L, Rn, Rd, ShiftRm) (Cond | (0b00<<26) | (1<<25) | (P<<24) | (U<<23) | (B<<22) | (U<<23) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | ShiftRm)
#define SDT_OFF(Cond, P, U, B, W, L, Rn, Rd, Imm12) (Cond | (0b00<<26) | (0<<25) | (P<<24) | (U<<23) | (B<<22) | (U<<23) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | Imm12)
// ldr reg, [addr, #+/-imm9]
#define LDR_IMM9(reg, addr, imm9) EMIT(0xe5100000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// ldrxx reg, [addr, #+/-imm9]
@@ -450,6 +487,11 @@ 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
#define MLS(Rd, Rm, Rn, Ra) EMIT(MLS_gen(c__, Rd, Ra, Rm, Rn))
#define SMUL_16_gen(cond, Rd, Rm, M, N, Rn) (cond | 0b00010110<<20 | (Rd)<<16 | (Rm)<<8 | 1<<7 | (M)<<6 | (N)<<5 | (Rn))
// Signed Mul between Rn[0..15] * Rm[0..15] => Rd
@@ -466,6 +508,10 @@ 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))
// BFI: Bit Field Insert: copy any number of low order bit from Rn to any position of Rd
#define BFI(rd, rn, lsb, width) EMIT(c__ | (0b0111110<<21) | (((lsb)+(width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b001<<4) | (rn))
@@ -532,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
@@ -543,6 +599,10 @@ Op is 20-27
// Preload Cache Rn-Rm
#define PLDn(Rn, Rm) EMIT(PLD_gen(0, 1, Rn, 0, 0, Rm))
#define DMB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0101<<4 | (opt))
// Data memory barrier Inner Sharable
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
#define SWP(Rt, Rt2, Rn) EMIT(SWP_gen(c__, 0, Rn, Rt, Rt2))
@@ -551,17 +611,17 @@ Op is 20-27
#define SDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0001<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
// Signed Div Rd <- Rn/Rm
#define SDIV(Rd, Rm, Rn) EMIT(SDIV_gen(c__, Rd, Rm, Rn))
#define SDIV(Rd, Rn, Rm) EMIT(SDIV_gen(c__, Rd, Rm, Rn))
#define UDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0011<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
// Unsigned Div Rd <- Rn/Rm
#define UDIV(Rd, Rm, Rn) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
#define UDIV(Rd, Rn, Rm) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
// Yield
#define YIELD(cond) EMIT(cond | 0b00110010<<20 | 0b1111<<12 | 1)
// VFPU
#define TRANSFERT64(C, op) ((0b1100<<24) | (0b010<<21) | (0b101<<9) | ((C)<<8) | ((op)<<4))
// UDF
#define UDF(imm16) EMIT(0b1110<<28 | 0b011<<25 | 0b11111<<20 | (((imm16)>>4)&0xfff) | 0b1111<<4 | ((imm16)&0xf))
// Move from FPSCR to Arm register
#define VMRS(Rt) EMIT(c__ | (0b1110<<24) | (0b1111<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
@@ -595,6 +655,8 @@ Op is 20-27
#define VMOVcond_32(cond, Sd, Sm) EMIT(cond | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15))
// Move between Sd and Imm
#define VMOV_i_32(Sd, Imm8) EMIT(c__ | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Imm8)>>4)&0xf)<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b00<<6) | ((Imm8)&15))
// Move between Dd and Imm
#define VMOV_i_64(Dd, Imm8) EMIT(c__ | (0b11101<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | ((((Imm8)>>4)&0xf)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b00<<6) | ((Imm8)&15))
#define VMOVtoDx_gen(Vd, D, Rt, opc1, opc2) (0b1110<<24 | 0<<23 | (opc1)<<21 | (Vd)<<16 | (Rt)<<12 | 0b1011<<8 | (D)<<7 | (opc2)<<5 | 1<<4)
// Move between Rt and Dm[x]
@@ -626,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
@@ -633,10 +699,14 @@ Op is 20-27
// Convert from double Dm to int32 Sd, with Round toward Zero mode
#define VCVT_S32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Convert from double Dm to uint32 Sd, with Round toward Zero mode
#define VCVT_U32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b100<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Convert from double Dm to int32 Sd, with Round selection from FPSCR
#define VCVTR_S32_F64(Sd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Convert from int32 Sm to double Dd
#define VCVT_F64_S32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b111<<19) | (0b000<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Convert from uint32 Sm to double Dd
#define VCVT_F64_U32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b111<<19) | (0b000<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Convert from single Sm to int32 Sd, with Round toward Zero mode
#define VCVT_S32_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Convert from single Sm to int32 Sd, with Round selection from FPSCR
@@ -648,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) )
@@ -683,6 +789,10 @@ Op is 20-27
// Neg F64 Dd = - Dm
#define VNEG_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Neg F64 Dd = - Dm
#define VNEG_F64_cond(cond, Dd, Dm) EMIT((cond) | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Neg F32 Dd = - Dm
#define VNEG_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Sqrt F64 Dd = - Dm
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
@@ -691,6 +801,13 @@ Op is 20-27
// Abs Dd = |Dm|
#define VABS_F64(Dd, Dm) EMIT(c__ | (0b11101<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15))
// Abs Dd = |Dm|
#define VABS_F32(Sd, Sm) EMIT(c__ | (0b11101<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b11<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15))
// MLS Dd = Dd - Dn*Dm
#define VMLS_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | 1<<6 | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// MLA Dd = Dd + Dn*Dm
#define VMLA_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | 0<<6 | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// NEON
@@ -771,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))
@@ -827,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))
@@ -840,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))
@@ -1245,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))
+3 -3
View File
@@ -10,10 +10,10 @@
arm_epilog:
//update register -> emu
//pop {r0}
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be EIP now)
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be Flags now)
//restore all used register
vpop {d8-d15}
pop {r4-r11, pc}
pop {r4-r12, pc}
//end, return...
//bx lr
@@ -22,6 +22,6 @@ arm_epilog:
arm_epilog_fast:
//restore all used register
vpop {d8-d15}
pop {r4-r11, pc}
pop {r4-r12, pc}
//end, return...
//bx lr
+114 -55
View File
@@ -73,12 +73,19 @@
! VMOV is VORR constrained -> (removed VORR)
! VEOR, VBSL, VBIT, VBIF differ only depending on 2 bits: 0/1 0/1 ... VEOR -> @<2> ... @ ... @ V\op\ (field, switchable var, assembly)
! Three registers of different lengths (when having L and W variants): op (field) -> Q (field)
! MRS: always APSR since program is always in userspace
! DBG: option (field and assembly) -> imm (field and assembly)
; ========== BEGINNING OF REGISTERED INSTRUCTIONS =========
# This instruction changes the instruction set to Thumb! Disabled (but valid)
#ARM_ 1 1 1 1 1 0 1 @<1> imm24 @ set imm24 = (imm24 << 2) + (param << 1)@ @ BLX <label>
# CPS marked as invalid (in userspace, treated as NOP)
;INVALIDATE 1 1 1 1 0 0 0 1 0 0 0 0 <4> <8> <2> 0 <1> <4>
ARM_ 1 1 1 1 0 0 0 1 0 0 0 0 (0) (0) (0) 1 (0) (0) (0) (0) (0) (0) @<1> (0) 0 0 0 0 (0) (0) (0) (0) SETEND \%cparam ? 'B' : 'L'\E
;INVALIDATE 1 1 1 1 0 0 0 1 0 0 1 0 <4> <8> 0 1 1 1 <4>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
@@ -172,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>
@@ -237,107 +244,141 @@ NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 0 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 0 0 <20>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 1 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 1 1 <6>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 0 0 <1> 1 <4>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 1 0 <3> 1 <4>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 0 <20>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 0 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 1 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> Rm VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
ARM_ 1 1 1 1 0 1 0 0 @<1> 0 0 1 Rn @<8> @<4> @<4> 'NOP'
ARM_ 1 1 1 1 0 1 0 0 U 1 0 1 Rn (1) (1) (1) (1) imm12 PLI [<Rn>, #+/-<imm12>]
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 1 <4> <8> <4> <4>
ARM_ 1 1 1 1 0 1 0 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm12 PLD\param ? "W" : ""\ [<Rn>, #+/-<imm12>]
ARM_ 1 1 1 1 0 1 0 1 U (1) 0 1 1 1 1 1 (1) (1) (1) (1) imm12 PLD [PC, #+/-<imm>]
;INVALIDATE 1 1 1 1 0 1 0 1 0 0 1 1 <4> <8> <4> <4>
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 0 0 0 <4>
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 (1) (1) (1) (1) CLREX
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 0 1 <1> <4>
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 0 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DSB \option\
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 1 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DMB \option\
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 1 0 @<4> @ param=0b1111 const char* option option,"SY","!!!"@ @ ISB \option\
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 0 1 1 1 <4>
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> 1 <3> <4>
;INVALIDATE 1 1 1 1 0 1 0 1 0 1 1 1 <4> <8> <4> <4>
;INVALIDATE 1 1 1 1 0 1 0 1 1 <1> 1 1 <4> <8> <4> <4>
ARM_ 1 1 1 1 0 1 1 0 @<1> 0 0 1 Rn @<8> @<3> 0 @<4> 'NOP'
ARMs 1 1 1 1 0 1 1 0 U 1 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLI [<Rn>, +/-<Rm>{, <shift>}]
ARMs 1 1 1 1 0 1 1 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLD\param ? "W" : ""\ [<Rn>, +/-<Rm>{, <shift>}]
;INVALIDATE 1 1 1 1 0 1 1 <3> 1 1 <4> <8> <3> 0 <4>
# Permanently undefined
INVALIDATE 1 1 1 1 0 1 1 1 1 1 1 1 <4> <8> 1 1 1 1 <4>
;INVALIDATE 1 1 1 1 0 <7> <4> <8> <4> <4>
; ===== No more 1 1 1 1 ..., so invalidate all of them ====
INVALIDATE 1 1 1 1 <28>
@@ -390,6 +431,8 @@ ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{,
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 0 0 (1) (1) (1) (1) Rd (0) (0) 0 (0) 0 0 0 0 (0) (0) (0) (0) MRS<c> <Rd>, APSR
ARM_ cond 0 0 0 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) (0) (0) 0 (0) 0 0 0 0 Rn @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, <Rn>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
@@ -437,6 +480,18 @@ ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 1 YIELD<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 0 WFE<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 1 WFI<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 1 0 0 SEV<c>
ARM_ cond/=1110 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 0 1 0 0 CSDB<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 1 1 1 1 imm4 DBG<c> #<imm>
INVALIDATE <4> 0 0 1 1 0 0 1 0 0 0 0 0 <8> <8>
ARM_ cond 0 0 1 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) imm12 @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, #<imm>
# MSR in system level is invalid/useless in application level
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 0 1 <8> <8>
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 1 <1> <8> <8>
INVALIDATE <4> 0 0 1 1 0 1 1 0 <4> <8> <8>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
@@ -495,6 +550,8 @@ ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARM_ cond 0 1 1 1 0 0 0 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn SDIV<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 0 0 1 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn UDIV<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
@@ -504,6 +561,7 @@ ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond/=1110 0 1 1 1 1 1 1 1 imm12 1 1 1 1 imm4 UDF<c> #<imm16>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
@@ -537,14 +595,14 @@ INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
@@ -558,6 +616,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>,
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt/=1111 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> APSR_nzcv, FPSCR
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
@@ -587,7 +646,7 @@ VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <S
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 U 1 Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
;INVALIDATE <4> 1 1 1 0 1 <1> 1 1 <8> 1 0 1 <4> 0 <4>
;INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 0 <4>
+7
View File
@@ -20,6 +20,7 @@
arm_lock_read_b:
// address is r0, return is r0
dmb ish
ldrexb r0, [r0]
bx lr
@@ -31,6 +32,7 @@ arm_lock_write_b:
arm_lock_read_h:
// address is r0, return is r0
dmb ish
ldrexh r0, [r0]
bx lr
@@ -43,6 +45,7 @@ arm_lock_write_h:
arm_lock_read_d:
// address is r0, return is r0
// r0 needs to be aligned
dmb ish
ldrex r0, [r0]
bx lr
@@ -55,6 +58,7 @@ arm_lock_write_d:
arm_lock_read_dd:
// address is r2, return is r0, r1
dmb ish
ldrexd r2, r3, [r2]
str r2, [r0]
str r3, [r1]
@@ -70,6 +74,7 @@ arm_lock_write_dd:
arm_lock_xchg:
// address is r0, value is r1, return old value in r0
// r0 needs to be aligned
dmb ish
ldrex r2, [r0]
strex r3, r1, [r0]
cmp r3, #1
@@ -80,6 +85,7 @@ arm_lock_xchg:
arm_lock_storeifnull:
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
// r0 needs to be aligned
dmb ish
ldrex r2, [r0]
cmp r2, #0
bne arm_lock_storeifnull_exit
@@ -93,6 +99,7 @@ arm_lock_storeifnull_exit:
arm_lock_storeifref:
push {r4}
dmb ish
arm_lock_storeifref_loop:
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return new [r0] value (so r1 or old value)
ldrex r3, [r0]
+1216 -796
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -9,7 +9,7 @@
.global arm_prolog
arm_prolog:
//save all used register
push {r4-r11, lr}
push {r4-r12, lr}
vpush {d8-d15}
//setup emu -> register
//push {r0}
+56 -32
View File
@@ -2,6 +2,8 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <sys/mman.h>
#include <setjmp.h>
#include "debug.h"
#include "box86context.h"
@@ -55,12 +57,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
return ret;
}
void FreeDynablock(dynablock_t* db)
void FreeDynablock(dynablock_t* db, int need_lock)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
@@ -76,16 +80,18 @@ void FreeDynablock(dynablock_t* db)
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
FreeDynablock(son, 0);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
free(db->sons);
free(db->instsize);
}
free(db->sons);
free(db->instsize);
free(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
}
@@ -99,7 +105,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i]);
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
}
free((*dynablocks)->direct);
}
@@ -116,7 +122,7 @@ void MarkDynablock(dynablock_t* db)
db = db->father; // mark only father
if(db->need_test)
return; // already done
db->need_test = 1; // test only blocks that can be marked (and so deleted)
db->need_test = 1;
setJumpTableDefault(db->x86_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault(db->sons[i]->x86_addr);
@@ -200,7 +206,7 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
FreeDynablock(db, 1);
);
kh_destroy(dynablocks, blocks);
}
@@ -258,7 +264,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
@@ -267,6 +273,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
if (!*created)
return block;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
@@ -274,32 +281,40 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
}
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(tmp != block) {
// a block appeard!
free(block);
*created = 0;
return tmp;
}
*created = 1;
return block;
}
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
{
// 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;
@@ -323,15 +338,19 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
if(!created)
return block; // existing block...
#if 0
if(box86_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
#endif
// fill the block
block->x86_addr = (void*)addr;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock(block, filladdr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
void* old = (void*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
@@ -342,10 +361,6 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
free(block);
block = NULL;
}
#if 0
if(box86_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
// check size
if(block && block->x86_size) {
int blocksz = block->x86_size;
@@ -358,7 +373,10 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
dblist->maxsz = blocksz;
}
}
protectDB((uintptr_t)block->x86_addr, block->x86_size);
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
// but check if it already need test
if(block->need_test || (block->father && block->father->need_test))
return NULL;
// fill-in jumptable
addJumpTableIfDefault(block->x86_addr, block->block);
for(int i=0; i<block->sons_size; ++i)
@@ -372,19 +390,21 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father);
FreeDynablock(father, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current);
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
@@ -393,6 +413,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t**
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
@@ -401,16 +422,18 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = X31_hash_code(father->x86_addr, father->x86_size);
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father);
FreeDynablock(father, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
@@ -419,6 +442,7 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
+20 -7
View File
@@ -19,6 +19,7 @@
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#endif
#ifdef ARM
@@ -29,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)
@@ -37,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;
@@ -45,12 +49,21 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
#ifdef HAVE_TRACE
dynablock_t* db = FindDynablockFromNativeAddress(x2);
printf_log(LOG_INFO, "Warning, jumping to a no-block address from %p (db=%p, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
}
if(!block) {
#ifdef HAVE_TRACE
dynablock_t* db = FindDynablockFromNativeAddress(x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
}
}
if(!block->done) {
// not finished yet... leave linker
+225 -81
View File
@@ -3,6 +3,7 @@
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include "debug.h"
#include "box86context.h"
@@ -58,13 +59,23 @@ 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));
}
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
dyn->next[dyn->next_sz++] = addr;
}
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
@@ -73,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;
}
@@ -204,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
@@ -229,54 +239,7 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
return (i==n)?1:0;
}
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
{
if(recurse == 10)
return X_PEND;
if(ninst == dyn->size)
return X_PEND; // no more instructions, or too many jmp loop, stop
uint32_t needed = dyn->insts[ninst].x86.use_flags;
if(needed) {
setf &= ~needed;
if(!setf) // all flags already used, no need to continue
return needed;
}
if(!needed && !dyn->insts[ninst].x86.set_flags && !dyn->insts[ninst].x86.jmp_insts) {
int start = ninst;
int end = ninst;
while(end<dyn->size && !dyn->insts[end].x86.use_flags && !dyn->insts[end].x86.set_flags && !dyn->insts[end].x86.jmp_insts)
++end;
needed = needed_flags(dyn, end, setf, recurse);
for(int i=start; i<end; ++i)
dyn->insts[i].x86.need_flags = needed;
return needed;
}
if(dyn->insts[ninst].x86.set_flags && (dyn->insts[ninst].x86.state_flags!=SF_MAYSET)) {
if((setf & ~dyn->insts[ninst].x86.set_flags) == 0)
return needed; // all done, gives all the flags needed
setf |= dyn->insts[ninst].x86.set_flags; // add new flags to continue
}
int jinst = dyn->insts[ninst].x86.jmp_insts;
if(dyn->insts[ninst].x86.jmp) {
dyn->insts[ninst].x86.need_flags = (jinst==-1)?X_PEND:needed_flags(dyn, jinst, setf, recurse+1);
if(dyn->insts[ninst].x86.use_flags) // conditionnal jump
dyn->insts[ninst].x86.need_flags |= needed_flags(dyn, ninst+1, setf, recurse);
} else
dyn->insts[ninst].x86.need_flags = needed_flags(dyn, ninst+1, setf, recurse);
if(dyn->insts[ninst].x86.state_flags==SF_MAYSET)
needed |= dyn->insts[ninst].x86.need_flags;
else
needed |= (dyn->insts[ninst].x86.need_flags & ~dyn->insts[ninst].x86.set_flags);
if(needed == (X_PEND|X_ALL))
needed = X_ALL;
return needed;
}
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;
@@ -305,11 +268,120 @@ 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);
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
__thread void* current_helper = NULL;
void CancelBlock()
{
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->predecessor);
free(helper->sons_x86);
free(helper->sons_arm);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
}
void* FillBlock(dynablock_t* block, uintptr_t addr) {
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
@@ -322,47 +394,115 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
// init the helper
dynarec_arm_t helper = {0};
current_helper = &helper;
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
// pass 0, addresses, x86 jump addresses, overall size of the block
uintptr_t end = arm_pass0(&helper, addr);
// no need for next anymore
free(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
free(helper.next);
CancelBlock();
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
// already protect the block and compute hash signature
protectDB(addr, end-addr+1);
uint32_t hash = X31_hash_code((void*)addr, end-addr+1);
// pass 1, addresses, x86 jump addresses, flags
arm_pass1(&helper, addr);
protectDB(addr, end-addr); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// Compute flag_need, without with current barriers
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end)
if(j<start || j>=end) {
helper.insts[i].x86.jmp_insts = -1;
else {
helper.insts[i].x86.use_flags |= X_PEND;
} else {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
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;
}
}
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.set_flags && !helper.insts[i].x86.need_flags) {
helper.insts[i].x86.need_flags = needed_flags(&helper, i+1, helper.insts[i].x86.set_flags, 0);
if((helper.insts[i].x86.need_flags&X_PEND) && (helper.insts[i].x86.state_flags==SF_MAYSET))
helper.insts[i].x86.need_flags = X_ALL;
// fill predecessors with the jump address
fillPredecessors(&helper);
// check for the optionnal barriers now
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].barrier_maybe) {
// out-of-block jump
if(helper.insts[i].x86.jmp_insts == -1) {
// nothing for now
} else {
// inside block jump
int k = helper.insts[i].x86.jmp_insts;
if(k>i) {
// jump in the future
if(helper.insts[k].pred_sz>1) {
// with multiple flow, put a barrier
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
} else {
// jump back
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
}
}
}
// check to remove useless barrier, in case of jump when destination doesn't needs flags
/*for(int i=helper.size-1; i>=0; --i) {
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
&& helper.insts[k].x86.barrier&BARRIER_FLAGS) {
//TODO: optimize FPU barrier too
if((!helper.insts[k].x86.need_flags)
||(helper.insts[k].x86.set_flags==X_ALL
&& helper.insts[k].x86.state_flags==SF_SET)
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
helper.insts[k].x86.barrier &= ~BARRIER_FLAGS; // remove flag barrier
}
}
}*/
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
for(int i = helper.size; i-- > 0;) {
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
) {
if(helper.insts[k].x86.barrier&BARRIER_FLAGS)
// jumpto barrier
helper.insts[i].x86.use_flags |= X_PEND;
if(helper.insts[i].x86.barrier&BARRIER_FLAGS && (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags))
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
else
helper.insts[i].x86.use_flags |= (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags);
}
if(helper.insts[i].x86.barrier&BARRIER_FLAGS)
// immediate barrier
helper.insts[i].x86.use_flags |= X_PEND;
}
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
// 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
@@ -370,8 +510,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
CancelBlock();
return NULL;
}
helper.block = p;
@@ -415,22 +554,22 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
// ok, free the helper now
free(helper.insts);
helper.insts = NULL;
free(helper.next);
helper.next = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->need_test = 0;
//block->x86_addr = (void*)start;
block->x86_size = end-start+1;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// Check if something changed, to abbort if it as
if(block->hash != hash) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
free(helper.sons_x86);
free(helper.sons_arm);
FreeDynarecMap(block, (uintptr_t)p, sz);
CancelBlock();
return NULL;
}
// fill sons if any
@@ -444,7 +583,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(created) { // avoid breaking a working block!
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i]+1;
son->x86_size = end-helper.sons_x86[i];
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
son->father = block;
son->done = 1;
@@ -459,8 +598,13 @@ 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);
helper.sons_arm = NULL;
current_helper = NULL;
block->done = 1;
return (void*)block;
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+25 -18
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)
@@ -37,7 +38,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x03:
INST_NAME("ADD Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -47,7 +48,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x2B:
INST_NAME("SUB Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -57,7 +58,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -65,9 +66,19 @@ uintptr_t dynarecFS(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 FS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x14);
emit_cmp32(dyn, ninst, ed, gd, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -174,7 +185,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -187,7 +198,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -199,7 +210,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
@@ -259,7 +270,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
@@ -278,7 +289,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 2: // CALL Ed
INST_NAME("CALL FS:Ed");
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x86.set_flags, 1) {
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
@@ -286,16 +297,12 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
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);
@@ -305,7 +312,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
+304 -26
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,19 +29,33 @@ 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;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -48,9 +63,67 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_add32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x0F: // more opcodes
opcode = F8;
switch(opcode) {
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x14);
UFLAG_IF {
SMULL(x3, gd, gd, ed);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul32);
} else {
MUL(gd, gd, ed);
}
break;
default:
DEFAULT;
}
break;
case 0x21:
INST_NAME("AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO2(x14);
emit_and32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0x23:
INST_NAME("AND Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x14);
emit_and32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x29:
INST_NAME("SUB GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO2(x14);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0x2B:
INST_NAME("SUB Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -58,9 +131,20 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sub32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x31:
INST_NAME("XOR GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO2(x14);
emit_xor32(dyn, ninst, gd, ed, x3, x14);
WBACK;
break;
case 0x33:
INST_NAME("XOR Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -68,9 +152,19 @@ 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);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
@@ -103,7 +197,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -112,7 +206,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1: //OR
INST_NAME("OR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -122,7 +216,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2: //ADC
INST_NAME("ADC GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -132,7 +226,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3: //SBB
INST_NAME("SBB GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -141,7 +235,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4: //AND
INST_NAME("AND GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -150,7 +244,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5: //SUB
INST_NAME("SUB GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -159,7 +253,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6: //XOR
INST_NAME("XOR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -168,7 +262,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7: //CMP
INST_NAME("CMP GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
@@ -191,7 +285,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -200,7 +294,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -210,7 +304,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -220,7 +314,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -229,7 +323,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -238,7 +332,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -247,7 +341,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -256,7 +350,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -278,7 +372,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -291,7 +385,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -303,7 +397,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
@@ -331,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);
@@ -340,13 +452,179 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
case 0xD1:
nextop = F8;
grab_tlsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
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_PENDING);
GETEDO2(x14);
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
GETEDO2(x14);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
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);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
break;
case 4:
case 6:
INST_NAME("SHL Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shl32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 5:
INST_NAME("SHR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shr32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 7:
INST_NAME("SAR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_sar32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
}
break;
case 0xD3:
nextop = F8;
grab_tlsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
AND_IMM8(x3, xECX, 0x1f);
TSTS_REG_LSL_IMM5(x3, x3, 0);
B_MARK2(cEQ);
RSB_IMM8(x3, x3, 0x20);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 31);
B_MARK(cNE);
MOV_REG_LSR_IMM5(x1, ed, 31);
ADD_REG_LSL_IMM5(x1, x1, ed, 0);
BFI(xFlags, x1, F_OF, 1);
MARK;
BFI(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
MARK2;
break;
case 1:
INST_NAME("ROR Ed, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
AND_IMM8(x3, xECX, 0x1f);
TSTS_REG_LSL_IMM5(x3, x3, 0);
B_MARK2(cEQ);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 1);
B_MARK(cNE);
MOV_REG_LSR_IMM5(x2, ed, 30); // x2 = d>>30
XOR_REG_LSR_IMM8(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
BFI(xFlags, x2, F_OF, 1);
MARK;
MOV_REG_LSR_IMM5(x2, ed, 31);
BFI(xFlags, x2, F_CF, 1);
UFLAG_DF(x2, d_none);
}
MARK2;
break;
case 2:
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
break;
case 3:
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
break;
case 4:
case 6:
INST_NAME("SHL Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shl32(dyn, ninst, ed, x3, x3, x14);
WBACK;
break;
case 5:
INST_NAME("SHR Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shr32(dyn, ninst, ed, x3, x3, x14);
WBACK;
break;
case 7:
INST_NAME("SAR Ed, CL");
SETFLAGS(X_ALL, SF_PENDING);
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
UFLAG_OP12(ed, x3);
MOV_REG_ASR_REG(ed, ed, x3);
WBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar32);
break;
}
break;
case 0xE9:
case 0xEB:
INST_NAME("(ignored) GS:");
@@ -362,7 +640,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
+92 -64
View File
@@ -43,7 +43,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x01:
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -52,7 +52,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -61,7 +61,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_add16c(dyn, ninst, x1, i32, x3, x14);
@@ -88,7 +88,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -97,7 +97,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -106,7 +106,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_or16c(dyn, ninst, x1, i32, x3, x14);
@@ -119,7 +119,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -129,7 +129,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x13:
INST_NAME("ADC Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -139,7 +139,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x15:
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
@@ -149,7 +149,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -159,7 +159,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -169,16 +169,22 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x1D:
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i16 = F16;
UXTH(x1, xEAX, 0);
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");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -187,7 +193,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -196,7 +202,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_and16c(dyn, ninst, x1, i32, x3, x14);
@@ -209,7 +215,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -218,7 +224,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -227,7 +233,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
@@ -236,7 +242,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -245,7 +251,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -254,7 +260,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_xor16c(dyn, ninst, x1, i32, x3, x14);
@@ -263,7 +269,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
@@ -271,7 +277,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
@@ -279,7 +285,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
MOVW(x2, i32);
UXTH(x1, xEAX, 0);
@@ -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);
@@ -417,7 +423,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_add16c(dyn, ninst, ed, i16, x2, x14);
@@ -425,7 +431,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_or16c(dyn, ninst, x1, i16, x2, x14);
@@ -434,7 +440,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_adc16c(dyn, ninst, x1, i16, x2, x14);
@@ -443,7 +449,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_sbb16c(dyn, ninst, x1, i16, x2, x14);
@@ -451,7 +457,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_and16c(dyn, ninst, x1, i16, x2, x14);
@@ -459,7 +465,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_sub16c(dyn, ninst, x1, i16, x2, x14);
@@ -467,7 +473,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_xor16c(dyn, ninst, x1, i16, x2, x14);
@@ -475,7 +481,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
@@ -489,7 +495,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEW(x1);
GETGW(x2);
@@ -500,15 +506,17 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("XCHG Ew, Gw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
GETGW(x14);
GETGD;
UXTH(x14, gd, 0);
ed = xEAX + (nextop&7);
UXTH(x1, ed, 0);
// do the swap 14 -> ed, 1 -> gd
BFI(gd, x1, 0, 16);
BFI(ed, x14, 0, 16);
} else {
GETGW(x14);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
GETGD;
UXTH(x14, gd, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
#if 0
MARKLOCK;
// do the swap with exclusive locking
@@ -535,7 +543,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
STRH_IMM8(gd, ed, fixedaddress);
}
break;
@@ -549,7 +557,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
LDRH_IMM8(x1, ed, fixedaddress);
BFI(gd, x1, 0, 16);
}
@@ -563,7 +571,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
BFI(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
STRH_IMM8(x1, ed, fixedaddress);
}
break;
@@ -576,7 +584,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
LDRH_IMM8(x1, ed, fixedaddress);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(x1, xEmu, x2);
@@ -650,16 +658,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xA7:
INST_NAME("CMPSW");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, 2);
LDRHAI_REG_LSL_IMM5(x1, xESI, x3);
LDRHAI_REG_LSL_IMM5(x2, xEDI, x3);
CALL(cmp16, -1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOVW(x2, u16);
UBFX(x1, xEAX, 0, 16);
@@ -679,10 +687,11 @@ 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);
CALL(cmp16, -1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0xB8:
@@ -789,7 +798,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x1, u16);
BFI(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
u16 = F16;
MOVW(x1, u16);
STRH_IMM8(x1, ed, fixedaddress);
@@ -896,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;
@@ -989,13 +1002,20 @@ 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) {
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
u16 = F16;
MOVW(x2, u16);
@@ -1009,13 +1029,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1);
emit_neg16(dyn, ninst, ed, x2, x14);
EWBACK;
break;
case 4:
INST_NAME("MUL AX, Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
@@ -1035,14 +1056,27 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(div16, -1, 0);
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
if(arm_div) {
GETEW(x1);
SETFLAGS(X_ALL, SF_SET);
UXTH(x2, xEAX, 0);
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, 0, 16);
BFI(xEDX, x14, 0, 16);
} else {
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(div16, -1, 0);
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
}
break;
case 7:
INST_NAME("IDIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
@@ -1053,20 +1087,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xF8:
INST_NAME("CLC");
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
SET_DFNONE(x1);
}
SET_DFNONE(x1);
BFC(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
SET_DFNONE(x1);
}
SET_DFNONE(x1);
MOVW(x1, 1);
BFI(xFlags, x1, F_CF, 1);
break;
@@ -1076,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_SET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1);
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
File diff suppressed because it is too large. Load diff
+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);\
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)");
+120 -56
View File
@@ -50,9 +50,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v1, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VADD_F32(v1, v1, v2);
} else {
VADD_F64(v1, v1, v2);
}
break;
case 0xC8:
case 0xC9:
@@ -63,9 +67,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCE:
case 0xCF:
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v1, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, v2);
} else {
VMUL_F64(v1, v1, v2);
}
break;
case 0xD0:
case 0xD1:
@@ -76,9 +84,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
break;
case 0xD8:
@@ -90,9 +102,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDE:
case 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
@@ -105,9 +121,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, v2);
} else {
VSUB_F64(v1, v1, v2);
}
break;
case 0xE8:
case 0xE9:
@@ -118,9 +138,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v1, v2, v1);
} else {
VSUB_F64(v1, v2, v1);
}
break;
case 0xF0:
case 0xF1:
@@ -131,9 +155,13 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, v2);
} else {
VDIV_F64(v1, v1, v2);
}
break;
case 0xF8:
case 0xF9:
@@ -144,143 +172,179 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFE:
case 0xFF:
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v1, v2, v1);
} else {
VDIV_F64(v1, v2, v1);
}
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
}
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
}
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
if(ST_IS_F(0)) {
VCMP_F32(v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
}
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
if(ST_IS_F(0)) {
VCMP_F32(v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
}
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
if(ST_IS_F(0)) {
VSUB_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
}
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
}
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
if(ST_IS_F(0)) {
VDIV_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
}
break;
default:
DEFAULT;
+402 -107
View File
@@ -23,28 +23,38 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static const double d_1 = 1.0;
static const double d_l2t = L2T;
static const double d_l2e = L2E;
static const double d_pi = PI;
static const double d_lg2 = LG2;
static const double d_ln2 = LN2;
static const double d_0 = 0.0;
static const float f_l2t = L2T;
static const float f_l2e = L2E;
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;
int i1, i2, i3;
int j32;
int parity;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
(void)u8;
switch(nextop) {
@@ -57,12 +67,19 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v2 = x87_do_push(dyn, ninst, x3);
VMOV_64(v2, v1);
v2 = x87_do_push(dyn, ninst, x3, X87_ST(nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
if(ST_IS_F(0)) {
VMOV_32(v2, v1);
} else {
VMOV_64(v2, v1);
}
// should set C1 to 0
break;
case 0xC8:
INST_NAME("FXCH ST0");
break;
case 0xC9:
case 0xCA:
case 0xCB:
@@ -72,11 +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, x1, x2, nextop&7);
i2 = x87_get_cache(dyn, ninst, x1, x2, 0);
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
// should set C1 to 0
break;
case 0xD0:
@@ -85,182 +99,447 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VNEG_F64(v1, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VNEG_F32(v1, v1);
} else {
VNEG_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE1:
INST_NAME("FABS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VABS_F64(v1, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VABS_F32(v1, v1);
} else {
VABS_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE4:
INST_NAME("FTST");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VCMP_F32_0(v1);
} else {
VCMP_F64_0(v1);
}
FCOM(x1, x2); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
#if 1
i1 = x87_get_current_cache(dyn, ninst, 0, NEON_CACHE_ST_D);
// value put in x14
if(i1==-1) {
// 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->n.x87stack;
if(i2) {
if(i2<0) {
SUB_IMM8(x14, x14, -i2);
} else {
ADD_IMM8(x14, x14, i2);
}
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
ADD_REG_LSL_IMM5(x1, xEmu, x14, 2);
LDR_IMM9(x1, x1, offsetof(x86emu_t, p_regs));
CMPS_IMM8(x1, 0b11);
MOVW_COND(cEQ, x14, 0b100000100000000); // empty: C3,C2,C0 = 101
B_MARK3(cEQ);
} else {
// simply move from cache reg to r2/r3
v1 = dyn->n.x87reg[i1];
VMOVfrV_D(x2, x3, v1);
}
// get exponant in r1
MOV_REG_LSR_IMM5(x1, x3, 20);
MOVW(x14, 0x7ff);
ANDS_REG_LSL_IMM5(x1, x1, x14, 0);
B_MARK(cNE); // not zero or denormal
BIC_IMM8_ROR(x1, x3, 0b10, 1); // remove sign bit
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
MOVW_COND(cEQ, x14, 0b100000000000000); // Zero: C3,C2,C0 = 100
MOVW_COND(cNE, x14, 0b100010000000000); // Denormal: C3,C2,C0 = 110
B_MARK3(c__);
MARK;
CMPS_REG_LSL_IMM5(x1, x14, 0); // infinite/NaN?
MOVW_COND(cNE, x14, 0b000010000000000); // normal: C3,C2,C0 = 010
B_MARK3(cNE);
ORR_IMM8(x1, x1, 0x08, 12); //prepare mask, 0x7ff | 0x800 => 0xfff
BIC_REG_LSL_IMM5(x1, x3, x1, 20);
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
MOVW_COND(cEQ, x14, 0b000010100000000); // infinity: C3,C2,C0 = 011
MOVW_COND(cNE, x14, 0b000000100000000); // NaN: C3,C2,C0 = 001
MARK3;
// Extract signa & Update SW
MOV_REG_LSR_IMM5(x1, x3, 31);
BFI(x14, x1, 9, 1); //C1
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BIC_IMM8(x1, x1, 0b01000111, 12);
ORR_REG_LSL_IMM5(x14, x14, x1, 0);
STRH_IMM8(x14, xEmu, offsetof(x86emu_t, sw));
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_refresh(dyn, ninst, x1, x2, 0);
CALL(fpu_fxam, -1, 0); // should be possible inline, but is it worth it?
#endif
break;
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_1));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
VMOV_i_32(v1, 0b01110000);
} else {
VMOV_i_64(v1, 0b01110000);
}
// should set C1 to 0
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_l2t));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_l2t));
VLDR_32(v1, x2, 0);
} else {
MOV32(x2, (&d_l2t));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_l2e));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_l2e));
VLDR_32(v1, x2, 0);
} else {
MOV32(x2, (&d_l2e));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_pi));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_pi));
VLDR_32(v1, x2, 0);
} else {
MOV32(x2, (&d_pi));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_lg2));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_lg2));
VLDR_32(v1, x2, 0);
} else {
MOV32(x2, (&d_lg2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_ln2));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_ln2));
VLDR_32(v1, x2, 0);
} else {
MOV32(x2, (&d_ln2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst, x1);
MOV32(x2, (&d_0));
VLDR_64(v1, x2, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
VMOV_8(v1/2, 0); // float is *2...
} 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);
VSQRT_F64(v1, v1);
break;
case 0xFC:
INST_NAME("FRNDINT");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1, 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");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2x, -1, 0);
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);
VMOV_64(0, v1); // prepare call to log2
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");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_ftan, -1, 0);
v1 = x87_do_push(dyn, ninst, x3);
MOV32(x2, (&d_1));
VLDR_64(v1, x2, 0);
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_C1 = 0;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C1 C2 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
// 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
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
} else {
VMOV_i_64(v2, 0b01110000);
}
break;
case 0xF3:
INST_NAME("FPATAN");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fpatan, -1, 0);
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);
VMOV_64(0, v2); // prepare call to atan2
VMOV_64(1, v1);
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
fpu_purgecache(dyn, ninst, x1, x2, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
SUB_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// should set C1 to 0
break;
case 0xF7:
INST_NAME("FINCSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
ADD_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// 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");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2xp1, -1, 0);
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);
VMOV_i_64(0, 0b01110000); // D0 = 1.0
VADD_F64(0, 0, v1); // prepare call to log2
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");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fsincos, -1, 0);
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); // would it be faster to do sqrt(1-sin()²) ???
VMOV_64(v2, 0);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
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");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fscale, -1, 0);
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);
//if(ST0.d!=0.0)
// ST0.d *= exp2(trunc(ST1.d));
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cEQ);
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");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fsin, -1, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
VMOV_64(0, v1); // prepare call to sin
CALL_1D(sin, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
case 0xFF:
INST_NAME("FCOS");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fcos, -1, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
VMOV_64(0, v1); // prepare call to cos
CALL_1D(cos, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
@@ -289,45 +568,59 @@ 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);
s0 = fpu_get_scratch_single(dyn);
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
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
VCVT_F64_F32(v1, s0);
if(!ST_IS_F(0)) {
VCVT_F64_F32(v1, s0);
}
// should set C1 to 0
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
@@ -335,8 +628,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("FLDENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
@@ -352,8 +646,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("FNSTENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
@@ -362,7 +657,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
ed = x1;
wb1 = 1;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw));
+43 -23
View File
@@ -52,10 +52,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("FCMOVB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cNE, v1, v2); // F_CF==1
if(ST_IS_F(0)) {
VMOVcond_32(cNE, v1, v2); // F_CF==1
} else {
VMOVcond_64(cNE, v1, v2); // F_CF==1
}
break;
case 0xC8:
case 0xC9:
@@ -67,10 +71,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("FCMOVE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cNE, v1, v2); // F_ZF==1
if(ST_IS_F(0)) {
VMOVcond_32(cNE, v1, v2); // F_ZF==1
} else {
VMOVcond_64(cNE, v1, v2); // F_ZF==1
}
break;
case 0xD0:
case 0xD1:
@@ -82,10 +90,14 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD7:
INST_NAME("FCMOVBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
if(ST_IS_F(0)) {
VMOVcond_32(cNE, v1, v2); // F_CF==1 | F_ZF==1
} else {
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
}
break;
case 0xD8:
case 0xD9:
@@ -97,16 +109,24 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
INST_NAME("FCMOVU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cNE, v1, v2); // F_PF==1
if(ST_IS_F(0)) {
VMOVcond_32(cNE, v1, v2); // F_PF==1
} else {
VMOVcond_64(cNE, v1, v2); // F_PF==1
}
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
@@ -129,7 +149,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -139,7 +159,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -149,7 +169,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -160,7 +180,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -172,7 +192,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -182,7 +202,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -192,7 +212,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
@@ -202,7 +222,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
GETED;
d0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
+142 -34
View File
@@ -50,10 +50,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("FCMOVNB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cEQ, v1, v2); // F_CF==0
if(ST_IS_F(0)) {
VMOVcond_32(cEQ, v1, v2); // F_CF==0
} else {
VMOVcond_64(cEQ, v1, v2); // F_CF==0
}
break;
case 0xC8:
case 0xC9:
@@ -65,10 +69,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("FCMOVNE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
if(ST_IS_F(0)) {
VMOVcond_32(cEQ, v1, v2); // F_ZF==0
} else {
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
}
break;
case 0xD0:
case 0xD1:
@@ -80,10 +88,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD7:
INST_NAME("FCMOVNBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
VMOVcond_64(cEQ, v1, v2); // F_CF==0 & F_ZF==0
if(ST_IS_F(0)) {
VMOVcond_32(cEQ, v1, v2); // F_CF==0 & F_ZF==0
} else {
VMOVcond_64(cEQ, v1, v2); // F_CF==0 & F_ZF==0
}
break;
case 0xD8:
case 0xD9:
@@ -95,10 +107,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
INST_NAME("FCMOVNU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cEQ, v1, v2); // F_PF==0
if(ST_IS_F(0)) {
VMOVcond_32(cEQ, v1, v2); // F_PF==0
} else {
VMOVcond_64(cEQ, v1, v2); // F_PF==0
}
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
@@ -106,14 +122,14 @@ 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:
INST_NAME("FNINIT");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
CALL(reset_fpu, -1, 0);
break;
case 0xE8:
@@ -126,9 +142,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
break;
case 0xF0:
@@ -141,9 +161,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
break;
@@ -159,11 +183,11 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -173,12 +197,12 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
@@ -198,14 +222,14 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
ed = x1;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
ed = x1; // will not be writen immediatly, so x1 is safe for now
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
@@ -223,13 +247,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
@@ -249,7 +273,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
// the FLD is immediatly followed by an FSTP
LDR_IMM9(x2, ed, 0);
@@ -259,26 +283,110 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; //0xDB
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
STR_IMM9(x2, ed, 0);
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
x87_do_pop(dyn, ninst, x3);
break;
default:
+80 -48
View File
@@ -46,9 +46,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FADD STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v1, v1, v2);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VADD_F32(v1, v1, v2);
} else {
VADD_F64(v1, v1, v2);
}
break;
case 0xC8:
case 0xC9:
@@ -59,9 +63,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCE:
case 0xCF:
INST_NAME("FMUL STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v1, v1, v2);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, v2);
} else {
VMUL_F64(v1, v1, v2);
}
break;
case 0xD0:
case 0xD1:
@@ -72,9 +80,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FCOM ST0, STx"); //yep
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
break;
case 0xD8:
@@ -86,9 +98,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDE:
case 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
@@ -101,9 +117,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
INST_NAME("FSUBR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v2, v1);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v1, v2, v1);
} else {
VSUB_F64(v1, v2, v1);
}
break;
case 0xE8:
case 0xE9:
@@ -114,9 +134,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FSUB STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v1, v1, v2);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, v2);
} else {
VSUB_F64(v1, v1, v2);
}
break;
case 0xF0:
case 0xF1:
@@ -127,9 +151,13 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FDIVR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v2, v1);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v1, v2, v1);
} else {
VDIV_F64(v1, v2, v1);
}
break;
case 0xF8:
case 0xF9:
@@ -140,22 +168,26 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFE:
case 0xFF:
INST_NAME("FDIV STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v1, v1, v2);
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, v2);
} else {
VDIV_F64(v1, v1, v2);
}
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -164,14 +196,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -180,14 +212,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -197,14 +229,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -215,14 +247,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -231,14 +263,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -247,14 +279,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -263,14 +295,14 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
+56 -41
View File
@@ -31,6 +31,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int parity;
uint8_t ed;
int v1, v2;
int i1, i2, i3;
MAYUSE(v2);
MAYUSE(v1);
@@ -45,7 +46,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
break; // not handling Tag...
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
MOVW(x1, nextop&7);
CALL(fpu_do_free, -1, 0);
break;
case 0xD0:
case 0xD1:
case 0xD2:
@@ -55,9 +59,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FST ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMOV_64(v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VMOV_32(v2, v1);
} else {
VMOV_64(v2, v1);
}
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
@@ -71,9 +79,8 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDE:
case 0xDF:
INST_NAME("FSTP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMOV_64(v2, v1);
// copy the cache value for st0 to stx
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
@@ -86,9 +93,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
INST_NAME("FUCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
break;
case 0xE8:
@@ -100,9 +111,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FUCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
@@ -138,41 +153,35 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x1);
#if 0
// can bus error...
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
#else
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
}
#endif
break;
case 1:
INST_NAME("FISTTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistt64, -1, 0);
x87_do_pop(dyn, ninst, x3);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -180,13 +189,13 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -195,28 +204,34 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("FRSTOR m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_frstor, -1, 0);
break;
case 6:
INST_NAME("FSAVE m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
MOVW(x2, offsetof(x86emu_t, sw));
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
LDRH_IMM8(x3, x2, 0);
BFI(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_IMM8(x3, ed, 0); // store whole sw flags
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->n.x87stack) {
// update top
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
BFI(x1, x2, 11, 3); // inject top
STRH_IMM8(x1, ed, 0); // store whole sw flags
break;
default:
DEFAULT;
+57 -24
View File
@@ -17,6 +17,7 @@
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
@@ -40,9 +41,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FADDP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VADD_F64(v2, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VADD_F32(v2, v2, v1);
} else {
VADD_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xC8:
@@ -54,9 +59,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCE:
case 0xCF:
INST_NAME("FMULP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VMUL_F64(v2, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VMUL_F32(v2, v2, v1);
} else {
VMUL_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xD0:
@@ -68,18 +77,26 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
case 0xD9:
INST_NAME("FCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, 1));
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, 1));
if(ST_IS_F(0)) {
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
@@ -93,9 +110,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
INST_NAME("FSUBRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v2, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v2, v1, v2);
} else {
VSUB_F64(v2, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xE8:
@@ -107,9 +128,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FSUBP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VSUB_F64(v2, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VSUB_F32(v2, v2, v1);
} else {
VSUB_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF0:
@@ -121,9 +146,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FDIVRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v2, v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v2, v1, v2);
} else {
VDIV_F64(v2, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF8:
@@ -135,9 +164,13 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFE:
case 0xFF:
INST_NAME("FDIVP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VDIV_F64(v2, v2, v1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
VDIV_F32(v2, v2, v1);
} else {
VDIV_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
+238 -33
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,13 +31,15 @@ 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 v1, v2;
int /*v0, */v1, v2;
int s0;
int fixedaddress;
int parity;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
//MAYUSE(v0);
MAYUSE(j32);
switch(nextop) {
@@ -58,6 +60,15 @@ 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->n.x87stack) {
// update top
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
BFI(x1, x2, 11, 3); // inject top
BFI(xEAX, x1, 0, 16);
break;
@@ -71,9 +82,14 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEF:
INST_NAME("FUCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0))
{
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
@@ -87,9 +103,14 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF7:
INST_NAME("FCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0))
{
VCMP_F32(v1, v2);
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
break;
@@ -140,17 +161,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
LDRSH_IMM8(x1, wback, fixedaddress);
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, x1);
VCVT_F64_S32(v1, s0);
if(ST_IS_F(0)) {
VMOVtoV(v1, x1);
VCVT_F32_S32(v1, v1);
} else {
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, x1);
VCVT_F64_S32(v1, s0);
}
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
@@ -159,7 +185,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
VCVTR_S32_F64(s0, v1);
}
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
@@ -172,9 +202,9 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
@@ -182,7 +212,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
VCVTR_S32_F64(s0, v1);
}
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
@@ -194,9 +228,9 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
@@ -204,7 +238,11 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
VCVTR_S32_F64(s0, v1);
}
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
@@ -217,32 +255,199 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbld, -1, 0);
break;
case 5: // could be inlined for most thing, but is it usefull?
case 5:
INST_NAME("FILD ST0, i64");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fild64, -1, 0);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
if(parity) {
LDRD_IMM8(x2, wback, 0); // x2/x3 is 64bits
} else {
LDR_IMM9(x2, wback, 0);
LDR_IMM9(x3, wback, 4);
}
if(ninst<dyn->size
&& dyn->insts[ninst+1].x86.addr
&& *(uint8_t*)dyn->insts[ninst+1].x86.addr==0xDF
&& (((*(uint8_t*)(dyn->insts[ninst+1].x86.addr+1))>>3)&7)==7)
{
MESSAGE(LOG_DUMP, "Hack for FILD/FISTP i64");
} else {
// 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(x1, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x1, x1, -a);
AND_IMM8(x1, x1, 7);
} else if(a>0) {
ADD_IMM8(x1, x1, a);
AND_IMM8(x1, x1, 7);
}
// 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); // last time x3 is used
VCVT_F64_U32(v1, s0);
VEOR(v2, v2, v2);
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, x1); // Store STll(0).ref
}
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbst, -1, 0);
x87_do_pop(dyn, ninst, x3);
break;
case 7: // could be inlined for most thing, but is it usefull?
INST_NAME("FISTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistp64, -1, 0);
parity = getedparity(dyn, ninst, addr, nextop, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
if(ninst
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)dyn->insts[ninst-1].x86.addr==0xDF
&& (((*(uint8_t*)(dyn->insts[ninst-1].x86.addr+1))>>3)&7)==5)
{
if(parity) {
STRD_IMM8(x2, ed, 0); // x2/x3 is 64bits
} else {
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
}
} else {
#if 1
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
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->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, 0);
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, 8); // load ll
B_MARK3(c__);
MARK;
VEOR(v0, v0, v0);
MOVW(x2, 0x41F0);
VMOVtoDx_16(v0, 3, x2); // V0 = (1<<32) as double
VMOVfrDx_32(x14, v1, 1); // get high part to extract sign
VABS_F64(v1 ,v1); //ST0 will be poped, so lost...
VDIV_F64(v2, v1, v0); // v2 = abs(ST0)/(1<<32) : so 32 bits high part
MSR_nzcvq_0();
VMRS(x2); // get fpscr
ORR_IMM8(x3, x2, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_U32_F64(s0, v2); // convert high part to U32
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMSR(x2); // put back fpscr
TSTS_IMM8_ROR(x3, 0b00000001, 0);
B_MARK2(cEQ); // not overflow...
MARKLOCK;
MOV_IMM(x3, 0b10, 1); // 0x80000000
MOVW(x2, 0);
B_MARK3(c__);
MARK2; // continue conversion, it fits an int64!
VCVT_F64_U32(v2, s0); // int part now
VMLS_F64(v1, v2, v0); // compute low part
VMOVfrV(x3, s0); // transfert high path
TSTS_IMM8_ROR(x14, 0b10, 1); // test high part with 0x800000000
B_MARKLOCK(cNE); // int overflow...
VCVT_U32_F64(s0, v1); // convert low part
VMOVfrV(x2, s0); // transfert low part
TSTS_IMM8_ROR(x14, 0b10, 1); // 0x800000000
B_MARK3(cEQ);
RSBS_IMM8(x2, x2, 0); // NEG(i64)
RSC_IMM8(x3, x3, 0);
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);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistp64, -1, 0);
#endif
}
x87_do_pop(dyn, ninst, x3);
break;
default:
+2 -2
View File
@@ -76,7 +76,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x86.need_flags==X_PEND))
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<256) {
@@ -210,7 +210,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(s1==xESP && (!dyn->insts || dyn->insts[ninst].x86.need_flags==X_PEND))
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<256) {
+197 -1
View File
@@ -282,6 +282,8 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
@@ -313,6 +315,8 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
@@ -432,7 +436,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
IFX(X_OF) {
if(c==1) {
UBFX(s3, s2, 0, 1);
UBFX(s3, s1, (31-c), 1);
XOR_IMM8_COND(cCS, s3, s3, 1);
BFI(xFlags, s3, F_OF, 1);
} else {
@@ -460,3 +464,195 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHRD32 instruction, from s1, fill s2 , shift s3, store result in s1 using s4 and s3 as scratch
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));
// same flags calc as shr32
SET_DF(s4, d_shr32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
CMPS_IMM8(s3, 0);
IFX(X_PEND) {
STR_IMM9_COND(cEQ, s1, xEmu, offsetof(x86emu_t, res));
}
B_NEXT(cEQ);
IFX(X_CF) {
MOVS_REG_LSR_REG(s1, s1, s3);
} else {
MOV_REG_LSR_REG(s1, s1, s3);
}
IFX(X_ZF|X_CF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
RSB_IMM8(s3, s3, 32);
IFX(X_ZF) {
ORRS_REG_LSL_REG(s1, s1, s2, s3);
} else {
ORR_REG_LSL_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);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s3, 31); // 32-c
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, 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)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_rol8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&7) {
BFI(s1, s1, 24, 8); // duplicate the value for rotate left
MOV_REG_ROR_IMM5(s1, s1, 32-(c&7));
}
//AND_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
BFI(xFlags, s1, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
ADD_REG_LSR_IMM5(s3, s1, s1, 7);
BFI(xFlags, s3, F_OF, 1);
}
}
}
// emit ROR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_ror8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&7) {
BFI(s1, s1, 8, 8); // duplicate the value for Rotate right
MOV_REG_ROR_IMM5(s1, s1, c&7);
}
IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 7);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 6);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
}
+9 -6
View File
@@ -326,8 +326,12 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
AND_IMM8(s3, 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);
AND_IMM8(s3, s3, 31);
if(s1==s2) {
AND_IMM8(s3, s1, 31);
} else {
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
}
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
@@ -370,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 {
@@ -397,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);
File diff suppressed because it is too large. Load diff
+124 -59
View File
@@ -23,23 +23,27 @@
#include "dynarec_arm_helper.h"
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
#define GETEX(a) \
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7); \
#define GETEX(a, w) \
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7,w);\
} else { \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0); \
VLDR_64(a, ed, fixedaddress); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);\
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);\
LDR_IMM9(x2, ed, fixedaddress+0); \
LDR_IMM9(x3, ed, fixedaddress+4); \
VMOVtoV_D(a, x2, x3); \
} \
}
#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;
@@ -64,12 +68,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -80,13 +84,13 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
VMOVD(d0, v0);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -96,12 +100,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -113,7 +117,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("CVTSI2SD Gx, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETED;
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
@@ -126,9 +130,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
@@ -142,9 +146,9 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
@@ -157,55 +161,101 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
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:
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
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");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
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");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
d1 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, d0);
VMOV_64(d1, v0);
VMOV_32(d1*2, s0);
VMOV_64(v0, d1);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(v0<16) {
VCVT_F32_F64(v0*2, d0);
} else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
VCVT_F32_F64(d1*2, d0);
VMOV_64(v0, d1);
}
break;
case 0x5C:
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
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");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
VCMP_F64(v0, d0);
VMRS_APSR();
@@ -215,16 +265,27 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
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");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
VCMP_F64(d0, v0);
VMRS_APSR();
@@ -235,11 +296,11 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PSHUFLW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -270,11 +331,11 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -290,40 +351,44 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("CMPSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(d0);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
u8 = F8;
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);
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;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
+99 -66
View File
@@ -23,9 +23,9 @@
#include "dynarec_arm_helper.h"
// Get Ex as a single, not a quad, with b a intermediary double
#define GETEX(a, b) \
if((nextop&0xC0)==0xC0) { \
b = sse_get_reg(dyn, ninst, x1, nextop&7); \
#define GETEX(a, b) \
if((nextop&0xC0)==0xC0) { \
b = sse_get_reg(dyn, ninst, x1, nextop&7,0);\
if(b<16) \
a = b; \
else { \
@@ -38,7 +38,7 @@
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0); \
VLDR_32(a, ed, fixedaddress); \
} else { \
GETED; \
@@ -46,9 +46,12 @@
} \
}
#define GETGX(a) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGX(a, w) \
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)
@@ -78,8 +81,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
else {
@@ -98,19 +101,26 @@ 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);
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:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
if(v0<16)
d0 = v0;
else {
@@ -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);
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:
@@ -138,9 +154,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
@@ -154,9 +170,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
@@ -181,7 +197,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("CVTSI2SS Gx, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETED;
if(v0<16)
d0 = v0;
@@ -203,7 +219,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
else {
@@ -214,10 +230,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
@@ -232,7 +248,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
else {
@@ -243,10 +259,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
@@ -259,7 +275,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -279,7 +295,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x52:
INST_NAME("RSQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -307,7 +323,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x53:
INST_NAME("RCPSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -330,7 +346,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -350,7 +366,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -370,7 +386,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s0, d0);
VCVT_F64_F32(v0, s0);
break;
@@ -378,9 +394,9 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -391,7 +407,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -411,7 +427,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5D:
INST_NAME("MINSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -434,7 +450,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -454,7 +470,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -480,12 +496,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -498,11 +514,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -534,12 +550,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
VLD1_64(v0, ed);
}
VEOR(v0+1, v0+1, v0+1);
@@ -548,13 +564,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDQU Ex,Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
VMOVfrV_D(x2, x3, v0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -566,11 +581,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SET);
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x3);
nextop = F8;
GETED;
GETGD;
SET_DFNONE(x3);
TSTS_REG_LSL_IMM5(ed, ed, 0);
MOVW_COND(cEQ, x3, 1);
MOVW_COND(cNE, x3, 0);
@@ -586,7 +601,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0xC2:
INST_NAME("CMPSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETGX(v0, 1);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
@@ -599,31 +614,49 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
s0 = d0*2;
u8 = F8;
if((u8&7)==6){
VCMP_F32(s1, s0);
} else {
VCMP_F32(s0, s1);
}
VCMP_F32(s0, s1);
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
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
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;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v1<16)
v0 = v1;
else {
@@ -634,10 +667,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
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);
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);
+465 -63
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"
@@ -25,10 +26,11 @@
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
#include "bridge.h"
void arm_fstp(x86emu_t* emu, void* p)
{
if(ST0.q!=STld(0).ref)
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, p);
else
memcpy(p, &STld(0).ld, 10);
@@ -50,6 +52,7 @@ void arm_fyl2x(x86emu_t* emu)
void arm_ftan(x86emu_t* emu)
{
ST0.d = tan(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fpatan(x86emu_t* emu)
{
@@ -64,20 +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);
}
void arm_fyl2xp1(x86emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
}
void arm_fsincos(x86emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
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)
{
@@ -85,17 +80,9 @@ void arm_frndint(x86emu_t* emu)
}
void arm_fscale(x86emu_t* emu)
{
ST0.d *= exp2(trunc(ST1.d));
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
}
void arm_fsin(x86emu_t* emu)
{
ST0.d = sin(ST0.d);
}
void arm_fcos(x86emu_t* emu)
{
ST0.d = cos(ST0.d);
}
void arm_fbld(x86emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
@@ -106,8 +93,8 @@ void arm_fild64(x86emu_t* emu, int64_t* ed)
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).ll = tmp;
STll(0).ref = ST0.q;
STll(0).sq = tmp;
STll(0).sref = ST0.sq;
}
void arm_fbstp(x86emu_t* emu, uint8_t* ed)
@@ -118,8 +105,8 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
void arm_fistp64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).ref==ST(0).q) {
memcpy(ed, &STll(0).ll, sizeof(int64_t));
if(STll(0).sref==ST(0).sq) {
memcpy(ed, &STll(0).sq, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
@@ -130,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
@@ -140,8 +164,8 @@ 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);
STld(0).ref = ST0.q;
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
}
void arm_ud(x86emu_t* emu)
@@ -156,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;
}
}
@@ -167,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;
}
@@ -176,58 +200,62 @@ 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);
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;
}
}
#define FPUFIRST 8
// Get a FPU double reg
int fpu_get_reg_double(dynarec_arm_t* dyn)
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
@@ -235,28 +263,370 @@ 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;
}
// Get a FPU quad reg
int fpu_get_reg_quad(dynarec_arm_t* dyn)
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;
for (int i=0; i<24; ++i)
dyn->fpuused[i]=0;
dyn->n.fpu_reg = 0;
for (int i=0; i<24; ++i) {
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[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)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return dyn->insts[ninst].n.neoncache[i].t;
// not in the cache yet, so will be fetched...
return NEON_CACHE_ST_D;
}
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a)
{
(void)ninst;
if(!dyn->insts)
return NEON_CACHE_ST_D;
for(int i=0; i<24; ++i)
if((dyn->n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->n.neoncache[i].t==NEON_CACHE_ST_D)
&& dyn->n.neoncache[i].n==a)
return dyn->n.neoncache[i].t;
// not in the cache yet, so will be fetched...
return NEON_CACHE_ST_D;
}
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
{
/*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;*/
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)
return i;
return -1;
}
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)
return i;
return -1;
}
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)
return i;
return -1;
}
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 || 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;
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(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)
{
if(dyn->insts[ninst+1].n.barrier)
return;
while(ninst>=0) {
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;
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
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)
{
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;
// check combined propagation too
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);
}
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;
}
if(ninst==maxinst)
neoncache_promote_double(dyn, ninst, a);
}
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a)
{
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;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if(dyn->n.combined1 || dyn->n.combined2) {
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);
}
}
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)
{
dyn->n.combined1=a;
dyn->n.combined2=b;
if( neoncache_get_current_st(dyn, ninst, a)==NEON_CACHE_ST_F
&& neoncache_get_current_st(dyn, ninst, b)==NEON_CACHE_ST_F )
return NEON_CACHE_ST_F;
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++)
@@ -336,7 +706,7 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uint32_t*)a1;
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(addr<0x10000) // too low, that is suspicious
return 0;
@@ -352,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;
}
+40 -10
View File
@@ -8,20 +8,14 @@ void arm_fstp(x86emu_t* emu, void* p);
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
void arm_f2xm1(x86emu_t* emu);
void arm_fyl2x(x86emu_t* emu);
void arm_ftan(x86emu_t* emu);
void arm_fpatan(x86emu_t* emu);
void arm_fxtract(x86emu_t* emu);
void arm_fprem(x86emu_t* emu);
void arm_fyl2xp1(x86emu_t* emu);
void arm_fsincos(x86emu_t* emu);
void arm_frndint(x86emu_t* emu);
void arm_fscale(x86emu_t* emu);
void arm_fsin(x86emu_t* emu);
void arm_fcos(x86emu_t* emu);
void arm_fbld(x86emu_t* emu, uint8_t* ed);
void arm_fild64(x86emu_t* emu, int64_t* ed);
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
void arm_fbst(x86emu_t* emu, uint8_t* ed);
void arm_fistp64(x86emu_t* emu, int64_t* ed);
void arm_fistt64(x86emu_t* emu, int64_t* ed);
void arm_fld(x86emu_t* emu, uint8_t* ed);
@@ -29,8 +23,15 @@ 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
// Get an FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn);
// Get an FPU double scratch reg
@@ -39,17 +40,44 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn);
int fpu_get_scratch_quad(dynarec_arm_t* dyn);
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn);
// Get an FPU double reg
int fpu_get_reg_double(dynarec_arm_t* dyn);
// Get an FPU double reg, with NEON_CACHE_TYPE
int fpu_get_reg_double(dynarec_arm_t* dyn, unsigned int t, unsigned int n);
// Free a FPU double reg
void fpu_free_reg_double(dynarec_arm_t* dyn, int reg);
// Get an FPU quad reg
int fpu_get_reg_quad(dynarec_arm_t* dyn);
int fpu_get_reg_quad(dynarec_arm_t* dyn, unsigned int t, unsigned int n);
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg);
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn);
// ---- Neon cache functions
// 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);
// 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);
// 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...
@@ -58,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
+146 -65
View File
@@ -22,9 +22,10 @@
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S *(int32_t*)(addr+=4, addr-4)
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
#define PK16(a) *(uint16_t*)(addr+a)
#define PKip(a) *(uint8_t*)(ip+a)
#define PK32(a) *(uint32_t*)(addr+a)
#define PK16(a) *(uint16_t*)(addr+a)
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
// GETGD get x86 register in gd
#define GETGD gd = xEAX+((nextop&0x38)>>3)
@@ -33,7 +34,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0); \
LDR_IMM9(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -42,7 +43,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0); \
LDR_IMM9(hint, wback, fixedaddress); \
ed = hint; \
}
@@ -52,7 +53,7 @@
MOV_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0); \
ed = ret; \
LDR_IMM9(ed, wback, fixedaddress); \
}
@@ -65,7 +66,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
ed = x1; \
}
@@ -74,8 +75,9 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, O, 0);\
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
ed = x1; \
}
@@ -93,7 +95,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -105,7 +107,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -117,7 +119,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
LDRSH_IMM8(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
@@ -137,7 +139,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
@@ -151,9 +153,10 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
if(wback!=x3) wback = x3; \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
@@ -166,7 +169,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
LDRSB_IMM8(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
@@ -204,6 +207,18 @@
// CALL_S will use x3 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret, M) call_c(dyn, ninst, F, x3, ret, M, 0)
// CALL_1D will use x3 for the call address. Return value in D0, 1 ARG in D0
#define CALL_1D(F, M) call_d(dyn, ninst, F, NULL, 1, x3, -1, M, 0)
// CALL_2D will use x3 for the call address. Return value in D0, 2 ARGs in D0, D1
#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))
@@ -232,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) \
@@ -243,11 +258,11 @@
j32 = GETMARKLOCK-(dyn->arm_size+8); \
Bcond(cond, j32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
#define IFX(A) if((dyn->insts[ninst].x86.need_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
#define IFXX(A) if((dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2) \
@@ -271,26 +286,22 @@
/* greater than leave 0 */ \
} \
SET_DFNONE(s1); \
IFX(X_OF|X_PEND) { \
BFC(xFlags, F_OF, 1); \
} \
IFX(X_AF|X_PEND) { \
BFC(xFlags, F_AF, 1); \
} \
IFX(X_SF|X_PEND) { \
BFC(xFlags, F_SF, 1); \
IFX(X_OF|X_AF|X_SF|X_PEND) { \
/* clear 0b100010010000 */ \
BIC_IMM8(xFlags, xFlags, 0b10001001, 14); \
} \
#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) { \
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); \
@@ -298,18 +309,31 @@
} \
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))); \
dyn->state_flags = (B==SF_SUBSET)?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)
#define JUMP(A, C)
#endif
#ifndef BARRIER
#define BARRIER(A)
@@ -317,17 +341,14 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x86.need_flags)
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x86.need_flags)
#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
@@ -365,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)
@@ -376,6 +398,9 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define retn_to_epilog STEPNAME(retn_to_epilog_)
#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)
@@ -444,23 +469,31 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_rol8c STEPNAME(emit_rol8c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_ror8c STEPNAME(emit_ror8c)
#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)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
#define x87_do_pop STEPNAME(x87_do_pop)
#define x87_get_current_cache STEPNAME(x87_get_current_cache)
#define x87_get_cache STEPNAME(x87_get_cache)
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
#define x87_get_st STEPNAME(x87_get_st)
#define x87_get_st_empty STEPNAME(x87_get_st)
#define x87_refresh STEPNAME(x87_refresh)
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#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)
@@ -482,8 +515,10 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
// put back (if needed) the single reg in place
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
#define fpuCacheTransform STEPNAME(fpuCacheTransform)
/* 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);
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);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
@@ -496,10 +531,11 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
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);
@@ -566,9 +602,13 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
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);
@@ -576,15 +616,21 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
// cache of the local stack counter, to avoid upadte at every call
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// fpu push. Return the Dd value to be used
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1);
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1);
// fpu pop. All previous returned Dd should be considered invalid
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1);
// get cache index for a x87 reg, return -1 if cache doesn't exist
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t);
// get cache index for a x87 reg, create the entry if needed
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int populate, int s1, int s2, int a, int t);
// get neoncache index for a x87 reg
int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
// get vfpu register for a x87 reg, create the entry if needed
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// get vfpu register for a x87 reg, create the entry if needed. Do not fetch the Stx if not already in cache
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// refresh a value from the cache ->emu (nothing done if value is not cached)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
@@ -595,9 +641,43 @@ 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);
#if STEP == 0
#define ST_IS_F(A) 0
#define X87_COMBINE(A, B) NEON_CACHE_ST_D
#define X87_ST0 NEON_CACHE_ST_D
#define X87_ST(A) NEON_CACHE_ST_D
#elif STEP == 1
#define ST_IS_F(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_F)
#define X87_COMBINE(A, B) neoncache_combine_st(dyn, ninst, A, B)
#define X87_ST0 neoncache_get_current_st(dyn, ninst, 0)
#define X87_ST(A) neoncache_get_current_st(dyn, ninst, A)
#else
#define ST_IS_F(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_F)
#if STEP == 3
#define X87_COMBINE(A, B) neoncache_st_coherency(dyn, ninst, A, B)
#else
#define X87_COMBINE(A, B) neoncache_get_st(dyn, ninst, A)
#endif
#define X87_ST0 neoncache_get_st(dyn, ninst, 0)
#define X87_ST(A) neoncache_get_st(dyn, ninst, A)
#endif
//MMX helpers
// get neon register for a MMX reg, create the entry if needed
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int a);
@@ -606,17 +686,17 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
//SSE/SSE2 helpers
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
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);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1);
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);
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
@@ -644,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);
+135 -22
View File
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box86context.h"
@@ -31,19 +32,91 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
int ninst = 0;
uintptr_t ip = addr;
uintptr_t init_addr = addr;
MAYUSE(init_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 && (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) {
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D || dyn->n.neoncache[j].t == NEON_CACHE_ST_F)) {
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
dyn->n.neoncache[j].v = 0;
else
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
}
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
@@ -66,48 +139,88 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INST_EPILOG;
if(dyn->insts && dyn->insts[ninst+1].x86.barrier) {
fpu_purgecache(dyn, ninst, 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(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
#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(!ok && !need_epilog && !dyn->insts && 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 && dyn->insts && (ninst==dyn->size))
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);
fpu_purgecache(dyn, ninst, x1, x2, x3);
++ninst;
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
+35 -7
View File
@@ -1,18 +1,46 @@
#define INIT uintptr_t sav_addr=addr
#define FINI dyn->isize = addr-sav_addr
#define FINI \
dyn->isize = addr-sav_addr;\
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 SETFLAGS(A, B)
#define READFLAGS(A)
#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) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define INST_EPILOG
#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) { \
dyn->insts = (instruction_arm_t*)realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
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 \
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), \
+10 -12
View File
@@ -1,17 +1,15 @@
#define INIT
#define FINI \
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 FINI
#define MESSAGE(A, ...)
#define EMIT(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 JUMP(A) dyn->insts[ninst].x86.jmp = A
#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 NEW_INST \
dyn->insts[ninst].x86.addr = ip; \
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
#define INST_EPILOG
#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; \
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
+40 -13
View File
@@ -7,28 +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, state=%d/%d, set=%X, use=%X, need=%X%s\n", \
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, \
(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; \
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:%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 || 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":""); \
}
+65 -13
View File
@@ -4,6 +4,60 @@
#include "dynarec_private.h"
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
#define NEON_CACHE_MM 3
#define NEON_CACHE_XMMW 4
#define NEON_CACHE_XMMR 5
#define NEON_CACHE_SCR 6
typedef union neon_cache_s {
int8_t v;
struct {
unsigned int t:4; // reg type
unsigned int n:4; // reg number
};
} neon_cache_t;
typedef union sse_cache_s {
int v;
struct {
uint8_t reg;
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;
@@ -11,6 +65,8 @@ typedef struct instruction_arm_s {
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;
@@ -18,8 +74,13 @@ typedef struct instruction_arm_s {
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;
int32_t size;
@@ -29,25 +90,16 @@ 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
int 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
int x87stack; // cache stack counter
int x87count; // number of x87 register used
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
flagcache_t f;
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
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;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+20 -8
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,25 +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_MAYSET 3
#define SF_SUBSET 4
#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_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);
+95 -48
View File
@@ -1,3 +1,4 @@
ARM_ 1 1 1 1 0 0 0 1 0 0 0 0 (0) (0) (0) 1 (0) (0) (0) (0) (0) (0) @<1> (0) 0 0 0 0 (0) (0) (0) (0) SETEND \%cparam ? 'B' : 'L'\E
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
@@ -82,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>
@@ -141,99 +142,128 @@ NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 1 1 <6>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <2> 0 0 <1> 1 <4>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 1 0 <3> 1 <4>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 0 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 0 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> 1 1 1 1 @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4] !@ %@ sprintf(align, ":%d", 8 << size)@ align[0] = '\0'@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 0 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> 1 1 1 1 VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 0 size @<1> @<1> Rm VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 0 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 1 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 32 << size)@ align[0] = '\0'@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[], \vecname[0x22 + param1_1+param1_1 + d]\[], \vecname[0x23 + param1_1+param1_1+param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 1 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
ARM_ 1 1 1 1 0 1 0 0 @<1> 0 0 1 Rn @<8> @<4> @<4> 'NOP'
ARM_ 1 1 1 1 0 1 0 0 U 1 0 1 Rn (1) (1) (1) (1) imm12 PLI [<Rn>, #+/-<imm12>]
ARM_ 1 1 1 1 0 1 0 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm12 PLD\param ? "W" : ""\ [<Rn>, #+/-<imm12>]
ARM_ 1 1 1 1 0 1 0 1 U (1) 0 1 1 1 1 1 (1) (1) (1) (1) imm12 PLD [PC, #+/-<imm>]
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 (1) (1) (1) (1) CLREX
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 0 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DSB \option\
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 0 1 @<4> @ param=0b1111=0b1110=0b1011=0b1010=0b0111=0b0110=0b0011=0b0010 const char* option option,"SY","ST","ISH","ISHST","NSH","NSHST","OSH","OSHST","!!!"@ @ DMB \option\
ARM_ 1 1 1 1 0 1 0 1 0 1 1 1 (1) (1) (1) (1) (1) (1) (1) (1) (0) (0) (0) (0) 0 1 1 0 @<4> @ param=0b1111 const char* option option,"SY","!!!"@ @ ISB \option\
ARM_ 1 1 1 1 0 1 1 0 @<1> 0 0 1 Rn @<8> @<3> 0 @<4> 'NOP'
ARMs 1 1 1 1 0 1 1 0 U 1 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLI [<Rn>, +/-<Rm>{, <shift>}]
ARMs 1 1 1 1 0 1 1 1 U @<1> 0 1 Rn (1) (1) (1) (1) imm5 type 0 Rm PLD\param ? "W" : ""\ [<Rn>, +/-<Rm>{, <shift>}]
INVALIDATE 1 1 1 1 0 1 1 1 1 1 1 1 <4> <8> 1 1 1 1 <4>
INVALIDATE 1 1 1 1 <28>
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
@@ -283,6 +313,8 @@ ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{,
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 0 0 (1) (1) (1) (1) Rd (0) (0) 0 (0) 0 0 0 0 (0) (0) (0) (0) MRS<c> <Rd>, APSR
ARM_ cond 0 0 0 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) (0) (0) 0 (0) 0 0 0 0 Rn @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, <Rn>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
@@ -330,6 +362,17 @@ ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 1 YIELD<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 0 WFE<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 1 1 WFI<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 1 0 0 SEV<c>
ARM_ cond/=1110 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 1 0 1 0 0 CSDB<c>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 1 1 1 1 imm4 DBG<c> #<imm>
INVALIDATE <4> 0 0 1 1 0 0 1 0 0 0 0 0 <8> <8>
ARM_ cond 0 0 1 1 0 0 1 0 @<2> 0 0 (1) (1) (1) (1) imm12 @ param=0b01=0b10 const char* spec_reg spec_reg,"APSR_g","APSR_nzcvq","APSR_nzcvqg"@ @ MSR<c> \spec_reg\, #<imm>
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 0 1 <8> <8>
INVALIDATE <4> 0 0 1 1 0 0 1 0 <2> 1 <1> <8> <8>
INVALIDATE <4> 0 0 1 1 0 1 1 0 <4> <8> <8>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
@@ -388,6 +431,8 @@ ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARM_ cond 0 1 1 1 0 0 0 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn SDIV<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 0 0 1 1 Rd (1) (1) (1) (1) Rm 0 0 0 1 Rn UDIV<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
@@ -397,6 +442,7 @@ ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond/=1110 0 1 1 1 1 1 1 1 imm12 1 1 1 1 imm4 UDF<c> #<imm16>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
@@ -427,14 +473,14 @@ INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 @ set imm8*=4@ @ VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
@@ -446,6 +492,7 @@ VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>,
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt/=1111 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> APSR_nzcv, FPSCR
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
@@ -472,6 +519,6 @@ VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <S
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 U 1 Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
INVALIDATE <32>
+62 -59
View File
@@ -200,13 +200,14 @@ const char* DumpRelType(int t)
return buff;
}
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym)
const char* DumpSym(elfheader_t *h, Elf32_Sym* sym, int version)
{
static char buff[4096];
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
memset(buff, 0, sizeof(buff));
sprintf(buff, "\"%s\", value=%p, size=%d, info/other=%d/%d index=%d",
sprintf(buff, "\"%s\", value=%p, size=%d, info/other=%d/%d index=%d (ver=%d/%s)",
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
sym->st_info, sym->st_other, sym->st_shndx);
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
return buff;
}
@@ -221,116 +222,118 @@ const char* IdxSymName(elfheader_t *h, int sym)
void DumpMainHeader(Elf32_Ehdr *header, elfheader_t *h)
{
if(box86_log>=LOG_DUMP) {
printf_log(LOG_DUMP, "ELF Dump main header\n");
printf_log(LOG_DUMP, " Entry point = %p\n", (void*)header->e_entry);
printf_log(LOG_DUMP, " Program Header table offset = %p\n", (void*)header->e_phoff);
printf_log(LOG_DUMP, " Section Header table offset = %p\n", (void*)header->e_shoff);
printf_log(LOG_DUMP, " Flags = 0x%X\n", header->e_flags);
printf_log(LOG_DUMP, " ELF Header size = %d\n", header->e_ehsize);
printf_log(LOG_DUMP, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
printf_log(LOG_DUMP, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
printf_log(LOG_DUMP, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
printf_log(LOG_DUMP, "ELF Dump ==========\n");
if(box86_dump) {
printf_dump(LOG_NEVER, "ELF Dump main header\n");
printf_dump(LOG_NEVER, " Entry point = %p\n", (void*)header->e_entry);
printf_dump(LOG_NEVER, " Program Header table offset = %p\n", (void*)header->e_phoff);
printf_dump(LOG_NEVER, " Section Header table offset = %p\n", (void*)header->e_shoff);
printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags);
printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize);
printf_dump(LOG_NEVER, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
printf_dump(LOG_NEVER, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
printf_dump(LOG_NEVER, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
printf_log(LOG_DUMP, "ELF Dump PEntries (%d)\n", h->numSHEntries);
printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries);
for (int i=0; i<h->numPHEntries; ++i)
printf_log(LOG_DUMP, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_log(LOG_DUMP, "ELF Dump PEntries ====\n");
printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
printf_log(LOG_DUMP, "ELF Dump Sections (%d)\n", h->numSHEntries);
printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries);
for (int i=0; i<h->numSHEntries; ++i)
printf_log(LOG_DUMP, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_log(LOG_DUMP, "ELF Dump Sections ====\n");
printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
}
}
void DumpSymTab(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->SymTab) {
if(box86_dump && h->SymTab) {
const char* name = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump SymTab(%d)=\n", h->numSymTab);
printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab);
for (int i=0; i<h->numSymTab; ++i)
printf_log(LOG_DUMP, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
printf_log(LOG_DUMP, "ELF Dump SymTab=====\n");
printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n");
}
}
void DumpDynamicSections(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->Dynamic) {
printf_log(LOG_DUMP, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
if(box86_dump && h->Dynamic) {
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
for (int i=0; i<h->numDynamic; ++i)
printf_log(LOG_DUMP, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_log(LOG_DUMP, "ELF Dump Dynamic=====\n");
printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
}
}
void DumpDynSym(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->DynSym) {
if(box86_dump && h->DynSym) {
const char* name = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump DynSym(%d)=\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i)
printf_log(LOG_DUMP, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i));
printf_log(LOG_DUMP, "ELF Dump DynSym=====\n");
printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i) {
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
}
printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n");
}
}
void DumpDynamicNeeded(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
for (int i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
printf_log(LOG_DUMP, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
}
}
void DumpDynamicRPath(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
}
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
}
}
void DumpRelTable(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name)
{
if(box86_log>=LOG_DUMP) {
if(box86_dump) {
const char* elfname = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
for (int i = 0; i<cnt; ++i)
printf_log(LOG_DUMP, " %s:Rel[%d] = %p (0x%X: %s, sym=0x%0X/%s)\n", elfname,
printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%X: %s, sym=0x%0X/%s)\n", elfname,
i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF32_R_TYPE(rel[i].r_info)),
ELF32_R_SYM(rel[i].r_info), IdxSymName(h, ELF32_R_SYM(rel[i].r_info)));
printf_log(LOG_DUMP, "ELF Dump Rel Table=====\n");
printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n");
}
}
void DumpRelATable(elfheader_t *h, int cnt, Elf32_Rela *rela, const char* name)
{
if(box86_log>=LOG_DUMP && h->rela) {
if(box86_dump && h->rela) {
const char* elfname = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
for (int i = 0; i<cnt; ++i)
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%X: %s, sym=0x%X/%s) Addend=%d\n", elfname,
printf_dump(LOG_NEVER, " %s:RelA[%d] = %p (0x%X: %s, sym=0x%X/%s) Addend=%d\n", elfname,
i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF32_R_TYPE(rela[i].r_info)),
ELF32_R_SYM(rela[i].r_info), IdxSymName(h, ELF32_R_SYM(rela[i].r_info)),
rela[i].r_addend);
printf_log(LOG_DUMP, "ELF Dump RelA Table=====\n");
printf_dump(LOG_NEVER, "ELF Dump RelA Table=====\n");
}
}
@@ -341,24 +344,24 @@ void DumpBinary(char* p, int sz)
unsigned char* d = (unsigned char*)p;
int delta = ((uintptr_t)p)&0xf;
for (int i = 0; sz; ++i) {
printf_log(LOG_DUMP, "%p ", (void*)(((uintptr_t)d)&~0xf));
printf_dump(LOG_NEVER, "%p ", (void*)(((uintptr_t)d)&~0xf));
int n = 16 - delta;
if (n>sz) n = sz;
int fill = 16-sz;
for (int j = 0; j<delta; ++j)
printf_log(LOG_DUMP, " ");
printf_dump(LOG_NEVER, " ");
for (int j = 0; j<n; ++j)
printf_log(LOG_DUMP, "%02X ", d[j]);
printf_dump(LOG_NEVER, "%02X ", d[j]);
for (int j = 0; j<fill; ++j)
printf_log(LOG_DUMP, " ");
printf_log(LOG_DUMP, " | ");
printf_dump(LOG_NEVER, " ");
printf_dump(LOG_NEVER, " | ");
for (int j = 0; j<delta; ++j)
printf_log(LOG_DUMP, " ");
printf_dump(LOG_NEVER, " ");
for (int j = 0; j<n; ++j)
printf_log(LOG_DUMP, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
printf_dump(LOG_NEVER, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
for (int j = 0; j<fill; ++j)
printf_log(LOG_DUMP, " ");
printf_log(LOG_DUMP, "\n");
printf_dump(LOG_NEVER, " ");
printf_dump(LOG_NEVER, "\n");
d+=n;
sz-=n;
delta=0;
+783 -314
View File
File diff suppressed because it is too large. Load diff
+4
View File
@@ -33,6 +33,8 @@ struct elfheader_s {
Elf32_Half* VerSym;
Elf32_Verneed* VerNeed;
int szVerNeed;
Elf32_Verdef* VerDef;
int szVerDef;
int e_type;
intptr_t delta; // should be 0
@@ -71,7 +73,9 @@ struct elfheader_s {
uint32_t memsz;
uint32_t stacksz;
int stackalign;
uintptr_t tlsaddr;
uint32_t tlssize;
uint32_t tlsfilesize;
int tlsalign;
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
+41 -8
View File
@@ -177,14 +177,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
FreeElfHeader(&h);
return NULL;
}
if(box86_log>=LOG_DUMP) DumpMainHeader(&header, h);
if(box86_dump) DumpMainHeader(&header, h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
if(box86_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
if(box86_dump && h->SymTab) DumpSymTab(h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
if(box86_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
if(box86_dump && h->Dynamic) DumpDynamicSections(h);
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
@@ -212,7 +212,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->relaent = val;
break;
case DT_PLTGOT:
h->pltgot = val;
h->pltgot = ptr;
break;
case DT_PLTREL:
h->pltrel = val;
@@ -221,7 +221,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->pltsz = val;
break;
case DT_JMPREL:
h->jmprel = val;
h->jmprel = ptr;
break;
case DT_STRTAB:
h->DynStrTab = (char *)(ptr);
@@ -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);
@@ -254,13 +258,21 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
break;
case DT_VERNEEDNUM:
h->szVerNeed = val / sizeof(Elf32_Verneed);
h->szVerNeed = val;
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
break;
case DT_VERNEED:
h->VerNeed = (Elf32_Verneed*)ptr;
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
break;
case DT_VERDEFNUM:
h->szVerDef = val;
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
break;
case DT_VERDEF:
h->VerDef = (Elf32_Verdef*)ptr;
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
}
}
if(h->rel) {
@@ -335,7 +347,6 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
if(box86_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
}
return h;
@@ -343,8 +354,11 @@ 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)
return "*";*/
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
@@ -355,5 +369,24 @@ const char* GetSymbolVersion(elfheader_t* h, int version)
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
const char* GetParentSymbolVersion(elfheader_t* h, int index)
{
if(!h->VerDef || (index<1))
return NULL;
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
if(def->vd_ndx==index) {
if(def->vd_cnt<1)
return NULL;
/*if(def->vd_flags&VER_FLG_BASE)
return NULL;*/
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
}
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
return NULL;
}
}
+2 -2
View File
@@ -111,7 +111,7 @@
} else getecommono(A, reg32_t, O)
#define getem(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->mmx87[(nextop&7)]; \
A = &emu->mmx[(nextop&7)]; \
} else getecommon(A, mmx87_regs_t)
#define getex(A) \
if((nextop&0xC0)==0xC0) { \
@@ -141,7 +141,7 @@
#define EX opex
#define GB emu->regs[(nextop>>3)&3].byte[(nextop>>5)&0x1]
#define GD emu->regs[((nextop&0x38)>>3)]
#define GM emu->mmx87[((nextop&0x38)>>3)]
#define GM emu->mmx[((nextop&0x38)>>3)]
#define GX emu->xmm[((nextop&0x38)>>3)]
// Alias
+122 -54
View File
@@ -3,6 +3,18 @@
_0f_0x00: /* VERx Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 0: /* SLDT Ew */
GET_EW;
EW->word[0] = 0;
if((nextop&0xC0)==0xC0)
EW->word[1] = 0;
break;
case 1: /* STR Ew */
GET_EW;
EW->word[0] = 0x7f; // dummy return
if((nextop&0xC0)==0xC0)
EW->word[1] = 0;
break;
case 4: //VERR
case 5: //VERW
GET_EW;
@@ -18,6 +30,18 @@
_0f_0x01:
nextop = F8;
switch((nextop>>3)&7) {
case 0: /* SGDT Ed */
GET_ED;
ED->word[0] = 0x7f; // dummy return...
ED->word[1] = 0x000c;
ED->word[2] = 0xd000;
break;
case 1: /* SIDT Ed */
GET_ED;
ED->word[0] = 0xfff; // dummy return, like "disabled"
ED->word[1] = 0;
ED->word[2] = 0;
break;
case 4: /* SMSW Ew */
GET_ED;
// dummy for now... Do I need to track CR0 state?
@@ -36,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;
@@ -203,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 */
@@ -214,6 +250,17 @@
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x09: /* PSIGNW Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
if (EM->sw[i] < 0) {
GM.sw[i] = -GM.sw[i];
} else if (EM->sw[i] == 0) {
GM.sw[i] = 0;
}
}
break;
case 0x0B: /* PMULHRSW Gm, Em */
nextop = F8;
GET_EM;
@@ -250,6 +297,33 @@
}
NEXT;
_0f_0x3A:
opcode = F8;
switch(opcode) {
case 0x0F: /* palignr */
nextop = F8;
GET_EM;
tmp8u = F8;
if (tmp8u >= 16) {
GM.q = 0;
} else if (tmp8u > 8) {
tmp8u -= 8;
GM.q >>= tmp8u*8;
} 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);
}
break;
default:
goto _default;
}
NEXT;
_0f_0x3F:
emu->old_ip = R_EIP;
R_EIP = ip-2;
@@ -375,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;
@@ -722,12 +806,13 @@
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
tmp32s = GD.sdword[0];
tmp8u=tmp32s&31;
tmp32s >>= 5;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
@@ -754,12 +839,13 @@
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
tmp32s = GD.sdword[0];
tmp8u=tmp32s&31;
tmp32s >>= 5;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
@@ -789,20 +875,10 @@
GET_ED;
switch((nextop>>3)&7) {
case 0: /* FXSAVE m512byte */
// should save flags & all
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(((void*)(ED))+32+i*16, &emu->mmx87[0], sizeof(emu->mmx87[0]));
// copy SSE regs
memcpy(((void*)(ED))+160, &emu->xmm[0], sizeof(emu->xmm));
fpu_fxsave(emu, ED);
break;
case 1: /* FXRSTOR m512byte */
// should restore flags & all
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx87[i], ((void*)(ED))+32+i*16, sizeof(emu->mmx87[0]));
// copy SSE regs
memcpy(&emu->xmm[0], ((void*)(ED))+160/4, sizeof(emu->xmm));
fpu_fxrstor(emu, ED);
break;
case 2: /* LDMXCSR Md */
emu->mxcsr = ED->dword[0];
@@ -844,12 +920,13 @@
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
tmp32s = GD.sdword[0];
tmp8u=tmp32s&31;
tmp32s >>= 5;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
@@ -875,10 +952,6 @@
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
@@ -889,10 +962,6 @@
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
@@ -905,10 +974,6 @@
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
@@ -920,10 +985,6 @@
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
@@ -940,12 +1001,13 @@
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
tmp32s = GD.sdword[0];
tmp8u=tmp32s&31;
tmp32s >>= 5;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg32_t*)(((uint32_t*)(ED))+tmp32s);
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
@@ -1055,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;
+25 -6
View File
@@ -8,9 +8,9 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FLD STx */
ll = ST(nextop&7).q;
ll = ST(nextop&7).sq;
fpu_do_push(emu);
ST0.q = ll;
ST0.sq = ll;
break;
case 0xC8:
case 0xC9:
@@ -20,9 +20,10 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FXCH STx */
ll = ST(nextop&7).q;
ST(nextop&7).q = ST0.q;
ST0.q = ll;
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,26 +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...
ST0.d *= exp2(trunc(ST1.d));
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;
+3 -3
View File
@@ -132,12 +132,12 @@
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).ref = ST0.q;
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
break;
case 7: /* FSTP tbyte */
GET_ED;
if(ST0.q!=STld(0).ref)
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, ED);
else
memcpy(ED, &STld(0).ld, 10);
+6 -6
View File
@@ -125,8 +125,8 @@
tmp64s = *(int64_t*)ED;
fpu_do_push(emu);
ST0.d = tmp64s;
STll(0).ll = tmp64s;
STll(0).ref = ST0.q;
STll(0).sq = tmp64s;
STll(0).sref = ST0.sq;
break;
case 6: /* FBSTP tbytes, ST0 */
GET_ED;
@@ -137,8 +137,8 @@
GET_ED;
if((uintptr_t)ED & 0x7) {
// un-aligned!
if(STll(0).ref==ST(0).q)
memcpy(ED, &STll(0).ll, sizeof(int64_t));
if(STll(0).sref==ST(0).sq)
memcpy(ED, &STll(0).sq, sizeof(int64_t));
else {
int64_t i64;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
@@ -148,8 +148,8 @@
memcpy(ED, &i64, sizeof(int64_t));
}
} else {
if(STll(0).ref==ST(0).q)
*(int64_t*)ED = STll(0).ll;
if(STll(0).sref==ST(0).sq)
*(int64_t*)ED = STll(0).sq;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
*(int64_t*)ED = 0x8000000000000000LL;
+32 -4
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;
@@ -218,8 +246,8 @@
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX.d[0] == EX->d[0]); break;
case 1: tmp8s=isless(GX.d[0], EX->d[0]); break;
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]); break;
case 1: tmp8s=isless(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
case 2: tmp8s=islessequal(GX.d[0], EX->d[0]) && !(isnan(GX.d[0]) || isnan(EX->d[0])); break;
case 3: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]); break;
case 4: tmp8s=(GX.d[0] != EX->d[0]); break;
case 5: tmp8s=isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(GX.d[0], EX->d[0]); break;
+20 -2
View File
@@ -182,6 +182,24 @@
}
break;
case 0xBD: /* LZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp32u = ED->dword[0];
if(tmp32u) {
tmp8u = 0;
while(!(tmp32u&(1<<(31-tmp8u)))) ++tmp8u;
GD.dword[0] = tmp8u;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CLEAR_FLAG(F_CF);
} else {
SET_FLAG(F_CF);
CLEAR_FLAG(F_ZF);
GD.dword[0] = 32;
}
break;
case 0xC2: /* CMPSS Gx, Ex, Ib */
nextop = F8;
GET_EX;
@@ -189,8 +207,8 @@
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX.f[0] == EX->f[0]); break;
case 1: tmp8s=isless(GX.f[0], EX->f[0]); break;
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]); break;
case 1: tmp8s=isless(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
case 2: tmp8s=islessequal(GX.f[0], EX->f[0]) && !(isnan(GX.f[0]) || isnan(EX->f[0])); break;
case 3: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]); break;
case 4: tmp8s=(GX.f[0] != EX->f[0]); break;
case 5: tmp8s=isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(GX.f[0], EX->f[0]); break;
+18 -12
View File
@@ -49,13 +49,13 @@ uint32_t* GetParityTab()
void PushExit(x86emu_t* emu)
{
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0);
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
Push(emu, endMarker);
}
void* GetExit()
{
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0);
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
}
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
@@ -211,12 +211,12 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
memcpy(newemu->mmx87, emu->mmx87, sizeof(emu->mmx87));
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->cw = emu->cw;
newemu->cw_mask_all = emu->cw_mask_all;
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
@@ -308,7 +308,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
if(trace_emm) {
// do emm reg is needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "mm%d:%016llx", i, emu->mmx87[i].q);
sprintf(tmp, "mm%d:%016llx", i, emu->mmx[i].q);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
@@ -323,13 +323,18 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
}
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
sprintf(tmp, "ST%d=%f", i, emu->mmx87[(emu->top+i)&7].d);
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, " ");
}
else {
sprintf(tmp, "Warning, incoherent fpu_stack=%d", emu->fpu_stack);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
strcat(buff, "\n");
}
@@ -401,7 +406,8 @@ void EmuCall(x86emu_t* emu, uintptr_t addr)
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
emu->longjmp = 0; // don't change anything because of the longjmp
if(emu->quitonlongjmp==1)
emu->longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
+4 -3
View File
@@ -28,10 +28,10 @@ typedef struct x86emu_s {
reg32_t regs[8];
x86flags_t eflags;
reg32_t ip;
uintptr_t old_ip;
// fpu / mmx
mmx87_regs_t mmx87[8];
uint16_t cw,cw_mask_all;
mmx87_regs_t x87[8];
mmx87_regs_t mmx[8];
uint16_t cw;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
@@ -42,6 +42,7 @@ typedef struct x86emu_s {
// sse
sse_regs_t xmm[8];
uint32_t mxcsr;
uintptr_t old_ip;
// defered flags
defered_flags_t df;
uint32_t op1;
+55 -30
View File
@@ -70,7 +70,7 @@ void x86Int3(x86emu_t* emu)
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
{
R_EIP += 2;
#ifdef RK3399
#if defined(RK3399) || defined(GOA_CLONE)
volatile // to avoid addr to be put in an VFPU register
#endif
uint32_t addr = Fetch32(emu);
@@ -86,7 +86,6 @@ void x86Int3(x86emu_t* emu)
int have_trace = 0;
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
pthread_mutex_lock(&emu->context->mutex_trace);
int tid = GetTID();
char buff[256] = "\0";
char buff2[64] = "\0";
@@ -96,12 +95,7 @@ void x86Int3(x86emu_t* emu)
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = NULL;
{
Dl_info info;
if(dladdr((void*)addr, &info))
s = info.dli_sname;
}
if(!s) s = GetNativeName((void*)addr);
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else
@@ -125,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;
@@ -144,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;
@@ -156,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) {
@@ -180,12 +183,12 @@ 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 = 1;
} else if(!strcmp(s, "my_mmap")) {
perr = 3;
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 1;
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "gtk_signal_connect_full")) {
@@ -196,41 +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")==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));
} 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_sprintf")==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, "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, "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, "__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);
@@ -239,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));
@@ -263,16 +283,16 @@ 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 {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
}
pthread_mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
w(emu, addr); // some function never come back, so unlock the mutex first!
pthread_mutex_lock(&emu->context->mutex_trace);
if(post)
switch(post) {
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
@@ -291,11 +311,16 @@ void x86Int3(x86emu_t* emu)
snprintf(buff2, 63, "NULL Surface");
}
break;
case 6: snprintf(buff2, 63, "(%S)", pu32?((wchar_t*)pu32):L"nil");
break;
}
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==2 && R_EAX==0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==3 && ((int)R_EAX)==-1)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
pthread_mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
+15 -15
View File
@@ -714,7 +714,7 @@ uint8_t rol8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -741,7 +741,7 @@ uint16_t rol16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -768,7 +768,7 @@ uint32_t rol32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -795,7 +795,7 @@ uint8_t ror8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -822,7 +822,7 @@ uint16_t ror16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -849,7 +849,7 @@ uint32_t ror32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -1276,10 +1276,10 @@ void div16(x86emu_t *emu, uint16_t s)
INTR_RAISE_DIV0(emu);
return;
}
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_SF);
CONDITIONAL_SET_FLAG(div == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
//CLEAR_FLAG(F_CF);
//CLEAR_FLAG(F_SF);
//CONDITIONAL_SET_FLAG(div == 0, F_ZF);
//CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_AX = (uint16_t)div;
R_DX = (uint16_t)mod;
@@ -1305,11 +1305,11 @@ void div32(x86emu_t *emu, uint32_t s)
INTR_RAISE_DIV0(emu);
return;
}
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_SF);
SET_FLAG(F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
//CLEAR_FLAG(F_CF);
//CLEAR_FLAG(F_AF);
//CLEAR_FLAG(F_SF);
//SET_FLAG(F_ZF);
//CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_EAX = (uint32_t)div;
R_EDX = (uint32_t)mod;
Loaded 100 of 914 files, more files were not shown because too many files have changed in this diff. Show more