Compare commits

...
379 Commits
Author SHA1 Message Date
ptitSeb e6e9fae178 Bumped to v0.1.6 2021-11-19 22:21:29 +01:00
ptitSeb 7042a1ae30 Try to use Github Actions 2021-11-19 21:52:10 +01:00
ptitSeb 7d277cc1ec Updated CHANGELOG 2021-11-19 21:43:49 +01:00
ptitSeb 1ac0465a03 Small change on unload of box64 2021-11-19 21:43:32 +01:00
ptitSeb 3533db97ff [DYNAREC] Reduce performance impact of StrongMem, and added old Strongmem method as BOX64_DYNAREC_STRONGMEM=2 2021-11-19 11:22:59 +01:00
ptitSeb 7888cae6c7 Merge pull request #166 from eerykitty/main
Minor changes to allow box64 to build and run on 64-bit PowerPC.
2021-11-19 07:48:02 +01:00
Joseph Allen b021beba6a Minor changes to allow box64 to build and run on ppc64le. 2021-11-18 17:48:52 -06:00
ptitSeb 684d67d12e Added wrapped __isoc99_scanf function (for #164) 2021-11-18 14:25:53 +01:00
ptitSeb 8d7683b851 Changed elfloader a bit to merge elf memory block if close enough (help load program on loongarch architecture) 2021-11-18 14:23:37 +01:00
ptitSeb e7290d78d5 [DYNAREC] Improved JIT handling, and added a HotPage detection to temporarily disable Dynarec when write occurs on the same page of some Dynablocks (help speedup some C#/Unity3D programs) 2021-11-18 14:21:16 +01:00
ptitSeb 4f0e98ade5 [DYNAREC] Added an option to simulate Strong Memory Model, and auto activate it when libmonobdgcw-2.0.so is detected (should help #110 and #158 at least) 2021-11-18 14:18:00 +01:00
ptitSeb 39dbfd9fd8 [DYNAREC] Removed special case for RimWorldLinux and generalized it for all program loading libmonodbwgc-2.0.so 2021-11-18 13:50:10 +01:00
ptitSeb 2d18558dc5 [TRACE] Fixed trace on function from a dlopen library not triggering preperly 2021-11-17 19:41:00 +01:00
ptitSeb 5fb9397521 [DYNAREC] Fixed a small issue with Segfault in Fillblock detection 2021-11-15 17:45:31 +01:00
ptitSeb f85e24dff8 [DYNAREC] Added some DMB to try help multi-tasked+JIT program (may help #110) 2021-11-14 21:43:02 +01:00
ptitSeb 2ea272fcd6 [DYNAREC] Added DMB emitter 2021-11-14 20:57:51 +01:00
ptitSeb d3e85b439b Added wrapped libxslt (from box86) (should help #161) 2021-11-14 15:19:25 +01:00
ptitSeb ea837908b6 Added wrapped libldap_r and liblber (helps wine) 2021-11-14 15:15:47 +01:00
ptitSeb a1573835dd Change ResolvePath behaviour in sync with box86 2021-11-14 10:44:55 +01:00
ptitSeb 34355d6b0c Added some data symbol to wrapped libxml2 (for #161 but it would probably be better to wrap libxslt directly) 2021-11-12 19:20:08 +01:00
ptitSeb 9557e4711f Added a few xcb symbols (for #161) 2021-11-12 12:19:50 +01:00
ptitSeb 6a1b9e050a [DYNAREC] Changed Dynarec a bit to try stabilise program using many threads and a JIT (help RimWorld Linux, but not enough to be 100% stable) 2021-11-11 20:47:10 +01:00
ptitSeb 6675b43dd0 [DYNAREC] Pass0 now alocate memory and do more stuff from pass1 2021-11-11 12:37:32 +01:00
ptitSeb 79d7e9f8eb Mark memprot as volatile to try help stability in heavily multithread programs 2021-11-11 12:37:01 +01:00
ptitSeb f5c9439f91 Improved CMPSS/CMPSD opcodes, improved test17 ([DYNAREC] too, and improved MINSS/MAXSS/MINSD/MAXSD too) 2021-11-07 15:06:55 +01:00
ptitSeb f73e4193f0 Chnaged memory protection tracking to reduce usage of lock, especially for [DYNAREC] reduced mutrex and chances of deadlock (help RimWorld) 2021-11-05 21:17:14 +01:00
ptitSeb 841003bc47 Added 1 wrapped function to freetype (for SOR4) 2021-11-02 22:21:36 +01:00
ptitSeb 27cf5c81b2 Better wrapping for libz inflate 2021-11-02 22:08:43 +01:00
ptitSeb 323783bf49 [DYNAREC] Fixed right shift emmiter with const = 1 (help wine 6.17, and probably many other stuffs) 2021-11-01 13:20:32 +01:00
ptitSeb fbd9604dc1 Added handling of ARCH_GET_FS to arch_prctl 2021-11-01 13:19:44 +01:00
ptitSeb 5494d417c0 [DEBUG] Don't overwrite trace if %pid is used 2021-11-01 11:28:17 +01:00
ptitSeb 472037cba2 [ARM64] Check if Atomics are supported (not used yet) 2021-11-01 11:27:36 +01:00
ptitSeb 1b19d8b909 Added Phytium paragraph to COMPILE.md 2021-10-30 12:12:13 +02:00
ptitSeb c2909c32ab Updated the CHANGELOG 2021-10-27 19:42:19 +02:00
ptitSeb a7c0c01bf4 [DYNAREC] Cancel a dynablock if a segfault occurs while building it 2021-10-27 19:42:01 +02:00
ptitSeb d80226ec61 Added signalfd wrapped function to libc 2021-10-26 20:10:29 +02:00
ptitSeb da81ba5be8 Fixed some program (like the one made in rust) that was getting the command line properly 2021-10-26 19:03:03 +02:00
ptitSeb f81874277c Added reboot wrapped function to libc 2021-10-26 18:30:38 +02:00
ptitSeb d93b97ee92 Added a bunch of aio_ and mq_ wrapped function to librt 2021-10-26 17:45:24 +02:00
ptitSeb 4812d20da5 Added mogery to major code contributor in chinese Readme too 2021-10-25 09:34:47 +02:00
ptitSeb 734e7cd47c Added @mogery to major code contributor 2021-10-25 09:34:12 +02:00
ptitSeb d052b35c40 Detect steamwebhelper and don't load it for now (until it's actually fixed) 2021-10-24 19:07:55 +02:00
ptitSeb 2bd3a3ccfa Optimized (and small fixes) to custom allocator ([DYNAREC] Speedup long launch time) 2021-10-24 19:06:23 +02:00
ptitSeb 1886c454ca Added 67 0F 67/7F ocpodes ([DYNAREC] too) (for The Last Federation) 2021-10-24 18:12:37 +02:00
ptitSeb 91ee1afe24 Added wrapped libncursesw.so.6 (for #148) 2021-10-23 19:02:49 +02:00
ptitSeb d867f578df Fixed SDL_Log wrapped function 2021-10-23 15:50:41 +02:00
ptitSeb b48ba048ed Added FcConfigAppFontAddDir wrapped function (for #150) 2021-10-22 20:54:37 +02:00
ptitSeb 35a21d8932 Merge pull request #147 from bbbruni/main
Add a debug mode compilation with disabled compiler optimizations
2021-10-21 22:14:19 +02:00
bbbruni 81ec174e2a Added PKGBUILD-x86_64-DEBUG 2021-10-21 22:47:08 +03:00
bbbruni 400ea800d9 Added PKGBUILD-tegra-DEBUG 2021-10-21 22:45:44 +03:00
bbbruni 0e1215268a Added PKGBUILD-rpi4-DEBUG 2021-10-21 22:44:24 +03:00
bbbruni a72d257443 Added PKGBUILD-rk3399-DEBUG 2021-10-21 22:42:28 +03:00
bbbruni 6a99a4b359 Changed DCMAKE_BUILD_TYPE to Debug 2021-10-21 22:40:57 +03:00
bbbruni b6764d1d6f Add debug version of PKGBUILD-arm64 2021-10-21 22:37:11 +03:00
bbbruni d5e105ce62 Disable compiler optimizations in debug mode 2021-10-21 22:31:50 +03:00
ptitSeb 45ee1e3c3c Added a new wrapped function to libc (for #143) 2021-10-21 19:31:33 +02:00
ptitSeb b1d0dde0b4 Proper fix for link issue on glibc 2.34+ (for #120) 2021-10-20 22:54:42 +02:00
ptitSeb cb06d28383 Added explicit link with libc (might help with #120) 2021-10-20 10:40:29 +02:00
ptitSeb 36bfcd21d4 Merge pull request #135 from mogery/getattr-align-wrap
Add alignment wrapper to pthread_getattr_np.
2021-10-18 10:12:48 +02:00
ptitSeb faa48276e5 Merge pull request #137 from Heasterian/patch-2
Fixing typo
2021-10-18 07:43:21 +02:00
ptitSeb 8e5d32430a Fixed build 2021-10-17 23:06:01 +02:00
Heasterian ac2d5b17dd Fixing typo 2021-10-17 23:59:46 +03:00
ptitSeb 0e2c63d9fb Merge pull request #136 from Heasterian/patch-1
Add Snapdragon 845 compilation
2021-10-17 22:21:33 +02:00
Heasterian 71b446774c Update COMPILE.md
Changes about compilation on Snapdragon 845 devices
2021-10-17 22:34:47 +03:00
Heasterian dac71e9f7b Update CMakeLists.txt
Adding configuration for Snapdragon 845 devices.
2021-10-17 22:31:45 +03:00
Gergő Móricz e1a2230e9c Add alignment wrapper to pthread_getattr_np.
This fixes stack corruption when using pthread_getattr_np on
hirsute (Ubuntu 21.04) and libc >=2.33

This should also fix #130.
2021-10-17 21:19:52 +02:00
ptitSeb 82bd4431e6 [TRAVIS] Try to use Graviton2 for Arm64 2021-10-14 08:58:27 +02:00
ptitSeb 7262288502 Merge pull request #132 from mogery/memory-map-fix
Map bricks below first 2GB of address space
2021-10-13 22:42:20 +02:00
mogery bcb0bdea77 Declare my_mmap and my_munmap to avoid warning
This adds a declaration of my_mmap and my_munmap to
src/tools/bridge.c in order to avoid a
-Wimplicit-function-declaration warning when compiling.

This should probably be moved to a header file in the
future.
2021-10-13 15:09:48 +02:00
mogery 4ca58d1f99 Fix incorrect brick cleanup
FreeBridge used free to clean up the pointer allocated by
my_mmap, which is incorrect and lead to a crash upon code
that exited gracefully.

The free was replaced with my_munmap.
2021-10-12 20:05:22 +02:00
mogery 0c27b82ff3 Map bricks below first 2GB of address space
This fixes an issue with mono where JIT compiled code would
near-call wrapped libraries, but fail because the difference
between PC and the call address did not fit into an imm32.

This was fixed by replacing posix_memalign with my_mmap and
providing the MAP_32BIT flag.

Fixes #131
2021-10-12 19:47:31 +02:00
ptitSeb 289deb3655 [DYNAREC] Added F2 0F E6 opcode 2021-10-05 23:07:32 +02:00
ptitSeb 8d69c17839 [DYNAREC] Added 67 89/C1/F7 opcodes 2021-10-05 23:06:58 +02:00
ptitSeb 348cb57240 Small fix for elfloader 2021-10-05 00:23:42 +02:00
ptitSeb 46f71f3947 Added some more crypto and ssl wrapped functions (bedrock server starts now) 2021-10-04 08:25:29 +02:00
ptitSeb 0ba4b04078 Added empty wrapped libnsl.so.1 2021-10-04 08:25:29 +02:00
ptitSeb 5a5f572162 Added Phytium profile 2021-10-02 09:46:33 +02:00
ptitSeb fb5bc122cc Added mallinfo wrapped function (for #121) 2021-09-29 08:10:06 +02:00
ptitSeb 4c328d0fca Fix g_source_new wrapped function and friends (helps Zoom) 2021-09-28 19:55:26 +02:00
ptitSeb dbce2758b2 Merge pull request #119 from Linux-Adaptation-Integrated-Toolkit/main
additional info for compilation document
2021-09-27 17:21:48 +02:00
zhaozhen 837f7edd55 additional info for compilation document 2021-09-27 22:21:49 +08:00
ptitSeb f054fb3a5f Merge pull request #118 from Jai-JAP/patch-1
Fix small typo in README.md
2021-09-26 19:12:26 +02:00
Jai A P 96831b144c Update README.md 2021-09-26 22:29:37 +05:30
ptitSeb d75116dab7 Merge pull request #117 from Linux-Adaptation-Integrated-Toolkit/main
add loongarch cmake fix and chinese document
2021-09-26 16:58:14 +02:00
zhaozhen 8da46ee305 add loongarch cmake fix and chinese document 2021-09-26 22:48:28 +08:00
ptitSeb 4cac721e74 Yeah, that too should help fix build for the untested loogarch64 support 2021-09-26 13:07:07 +02:00
ptitSeb 3fda41cbf6 Still more build fix for the untested loogarch64 support 2021-09-26 13:01:08 +02:00
ptitSeb 053d5e9b8d One more build fix for the untested loogarch64 support 2021-09-26 12:50:20 +02:00
ptitSeb 40cb14bf31 And yet another build fixe for the untested loogarch64 support 2021-09-26 12:35:45 +02:00
ptitSeb 27d18e4169 Another build fixe for the untested loogarch64 support 2021-09-26 12:24:47 +02:00
ptitSeb 5403002a36 Some build fixes for the untested loogarch64 support 2021-09-26 12:15:40 +02:00
ptitSeb 22f1a6c5ca CMake have an option for loongarch64 now 2021-09-26 12:09:16 +02:00
ptitSeb 783e9a4b74 More untested support for loongarch64 va_list 2021-09-26 12:06:01 +02:00
ptitSeb 202a067a61 Added some untested support for loongarch64 va_list 2021-09-26 11:46:04 +02:00
ptitSeb f2d1a8bc70 [DYNAREC] Somme fix for 66 83 opcodes 2021-09-26 11:29:45 +02:00
ptitSeb b6bc7922b3 Fixed some elf loading issues (like Torchlight2) 2021-09-23 19:54:52 +02:00
ptitSeb 7e4af27ba7 More work on gtk and nss3+friends 2021-09-21 20:50:52 +02:00
ptitSeb 06bbf93bf8 More work on gtk wrapping 2021-09-20 21:51:15 +02:00
ptitSeb e08bdd644b Added minimum wrapped libsecret-1 2021-09-19 21:29:06 +02:00
ptitSeb 1c5ddfafcd And 2 more wrapped gtk functions 2021-09-19 19:36:54 +02:00
ptitSeb 0f4db4c230 More gtk wrapped functions 2021-09-19 19:00:42 +02:00
ptitSeb 960ce86289 Fixed some nasty copypasta on EmuCall 2021-09-19 19:00:19 +02:00
ptitSeb b2bd3103d8 Fixed va_list conversion for aarch64 2021-09-19 18:59:34 +02:00
ptitSeb 745fd1b702 A bit more log on Interpretor mode 2021-09-19 18:59:01 +02:00
ptitSeb 6df1b65249 Added 1 more gtk function 2021-09-19 16:29:10 +02:00
ptitSeb 510f8d45e8 Added wrapped g_signal_connect_object 2021-09-19 16:24:43 +02:00
ptitSeb c5d328a5da Fixed a bug with some TLS relocation when symbol is in another elf (helps c++ softs, probably other too) 2021-09-19 16:06:24 +02:00
ptitSeb 1430c811cd Added 1 wrapped function to xcbxfixes (for #28) 2021-09-19 13:33:19 +02:00
ptitSeb ec2eadd893 More work on GTK wrapping. Still not ok, but better 2021-09-19 12:36:01 +02:00
ptitSeb 56c272c17a Added some more wrapped functions to xcb, gio2 and gobject2 (for #46) 2021-09-19 09:38:46 +02:00
ptitSeb 6f92db542b Updated wrapped libnns3, libnssutil3 and libsmime3 with more wrapped functions (from box86) 2021-09-18 21:46:00 +02:00
ptitSeb 8531750631 Added wrapped libsndfile (dwarf fortress have sound now, and seems completly playable) 2021-09-18 21:15:35 +02:00
ptitSeb 9414ece323 Added wrapped gtk2 (enough to launch Dwarf Fortress and some simple gtk2 samples) 2021-09-18 21:01:13 +02:00
ptitSeb c64cb5b92b Added 66 0F 38 39/3C opcodes ([DYNAREC] too) (for #81) 2021-09-18 08:49:55 +02:00
ptitSeb 2b1e12dafd Fixed 66 0F 3A 22 opcode for REX.W ([DYNAREC] too) (should help #81) 2021-09-16 20:54:40 +02:00
ptitSeb b4ca2be9e0 Added some libcrypto wrapped functions (for #99) 2021-09-14 21:30:41 +02:00
ptitSeb 203de52d71 Added syscall 120 (for #99) 2021-09-14 21:27:21 +02:00
ptitSeb c48333db44 Added syscall 118 (for #99) 2021-09-13 19:53:44 +02:00
ptitSeb e3552befe9 Try to use mmap first when loading elf file into memory 2021-09-12 18:37:03 +02:00
ptitSeb 6141421f92 [DYNAREC] some fixes to alternate handling and vsyscall support 2021-09-12 13:59:10 +02:00
ptitSeb 911ecc4489 Added minimal wrapped libnsp4, libnss3, libnssutil3 and linsmime3 2021-09-08 20:55:05 +02:00
ptitSeb 63ab450d87 Added 66 0F 7C ocpode (for #111) 2021-09-08 20:54:19 +02:00
ptitSeb bcc29168cd [TRAVIS] Refined the script a little bit 2021-09-08 20:53:50 +02:00
ptitSeb 4a9b0128d7 [TRAVIS] Move travis integration 2021-09-05 13:57:51 +02:00
ptitSeb 6cc56ac5f7 [TRAVIS] Specified focal as distrib to use 2021-09-05 13:42:36 +02:00
ptitSeb f53c967e18 [TRAVIS] Added python3 to travis script 2021-09-05 13:38:13 +02:00
ptitSeb b309933571 [TRAVIS] Small change 2021-09-05 13:29:17 +02:00
ptitSeb c7e8044f92 [TRAVIS] Try some travis build 2021-09-05 13:19:28 +02:00
ptitSeb 29720048e2 Started a new dev. cycle 2021-09-05 13:08:37 +02:00
ptitSeb 716ac9e041 Bumped to v0.1.4 2021-09-05 11:34:21 +02:00
ptitSeb fb835fbe66 Added major contributor list in README 2021-09-05 11:28:12 +02:00
ptitSeb 4aac3444bd Added (empty) wrapped libgssapi.so.3 (for #27) 2021-09-04 14:07:49 +02:00
ptitSeb 0a343b72f2 Added syscall 56 (for #109) 2021-09-04 13:50:22 +02:00
ptitSeb ab9178f638 Fixed 66 0F 3A 40 SSE4x opcode (for #108) 2021-09-04 13:43:16 +02:00
ptitSeb 1b8d952d88 Added 66 0F 3A 40 SSE4x opcode (for #108) 2021-09-04 13:06:16 +02:00
ptitSeb e8e966cd80 Added wrapped iopl that answer 'unsuported operation' for now 2021-09-04 12:19:43 +02:00
ptitSeb 8b80cc328f [DYNAREC] Fixed (agaim) BTR/BTS/BTC with imm8==0 2021-09-04 12:19:08 +02:00
ptitSeb 72986e8ba3 Don't limit mmap on 47bits if wine is not detected 2021-09-04 10:18:16 +02:00
ptitSeb 3df01a153d Added BOX64_NOPULSE info to the README 2021-09-04 09:35:33 +02:00
ptitSeb 5d5ef75337 Add some support vor VSyscall 2021-09-02 20:25:58 +02:00
ptitSeb c3ef6380a7 Added a few atk wrapped function (for #56) 2021-08-31 20:43:08 +02:00
ptitSeb c2782b269f Added 2 pango wrapped function (for #56) 2021-08-31 20:40:55 +02:00
ptitSeb 1cb55b2633 Added 66 0F 3A 22 SSE4.x opcode ([DYNAREC] too) (for #106) 2021-08-30 22:38:38 +02:00
ptitSeb 823c6a138a Added syscall 332 2021-08-30 22:07:51 +02:00
ptitSeb e10a78d671 [DYNAREC] Fixed BTS/BTR/BTC with imm8==0 (helps EWJ SE Win95, probably other too) 2021-08-29 15:12:10 +02:00
ptitSeb 04b9195cd2 Added 66 0F B7 opcode ([DYNAREC] too) 2021-08-29 13:30:04 +02:00
ptitSeb 3aa12a52eb Added AES-NI cpu extension support ([DYNAREC] too, using AES extension if available) 2021-08-28 16:46:59 +02:00
ptitSeb 5f31e0e093 [DYNAREC] Added detection of available CPU Extensions 2021-08-28 15:18:07 +02:00
ptitSeb 39f2b508f8 Added some more atk wrapped functions (for #101) 2021-08-23 23:29:30 +02:00
ptitSeb 5b5285940f Added a atk wrapped function (for #101) 2021-08-23 10:41:22 +02:00
ptitSeb c49da85606 Added 1 x11 wrapped function 2021-08-23 10:41:00 +02:00
ptitSeb 5cc3512a59 Added syscall 257 (for #98) 2021-08-22 21:15:11 +02:00
ptitSeb cbd1d3781b Added many Notes on README about current status of box64 2021-08-22 09:40:56 +02:00
ptitSeb 5bca9b52b3 Moved LICENSE file back to root (for #93) 2021-08-21 17:40:45 +02:00
ptitSeb fd21d6a8da Merge pull request #89 from nniro/main
Added syscall 82 (for #88)
2021-08-13 20:17:28 +02:00
Nicholas Niro c8ebce5732 Added syscall 82 (for #88) 2021-08-13 14:16:01 -04:00
ptitSeb fce5aa5a6b Added disabled wrapped libfuse (not working for now) 2021-08-10 18:37:12 +02:00
ptitSeb 2ac2996abd Added vfork wrapped function 2021-08-10 15:32:08 +02:00
ptitSeb 53fb83487a Added some comment on vDSO 2021-08-10 15:31:52 +02:00
ptitSeb 3597284e8d Some changes on getstacksize for thread 2021-08-10 15:31:11 +02:00
ptitSeb 4e8f387f79 Small changes in libc and libpthread wrapped lib 2021-08-10 12:06:43 +02:00
ptitSeb 305e6326a6 Small fix for Default and Ignore signal handling 2021-08-10 12:05:53 +02:00
ptitSeb e98c7eaa0f Small fix for log on syscall 2021-08-10 12:04:49 +02:00
ptitSeb 02462b2c12 [DYNAREC] Added 65 39 opcode 2021-08-10 12:04:11 +02:00
ptitSeb 4d9559f345 Added handling of longjmp inside signals handler (from box86) 2021-08-09 14:06:38 +02:00
ptitSeb ed63000e23 Fixed syntex in CMakeList.txt project 2021-08-06 10:40:17 +02:00
ptitSeb cc307df592 Try to add generic ARM profile when building with Dynarec (for #82) 2021-08-06 09:12:40 +02:00
ptitSeb 2d321bbd33 Added 4 more libXt wrapped functions 2021-08-03 09:50:10 +02:00
ptitSeb 5b5f7c133e Added setcontext wrapped function 2021-08-03 09:34:34 +02:00
ptitSeb 69484d7f3c Added _IO_init wrapped function 2021-08-03 09:06:20 +02:00
ptitSeb 43f5438d93 Merge pull request #79 from rajdakin/genfixes
Fixes
2021-08-01 20:04:03 +02:00
rajdakin 2b920d6936 Removed the Mapping import 2021-08-01 18:58:21 +02:00
rajdakin 01bf3e741e Forgot to update version number 2021-08-01 17:33:03 +02:00
rajdakin f014d4580a Added a useful script 2021-08-01 17:12:36 +02:00
rajdakin 1f02ab17e3 Fixed SDL2 build, allowing to include structures in function signatures 2021-08-01 17:06:40 +02:00
rajdakin e1d8f1d7e5 Fixed some wrapped functions, upgraded the rebuild_wrapper script [SDL2 DOESN'T WORK, FIX UNDERWAY] 2021-07-31 13:38:22 +02:00
rajdakin c8640caba3 Started adding GOWM macro 2021-07-31 13:36:45 +02:00
rajdakin f4ea86378e Fixed minor issues 2021-07-31 13:36:36 +02:00
ptitSeb 16011f4b34 Fix NOALIGN build 2021-07-31 11:58:03 +02:00
ptitSeb 5a3316b872 Fix for Clang lld in cmake 2021-07-30 15:00:18 +02:00
ptitSeb 9f50a19856 Try to handle Clang (for linker) 2021-07-30 14:42:01 +02:00
ptitSeb 6207b3fa38 Added 64 66 89 and changed 64 66 0F D6 opcodes ([DYNAREC] too) (for #77) 2021-07-30 09:04:21 +02:00
ptitSeb 35d2103189 Added syscall 315 (for #74) 2021-07-28 21:14:17 +02:00
ptitSeb 84626f065c [DYNAREC] Try toavoid segfault when exploring code for a native call building dynablock (for #73) 2021-07-28 16:18:06 +02:00
ptitSeb eaedda8ceb Added 1 libc wrapped function (for #73) 2021-07-28 15:19:32 +02:00
ptitSeb 4e9c25893c Fixed some typo in some new GL wrapped function (for #73) 2021-07-28 15:17:44 +02:00
ptitSeb eb5bebb344 Added a new large batch of wrapped GL extensions (for #73) 2021-07-28 14:06:48 +02:00
ptitSeb 296ee1baca Try to force 47bits on mmap64 all the time (not just when wine64 is detected) 2021-07-28 13:19:32 +02:00
ptitSeb 58b5c6ded9 Handled privilieged instruction (as handled by wine64) as privilegde and generate a SIGSEGV (should help #27 and some other Wine64 games/programs) 2021-07-28 11:13:59 +02:00
ptitSeb ecc07a235c Added wrapped dbus_message_get_args and a generic mothod to convert VAARG '...' to valist (helps wine64) 2021-07-27 15:43:56 +02:00
ptitSeb fc4f0e3bae Added wrapped libkrb5 and libgss_krb5 (for Wiee64) 2021-07-27 13:52:21 +02:00
ptitSeb e00d35f5bf Added 64 F7 opcode ([DYNAREC] too) (for #73) 2021-07-27 13:28:46 +02:00
ptitSeb 790022483b Fixed potential issues in some FF opcodes (for #72) 2021-07-27 10:32:00 +02:00
ptitSeb 100cdd329a Made librarian messages on lib dependancies issue on unload as LOG_DEBUG 2021-07-26 15:03:25 +02:00
ptitSeb 9c441df959 Merge pull request #69 from Jai-JAP/aur
Rename archlinux/ to pkgbuilds/
2021-07-22 14:40:58 +02:00
Jai-JAP a8ae44a881 Rename archlinux/ to pkgbuilds/ 2021-07-22 17:46:32 +05:30
ptitSeb 2f5fe43955 Merge pull request #68 from Jai-JAP/aur
Create pkgbuilds in archlinux/ folder
2021-07-22 14:05:53 +02:00
Jai A P 86820cf1b1 Update archlinux/* 2021-07-22 17:31:00 +05:30
Jai A P e511e1bf96 Update archlinux/* 2021-07-22 17:16:04 +05:30
Jai A P 5fb1c6c497 Create pkgbuilds in archlinux/ folder 2021-07-22 16:10:03 +05:30
ptitSeb 607bb28677 Fixed status of C2 x87 flags after sin, cos, sincos and tan function ([DYNAREC] too) (thank @icecream95 for the debugging on box86) 2021-07-21 13:34:06 +02:00
ptitSeb 36e5fb50ec Added F3 0F BD opcode ([DYNAREC] too) (for #27) 2021-07-19 13:31:11 +02:00
ptitSeb 74405a8b00 Added a couple of wrapped libc function (will help #65 among other) 2021-07-19 08:15:21 +02:00
ptitSeb 4b1ecc16ff Added a few more lzma wrapped functions 2021-07-18 17:06:54 +02:00
ptitSeb 139d5128a0 Made IRETQ to restore RSP and SS ([DYNAREC] too) (helps Wine64 exceptions handling) 2021-07-17 18:03:23 +02:00
ptitSeb 7b8bd8a285 Less log for generated signals 2021-07-17 18:02:34 +02:00
ptitSeb 445d232ee7 Added the macro, for later use (maybe) 2021-07-17 18:01:59 +02:00
ptitSeb 8ad472c118 don't try to restore pointer in my___libc_start_main if quit is true for current emu struct 2021-07-17 18:01:24 +02:00
ptitSeb fd6895782f [DYNAREC] Try to avoid segfault when discovering natuve function durring building of dynablock 2021-07-17 18:00:10 +02:00
ptitSeb abdd03cdfa [DYNAREC] Added 8F opcode and improved 8C one 2021-07-17 17:59:13 +02:00
ptitSeb ba3359353f Added 66 8C opcode (for #61) 2021-07-16 16:28:35 +02:00
ptitSeb ca473b06dc [DYNAREC] Fixed a potential deadlock (for #64, thx again) 2021-07-16 15:38:40 +02:00
ptitSeb 2ee0230793 Added syscall 12 (for #45) 2021-07-15 11:09:04 +02:00
ptitSeb 35119f8db2 Handling HLT / CLI / STI has privileged instruction (and so trigger a GPF) 2021-07-15 11:03:06 +02:00
ptitSeb c95af7c81b [DYNAREC] Don't limit the retry pattern on access error signal, as it often happens when creating new bridges (might help #57) 2021-07-15 09:25:01 +02:00
ptitSeb a9aa474884 Added 1 wrapped function to libX11 (for #56) 2021-07-14 15:16:17 +02:00
ptitSeb 259fe4a238 [DYNAREC] Fixed P flag computation for Test32 emiter (help #34) 2021-07-14 13:30:26 +02:00
ptitSeb f73bbfc0af Fixed regression introduced with 27d79eddec (for #54) 2021-07-14 11:05:21 +02:00
ptitSeb e7478f3390 Make library loaded with absolute path not wrapped (unless BOX64_PREFER_WRAPPED=1 is used) 2021-07-14 10:41:27 +02:00
ptitSeb 9be89e8ba2 Try to make the 32bits mmap more resiliant 2021-07-14 10:40:09 +02:00
ptitSeb 5287e42b02 Added some xml2 wrapped functions (for #44) 2021-07-13 19:12:13 +02:00
ptitSeb e0a7f775c9 Added some posix_* wrapped functions (for #44) 2021-07-13 19:01:05 +02:00
ptitSeb f1d238b78d Added wrapped libmpg123 (for #53) 2021-07-13 18:40:15 +02:00
ptitSeb 41ebdc7604 Added 1 more wrapped function and fixed signature of 2 other 2021-07-13 17:42:43 +02:00
ptitSeb e3fde0807f Added 1 wrapped libc function 2021-07-13 17:36:08 +02:00
ptitSeb 4007ff2610 More wrapped functions (for #44) 2021-07-13 16:47:27 +02:00
ptitSeb 27d79eddec Fixed and improved handling of segments and Call Far and signal (helps Wine64) 2021-07-13 15:45:36 +02:00
ptitSeb 0e5bc91a14 Added a couple of libc wrapped functions 2021-07-13 15:44:37 +02:00
ptitSeb c715141bf0 Added a few more libc wrapped functions (for #41) 2021-07-13 07:49:22 +02:00
ptitSeb 3d656b5008 Fixed ELF Signature detection 2021-07-12 22:17:50 +02:00
ptitSeb d84afba7c8 Added 2 more libc wrapped function (for #44) 2021-07-12 14:33:45 -05:00
ptitSeb 7559df965b Fix memory issue when launching box86 from box64 main 2021-07-12 14:28:15 -05:00
ptitSeb 10702c160a Added more libc wrapped function (for #44) 2021-07-12 14:08:56 -05:00
ptitSeb a66bb7453b Use box86 to launch x86 binary (if box86 is present in same folder as box64) 2021-07-12 13:43:00 -05:00
ptitSeb 5406a040fb Name Trace build as box64 (remove the trailing t) 2021-07-12 11:42:53 -05:00
ptitSeb 77421d2eed Added a bunch of wrapped libc function (for #41) 2021-07-12 10:52:21 -05:00
ptitSeb 78b9b0cec8 [DYNAREC] Fixed shrd/shld emiter when both regs are the same (for #33) 2021-07-12 10:35:04 -05:00
ptitSeb 16a3d46193 Added 1 wrapped libc function (for #44) 2021-07-12 09:47:46 -05:00
ptitSeb 2976bf5e6a Added some more libc wrapped functions 2021-07-12 14:27:12 +02:00
ptitSeb b370540447 Remove useless Error message on data_start not found 2021-07-12 13:46:13 +02:00
ptitSeb 6d7c0f75e7 Handling of flag RTLD_NOW in dlopen 2021-07-12 13:41:05 +02:00
ptitSeb 81a7eca5ef Merge pull request #49 from Jai-JAP/docs
Moved documentation to "docs/" folder
2021-07-12 07:37:59 +02:00
Jai-JAP 2711a7e522 Moved documentation to "docs/" folder. 2021-07-12 10:53:50 +05:30
Jai-JAP cc8f926d66 Moved documentation to "docs/" folder. 2021-07-12 10:52:59 +05:30
ptitSeb 486aa58b15 Added 66 0F 3A 0A opcode (for #33) 2021-07-11 21:58:59 +02:00
ptitSeb 8711693698 Added 66 0F 3A 20 opcode (for #33) 2021-07-11 20:46:17 +02:00
ptitSeb e6f615a1f8 Added 66 0F 38 14 opcode (for #33) 2021-07-11 20:06:36 +02:00
ptitSeb 813ed6f9a1 Fixed 66 0F 3A 0E opcode (for #33) 2021-07-11 18:21:38 +02:00
ptitSeb 85dba348a7 Added 66 0F 38 0E opcode (for #33) 2021-07-11 17:28:57 +02:00
ptitSeb a7422d11ed Splitted mmx and x87 register (from box86) 2021-07-11 17:22:27 +02:00
ptitSeb b39fbc0cfd [DYNAREC] Stop building block if protection of next byte is 0 without the Custom flags 2021-07-10 18:28:18 +02:00
ptitSeb f000951fc9 Fixed some issue with memory protection tracking 2021-07-10 17:42:20 +02:00
ptitSeb edeac868d0 (Re?)add 66 0F 38 17 opcode 2021-07-10 17:41:53 +02:00
ptitSeb a618dee15c Refined .deb build script with arch naming and postinst 2021-07-10 10:01:49 +02:00
ptitSeb 8b48773176 Added 67 E8 opcode ([DYNAREC] too) (for #45) 2021-07-10 08:13:45 +02:00
ptitSeb 9a17d9a35e Added memmem wrapped function (for #33) 2021-07-10 08:07:44 +02:00
ptitSeb a2ca22972c Added C2 opcode (for #44) 2021-07-09 23:57:16 +02:00
ptitSeb b05c449dd0 Added F3 0F B8 opcode (for #33) 2021-07-09 21:31:50 +02:00
ptitSeb bdb918c9c2 Added 66 90-97 opcodes ([DYNAREC] too) (for #44) 2021-07-09 21:23:08 +02:00
ptitSeb 7ae9dca562 [DYNAREC] Fixed emiter for shr32c, sar32c and shrd32c (for #44) 2021-07-09 21:06:36 +02:00
ptitSeb 005e3ddf7d Added 66 0F 3A 17 opcode (for #33) 2021-07-09 20:31:09 +02:00
ptitSeb c5fbc5efd3 Improved log when encountering SIGILL (to help diagnose #44) 2021-07-09 18:25:04 +02:00
ptitSeb 4b06a0126e Added dummy 36 prefix ([DYNAREC] too) (for #44) 2021-07-09 18:09:03 +02:00
ptitSeb f8ef852b46 Added 66 0F C8..CF opcodes ([DYNAREC] too) 2021-07-09 17:32:13 +02:00
ptitSeb 741b03761a Added 66 0F 3A 21 opcode (for #33) 2021-07-09 17:21:30 +02:00
ptitSeb 8ccde3ed4a Added 66 0F BA opcodes (for #44) 2021-07-09 17:08:50 +02:00
ptitSeb b6ce8efa20 Removed an out-of-place comment 2021-07-09 17:07:56 +02:00
ptitSeb 2bf49e8a11 [DYNAREC] Fixed 66 REX.W opcodes 2021-07-09 17:01:00 +02:00
ptitSeb 0cfb48f3c7 Added msgstl wrapped function (for #43) 2021-07-09 16:58:52 +02:00
ptitSeb fcd9eba0da Added one cups wrapped functions (for #42) 2021-07-09 15:32:03 +02:00
ptitSeb 6d7e729563 Added some atk wrapped functions (for #42) 2021-07-09 15:29:22 +02:00
ptitSeb 102744665c Added some cairo functions (for #42) 2021-07-09 15:26:49 +02:00
ptitSeb dd885a694e Added a couple more libc function (for #37) 2021-07-09 14:28:41 +02:00
ptitSeb ecf8ffbbdc First try at building .deb package using cmake CPack 2021-07-09 14:26:29 +02:00
ptitSeb c1e67c31bc Added F0 0F BA opcodes (for #21) 2021-07-09 11:48:57 +02:00
ptitSeb 6eccdc1baf Added handling of flag 0x4 for wrapped dlopen 2021-07-09 11:27:17 +02:00
ptitSeb 7aa7ef6baf Added wrapped euidaccess and eaccess functions to libc (for #21) 2021-07-09 09:02:20 +02:00
ptitSeb 66ed68ca48 Added a large batch of wrapped libGL functions, including full 4.5 set (for #21) 2021-07-09 00:16:52 +02:00
ptitSeb d20d007933 Added wrapped getrandom function to libc 2021-07-08 19:27:15 +02:00
ptitSeb a91d2d0841 Added a few more wrapped libGL functions (for #21) 2021-07-08 19:12:06 +02:00
ptitSeb 649b7772f1 Fixed BOX64_JITGDB=2 that wasn't working 2021-07-08 14:48:20 +02:00
ptitSeb fe6304b7cd [DYNAREC] Added 66 0F D2 opcodes (for geekbench5) 2021-07-08 12:43:44 +02:00
ptitSeb e9b6f3559b [DYNAREC] Added 66 0F EE opcodes (for geekbench5) 2021-07-08 12:14:04 +02:00
ptitSeb 53b2578b8e [DYNAREC] Added 64 FF opcodes (for geekbench5) 2021-07-08 12:00:48 +02:00
ptitSeb 9507601ee6 Added 64 0F B6 ocpode (for #28) 2021-07-08 10:07:54 +02:00
ptitSeb 52e4edd147 Added dummy version of __cxa_thread_atexit_impl (for #28) 2021-07-08 10:05:26 +02:00
ptitSeb acc3ed85cb Added wrapped curl_multi_wait (for #21) 2021-07-08 09:50:36 +02:00
ptitSeb dbbda60d9e Added option 20219 to crul wrapped lib (for #21) 2021-07-08 09:48:15 +02:00
ptitSeb 401071c40a [DYNAREC] Better handling of SHL/SHR/SAR Eb, 0 (for obfuscated code) 2021-07-07 23:10:40 +02:00
ptitSeb 928eb2a32b Added dummy 0F 09 opcode ([DYNAREC] too) (for #34) 2021-07-07 17:26:27 +02:00
ptitSeb 1c0b1721cd Added F4 opcode (for #34) 2021-07-07 17:06:33 +02:00
ptitSeb 15a7d0b9b5 Added a few more libc and libX11 wraped functions 2021-07-07 13:55:31 +02:00
ptitSeb 6670e924bf Added 66 0F B1 opcode 2021-07-07 13:54:49 +02:00
ptitSeb 5b5b974341 Added syscall 434 (for #21) 2021-07-07 08:42:18 +02:00
ptitSeb ad85b7c4c6 Added msgget wrapped function to libc (for #37) 2021-07-07 08:29:20 +02:00
ptitSeb a5490dc6f2 Merge pull request #36 from Azkali/main
Update comment for binfmt conf
2021-07-07 00:02:32 +02:00
ptitSeb 5c52fa6007 [DYNAREC] Fixed FISTP i64 (help #14) 2021-07-07 00:00:21 +02:00
ptitSeb f8ecf14763 [DYNAREC] Added Need optim message to FINIT 2021-07-07 00:00:01 +02:00
The Great Wizard Azkali d2f7e15fcd Update comment for binfmt conf 2021-07-06 22:51:28 +02:00
ptitSeb 66ac772585 Merge pull request #35 from Azkali/main
Fix missing CONFIG_64BIT kernel for older kernel
2021-07-06 22:43:33 +02:00
The Great Wizard Azkali dd365e0b14 Fix missing CONFIG_64BIT kernel for older kernel
On older kernel < 5.X sigcontext.h defines this flag `#ifdef CONFIG_64BIT` which prevents building on some platforms.
2021-07-06 22:35:21 +02:00
ptitSeb d612656978 Added syscall 6 and fixed syscall 5 (for #14) 2021-07-06 22:24:52 +02:00
ptitSeb 91787c4dbf Try to fix compilation on old libc 2021-07-06 18:31:55 +02:00
ptitSeb c534a9d78c Fixed some case of crash with emulated RW in SDL1 (helps #14) 2021-07-06 17:52:07 +02:00
ptitSeb 06053027a9 Added syscall 35 (for #14) 2021-07-06 17:37:11 +02:00
ptitSeb 9291d15215 Fixed some return values from many syscalls (should help #14) 2021-07-06 17:31:34 +02:00
ptitSeb d07036b8ec Added 0F D7 opcode ([DYNAREC] too) (for #32) 2021-07-06 16:37:02 +02:00
ptitSeb cb73eaf776 Work on CMPSS and CMPSD ([DYNAREC] too) 2021-07-06 14:23:57 +02:00
ptitSeb bb38d8d1ca [DYNAREC] Added 66 0F 50 opcode, and changed a bit 66 0F D7 (for CB15) 2021-07-06 09:44:07 +02:00
ptitSeb cc269337f2 [DYNAREC] Added F3 0F 53 opcode (for CB15) 2021-07-06 09:29:58 +02:00
ptitSeb a2aa5fc650 Added 66 0F 38 08/09/0A opcodes ([DYNAREC] too) (for #32 / Zoom) 2021-07-05 23:01:09 +02:00
ptitSeb 26d4f21fa7 [DYNAREC] Added 66 0F 5E opcode (for CB15) 2021-07-05 22:37:04 +02:00
ptitSeb 7f390a5499 [DYNAREC] Added F0 09 opcode (for CB15) 2021-07-05 22:28:19 +02:00
ptitSeb b9f38bcefd [DYNAREC] Added 66 0F C2 opcode (for CB15) 2021-07-05 22:18:23 +02:00
ptitSeb 81b1f61aec Added 66 0F 38 1C/1D/1E opcodes ([DYNAREC] too) (for #17 / Zoom) 2021-07-05 22:05:54 +02:00
ptitSeb ab83d86300 Added F0 80 opcode ([DYNAREC] too) 2021-07-05 21:58:11 +02:00
ptitSeb 450cad7a4d Fixed R_X86_64_TPOFF64 reloc on local elf (should help #31) 2021-07-05 21:00:38 +02:00
ptitSeb c1ee744205 [DYNAREC] Added 66 0F D7 opcode (for CB15) 2021-07-05 20:49:15 +02:00
ptitSeb f21afb3277 [DYNAREC] Added a faked 0F 01 opcode to avoid break of dynarec block 2021-07-05 20:48:51 +02:00
ptitSeb 7948a25945 Added FT_Property_Get wrapped function (for #17, #30) 2021-07-05 17:56:48 +02:00
ptitSeb 7711131d5c [DYNAREC] Added 8C opcode 2021-07-05 17:38:00 +02:00
ptitSeb c6119efb04 [DYNAREC] Added 0F 05 opcode (for Wine64 and probbly a few others) 2021-07-05 17:24:24 +02:00
ptitSeb d0dee6cb50 [DYNAREC] Added DC opcodes (for CB15) 2021-07-05 17:13:30 +02:00
ptitSeb e3bbfe3052 Added more xkbcommon wrapped functions (for #29) 2021-07-05 16:24:31 +02:00
ptitSeb 85a460afb7 Forgot this file from previous commit 2021-07-05 16:21:14 +02:00
ptitSeb 28a2dba9f7 Added F2 0F D0 opcode ([DYNAREC] too) 2021-07-05 16:17:17 +02:00
ptitSeb 4e7f86979d Added syscall 8 (for #14) 2021-07-05 15:15:28 +02:00
ptitSeb 303390bf00 Added more xkcbcommon wrapped functions (for #29) 2021-07-05 15:14:17 +02:00
ptitSeb 623e81a422 Added syscall 73 (for #14) 2021-07-05 15:00:37 +02:00
ptitSeb 13e574db3f Added syscalls 42 and 43 (for #14) 2021-07-05 14:16:53 +02:00
ptitSeb 7bd4aae433 Added syscall 45 2021-07-05 13:56:08 +02:00
ptitSeb 69382682c4 Added minimum wrapped libxcb-glx (for #17) 2021-07-05 13:54:05 +02:00
ptitSeb 7535b4ac61 Small update COMPILE.md 2021-07-05 13:40:50 +02:00
ptitSeb 3bab7d6c53 Fix non-dynarec build 2021-07-05 13:35:05 +02:00
ptitSeb a8a45aede3 Try to speedup a bit FindR64COPYRel 2021-07-05 11:55:10 +02:00
ptitSeb 28c6d72110 Added a few more wrapped function xkbcommon (for #17) 2021-07-05 11:36:13 +02:00
ptitSeb c3cd14f3c5 Removed mutex per bridge and use a global one (remove chance of freeze on fork) 2021-07-05 11:35:27 +02:00
ptitSeb 2010f8dcce Added 64 FF ocpodes (for #20) 2021-07-05 10:29:38 +02:00
ptitSeb abcb12f9ed Added 0F C3 opcode ([DYNAREC] too) (for #20) 2021-07-05 10:25:09 +02:00
ptitSeb 283a4dda20 Small optim on interpreted 0F 10/11 opcodes 2021-07-05 10:17:16 +02:00
ptitSeb 3355f39e9f Added syscalls 203 and 204 (for #27) 2021-07-05 08:50:10 +02:00
ptitSeb a4cd4c0745 Added a couple of libc wrapped symbol (for #21) 2021-07-05 08:47:20 +02:00
ptitSeb 3834546100 Added fallback for SDL_GetJoystickGUIDInfo wrapped function if not in native lib (for #18) 2021-07-05 08:43:09 +02:00
ptitSeb a3d7f9cd85 Added syscall 44 (for #14) 2021-07-05 08:15:22 +02:00
ptitSeb 10247fcf85 Merge pull request #19 from Jai-JAP/patch-1
Fix broken link and a typo in Readme.md
2021-07-04 23:27:35 +02:00
ptitSeb b1183e55fd Added a few more xcb wrapped functions (for #17) 2021-07-04 23:26:57 +02:00
ptitSeb b6c9377551 Always more libc wrapped functions (for #17) 2021-07-04 23:18:28 +02:00
ptitSeb c9a4b94efe Added 1 more freetype wrapped functions (for #17) 2021-07-04 23:11:15 +02:00
ptitSeb 04658cafcc Added more libc wrapped functions (for #17) 2021-07-04 23:08:30 +02:00
ptitSeb 27b3a3f33c Improved TLS handling (for #17, but probably help many other programs) 2021-07-04 22:58:06 +02:00
ptitSeb d60a0ef58d Added syscall 41 (for #14) 2021-07-04 15:43:38 +02:00
ptitSeb fff2effd5b Added pcre_free wrapped symbol (still for #17) 2021-07-04 14:44:04 +02:00
ptitSeb bb7e473e7b End a few more libc wrapped functions 2021-07-04 14:43:36 +02:00
Jai-JAP 908641a414 Update README.md 2021-07-04 16:42:56 +05:30
Jai-JAP 69bd28cc65 Update README.md
Fix broken link and a typo
2021-07-04 16:25:40 +05:30
ptitSeb 0126a0d575 Added a couple of wrapped functions to libdbus (for #17) 2021-07-04 11:11:30 +02:00
ptitSeb 6cee821138 Added syscall 319 (for #17) 2021-07-04 11:07:17 +02:00
ptitSeb bbed3403e8 Added wrapped libxkbcommon (for #17) 2021-07-04 11:04:53 +02:00
ptitSeb 9a0824af69 Added wrapped libxkbcommon-x11 (for #17) 2021-07-04 10:48:39 +02:00
ptitSeb 53375ca728 Redirected libc wrapped function mcount to _mcount as it may not exist 2021-07-04 10:39:27 +02:00
ptitSeb f0503b67eb Fixed a typo in libpcre (for #17) 2021-07-04 10:37:08 +02:00
ptitSeb 9c0daf0ed5 Added wrapped libxcb-test (for #17) 2021-07-04 10:34:02 +02:00
ptitSeb 796e6d3a87 Added wrapped libxcb-keysyms (for #17) 2021-07-04 10:30:17 +02:00
ptitSeb 6112505757 Added wrapped libxcb-image (for #17) 2021-07-04 10:27:48 +02:00
ptitSeb 9b547c7884 Added wrapped libxcb-randr (for #17) 2021-07-04 10:19:35 +02:00
ptitSeb 1687c48c1b Added wrapped libxcb-shm (for #17) 2021-07-04 10:15:42 +02:00
ptitSeb f5981c4dca Added wrapped libxcb-shape (for #17) 2021-07-04 10:09:17 +02:00
ptitSeb 6f183aa1cc Added wrapped libxcb-xfixes (for #17) 2021-07-04 10:05:05 +02:00
ptitSeb 56f6ad84bb Added wrapped libpcre.so.3 (for #17) 2021-07-04 09:58:02 +02:00
ptitSeb ed9a29b25f Added a few wrapped function to libc 2021-07-04 09:30:11 +02:00
ptitSeb 20ba6261b6 Added syscall 79 (for #14) 2021-07-04 09:16:33 +02:00
ptitSeb 905b27f216 Added some more SDL2 GameController wrapped functions (for #18) 2021-07-04 09:05:16 +02:00
ptitSeb c218631c56 Merge pull request #16 from Heasterian/main
New Tegra X1 compilation target
2021-07-04 08:52:54 +02:00
ptitSeb bd600a6135 Started a new dev. cycle 2021-07-04 08:52:16 +02:00
Heasterian 67c80f683e One more extension for Tegra T1 2021-07-03 23:26:17 +03:00
Heasterian 1fb65cbce2 Fix minor misspelling 2021-07-03 22:29:27 +03:00
Heasterian 7aa5705400 Addtional Tegra X1 target 2021-07-03 22:26:29 +03:00
Heasterian bd21214467 New TegraX1 target 2021-07-03 22:17:32 +03:00
ptitSeb de8b4da6b5 Create FUNDING.yml 2021-07-03 14:46:14 +02:00
663 changed files with 46209 additions and 4361 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: ptitSeb
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: paypal.me/0ptitSeb
+83
View File
@@ -0,0 +1,83 @@
### Auto build Box64 and release its binary with Github Action
name: Build and Release Box64
on:
workflow_dispatch:
release:
push:
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "**/*.yml"
pull_request:
types: [assigned, opened, synchronize, reopened]
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "**/*.yml"
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RPI4ARM64, RK3326, RK3399, RK3288, TEGRAX1, PHYTIUM, SD845]
type: [Release, Trace]
runs-on: ubuntu-latest
steps:
- name: "Checkout Box64 Repository"
uses: actions/checkout@v2
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
else
if [[ ${{ matrix.platform }} == 'X64' ]]; then
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=gcc" >> $GITHUB_ENV
sudo apt-get -y install git cmake make python3
ls /bin/*gcc*
else
echo BOX64_PLATFORM_MARCRO="-DARM_DYNAREC=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
fi
fi
if [[ ${{ matrix.type }} == 'Release' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
else
echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}"
echo "Build type: ${{ env.BOX64_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}"
- name: "Build Box64"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX64_COMPILER }} ${{ env.BOX64_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box64
+5
View File
@@ -59,3 +59,8 @@ build*/
src/git_head.h
backup/
# LLVMprivateGenerator
/LLVMprivateGenerator/*
!/LLVMprivateGenerator/Makefile
!/LLVMprivateGenerator/main.cpp
!/LLVMprivateGenerator/registered_structs.cpp
Executable
+24
View File
@@ -0,0 +1,24 @@
language: c
arch:
- amd64
- arm64-graviton2
os: linux
dist: focal
compiler:
- gcc
addons:
apt:
packages:
- python3
#Build steps
before_script:
- mkdir build
- cd build
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ]; then cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; else cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo ; fi
script:
- make
- ctest --output-on-failure
-52
View File
@@ -1,52 +0,0 @@
v0.1.2
======
* OpenSource!
* A few more opcode added to the Interpretor and the Dynarec
* Improved Native Function calling
* Added some function to limit allocated memory to 47bits space (for Wine)
* Improved and Fixed the functions to limit allocated memory to 32bits space
* Wine is starting now, but not everything and every version works
v0.1.0
======
* Improvement to ElfLoader
* More opcode added to the Dynarec
* More lib wrapping
* Some fixes to a few function signature
* Improvement to Signal handling, and internal mutex handling
* A few fixes to some dynarec opcodes
* A few fixes to some interpretor opcodes
v0.0.8
======
* Improvement to SSE/x87 handling
* More opcode added to the Dynarec
* More lib wrapping
v0.0.6
======
* Added Dynarec for ARM64
* Many general CPU opcode added to the Dynarec
* Many SSEx opcodes added to the Dynarec
* Added a few more symbols in libc
* A few changes to the "thread once" handling
* New Logo and Icon from @grayduck
v0.0.4
======
* Added a lot of opcodes
* Added SDL1 and SDL2 wrapping
* OpenGL/GLU wrapping done
* libasound / libpulse wrapping done
* libopenal / libalure / libalut wrapping done
* Many X11 libs wrapped
* Added "install" with binfmt integration
* A few games are actualy starting now (old WorldOfGoo, Into The Breach, VVVVVV and Thimbeweed Park)
v0.0.2
======
* Using box86 as a base, implemented most planned box64 part except dynarec
* Wrapped a few libs
* ELF loader a bit crude, but seems working
* Signal handling implemented
* MMX and x87 are sharing their registers
+128 -12
View File
@@ -2,14 +2,26 @@ cmake_minimum_required(VERSION 3.4)
cmake_policy(SET CMP0065 NEW)
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
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 Box64" OFF)
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(RK3399 OR RPI4ARM64 OR RK3326)
if(LARCH64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -50,18 +62,32 @@ if(RPI4ARM64)
add_definitions(-DRPI4ARM64)
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
endif()
if(RK3326)
elseif(RK3326)
add_definitions(-DRK3326)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto")
endif()
if(RK3399)
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")
elseif(TEGRAX1)
add_definitions(-DTEGRAX1)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
elseif(PHYTIUM)
add_definitions(-DPHYSIUM)
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+crc+simd+crypto+aes")
elseif(SD845)
add_definitions(-DSD845)
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
elseif(LARCH64)
add_definitions(-DLARCH64)
add_definitions(-pipe -march=loongarch64)
set(CMAKE_ASM_FLAGS "-pipe -march=loongarch64")
elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
if(NOGIT)
@@ -69,7 +95,7 @@ if(NOGIT)
endif()
if(HAVE_TRACE)
set(BOX64 box64t)
set(BOX64 box64)
else()
set(BOX64 box64)
endif()
@@ -177,6 +203,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
"${BOX64_ROOT}/src/tools/my_cpuid.c"
"${BOX64_ROOT}/src/tools/gtkclass.c"
"${BOX64_ROOT}/src/tools/pathcoll.c"
"${BOX64_ROOT}/src/tools/fileutils.c"
"${BOX64_ROOT}/src/tools/wine_tools.c"
@@ -195,11 +222,24 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped/wrappedgconf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX64_ROOT}/src/wrapped/wrappedglib2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgmodule2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX64_ROOT}/src/wrapped/wrappedgobject2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
@@ -208,6 +248,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
@@ -215,12 +256,15 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpcre.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsndfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
@@ -230,6 +274,14 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbglx.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbimage.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshape.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcomposite.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxdamage.c"
@@ -248,10 +300,17 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
"${BOX64_ROOT}/src/wrapped/wrappedmpg123.c"
"${BOX64_ROOT}/src/wrapped/wrappednsl.c"
"${BOX64_ROOT}/src/wrapped/wrappednspr4.c"
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX64_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX64_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
@@ -261,20 +320,29 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsecret1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedselinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
"${BOX64_ROOT}/src/wrapped/wrappedxslt.c"
"${BOX64_ROOT}/src/wrapped/wrappedldapr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlber.c"
)
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
@@ -339,7 +407,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
@@ -396,24 +464,37 @@ add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
#add_dependencies(${BOX64} PRINTER)
target_link_libraries(${BOX64} m dl rt pthread)
target_link_libraries(${BOX64} c m dl rt pthread)
if(ARM_DYNAREC)
target_link_libraries(${BOX64} dynarec)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--image-base=${BOX64_ELF_ADDRESS}")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
endif()
endif()
else()
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
else()
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
endif()
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
if(_x86_64 OR _aarch64)
add_definitions(-DCONFIG_64BIT)
endif()
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX64}
@@ -434,6 +515,36 @@ 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 "Box64 - Linux Userspace x86_64 Emulator with a twist")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MAJOR\\s*")
string(REGEX REPLACE "BOX64_MAJOR" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX64_MAJOR ${TEMP_STRING})
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MINOR\\s*")
string(REGEX REPLACE "BOX64_MINOR" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX64_MINOR ${TEMP_STRING})
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_REVISION\\s*")
string(REGEX REPLACE "BOX64_REVISION" "" TEMP_STRING ${TEMP_STRING})
string(REGEX MATCH "[0-9]" BOX64_REVISION ${TEMP_STRING})
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX64_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${BOX64_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
if(_aarch64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
elseif(_x86_64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
else()
#probably wrong...
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
endif()
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
INCLUDE(CPack)
add_test(test01 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
@@ -519,6 +630,11 @@ add_test(test17 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.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)
+12
View File
@@ -0,0 +1,12 @@
all: dumpSigs
dumpSigs: main.o registered_structs.o
g++ -g3 -std=gnu++17 -fno-rtti main.o registered_structs.o -o dumpSigs "-L$(LLVM_install_dir)/lib" -lclang-cpp -lclangTooling -Wl,-rpath "-Wl,$(LLVM_install_dir)/lib"
main.o: main.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c main.cpp -Wfatal-errors "-I$(LLVM_install_dir)/include" -o main.o
registered_structs.o: registered_structs.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c registered_structs.cpp -Wfatal-errors -o registered_structs.o
clean:
$(RM) dumpSigs main.o registered_structs.o
+458
View File
@@ -0,0 +1,458 @@
#include <algorithm>
#include <fstream>
#include <iostream>
#include <numeric>
#include <unordered_map>
#include <utility>
#include <vector>
#include <llvm/Support/raw_ostream.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/Decl.h>
#include <clang/AST/Mangle.h>
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
clang::MangleContext *mangler = nullptr;
std::unordered_map<std::string, std::pair<std::string, bool>> funMap;
std::vector<std::string> funList;
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig);
clang::QualType getPointedType(const clang::QualType q) {
if (const clang::PointerType *p = q->getAs<clang::PointerType>())
return getPointedType(p->getPointeeType());
else if (const clang::ReferenceType *r = q->getAs<clang::ReferenceType>())
return getPointedType(r->getPointeeType());
else
return q;
}
std::string record2name(const clang::RecordDecl &q, const clang::QualType *qorig) {
std::string s = q.getNameAsString();
if (s == "") {
if (!qorig) return "????.!";
if (const clang::TypedefType *tt = (*qorig)->getAs<clang::TypedefType>()) {
// Typedef
if (clang::TypedefNameDecl *td = tt->getDecl()) {
return td->getNameAsString();
} else {
return "<typedef with no declaration>";
}
} else {
return std::string("<unknown type ") + (*qorig)->getTypeClassName() + ">";
}
} else {
return s;
}
}
char ptr2char(const std::string &str) __attribute__((const));
const char *ptr2str(const std::string &str) __attribute__((const));
char type2char(const clang::QualType &qual /* Canonical */, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
switch (static_cast<const clang::BuiltinType&>(*qual).getKind()) {
case clang::BuiltinType::Kind::Void:
return 'v';
case clang::BuiltinType::Kind::Bool:
return 'i';
case clang::BuiltinType::Kind::Char_U:
return 'C';
case clang::BuiltinType::Kind::Char_S:
return 'c';
case clang::BuiltinType::Kind::Char8:
return 'c';
case clang::BuiltinType::Kind::UChar:
return 'C';
case clang::BuiltinType::Kind::SChar:
return 'c';
case clang::BuiltinType::Kind::WChar_U:
return 'W';
case clang::BuiltinType::Kind::UShort:
return 'W';
case clang::BuiltinType::Kind::WChar_S:
return 'w';
case clang::BuiltinType::Kind::Char16:
return 'w';
case clang::BuiltinType::Kind::Short:
return 'w';
case clang::BuiltinType::Kind::UInt:
return 'u';
case clang::BuiltinType::Kind::Char32:
return 'i';
case clang::BuiltinType::Kind::Int:
return 'i';
case clang::BuiltinType::Kind::ULong:
return 'L';
case clang::BuiltinType::Kind::Long:
return 'l';
case clang::BuiltinType::Kind::ULongLong:
return 'U';
case clang::BuiltinType::Kind::LongLong:
return 'I';
case clang::BuiltinType::Kind::UInt128:
return 'H';
case clang::BuiltinType::Kind::Int128:
return 'H';
case clang::BuiltinType::Kind::Float:
return 'f';
case clang::BuiltinType::Kind::Double:
return 'd';
case clang::BuiltinType::Kind::LongDouble:
return 'D';
case clang::BuiltinType::Kind::NullPtr:
return 'p'; // nullptr_t
case clang::BuiltinType::Kind::Half:
case clang::BuiltinType::Kind::BFloat16:
case clang::BuiltinType::Kind::ShortAccum:
case clang::BuiltinType::Kind::Accum:
case clang::BuiltinType::Kind::LongAccum:
case clang::BuiltinType::Kind::UShortAccum:
case clang::BuiltinType::Kind::UAccum:
case clang::BuiltinType::Kind::ULongAccum:
case clang::BuiltinType::Kind::ShortFract:
case clang::BuiltinType::Kind::Fract:
case clang::BuiltinType::Kind::LongFract:
case clang::BuiltinType::Kind::UShortFract:
case clang::BuiltinType::Kind::UFract:
case clang::BuiltinType::Kind::ULongFract:
case clang::BuiltinType::Kind::SatShortAccum:
case clang::BuiltinType::Kind::SatAccum:
case clang::BuiltinType::Kind::SatLongAccum:
case clang::BuiltinType::Kind::SatUShortAccum:
case clang::BuiltinType::Kind::SatUAccum:
case clang::BuiltinType::Kind::SatULongAccum:
case clang::BuiltinType::Kind::SatShortFract:
case clang::BuiltinType::Kind::SatFract:
case clang::BuiltinType::Kind::SatLongFract:
case clang::BuiltinType::Kind::SatUShortFract:
case clang::BuiltinType::Kind::SatUFract:
case clang::BuiltinType::Kind::SatULongFract:
case clang::BuiltinType::Kind::Float16:
case clang::BuiltinType::Kind::Float128:
case clang::BuiltinType::Kind::Overload:
case clang::BuiltinType::Kind::BoundMember:
case clang::BuiltinType::Kind::PseudoObject:
case clang::BuiltinType::Kind::Dependent:
case clang::BuiltinType::Kind::UnknownAny:
case clang::BuiltinType::Kind::ARCUnbridgedCast:
case clang::BuiltinType::Kind::BuiltinFn:
case clang::BuiltinType::Kind::ObjCId:
case clang::BuiltinType::Kind::ObjCClass:
case clang::BuiltinType::Kind::ObjCSel:
#define IMAGE_TYPE(it, id, si, a, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLImageTypes.def>
#undef IMAGE_TYPE
case clang::BuiltinType::Kind::OCLSampler:
case clang::BuiltinType::Kind::OCLEvent:
case clang::BuiltinType::Kind::OCLClkEvent:
case clang::BuiltinType::Kind::OCLQueue:
case clang::BuiltinType::Kind::OCLReserveID:
case clang::BuiltinType::Kind::IncompleteMatrixIdx:
case clang::BuiltinType::Kind::OMPArraySection:
case clang::BuiltinType::Kind::OMPArrayShaping:
case clang::BuiltinType::Kind::OMPIterator:
#define EXT_OPAQUE_TYPE(et, id, e) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLExtensionTypes.def>
#define SVE_TYPE(n, id, si) case clang::BuiltinType::Kind::id:
#include <clang/Basic/AArch64SVEACLETypes.def>
#define PPC_VECTOR_TYPE(n, id, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/PPCTypes.def>
#undef EXT_OPAQUE_TYPE
#undef SVE_TYPE
#undef PPC_VECTOR_TYPE
return '!';
default:
return ':';
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return 'i';
} else {
return type2char(ed->getIntegerType().getCanonicalType(), qorig);
}
} else if (qual->isFunctionPointerType()) {
return '@';
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return 'p';
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '!';
} else if (!rc->isCompleteDefinition()) {
return 'p';
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
char ret = ptr2char(str);
if (ret) return ret;
else {
return '!';
}
}
} else {
return '!';
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '?';
} else if (rc->getNameAsString() == "__builtin_va_list") {
// va_list
return 'A';
} else {
return '?';
}
} else {
return '?';
}
}
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
#define GO(chr) || (c == chr)
return (c == 'v')
GO('i') GO('u')
GO('I') GO('U')
GO('l') GO('L')
GO('f') GO('d')
GO('D') GO('K')
GO('0') GO('1')
GO('C') GO('c')
GO('W') GO('w')
GO('H')
GO('p');
#undef GO
}
bool isTypeValid(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
if (c == 'A') return false;
if (c == 'V') return false;
return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
}
const std::string type2string(const clang::QualType &qual, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
return std::string("(builtin) ") + static_cast<const clang::BuiltinType&>(*qual).getName(clang::PrintingPolicy{{}}).data();
} else if (qual->isFunctionPointerType()) {
return "Callback (function pointer)";
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
std::string prefix = qual->isAnyPointerType() ? "Pointer to " : "Reference to ";
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return prefix + "trivial object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return prefix + "unknown record";
} else if (!rc->isCompleteDefinition()) {
return prefix + "incomplete record " + rc->getNameAsString();
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
const char *ret = ptr2str(str);
if (ret[0] != '\0') {
return prefix + ret;
} else {
if (mangler && mangler->shouldMangleDeclName(rc)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(rc, strstr);
}
return prefix + "unknown record " + str + " (=== " + mangled + ")";
} else {
return prefix + "unknown record " + str;
}
}
}
} else {
return prefix + "non-trivial or typedef'ed object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
//return "Pointer (maybe to callback)";
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return "Enumeration with unknown underlying integer type (assuming int)";
} else {
return "Enumeration with underlying type " + type2string(ed->getIntegerType().getCanonicalType(), nullptr);
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return "Unknown record";
} else if (rc->getNameAsString() == "__builtin_va_list") {
return "va_list";
} else {
return "Unknown record " + std::string(rc->getName().data());
}
} else {
return std::string("??? ") + qual->getTypeClassName();
}
}
class Visitor : public clang::RecursiveASTVisitor<Visitor> {
public:
clang::ASTContext &context;
bool shouldVisitTemplateInstantiations() const /* override */ { return true; }
Visitor(clang::CompilerInstance &ci) : context(ci.getASTContext()) {
if (!mangler) {
mangler = clang::ItaniumMangleContext::create(context, ci.getDiagnostics());
}
}
~Visitor() {
if (mangler) {
delete mangler;
mangler = nullptr;
}
}
bool VisitDecl(clang::Decl *decl) /* override */ {
std::cerr << std::flush;
if (!decl) return true;
if ((decl->getKind() >= clang::Decl::Kind::firstFunction) && (decl->getKind() <= clang::Decl::Kind::lastFunction)) {
clang::DeclaratorDecl *ddecl = static_cast<clang::DeclaratorDecl*>(decl);
std::cout << "Function detected!\n";
std::string funName{ddecl->getName()};
auto niceprint = [](const std::string &infotype, const auto &dat){ std::cout << " " << infotype << ": " << dat << "\n"; };
niceprint("Function name", funName);
if (mangler && mangler->shouldMangleDeclName(ddecl)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(ddecl, strstr);
}
niceprint("Function mangled name", mangled);
funName = std::move(mangled);
}
bool valid;
std::string funTypeStr{""};
if (ddecl->getFunctionType()->isFunctionNoProtoType()) {
const clang::FunctionNoProtoType *funType = static_cast<const clang::FunctionNoProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType) +
" (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Is sugared", funType->isSugared());
if (funType->isSugared()) {
clang::QualType qft{funType, 0};
niceprint("Desugared", type2string(funType->desugar(), &qft));
}
funTypeStr = type2char(retType.getCanonicalType(), &retType) + std::string("Fv");
valid = isTypeValid(retType.getCanonicalType(), &retType);
} else {
const clang::FunctionProtoType *funType = static_cast<const clang::FunctionProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType)
+ " (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Parameter count", funType->getNumParams());
for (const clang::QualType &type : funType->getParamTypes()) {
niceprint(" " + type2string(type, &type),
type2string(type.getCanonicalType(), &type) + " (" + type2char(type.getCanonicalType(), &type) + ")");
}
niceprint("Variadic function", funType->isVariadic() ? "yes" : "no");
funTypeStr =
type2char(retType.getCanonicalType(), &retType) +
((funType->getNumParams() == 0)
? std::string("Fv") : std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), std::string("F"),
[](const std::string &acc, const clang::QualType &qual){ return acc + type2char(qual.getCanonicalType(), &qual); }));
if (funType->isVariadic()) funTypeStr += "V";
valid = !funType->isVariadic() &&
std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), isTypeValid(retType.getCanonicalType(), &retType),
[](bool acc, const clang::QualType &qual){ return acc && isTypeValid(qual.getCanonicalType(), &qual); });
}
niceprint("Conclusion", "");
niceprint("Function final name", funName);
niceprint("Function type", funTypeStr);
niceprint("Valid function type", valid ? "yes" : "no");
std::cout << "\n";
funMap[funName] = std::make_pair(funTypeStr, valid);
funList.push_back(funName);
}
return true;
}
};
class Consumer : public clang::ASTConsumer {
public:
Visitor visitor;
Consumer(clang::CompilerInstance &ci) : visitor(ci) {
}
void HandleTranslationUnit(clang::ASTContext &context) override {
visitor.TraverseDecl(context.getTranslationUnitDecl());
}
};
class Action : public clang::ASTFrontendAction {
public:
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef inFile) override {
return std::make_unique<Consumer>(ci);
}
};
int main(int argc, const char **argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " (filenames) -- [-I...]" << std::endl;
return 2;
}
/*int fakeargc = argc + 1;
const char **fakeargv = new const char*[fakeargc];
memcpy(fakeargv, argv, argc * sizeof(char*));
fakeargv[fakeargc - 1] = "--";*/
llvm::cl::OptionCategory opcat{""};
clang::tooling::CommonOptionsParser op{argc, argv, opcat};
std::vector<std::string> paths; for (int i = 1; i < argc; ++i) paths.push_back(argv[i]);
clang::tooling::ClangTool tool{op.getCompilations(), paths};
tool.run(clang::tooling::newFrontendActionFactory<Action>().get());
std::cout << "Done, outputing output.h" << std::endl;
std::sort(funList.begin(), funList.end());
std::fstream file{"output.h", std::ios_base::out};
for (const std::string &funName : funList) {
if (!funMap[funName].second) {
file << "//";
}
file << "GO(" << funName << ", " << funMap[funName].first << ")\n";
}
return 0;
}
+267
View File
@@ -0,0 +1,267 @@
#include <string>
#define ALL START() \
/* libc */ \
STRUCT("_IO_FILE", "a FILE") \
STRUCT("_G_fpos_t", "a file position") \
STRUCT("sockaddr", "a socket address") \
STRUCT("itimerspec", "an itimerspec") \
STRUCT("timespec", "a timespec") \
STRUCT("itimerval", "an itimerval") \
STRUCT("timeval", "a timeval") \
STRUCT("timex", "a timex") \
STRUCT("timezone", "a timezone") \
STRUCT("dirent", "a dirent") \
STRUCT("dirent64", "a dirent64") \
STRUCT("__dirstream", "a dir stream") \
STRUCT("tm", "a time structure (tm)") \
STRUCT("cmsghdr", "a cmsghdr") \
STRUCT("msghdr", "a msghdr") \
STRUCT("rpcent", "an rpcent") \
STRUCT("random_data", "a random_data structure") \
STRUCT("drand48_data", "a drand48_data structure") \
STRUCT("termios", "a termios") \
STRUCT("iovec", "an iovec") \
STRUCT("file_handle", "a file handle") \
STRUCT("lconv", "an lconv") \
STRUCT("__locale_struct", "a locale structure") \
STRUCT("aliasent", "an alias") \
STRUCT("fstab", "an fstab") \
STRUCT("group", "a group") \
STRUCT("hostent", "a hostent") \
STRUCT("protoent", "a protoent") \
STRUCT("passwd", "a password") \
STRUCT("spwd", "an spwd") \
STRUCT("ttyent", "a ttyent") \
STRUCT("utmp", "an utmp structure") \
STRUCT("utmpx", "an utmpx structure") \
STRUCT("ifaddrs", "an ifaddrs structure") \
STRUCT("statfs", "a statfs structure") \
STRUCT("statfs64", "a statfs64 structure") \
STRUCT("statvfs", "a statvfs structure") \
STRUCT("statvfs64", "a statvfs64 structure") \
STRUCT("timeb", "a timeb structure") \
STRUCT("_ftsent", "an _ftsent structure") \
STRUCT("sysinfo", "a sysinfo structure") \
STRUCT("rlimit", "an rlimit structure") \
STRUCT("rlimit64", "an rlimit64 structure") \
STRUCT("rusage", "an rusage structure") \
STRUCT("entry", "an entry structure") \
STRUCT("pollfd", "a pollfd structure") \
STRUCT("re_pattern_buffer", "a re_pattern_buffer structure") \
STRUCT("sembuf", "a sembuf structure") \
STRUCT("tms", "a tms structure") \
STRUCT("utsname", "an utsname structure") \
STRUCT("utimbuf", "an utimbuf structure") \
STRUCT2("__va_list_tag", "__va_list_tag (aka, a va_list)", 'A') \
/* ncurses */ \
STRUCT("_win_st", "a _win_st structure") \
STRUCT("MEVENT", "an MEVENT structure") \
TYPEDEF("cchar_t", "a cchar_t") \
/* zlib */ \
STRUCT("gz_header_s", "a gz_header_s structure") \
STRUCT("gzFile_s", "a gzFile_s structure") \
STRUCT("z_stream_s", "a z_stream_s structure") \
\
END()
#define START()
#define STRUCT(s, ret) if (str == s) { return 'p'; } else
#define STRUCT2(s, ret, c) if (str == s) { return c; } else
#define TYPEDEF(s, ret) if (str == s) { return 'p'; } else
#define END() { return 0; }
char ptr2char(const std::string &str) {
/*if ((str == "_IO_FILE")
|| (str == "_G_fpos_t")
|| (str == "sockaddr")
|| (str == "itimerspec")
|| (str == "timespec")
|| (str == "itimerval")
|| (str == "timeval")
|| (str == "timex")
|| (str == "timezone")
|| (str == "dirent")
|| (str == "dirent64")
|| (str == "__dirstream")
|| (str == "tm")
|| (str == "cmsghdr")
|| (str == "msghdr")
|| (str == "rpcent")
|| (str == "random_data")
|| (str == "drand48_data")
|| (str == "termios")
|| (str == "iovec")
|| (str == "file_handle")
|| (str == "lconv")
|| (str == "__locale_struct")
|| (str == "aliasent")
|| (str == "fstab")
|| (str == "group")
|| (str == "hostent")
|| (str == "protoent")
|| (str == "passwd")
|| (str == "spwd")
|| (str == "ttyent")
|| (str == "utmp")
|| (str == "utmpx")
|| (str == "ifaddrs")
|| (str == "statfs")
|| (str == "statfs64")
|| (str == "statvfs")
|| (str == "timeb")
|| (str == "_ftsent")
|| (str == "sysinfo")
|| (str == "rlimit")
|| (str == "rlimit64")
|| (str == "rusage")
|| (str == "entry")
|| (str == "pollfd")
|| (str == "re_pattern_buffer")
|| (str == "sembuf")
|| (str == "tms")
|| (str == "utsname")
|| (str == "utimbuf")
// ncurses
|| (str == "_win_st")
|| (str == "cchar_t")
) {
// FILE*, fpos_t*, ...
return 'p';
} else if (str == "__va_list_tag") {
return 'A';
} else {
return 0;
}*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
#define START()
#define STRUCT(s, ret) if (str == s) { return ret; } else
#define STRUCT2(s, ret, c) if (str == s) { return ret; } else
#define TYPEDEF(s, ret) if (str == s) { return ret; } else
#define END() return "";
const char *ptr2str(const std::string &str) {
/*if (str == "_IO_FILE") {
return "a FILE";
} else if (str == "_G_fpos_t") {
return "a file position";
} else if (str == "sockaddr") {
return "a socket address";
} else if (str == "itimerspec") {
return "an itimerspec";
} else if (str == "timespec") {
return "a timespec";
} else if (str == "itimerval") {
return "an itimerval";
} else if (str == "timeval") {
return "a timeval";
} else if (str == "timex") {
return "a timex";
} else if (str == "timezone") {
return "a timezone";
} else if (str == "dirent") {
return "a dirent";
} else if (str == "dirent64") {
return "a dirent64";
} else if (str == "__dirstream") {
return "a dir stream";
} else if (str == "tm") {
return "a time structure (tm)";
} else if (str == "cmsghdr") {
return "a cmsghdr";
} else if (str == "msghdr") {
return "a msghdr";
} else if (str == "rpcent") {
return "an rpcent";
} else if (str == "random_data") {
return "a random_data structure";
} else if (str == "drand48_data") {
return "a drand48_data structure";
} else if (str == "termios") {
return "a termios";
} else if (str == "iovec") {
return "an iovec";
} else if (str == "file_handle") {
return "a file handle";
} else if (str == "lconv") {
return "an lconv";
} else if (str == "__locale_struct") {
return "a locale structure";
} else if (str == "aliasent") {
return "an alias";
} else if (str == "fstab") {
return "an fstab";
} else if (str == "group") {
return "a group";
} else if (str == "hostent") {
return "a hostent";
} else if (str == "protoent") {
return "a protoent";
} else if (str == "passwd") {
return "a password";
} else if (str == "spwd") {
return "an spwd";
} else if (str == "ttyent") {
return "a ttyent";
} else if (str == "utmp") {
return "an utmp structure";
} else if (str == "utmpx") {
return "an utmpx structure";
} else if (str == "ifaddrs") {
return "an ifaddrs structure";
} else if (str == "statfs") {
return "a statfs structure";
} else if (str == "statfs64") {
return "a statfs64 structure";
} else if (str == "statvfs") {
return "a statvfs structure";
} else if (str == "statvfs64") {
return "a statvfs64 structure";
} else if (str == "timeb") {
return "a timeb structure";
} else if (str == "_ftsent") {
return "an _ftsent structure";
} else if (str == "sysinfo") {
return "a sysinfo structure";
} else if (str == "rlimit") {
return "an rlimit structure";
} else if (str == "rlimit64") {
return "an rlimit64 structure";
} else if (str == "rusage") {
return "an rusage structure";
} else if (str == "entry") {
return "an entry structure";
} else if (str == "pollfd") {
return "a pollfd structure";
} else if (str == "re_pattern_buffer") {
return "a re_pattern_buffer structure";
} else if (str == "sembuf") {
return "a sembuf structure";
} else if (str == "tms") {
return "a tms structure";
} else if (str == "utsname") {
return "an utsname structure";
} else if (str == "utimbuf") {
return "an utimbuf structure";
} else if (str == "__va_list_tag") {
return "__va_list_tag (aka, a va_list)";
// ncurses
} else if (str == "_win_st") {
return "a _win_st structure";
} else if (str == "cchar_t") {
return "a cchar_t";
} else return "";*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
-51
View File
@@ -1,51 +0,0 @@
# box64
![Official logo](Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
----
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 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/).
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/emu/x86primop.c) for copyright details
<img src="Box64Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
----
Usage
----
There are a few environment variables to control the behaviour of Box64.
See [here](USAGE.md) for all environment variables and what they do.
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
----
Version history
----
The change log is available [here](CHANGELOG.md)
----
Final words
----
(If you use Box64 in your project, please don't forget to mention Box64!)
+86
View File
@@ -0,0 +1,86 @@
v0.1.6
======
* Introduce "HotPage", to temporarily disable Dynarec on a page were writing is also occuring (can help speed up C# code)
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
* Introduce BOX64_DYNAREC_STRONGMEM for the (Arm) dynarec to emulate StrngMemory Model (needed by some games, like RimWorld)
* More functions wrapped
* Improve speed of the custom allocator used by dynarec and Hash (speedup loading)
* Added a workaround for streamwebhelper to not load it
* More opcodes added
* More wrapped libraries, including gtk2
* Added a fix for linking box64 on system using glibc 2.34+
* Some residual fixes on thread attribute handling
* Better handling of app that want 32bits jumps, like unity3d/mono (thanks mogery)
* More ARM hardware option in CMake (Phytium, NX...)
* Added loongarch64 support (interpretor only)
* Some fixes to elfloader
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
v0.1.4
======
* Reworked README a bit
* Added some more wrapped libs
* Added some SSE4x opcodes
* Preliminary support for VSyscall (still missing VDSO)
* Added support for AES-NI cpu extension, also in Dynarec (and using ARM extension if present)
* Added some syscall
* Added some more wrapped functions
* Improvment to the handling of longjmp inside signal handlers
* Improved wrapper helpers (from rajdakin)
* Some fixes to opcodes (especially C2 flags for some x87 opcodes)
* Handling of some specific opcode as privileged instruction (instead of NOP)
* Fixed ELF signature detection
* Some fixes to a few env. var. handling
v0.1.2
======
* OpenSource!
* A few more opcode added to the Interpretor and the Dynarec
* Improved Native Function calling
* Added some function to limit allocated memory to 47bits space (for Wine)
* Improved and Fixed the functions to limit allocated memory to 32bits space
* Wine is starting now, but not everything and every version works
v0.1.0
======
* Improvement to ElfLoader
* More opcode added to the Dynarec
* More lib wrapping
* Some fixes to a few function signature
* Improvement to Signal handling, and internal mutex handling
* A few fixes to some dynarec opcodes
* A few fixes to some interpretor opcodes
v0.0.8
======
* Improvement to SSE/x87 handling
* More opcode added to the Dynarec
* More lib wrapping
v0.0.6
======
* Added Dynarec for ARM64
* Many general CPU opcode added to the Dynarec
* Many SSEx opcodes added to the Dynarec
* Added a few more symbols in libc
* A few changes to the "thread once" handling
* New Logo and Icon from @grayduck
v0.0.4
======
* Added a lot of opcodes
* Added SDL1 and SDL2 wrapping
* OpenGL/GLU wrapping done
* libasound / libpulse wrapping done
* libopenal / libalure / libalut wrapping done
* Many X11 libs wrapped
* Added "install" with binfmt integration
* A few games are actualy starting now (old WorldOfGoo, Into The Breach, VVVVVV and Thimbeweed Park)
v0.0.2
======
* Using box86 as a base, implemented most planned box64 part except dynarec
* Wrapped a few libs
* ELF loader a bit crude, but seems working
* Signal handling implemented
* MMX and x87 are sharing their registers
+67 -2
View File
@@ -31,6 +31,71 @@ If it's the first install, you also need:
sudo systemctl restart systemd-binfmt
```
#### for TEGRA X1
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Snapdragon 845
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
----
#### for Phytium
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for LoongArch
Using a 64bits OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DLARCH64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Other ARM64 Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
@@ -57,11 +122,11 @@ The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both opti
*To have a Trace Enabled build*
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
To have a trace enabled build ( ***the interpretor will be slightly slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
*To have 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`.
*Not building from a git clone*
+114
View File
@@ -0,0 +1,114 @@
# box64
![Official logo](img/Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[中文](README_CN.md)
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 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/).
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](../src/emu/x64primop.c) for copyright details
<img src="img/Box64Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
----
Usage
----
There are a few environment variables to control the behaviour of Box64.
See [here](USAGE.md) for all environment variables and what they do.
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
----
Version history
----
The change log is available [here](CHANGELOG.md)
----
Notes about 32-bit platforms
----
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bits libraries. Box64 doesn't include any 64-bits <-> 32-bits translation.
So understand that box64 will only runs 64bits linux binaries. For 32bits binaries, you need box86 (with all the multiarch or proot trickery it imply on 64bits OS).
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when argument is "-m"
----
Notes about Unity game emulation
----
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not always emulated in a 100% accurate way).
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
So, not all Unity games work and can require a high OpenGL profile, but many actualy works now
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game start then quit before showing anything.
----
Notes about GTK programs
----
GTK libraries are not wrapped yet on box64 (contrary to box86). Many games use gtk (setup too), like Unity game for the Screen Selection dialog. While Unity game can run without that dialog (using default setup), many just can't. For now, you'll need o put the set of gtk x86_64 libraries in the game folder (or some other folder known by box64) to get gtk support. GTK Wrapping is planned on box64.
----
Notes about Steam
----
Not that Steam is an hybrid 32bits / 64bits. You NEED box86 to run steam, as the client app is a 32bits binaries. It also use a 64bits local server binaries, but like most stuff using libcef/chromium. it's not working correctly on box64 for now.
So: no Steam for now on box64.
----
Notes about Wine
----
Wine 64bits is supported on box64. Be aware that 64bits wine also include 32bits componant, to be able to run 32bits windws programs. The 32bits will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64bits setup can run both 32bits and 64bits windows program (just use `wine` and `wine64` respectivelly)
----
Notes about Vulkan
----
Box64 Does not wrap Vulkan libraries yet. It's planned, but for now, vulkan program will not run on box64.
----
Final word
----
I want to thank everyone who has contributed to box64 developpement.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
And I also thank the many other people who participated even once in the project.
(If you use Box64 in your project, please don't forget to mention it!)
+119
View File
@@ -0,0 +1,119 @@
# box64
![Official logo](img/Box64Logo.png "Official Logo")
Linux上用户空间的x86_64应用模拟器
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[English](README.md)
在ARM或其他非X86_64架构的Linux操作系统上,使用Box64可以运行x86_64 Linux程序(例如游戏),请注意,主机系统需要**64位小端**。
您可以在Youtube的[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)或[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)频道找到更多Box64视频。
Box64使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以它很容易与大多数应用程序集成和使用,并且在很多情况下性能会出奇的高。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看示例的基准测试分析。
Box64为ARM64平台集成了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/)找到。
注:DynaRec需要针对不同平台编写一部分汇编代码,目前仅支持ARM64。
一些x64内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x64primop.c](../src/emu/x64primop.c)了解版权详情
<img src="img/Box64Icon.png" width="96" height="96">
Logo和图标由grayduck制作,感谢!
----
使用方法
----
若干环境变量可以设置Box64的行为。
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
请注意:Box64的Dynarec提供了一种机制来处理JIT代码,包含内存保护和段错误信号处理程序。简单地说,如果您想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),您仍然会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的东西,不要在每个段错误时都停止,如果您想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
----
编译/安装
----
> 编译说明可以在[这里](COMPILE.md)查看。
----
版本历史
----
版本日志在[这里](CHANGELOG.md)。
----
32位平台的注意事项
----
Box64的工作原理是直接将函数调用从x86_64转换到主机系统,主机系统(Box64运行的系统)需要有64位的库。Box64并不包括任何64位<->32位的转换。
所以请理解,Box64只能运行64位的Linux二进制文件。对于32位的二进制文件,需要Box86(在64位的操作系统上需要所有的multiarch库或一些proot技巧)。
请注意,许多(基于mojo的)安装程序,即使存在x86_64版本,但在检测到架构为ARM64时会退回到"x86",这时会尝试使用(如果有)box86进行安装。这时你可以使用一个假的"uname",当它的参数为"-m"时返回"x86_64"。
----
关于Unity游戏模拟的注意事项
----
当前Unity游戏模拟是一件碰运气的事情。Unity使用Mono(它的信号表示,并不总能100%成功模拟)。
您还应该注意,一些Unity3D游戏需要OpenGL 3+,目前在ARM SBC(单板计算机)上提供OpenGL 3+是很棘手的。
所以,并不是所有的Unity游戏都能工作,而且可能需要很高的OpenGL配置,但现在很多游戏都能工作。
提示:如果游戏开始后在显示任何东西之前退出,在Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
----
关于GTK程序的注意事项
----
GTK库尚未封装在Box64内(与Box86相反)。许多游戏(包括设置)都使用gtk,例如Unity游戏的屏幕选择对话框。有些Unity游戏可以在没有该对话框的情况下运行(使用默认设置),还有一些不能。您需要将一套gtk x86_64库放在游戏目录(或其他一些Box64识别的目录)中以获得gtk支持。Box64有计划封装GTK原生库。
----
关于Steam的注意事项
----
Steam并不是32位/64位混合的,而是32位的,因此您需要Box86才能运行Steam。Steam也使用64位的本地服务器程序,但像大多数使用libcef/chromium的程序一样,在box64上暂时无法正常工作。
所以:目前在box64上无法运行Steam。
----
关于Wine的注意事项
----
box64支持64位Wine,但请注意,64位的Wine还包含32位的组件,以便能够运行32位的Windws程序。32位程序需要Box86,没有它就不能运行。在Box64和Box86共存的系统上,设置64位Wine可以同时运行32位和64位windows程序(只需分别使用 `wine` 和 `wine64`)。
----
关于Vulkan注意事项
----
Box64尚未封装原生Vulkan库,有计划这么做,但目前,vulkan程序不能在box64上运行。
----
结语
----
我要感谢所有为 box64 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/)
* 硬件捐赠和LoongArch迁移:[xiaoji](https://www.linuxgame.cn)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box64,请不要忘记提及!)
+16
View File
@@ -115,6 +115,17 @@ 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)
#### BOX64_DYNAREC_BIGBLOCK
Enables/Disables Box64's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
#### BOX64_DYNAREC_STRONGMEM
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX64_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -134,6 +145,11 @@ Allow Box64 to continue even if a library is missing.
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX64_NOPULSE
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
#### BOX64_JITGDB
* 0 : Just print the Segfault message on segfault (default)
File renamed without changes.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

File renamed without changes.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 180 KiB

+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-arm64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-arm64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm64-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
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-arm64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-arm64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm64-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
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
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)
}
package() {
cd "$srcdir/${pkgname%-rk3399-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
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
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=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rk3399-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
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
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}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
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
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
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}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
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
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-tegra-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-tegra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-tegra-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-tegra-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
@@ -0,0 +1,44 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-tegra-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-tegra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-tegra-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-tegra-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
}
+43
View File
@@ -0,0 +1,43 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-x64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-x64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x64-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
}
+43
View File
@@ -0,0 +1,43 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-x64-git
pkgver=1116.9243ea4
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=Debug
fi
}
build() {
cd "$srcdir/${pkgname%-x64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x64-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
}
+24
View File
@@ -0,0 +1,24 @@
# The directory containing all PKGBUILDs for BOX64
## FAQ
### 1. How to use it?
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
```sh
mv ./PKGBUILD-<your-platform> ./PKGBUILD
cd ..
makepkg -si
```
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 64-bit Archlinux ARM.
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
### 2. What platforms are currently supported.
All specified in [COMPILE.md](../COMPILE.md).
### 3. Any advantages with that sollution?
This might give you some advantages like those:
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
- your `box64` 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 box64 to .deb or .rpm installer files.
Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
systemctl restart systemd-binfmt
+675 -325
View File
File diff suppressed because it is too large. Load diff
+21 -8
View File
@@ -88,6 +88,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;
@@ -110,6 +111,7 @@ 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
}
@@ -128,6 +130,7 @@ static void init_mutexes(box64context_t* context)
#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);
}
@@ -160,7 +163,16 @@ box64context_t *NewBox64Context(int argc)
context->versym = NewDictionnary();
context->system = NewBridge();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
// create the vsyscalls
context->vsyscalls[0] = AddVSyscall(context->system, 96);
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
// get handle to box64 itself
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
context->dlprivate = NewDLPrivate();
@@ -258,6 +270,13 @@ void FreeBox64Context(box64context_t** context)
if(ctx->tlsdata)
free(ctx->tlsdata);
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX64Emu(&ctx->emu_sig);
finiAllHelpers(ctx);
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
@@ -268,13 +287,7 @@ void FreeBox64Context(box64context_t** context)
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX64Emu(&ctx->emu_sig);
finiAllHelpers(ctx);
pthread_mutex_destroy(&ctx->mutex_bridge);
free(ctx);
}
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 1
#define BOX64_REVISION 2
#define BOX64_REVISION 6
#endif //__BOX64_VERSION_H_
+309 -247
View File
@@ -31,21 +31,21 @@
// init inside dynablocks.c
KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
static pthread_mutex_t mutex_mmap;
static mmaplist_t *mmaplist;
static size_t mmapsize;
static mmaplist_t *mmaplist = NULL;
static size_t mmapsize = 0;
static size_t mmapcap = 0;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
static uintptr_t* box64_jmptbldefault1[1<<JMPTABL_SHIFT];
static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT];
#endif
#define MEMPROT_SHIFT 12
#define MEMPROT_SHIFT2 (32-MEMPROT_SHIFT)
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
static pthread_mutex_t mutex_prot;
KHASH_MAP_INIT_INT(memprot, uint8_t*)
static kh_memprot_t *memprot;
#define MEMPROT_SHIFT 12
#define MEMPROT_SHIFT2 (16+12)
#define MEMPROT_SIZE (1<<16)
static uint8_t *volatile memprot[1<<20]; // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection]
static uint8_t memprot_default[MEMPROT_SIZE];
static int inited = 0;
typedef struct blocklist_s {
@@ -62,8 +62,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;
@@ -72,86 +72,123 @@ 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, size_t maxsize, size_t* 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 size_t 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, size_t 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, size_t newsize)
@@ -160,15 +197,21 @@ static int expandBlock(void* block, void* sub, size_t newsize)
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
// unsigned bitfield of this length gets "promoted" to *signed* int...
if((size_t)(s->next.size + n->next.size) < newsize)
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) {
@@ -197,11 +240,11 @@ void* customMalloc(size_t size)
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
size_t rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
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;
}
@@ -225,14 +268,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;
}
@@ -254,7 +297,7 @@ 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;
}
@@ -280,8 +323,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;
}
@@ -298,6 +341,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, size_t size)
@@ -305,13 +350,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
// look for free space
void* sub = NULL;
for(size_t i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size) {
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);
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);
@@ -321,9 +368,17 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
for(size_t 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, "BOX64: Warning, sub not found, corrupted mmaplist[%zu] info?\n", i);
if(box64_log >= LOG_DEBUG)
printBlock(mmaplist[i].block, mmaplist[i].first);
}
}
}
@@ -333,8 +388,11 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
{
size_t i = mmapsize++;
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\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, box64_pagesize, MMAPSIZE)) {
@@ -353,21 +411,23 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t 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;
@@ -376,6 +436,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
kh_value(blocks, k) = db;
for(size_t 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;
}
@@ -388,15 +449,18 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t 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(size_t 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, "BOX64: Warning, Free a chunk in a locked mmaplist[%zu]\n", i);
++mmaplist[i].locked;
}
return;
}
@@ -433,7 +497,6 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t 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, box64_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
@@ -457,18 +520,14 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t 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;
}
@@ -477,7 +536,6 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_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
@@ -489,12 +547,9 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_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)
@@ -693,43 +748,35 @@ uintptr_t getJumpTableAddress64(uintptr_t addr)
}
// Remove the Write flag from an adress range, so DB can be executed safely
void protectDBnolock(uintptr_t addr, uintptr_t size)
void protectDB(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
int ret;
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}*/
memprot[i] = newblock;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
if(!(prot&PROT_DYNAREC))
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
if((prot&PROT_WRITE)) {
prot&=~PROT_WRITE;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i>>16][i&0xffff] = prot|PROT_DYNAREC; // need to use atomic exchange?
}
}
}
void protectDB(uintptr_t addr, size_t size)
{
pthread_mutex_lock(&mutex_prot);
protectDBnolock(addr, size);
pthread_mutex_unlock(&mutex_prot);
}
void lockDB()
{
pthread_mutex_lock(&mutex_prot);
}
void unlockDB()
{
pthread_mutex_unlock(&mutex_prot);
}
@@ -739,90 +786,109 @@ void unprotectDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
/*if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}*/
memprot[i] = newblock;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if(prot&PROT_DYNAREC) {
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
prot&=~PROT_DYNAREC;
prot|=PROT_WRITE;
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i>>16][i&0xffff] = prot; // need to use atomic exchange?
}
}
pthread_mutex_unlock(&mutex_prot);
}
int isprotectedDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1LL;
if(end<idx) { // memory addresses higher than 48bits are not tracked
dynarec_log(LOG_DEBUG, "00\n");
return 0;
}
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i>>16][i&0xffff];
if((prot&PROT_WRITE)) {
dynarec_log(LOG_DEBUG, "0\n");
return 0;
}
}
dynarec_log(LOG_DEBUG, "1\n");
return 1;
}
#endif
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t last = idx<<MEMPROT_SHIFT;
uint8_t oldprot = 0xff;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
}
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
for(uintptr_t ii = start; ii<=finish; ++ii) {
uint32_t dyn = block[ii]&PROT_DYNAREC;
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
if(oldprot!=prot) {
if(oldprot!=0xff)
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i<<MEMPROT_SHIFT;
oldprot = prot;
}
} else if(prot!=0xff) {
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i << MEMPROT_SHIFT;
oldprot = 0xff;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
block[ii] = prot|dyn|PROT_ALLOC;
#else
memprot[i] = newblock;
#endif
}
i+=finish-start; // +1 from the "for" loop
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t dyn=(memprot[i>>16][i&0xffff]&PROT_DYNAREC);
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i>>16][i&0xffff] = prot|dyn;
}
if(oldprot!=0xff)
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
pthread_mutex_unlock(&mutex_prot);
}
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(MEMPROT_SIZE, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
#else
memprot[i] = newblock;
#endif
}
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
i+=finish-start; // +1 from the "for" loop
}
for (uintptr_t i=idx; i<=end; ++i)
memprot[i>>16][i&0xffff] = prot;
pthread_mutex_unlock(&mutex_prot);
}
@@ -831,18 +897,26 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
for (uintptr_t i=(idx>>16); i<=(end>>16); ++i)
if(memprot[i]==memprot_default) {
uint8_t* newblock = calloc(1<<16, sizeof(uint8_t));
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (arm64_lock_storeifref(&memprot[i], newblock, memprot_default) != newblock) {
free(newblock);
}
#else
memprot[i] = newblock;
#endif
}
for (uintptr_t i=idx; i<=end; ++i) {
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
uint8_t* block = memprot[i>>16];
for(uintptr_t ii = start; ii<=finish; ++ii) {
if(!block[ii])
block[ii] = prot;
@@ -865,7 +939,7 @@ void loadProtectionFromMap()
uintptr_t s, e;
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
allocProtection(s, e-s, prot|PROT_ALLOC);
}
}
fclose(f);
@@ -873,8 +947,9 @@ void loadProtectionFromMap()
static int blockempty(uint8_t* mem)
{
for (int i=0; i<(MEMPROT_SIZE); ++i)
if(mem[i])
uint32_t *p4 = (uint32_t*)mem;
for (int i=0; i<(MEMPROT_SIZE)/4; ++i, ++p4)
if(*p4)
return 0;
return 1;
}
@@ -884,19 +959,35 @@ void freeProtection(uintptr_t addr, size_t size)
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
if(end>=(1LL<<(20+16)))
end = (1LL<<(20+16))-1;
if(end<idx) // memory addresses higher than 48bits are not tracked
return;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k!=kh_end(memprot)) {
const uint32_t key = (i>>16);
if(memprot[key]!=memprot_default) {
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t *block = kh_value(memprot, k);
uint8_t *block = memprot[key];
memset(block+start, 0, finish-start+1);
if(blockempty(block)) {
free(block);
kh_del(memprot, memprot, k);
#if 0 //def ARM64 //disabled for now, not usefull with the mutex
if (blockempty(block)) {
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)memprot_default);
if(!blockempty(block)) {
block = (void*)arm64_lock_xchg(&memprot[key], (uintptr_t)block);
for (int i = 0; i < 0x10000; ++i) {
memprot[key][i] |= block[i];
}
}
if (block != memprot_default) free(block);
}
#else
if(blockempty(block)) {
memprot[key] = memprot_default;
free(block);
}
#endif
i+=finish-start; // +1 from the "for" loop
}
}
@@ -905,65 +996,52 @@ void freeProtection(uintptr_t addr, size_t size)
uint32_t getProtection(uintptr_t addr)
{
const uint32_t key = (addr>>32)&0xffffffff;
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
if(addr>=(1LL<<48))
return 0;
}
const uintptr_t idx = ((addr&0xffffffff)>>MEMPROT_SHIFT);
uint32_t ret = kh_val(memprot, k)[idx];
pthread_mutex_unlock(&mutex_prot);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
uint32_t ret = memprot[idx>>16][idx&0xffff];
return ret;
}
#define LOWEST (void*)0x20000
int availableBlock(uint8_t* p, size_t n)
{
for (size_t i=0; i<n; ++i, ++p)
if(*p)
return 0;
return 1;
}
static uintptr_t nextFree(uintptr_t addr)
{
if(addr>=(1LL<<48))
return 0;
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(memprot[idx>>16]==memprot_default) {
return addr;
}
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
return (addr&~0xffffffffLL)+(i<<MEMPROT_SHIFT);
for (uintptr_t i=(idx&0xffff); i<MEMPROT_SIZE; ++i)
if(!memprot[idx>>16][i]) {
return ((idx>>16)<<(16+12))+(i<<MEMPROT_SHIFT);
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
addr += (1LL<<(16+12));
addr &= ~((1LL<<(16+12)-1LL));
} while(1);
}
static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
{
if(addr>=(1LL<<48))
return 0;
uintptr_t mfree = 0;
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
mfree+=0x100000000LL;
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(memprot[idx>>16]==memprot_default) {
mfree+=(1LL<<(16+12));
if(mfree>sz) {
return addr;
}
} else {
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
mfree+=1<<MEMPROT_SHIFT;
for (uintptr_t i=(idx&0xffffLL); i<MEMPROT_SIZE; ++i)
if(!memprot[idx>>16][i]) {
mfree+=(1<<MEMPROT_SHIFT);
} else
return mfree;
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
addr += (1LL<<(12+16));
addr &= ~((1LL<<(12+16))-1LL);
} while(1);
}
void* find32bitBlock(size_t size)
@@ -974,12 +1052,10 @@ void* find47bitBlock(size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = 0x100000000LL;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
@@ -990,12 +1066,10 @@ void* find47bitBlock(size_t size)
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size);
return NULL;
}
@@ -1003,17 +1077,14 @@ void* find47bitBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x800000000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
return NULL;
}
@@ -1021,17 +1092,14 @@ void* findBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
return NULL;
}
@@ -1048,9 +1116,6 @@ int unlockCustommemMutex()
}
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
return ret;
}
@@ -1063,9 +1128,6 @@ void relockCustommemMutex(int locks)
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
}
@@ -1076,9 +1138,6 @@ static void init_mutexes(void)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
pthread_mutex_init(&mutex_prot, &attr);
#ifdef DYNAREC
pthread_mutex_init(&mutex_mmap, &attr);
#endif
pthread_mutexattr_destroy(&attr);
}
@@ -1095,7 +1154,9 @@ void init_custommem_helper(box64context_t* ctx)
if(inited) // already initialized
return;
inited = 1;
memprot = kh_init(memprot);
memset(memprot_default, 0, sizeof(memprot_default));
for(int i=0; i<(1<<20); ++i)
memprot[i] = memprot_default;
init_mutexes();
#ifdef DYNAREC
#ifdef ARM64
@@ -1143,6 +1204,7 @@ void fini_custommem_helper(box64context_t *ctx)
dblist_oversized = NULL;
}
mmapsize = 0;
mmapcap = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
for (uintptr_t idx3=0; idx3<=0xffff; ++idx3)
if(dynmap123[idx3]) {
@@ -1157,7 +1219,6 @@ void fini_custommem_helper(box64context_t *ctx)
}
free(mmaplist);
pthread_mutex_destroy(&mutex_mmap);
for (int i3=0; i3<(1<<DYNAMAP_SHIFT); ++i3)
if(box64_jmptbl3[i3]!=box64_jmptbldefault2) {
for (int i2=0; i2<(1<<DYNAMAP_SHIFT); ++i2)
@@ -1173,10 +1234,11 @@ void fini_custommem_helper(box64context_t *ctx)
}
#endif
uint8_t* m;
kh_foreach_value(memprot, m,
free(m);
);
kh_destroy(memprot, memprot);
for(int i=0; i<(1<<20); ++i) {
m = memprot[i];
if(m!=memprot_default)
free(m);
}
for(int i=0; i<n_blocks; ++i)
#ifdef USE_MMAP
+50 -9
View File
@@ -230,13 +230,16 @@
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define LDRSH_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSHxw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b01, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSBx_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, 0b10, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRSBw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, 0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRSBxw_U12(Rt, Rn, imm12) EMIT(LDRSH_gen(0b00, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSHw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSHxw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRSBx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, 0b10, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRSBw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, 0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRSBxw_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b00, 0b01, rex.w?0b10:0b11, ((uint32_t)(imm12>>0))&0xfff, Rn, Rt))
#define LDRS_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_REG(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
#define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
@@ -348,6 +351,9 @@
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
// Data Memory Barrier
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
// BR and Branches
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
@@ -628,9 +634,11 @@
// REV
#define REV_gen(sf, opc, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | (opc)<<10 | (Rn)<<5 | (Rd))
#define REVx(Rd, Rn) EMIT(REV_gen(1, 0b11, Rn, Rd))
#define REVw(Rd, Rn) EMIT(REV_gen(0, 0b10, Rn, Rd))
#define REV64x(Rd, Rn) EMIT(REV_gen(1, 0b11, Rn, Rd))
#define REV32w(Rd, Rn) EMIT(REV_gen(0, 0b10, Rn, Rd))
#define REVxw(Rd, Rn) EMIT(REV_gen(rex.w, 0b10|rex.w, Rn, Rd))
#define REV16w(Rd, Rn) EMIT(REV_gen(0, 0b01, Rn, Rd))
#define REV16x(Rd, Rn) EMIT(REV_gen(1, 0b01, Rn, Rd))
// MRS
#define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
@@ -992,6 +1000,11 @@
#define FMULS(Sd, Sn, Sm) EMIT(FMUL_scalar(0b00, Sm, Sn, Sd))
#define FMULD(Dd, Dn, Dm) EMIT(FMUL_scalar(0b01, Dm, Dn, Dd))
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMLAS(Sd, Sn, Sm) EMIT(FMLA_vector(0, 0, 0, Sm, Sn, Sd))
#define VFMLAQS(Sd, Sn, Sm) EMIT(FMLA_vector(1, 0, 0, Sm, Sn, Sd))
#define CFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
// DIV
#define FDIV_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFDIVS(Sd, Sn, Sm) EMIT(FDIV_vector(0, 0, Sm, Sn, Sd))
@@ -1419,6 +1432,25 @@
#define VCHIQQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b10, 0, Rm, Rn, Rd))
#define VCHIQQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b11, 0, Rm, Rn, Rd))
// Less Than 0
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
#define CMLT_0_16(Rd, Rn) EMIT(CMLT_0_vector(0, 0b01, Rn, Rd))
#define CMLT_0_32(Rd, Rn) EMIT(CMLT_0_vector(0, 0b10, Rn, Rd))
#define CMLTQ_0_8(Rd, Rn) EMIT(CMLT_0_vector(1, 0b00, Rn, Rd))
#define CMLTQ_0_16(Rd, Rn) EMIT(CMLT_0_vector(1, 0b01, Rn, Rd))
#define CMLTQ_0_32(Rd, Rn) EMIT(CMLT_0_vector(1, 0b10, Rn, Rd))
#define CMLTQ_0_64(Rd, Rn) EMIT(CMLT_0_vector(1, 0b11, Rn, Rd))
// Equal 0
#define CMEQ_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b0100<<13 | 1<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMEQ_0_8(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b00, Rn, Rd))
#define CMEQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b01, Rn, Rd))
#define CMEQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(0, 0b10, Rn, Rd))
#define CMEQQ_0_8(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b00, Rn, Rd))
#define CMEQQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b01, Rn, Rd))
#define CMEQQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b10, Rn, Rd))
#define CMEQQ_0_64(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b11, Rn, Rd))
// Vector Float CMP
// EQual
#define FCMP_vector(Q, U, E, sz, Rm, ac, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (E)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b1110<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1698,4 +1730,13 @@
#define SQDMULHQ_16(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SQDMULHQ_32(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b10, Vm, Vn, Vd))
// AES extensions
#define AES_gen(D, Rn, Rd) (0b01001110<<24 | 0b00<<22 | 0b10100<<17 | 0b0010<<13 | (D)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define AESD(Vd, Vn) EMIT(AES_gen(1, Vn, Vd))
#define AESE(Vd, Vn) EMIT(AES_gen(0, Vn, Vd))
#define AESMC_gen(D, Rn, Rd) (0b01001110<<24 | 0b00<<22 | 0b10100<<17 | 0b0011<<13 | (D)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define AESIMC(Vd, Vn) EMIT(AESMC_gen(1, Vn, Vd))
#define AESMC(Vd, Vn) EMIT(AESMC_gen(0, Vn, Vd))
#endif //__ARM64_EMITTER_H__
+22 -3
View File
@@ -21,6 +21,7 @@
arm64_lock_read_b:
dmb ish
// address is x0, return is x0
ldaxrb w0, [x0]
ret
@@ -29,9 +30,11 @@ arm64_lock_write_b:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrb w0, w1, [x2]
dmb ish
ret
arm64_lock_read_h:
dmb ish
// address is x0, return is x0
ldaxrh w0, [x0]
ret
@@ -40,9 +43,11 @@ arm64_lock_write_h:
// address is x0, value is x1, return is x0
mov x2, x0
stlxrh w0, w1, [x2]
dmb ish
ret
arm64_lock_read_d:
dmb ish
// address is x0, return is x0
ldaxr w0, [x0]
ret
@@ -51,9 +56,11 @@ arm64_lock_write_d:
// address is x0, value is w1, return is x0
mov x2, x0
stlxr w0, w1, [x2]
dmb ish
ret
arm64_lock_read_dd:
dmb ish
// address is x0, return is x0
ldaxr x0, [x0]
ret
@@ -62,9 +69,11 @@ arm64_lock_write_dd:
// address is x0, value is x1, return is x0
mov x2, x0
stlxr w0, x1, [x2]
dmb ish
ret
arm64_lock_read_dq:
dmb ish
// address is r2, return is r0, r1
ldaxp x4, x3, [x2]
str x4, [x0]
@@ -76,37 +85,47 @@ arm64_lock_write_dq:
// r0 needs to be aligned
stlxp w3, x0, x1, [x2]
mov w0, w3
dmb ish
ret
arm64_lock_xchg:
dmb ish
arm64_lock_xchg_0:
// address is x0, value is x1, return old value in x0
ldaxr x2, [x0]
stlxr w3, x1, [x0]
cbnz w3, arm64_lock_xchg
cbnz w3, arm64_lock_xchg_0
dmb ish
mov x0, x2
ret
arm64_lock_storeifnull:
dmb ish
arm64_lock_storeifnull_0:
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
ldaxr x2, [x0]
cbnz x2, arm64_lock_storeifnull_exit
mov x2, x1
stlxr w3, x2, [x0]
cbnz w3, arm64_lock_storeifnull
cbnz w3, arm64_lock_storeifnull_0
arm64_lock_storeifnull_exit:
dmb ish
mov x0, x2
ret
arm64_lock_storeifref:
dmb ish
arm64_lock_storeifref_0:
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
ldaxr x3, [x0]
cmp x2, x3
bne arm64_lock_storeifref_exit
stlxr w4, x1, [x0]
cbnz w4, arm64_lock_storeifref
cbnz w4, arm64_lock_storeifref_0
mov x0, x1
ret
arm64_lock_storeifref_exit:
dmb ish
mov x0, x3
ret
+3 -2
View File
@@ -18,9 +18,10 @@ arm64_next:
stp x12, x13, [sp, (8 * 4)]
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
str x18, [sp, (8 * 10)]
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
mov x2, lr // "from" is in lr, so put in x2
add x3, sp, 8*11 // x3 is address to change rip
// call the function
bl LinkNext
// preserve return value
@@ -31,7 +32,7 @@ arm64_next:
ldp x12, x13, [sp, (8 * 4)]
ldp x14, x15, [sp, (8 * 6)]
ldp x16, x17, [sp, (8 * 8)]
ldr x18, [sp, (8 * 10)]
ldp x18, x27, [sp, (8 * 10)]
add sp, sp, (8 * 12)
// return offset is jump address
br x3
+9
View File
@@ -1312,6 +1312,15 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// AES
if(isMask(opcode, "0100111000101000010f10nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "AES%c V%d.16B, V%d.16B", sf?'D':'E', Rd, Rn);
return buff;
}
if(isMask(opcode, "0100111000101000011f10nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "AES%sMC V%d.16B, V%d.16B", sf?"I":"", Rd, Rn);
return buff;
}
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
+169 -58
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include "debug.h"
#include "box64context.h"
@@ -47,6 +48,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
ret->minstart = text;
ret->maxend = text+textsz-1;
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
@@ -55,12 +58,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 x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, 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 x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->parent, 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 +81,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*)arm64_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 +106,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], 1);
}
free((*dynablocks)->direct);
}
@@ -116,7 +123,8 @@ 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)
dynarec_log(LOG_DEBUG, "MarkDynablock %p with %d son(s) %p-%p\n", db, db->sons_size, db->x64_addr, db->x64_addr+db->x64_size-1);
db->need_test = 1;
setJumpTableDefault64(db->x64_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault64(db->sons[i]->x64_addr);
@@ -145,24 +153,19 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
// Mark will try to find *any* blocks that intersect the range to mark
if(!dynablocks)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz -1;
uintptr_t start = addr;
uintptr_t end = addr+size-1;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
uintptr_t sizedb = dynablocks->textsz;
dynablock_t *db;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if((db=dynablocks->direct[i-startdb]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
dynarec_log(LOG_DEBUG, "MarkDirectDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)startdb, (void*)sizedb);
for(uintptr_t i = 0; i<sizedb; ++i)
if((db=dynablocks->direct[i]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
}
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
@@ -198,7 +201,7 @@ int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t si
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
FreeDynablock(db, 1);
);
kh_destroy(dynablocks, blocks);
// check emptyness
@@ -213,13 +216,14 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
{
if(!dynablocks)
return;
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p\n", (void*)addr, (void*)addr+size-1);
if(dynablocks->direct) {
uintptr_t new_addr = addr - dynablocks->maxsz;
uintptr_t new_size = size + dynablocks->maxsz;
MarkDirectDynablock(dynablocks, new_addr, new_size);
uintptr_t new_addr = dynablocks->minstart;
uintptr_t new_size = dynablocks->maxend - new_addr + 1;
MarkDirectDynablock(dynablocks, addr, size);
// the blocks check before
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
MarkDirectDynablock(getDB(idx), addr, size);
}
}
@@ -267,6 +271,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(arm64_lock_storeifnull(&dynablocks->direct, p)!=p)
@@ -281,20 +286,30 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
pthread_mutex_unlock(&my_context->mutex_dyndump);
free(block);
*created = 0;
return tmp;
}
*created = 1;
pthread_mutex_lock(&my_context->mutex_dyndump);
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(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
static dynablock_t* internalDBGetBlock(x64emu_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;
@@ -323,15 +338,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
if(!created)
return block; // existing block...
#if 0
if(box64_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
#endif
// fill the block
block->x64_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 = FillBlock64(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*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
@@ -342,24 +361,20 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
free(block);
block = NULL;
}
#if 0
if(box64_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
// check size
if(block && block->x64_size) {
if(dynablocks->minstart>addr)
dynablocks->minstart = addr;
int blocksz = block->x64_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
if(dynablocks->maxend<addr+blocksz) {
dynablocks->maxend = addr+blocksz;
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz-1)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
dblist->maxsz = blocksz;
if(dblist->minstart>addr)
dblist->minstart = addr;
}
}
lockDB();
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
// fill-in jumptable
addJumpTableIfDefault64(block->x64_addr, block->block);
for(int i=0; i<block->sons_size; ++i) {
@@ -367,39 +382,133 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
block->sons[i]->done = 1;
}
block->done = 1;
unlockDB();
}
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", GetTID(), created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
return block;
}
#define MAX_HOTPAGE 64
#define HOTPAGE_STEP 64
static int volatile hotpage_count[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage_size[MAX_HOTPAGE] = {0};
static volatile int hotpages = 0;
int IsInHotPage(uintptr_t addr) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if((hotpage_count[i]>0) && (addr>=hotpage[i]) && (addr<hotpage[i]+0x1000*(hotpage_size[i]+1))) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
return 1;
}
}
return 0;
}
int AreaInHotPage(uintptr_t start, uintptr_t end) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(hotpage_count[i]>0)
if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
return 1;
}
}
return 0;
}
void AddHotPage(uintptr_t addr) {
addr&=~0xfff;
// look for same address
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(addr>=hotpage[i] && addr<hotpage[i]+0x1000*(hotpage_size[i]+1)) {
if(!hotpage_count[i])
++hotpages;
hotpage_count[i] = HOTPAGE_STEP;
return;
}
if(addr==hotpage[i]+0x1000*(hotpage_size[i]+1)) {
++hotpage_size[i];
hotpage_count[i] = HOTPAGE_STEP;
return;
}
if(addr+0x1000==hotpage[i]) {
++hotpage_size[i];
hotpage[i] = addr;
hotpage_count[i] = HOTPAGE_STEP;
return;
}
}
// look for empty spot / minium
int mincnt = hotpage_count[0];
int minidx = 0;
for(int i=1; i<MAX_HOTPAGE; ++i)
if(hotpage_count[i]<mincnt) {
mincnt = hotpage_count[i];
minidx = i;
}
if(hotpage_count[minidx]) {
dynarec_log(LOG_NONE, "Warning, not enough Hotpage, replacing %p(%p/%d) with %p\n", (void*)hotpage[minidx], (void*)(0x1000*(hotpage_size[minidx]+1)), hotpage_count[minidx], (void*)addr);
hotpage_size[minidx] = 0;
} else
++hotpages;
hotpage[minidx] = addr;
hotpage_count[minidx] = HOTPAGE_STEP;
}
dynablock_t* DBGetBlock(x64emu_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)) {
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) with %d son(s) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->sons_size, (void*)addr);
return NULL;
}
dynablock_t *father = db->father?db->father:db;
if(AreaInHotPage((uintptr_t)father->x64_addr, (uintptr_t)father->x64_addr + father->x64_size - 1)) {
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with %d son(s) for %p because it's in a hotpage\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->sons_size, (void*)addr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
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->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr)
if(*current && IntervalIntersects(
(uintptr_t)father->x64_addr,
(uintptr_t)father->x64_addr+father->x64_size-1,
(uintptr_t)(*current)->x64_addr,
(uintptr_t)(*current)->x64_addr+(*current)->x64_size-1))
*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;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->hash, father->sons_size, (void*)addr);
protectDB((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
@@ -408,26 +517,28 @@ dynablock_t* DBAlternateBlock(x64emu_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->x64_addr, father->x64_size);
if(hash!=father->hash) {
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_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;
lockDB();
protectDBnolock((uintptr_t)father->x64_addr, father->x64_size);
protectDB((uintptr_t)father->x64_addr, father->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
unlockDB();
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
+2 -1
View File
@@ -29,7 +29,8 @@ typedef struct dynablock_s {
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
int maxsz; // maxblock size (for this block or previous block)
uintptr_t maxend; // max address end for anyblock on this blocklist
uintptr_t minstart; // min start address for block overlapping this blocklist
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
+30 -12
View File
@@ -19,6 +19,7 @@
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#endif
#ifdef DYNAREC
@@ -32,7 +33,7 @@ void arm64_epilog_fast() EXPORTDYN;
#ifdef DYNAREC
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
{
#ifdef HAVE_TRACE
if(!addr) {
@@ -45,10 +46,22 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr); // set new address
R_RIP = addr; // but also new RIP!
*x3 = addr; // and the RIP in x27 register
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
}
if(!block) {
#ifdef HAVE_TRACE
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
#endif
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
}
}
if(!block->done) {
// not finished yet... leave linker
@@ -101,16 +114,17 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
while(!emu->quit) {
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
CHECK_FLAGS(emu);
@@ -118,6 +132,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -139,7 +154,8 @@ void DynaCall(x64emu_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_RBX = old_rbx;
R_RDI = old_rdi;
@@ -180,22 +196,24 @@ int DynaRun(x64emu_t* emu)
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);;
current = block;
while(!emu->quit) {
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
// block is here, let's run it!
#ifdef ARM64
arm64_prolog(emu, block->block);
#endif
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
+66 -20
View File
@@ -58,13 +58,15 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha
}
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(!box64_dynarec_bigblock)
return;
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
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) {
@@ -333,28 +335,64 @@ 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 CancelBlock64()
{
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->table64);
free(helper->sons_x64);
free(helper->sons_arm);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
}
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
block->done = 1;
return (void*)block;
}
// protect the 1st page
protectDB(addr, 1);
// 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_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_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;
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64();
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
// already protect the block and compute hash signature
protectDB(addr, end-addr); //end is 1byte after actual end
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
CancelBlock64();
return NULL;
}
// protect the block of it goes over the 1st page
if((addr&~0xfff)!=(end&~0xfff)) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// pass 1, addresses, x64 jump addresses, flags
arm_pass1(&helper, addr);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
@@ -373,6 +411,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
helper.insts[i].x64.jmp_insts = k;
}
}
// pass 1, flags
arm_pass1(&helper, addr);
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.set_flags && !helper.insts[i].x64.need_flags) {
helper.insts[i].x64.need_flags = needed_flags(&helper, i+1, helper.insts[i].x64.set_flags, 0);
@@ -386,10 +426,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
free(helper.table64);
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock64();
return NULL;
}
helper.block = p;
@@ -443,8 +481,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
// ok, free the helper now
free(helper.insts);
free(helper.next);
helper.insts = NULL;
free(helper.table64);
helper.table64 = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
@@ -453,13 +492,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
block->x64_size = end-start;
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abbort if it as
if(block->hash != hash) {
if((block->hash != hash)) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
free(helper.sons_x64);
free(helper.sons_arm);
FreeDynarecMap(block, (uintptr_t)p, sz);
CancelBlock64();
return NULL;
} // fill sons if any
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_INFO, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
CancelBlock64();
return NULL;
//protectDB(addr, end-addr);
}
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
@@ -488,7 +531,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
free(sons);
}
free(helper.sons_x64);
helper.sons_x64 = NULL;
free(helper.sons_arm);
helper.sons_arm = NULL;
current_helper = NULL;
//block->done = 1;
return (void*)block;
}
+118 -73
View File
@@ -422,6 +422,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i64 = F32S;
emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x36:
INST_NAME("SS:");
break;
case 0x38:
INST_NAME("CMP Eb, Gb");
@@ -636,17 +639,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BARRIER(2); \
JUMP(addr+i8);\
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
}
GOCOND(0x70, "J", "ib");
@@ -843,6 +844,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gb1, x1, gb2*8, 8);
BFIx(eb1, x4, eb2*8, 8);
} else {
DMB_ISH();
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
@@ -851,6 +853,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// do the swap 14 -> strb(ed), 1 -> gd
STLXRB(x3, x4, ed);
CBNZx_MARKLOCK(x3);
DMB_ISH();
BFIx(gb1, x1, gb2*8, 8);
}
break;
@@ -866,6 +869,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
DMB_ISH();
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
@@ -877,6 +881,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRxw_U12(x1, ed, 0);
STRxw_U12(gd, ed, 0);
MARK2;
DMB_ISH();
MOVxw_REG(gd, x1);
}
break;
@@ -950,6 +955,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = wback;
}
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(x4, wback, fixedaddress);
ed = x4;
@@ -960,14 +969,28 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
LDRxw_U12(gd, ed, fixedaddress);
}
break;
case 0x8C:
INST_NAME("MOV Ed, Seg");
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= seg
LDRH_U12(xRAX+(nextop&7)+(rex.b<<3), xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
STRH_U12(x3, ed, fixedaddress);
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop=F8;
@@ -985,6 +1008,24 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x8F:
INST_NAME("POP Ed");
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP1(xRAX+(nextop&7)+(rex.b<<3));
} else {
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
if(ed==xRSP) {
STRx_U12(x2, ed, fixedaddress);
} else {
// complicated to just allow a segfault that can be recovered correctly
SUBx_U12(xRSP, xRSP, 8);
STRx_U12(x2, ed, fixedaddress);
ADDx_U12(xRSP, xRSP, 8);
}
}
break;
case 0x90:
case 0x91:
case 0x92:
@@ -1357,49 +1398,61 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
case 6:
INST_NAME("SHL Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1, 1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
LSLw(ed, ed, u8);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl8);
if(u8) {
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
LSLw(ed, ed, u8);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl8);
} else {
NOP;
}
break;
case 5:
INST_NAME("SHR Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1, 1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
if(u8) {
LSRw(ed, ed, u8);
EBBACK;
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
if(u8) {
LSRw(ed, ed, u8);
EBBACK;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr8);
} else {
NOP;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr8);
break;
case 7:
INST_NAME("SAR Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETSEB(x1, 1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
if(u8) {
ASRw(ed, ed, u8);
EBBACK;
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF{
MOV32w(x4, u8); UFLAG_OP2(x4);
};
UFLAG_OP1(ed);
if(u8) {
ASRw(ed, ed, u8);
EBBACK;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar8);
} else {
NOP;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar8);
break;
}
break;
@@ -1914,7 +1967,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xDB:
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDC:
addr = dynarec64_DC(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDD:
addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
@@ -1925,17 +1980,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#define GO(Z) \
BARRIER(2); \
JUMP(addr+i8); \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
if(Z) {CBZx(xRCX, i32);} else {CBNZx(xRCX, i32);}; \
}
case 0xE0:
INST_NAME("LOOPNZ");
@@ -1974,12 +2027,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr-1));
#endif
}
#if STEP == 0
if(isNativeCall(dyn, addr+i32, NULL, NULL))
tmp = 3;
else
tmp = 0;
#elif STEP < 2
#if STEP < 2
if(isNativeCall(dyn, addr+i32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;
else
@@ -1997,7 +2045,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
sse_purge07cache(dyn, ninst, x3);
if(box64_log<2 && dyn->insts && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
if(box64_log<2 && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
//GETIP(ip+3+8+8); // read the 0xCC
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
POP1(xRIP); // pop the return address
@@ -2059,18 +2107,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = F8S;
}
JUMP(addr+i32);
if(dyn->insts) {
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
PASS2IF(dyn->insts[ninst].x64.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
if(tmp==4) {
NOP;
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size);
if(tmp==4) {
NOP;
} else {
B(tmp);
}
B(tmp);
}
}
*need_epilog = 0;
@@ -2339,8 +2385,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(dyn->insts &&
((ninst && dyn->insts[ninst-1].x64.set_flags)
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
+89 -20
View File
@@ -88,12 +88,42 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
#if 0//STEP == 3
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
case 0x01:
INST_NAME("FAKE xgetbv");
nextop = F8;
addr = fakeed(dyn, addr, ninst, nextop);
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
break;
case 0x05:
INST_NAME("SYSCALL");
GETIP(addr);
STORE_XEMU_CALL(xRIP);
CALL_S(x64Syscall, -1);
LOAD_XEMU_CALL(xRIP);
TABLE64(x3, addr); // expected return address
CMPSx_REG(xRIP, x3);
B_MARK(cNE);
LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit));
CBZw_NEXT(w1);
MARK;
LOAD_XEMU_REM();
jump_to_epilog(dyn, 0, xRIP, ninst);
break;
case 0x09:
INST_NAME("WBINVD");
break;
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
@@ -962,18 +992,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BARRIER(2); \
JUMP(addr+i32_);\
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
}
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
GOCOND(0x80, "J", "Id");
#undef GO
@@ -1307,11 +1335,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = x1;
}
u8 = F8;
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
u8&=(rex.w?0x3f:0x1f);
if(u8) {
LSRxw(x4, ed, u8);
} else {
MOVw_REG(x4, ed);
}
BFIw(xFlags, x4, F_CF, 1);
TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
@@ -1330,11 +1363,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = x1;
}
u8 = F8;
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
u8&=(rex.w?0x3f:0x1f);
if(u8) {
LSRxw(x4, ed, u8);
} else {
MOVw_REG(x4, ed);
}
BFIw(xFlags, x4, F_CF, 1);
TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction
//MOVW(x14, 1); // already 0x01
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
@@ -1353,10 +1391,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = x1;
}
u8 = F8;
LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));
u8&=(rex.w?0x3f:0x1f);
if(u8) {
LSRxw(x4, ed, u8);
} else {
MOVw_REG(x4, ed);
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
}
@@ -1496,7 +1539,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break; // not NaN
}
break;
case 0xC3:
INST_NAME("MOVNTI Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
}
break;
case 0xC4:
INST_NAME("PINSRW Gm,Ed,Ib");
nextop = F8;
@@ -1586,6 +1639,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMUL_16(q0, q0, q1);
break;
case 0xD7:
nextop = F8;
INST_NAME("PMOVMSKB Gd, Em");
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
GETEM(q0, 0);
GETGD;
TABLE64(x1, (uintptr_t)&mask_shift8);
VLDR64_U12(v0, x1, 0); // load shift
MOVI_8(v1, 0x80); // load mask
VAND(q1, v1, q0);
USHL_8(q1, q1, v0); // shift
UADDLV_8(q1, q1); // accumalte
VMOVBto(gd, q1, 0);
break;
case 0xD8:
INST_NAME("PSUBUSB Gm, Em");
nextop = F8;
+214 -1
View File
@@ -32,7 +32,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop;
uint8_t u8;
uint8_t gd, ed, eb1, eb2;
uint8_t wback, wb1, wb2;
uint8_t wback, wb1, wb2, wb;
int64_t i64, j64;
int v0;
int q0;
@@ -199,6 +199,20 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x39:
INST_NAME("CMP Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5);
break;
case 0x66:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x80:
nextop = F8;
grab_segdata(dyn, addr, ninst, x1, seg);
@@ -625,6 +639,205 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
INST_NAME("TEST Ed, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, 4);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
break;
case 2:
INST_NAME("NOT Ed");
GETEDO(x6, 4);
MVNxw_REG(ed, ed);
WBACKO(x6);
break;
case 3:
INST_NAME("NEG Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, 0);
emit_neg32(dyn, ninst, rex, ed, x3, x4);
WBACKO(x6);
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
GETEDO(x6, 0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
UMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
UMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
GETEDO(x6, 0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
SMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
SMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2);
GETEDO(x6, 0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
if(MODREG) {
MOVw_REG(x4, ed);
ed = x4;
}
UDIVx(x2, x3, ed);
MSUBx(x4, x2, ed, xRAX);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETEDO(x6, 0);
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETEDO(x6, 0);
CBZxw_MARK(xRDX);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(div64, -1);
B_NEXT_nocond;
MARK;
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2);
}
}
break;
case 7:
INST_NAME("IDIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2)
GETSEDOw(x6, 0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
SDIVx(x2, x3, wb);
MSUBx(x4, x2, wb, x3);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
GETEDO(x6, 0);
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETEDO(x6, 0);
CBZxw_MARK(xRDX);
MVNx_REG(x2, xRDX);
CBZxw_MARK(x2);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL((void*)idiv64, -1);
B_NEXT_nocond;
MARK;
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2)
}
}
break;
}
break;
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEDO(x6, 0);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
WBACKO(x6);
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEDO(x6, 0);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
WBACKO(x6);
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
GETEDOx(x6, 0);
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst==dyn->size-1) {
*need_epilog = 0;
*ok = 0;
}
GETIP(addr);
PUSH1(xRIP);
jump_to_next(dyn, 0, ed, ninst);
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
BARRIER(1);
GETEDOx(x6, 0);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 6: // Push Ed
INST_NAME("PUSH Ed");
GETEDOx(x6, 0);
PUSH1(ed);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
+28 -13
View File
@@ -55,7 +55,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
if(rex.w && opcode!=0x0f) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
switch(opcode) {
case 0x01:
@@ -172,9 +172,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i16 = F16;
i16 = F16S;
UXTHw(x1, xRAX);
MOV32w(x2, i16);
MOVZw(x2, i16);
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
@@ -341,7 +341,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
@@ -350,7 +350,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -360,7 +360,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -370,7 +370,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -379,7 +379,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -388,7 +388,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -397,7 +397,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -407,7 +407,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x2, i16);
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
@@ -454,8 +454,23 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x90:
INST_NAME("NOP");
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
MOVw_REG(x2, xRAX);
BFIx(xRAX, gd, 0, 16);
BFIx(gd, x2, 0, 16);
}
break;
case 0x98:
+327 -4
View File
@@ -66,7 +66,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
#if 0//STEP > 1
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
@@ -256,6 +256,51 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SQXTN2_16(q0, v0);
break;
case 0x08:
INST_NAME("PSIGNB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v1 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn);
NEGQ_8(v0, q0); // get NEG
CMLTQ_0_8(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
CMEQQ_0_8(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x09:
INST_NAME("PSIGNW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v1 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn);
NEGQ_16(v0, q0); // get NEG
CMLTQ_0_16(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
CMEQQ_0_16(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0A:
INST_NAME("PSIGND Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v1 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn);
NEGQ_32(v0, q0); // get NEG
CMLTQ_0_32(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
CMEQQ_0_32(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0B:
INST_NAME("PMULHRSW Gx,Ex");
nextop = F8;
@@ -264,6 +309,31 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SQRDMULHQ_16(q0, q0, q1);
break;
case 0x1C:
INST_NAME("PABSB Gx,Ex");
nextop = F8;
GETEX(q1, 0);
GETG;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
ABSQ_8(q0, q1);
break;
case 0x1D:
INST_NAME("PABSW Gx,Ex");
nextop = F8;
GETEX(q1, 0);
GETG;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
ABSQ_16(q0, q1);
break;
case 0x1E:
INST_NAME("PABSD Gx,Ex");
nextop = F8;
GETEX(q1, 0);
GETG;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
ABSQ_32(q0, q1);
break;
case 0x20:
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
nextop = F8;
@@ -311,6 +381,123 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SXTL_32(q0, q1); // 32bits->64bits
break;
case 0x39:
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0);
SMINQ_32(q0, q0, q1);
break;
case 0x3D:
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0);
SMAXQ_32(q0, q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
if(arm64_aes) {
GETEX(q1, 0);
GETGX_empty(q0);
AESIMC(q0, q1);
} else {
GETEX(q1, 0);
GETGX_empty(q0);
if(q0!=q1) {
VMOVQ(q0, q1);
}
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(arm_aesimc, -1);
}
break;
case 0xDC:
INST_NAME("AESENC Gx, Ex"); // AES-NI
nextop = F8;
if(arm64_aes) {
GETEX(q1, 0);
GETGX(q0);
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
AESMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(arm_aese, -1);
GETGX(q0);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDD:
INST_NAME("AESENCLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm64_aes) {
GETEX(q1, 0);
GETGX(q0);
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(arm_aeselast, -1);
GETGX(q0);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDE:
INST_NAME("AESDEC Gx, Ex"); // AES-NI
nextop = F8;
if(arm64_aes) {
GETEX(q1, 0);
GETGX(q0);
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
AESIMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(arm_aesd, -1);
GETGX(q0);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDF:
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm64_aes) {
GETEX(q1, 0);
GETGX(q0);
v0 = fpu_get_scratch(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(arm_aesdlast, -1);
GETGX(q0);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
default:
DEFAULT;
}
@@ -354,6 +541,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VEXTQ_8(q0, q1, q0, u8);
}
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
nextop = F8;
GETGX(q0);
GETED(1);
u8 = F8;
if(rex.w) {
VMOVQDfrom(q0, (u8&1), ed);
} else {
VMOVQSfrom(q0, (u8&3), ed);
}
break;
default:
DEFAULT;
}
@@ -377,6 +578,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GOCOND(0x40, "CMOV", "Gw, Ew");
#undef GO
case 0x50:
nextop = F8;
INST_NAME("PMOVMSKD Gd, Ex");
GETEX(q0, 0);
GETGD;
VMOVQDto(x1, q0, 1);
VMOVQDto(gd, q0, 0);
LSRx(x1, x1, 63);
LSRx(gd, gd, 63);
BFIx(gd, x1, 1, 1);
break;
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
@@ -465,7 +678,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
VFMINQD(v0, v0, q0);
break;
case 0x5E:
INST_NAME("DIVPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFDIVQD(v0, v0, q0);
break;
case 0x5F:
INST_NAME("MAXPD Gx, Ex");
nextop = F8;
@@ -1090,6 +1309,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
BFIx(gd, x1, 0, 16); // insert in Gw
break;
case 0xB7:
INST_NAME("MOVZX Gw, Ew");
nextop = F8;
if(MODREG) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
UBFXxw(x1, eb1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff>>1, 1, rex, 0, 0);
LDRH_U12(x1, ed, fixedaddress);
}
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
BFIx(gd, x1, 0, 16); // insert in Gw
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
@@ -1175,6 +1408,38 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16);
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
switch(u8&7) {
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
case 0: FCMEQQD(v0, v0, v1); break; // Equal
case 1: FCMGTQD(v0, v1, v0); break; // Less than
case 2: FCMGEQD(v0, v1, v0); break; // Less or equal
case 3: FCMEQQD(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
FCMEQQD(q0, v1, v1);
VANDQ(v0, v0, q0);
}
VMVNQ(v0, v0);
break; // NaN (NaN is not equal to himself)
case 4: FCMEQQD(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: FCMGTQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 6: FCMGEQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
case 7: FCMEQQD(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
FCMEQQD(q0, v1, v1);
VANDQ(v0, v0, q0);
}
break; // not NaN
}
break;
case 0xC4:
INST_NAME("PINSRW Gx,Ed,Ib");
nextop = F8;
@@ -1224,7 +1489,37 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* BSWAP reg */
INST_NAME("BSWAP Reg");
gd = xRAX+(opcode&7)+(rex.b<<3);
if(rex.w) {
REV64x(gd, gd);
} else {
REV16w(x1, gd);
BFIx(gd, x1, 0, 16);
}
break;
case 0xD2:
INST_NAME("PSRLD Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
SQSHRN_32(v0, q1, 0); // S64x1->S32x1
VMOVeS(v0, 1, v0, 0); // S32x1->S32x2
NEG_32(v0, v0); // neg, because SHR
VMOVeD(v0, 1, v0, 0); // S32x2->S32x4
USHLQ_32(q0, q0, v0); // SHR x4
break;
case 0xD3:
INST_NAME("PSRLQ Gx,Ex");
nextop = F8;
@@ -1262,7 +1557,29 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0xD7:
nextop = F8;
INST_NAME("PMOVMSKB Gd, Ex");
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
GETEX(q0, 0);
GETGD;
TABLE64(x1, (uintptr_t)&mask_shift8);
VLDR64_U12(v0, x1, 0); // load shift
MOVI_8(v1, 0x80); // load mask
VAND(q1, v1, q0);
USHL_8(q1, q1, v0); // shift
UADDLV_8(q1, q1); // accumalte
VMOVBto(gd, q1, 0);
// and now the high part
VMOVeD(q1, 0, q0, 1);
VAND(q1, v1, q1); // keep highest bit
USHL_8(q1, q1, v0); // shift
UADDLV_8(q1, q1); // accumalte
VMOVBto(x1, q1, 0);
BFIx(gd, x1, 8, 8);
break;
case 0xD8:
INST_NAME("PSUBUSB Gx, Ex");
nextop = F8;
@@ -1443,7 +1760,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q0, 0);
SQADDQ_16(v0, v0, q0);
break;
case 0xEE:
INST_NAME("PMAXSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SMAXQ_16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
nextop = F8;
+50 -1
View File
@@ -22,6 +22,7 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
@@ -30,6 +31,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int v0, v1;
int64_t fixedaddress;
// REX prefix before the 66 are ignored
@@ -46,10 +48,56 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch(opcode) {
case 0x0F:
opcode = F8;
switch(opcode) {
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, _FS);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VSTR64_REG(v0, ed, x4);
}
break;
default:
DEFAULT;
}
break;
case 0x89:
INST_NAME("MOV FS:Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(rex.w) {
MOVx_REG(ed, gd);
} else {
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
}
} else {
grab_segdata(dyn, addr, ninst, x4, _FS);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
if(rex.w) {
STRx_REG(gd, ed, x4);
} else {
STRH_REG(gd, ed, x4);
}
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
@@ -62,6 +110,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, _FS);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
if(rex.w) {
LDRx_REG(gd, ed, x4);
+278 -14
View File
@@ -26,21 +26,29 @@
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
a = mmx_get_reg(dyn, ninst, x1, gd)
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t gd, ed, wback, wb;
int64_t fixedaddress;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64;
int v0, s0;
int64_t j64, i64;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
// REX prefix before the 67 are ignored
@@ -83,11 +91,51 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x6F:
INST_NAME("MOVQ Gm, Em");
nextop = F8;
GETGm;
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7); // no rex.b on MMX
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, v1, 0);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
case 0x7F:
INST_NAME("MOVQ Em, Gm");
nextop = F8;
GETGM(v0);
if(MODREG) {
v1 = mmx_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOV(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop=F8;
@@ -103,20 +151,91 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 2:
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);
WBACK;
break;
case 3:
INST_NAME("RCR Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);
WBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
break;
case 5:
INST_NAME("SHR Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) {
WBACK;
}
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) {
WBACK;
}
break;
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
if(dyn->insts) { \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
} \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->arm_size); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (32bits)");
@@ -157,6 +276,151 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
#undef GO
case 0xE8:
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
INST_NAME("TEST Ed, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32H(x1, 4);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, ed, x2, x3, x4);
break;
case 2:
INST_NAME("NOT Ed");
GETED32(4);
MVNxw_REG(ed, ed);
WBACK;
break;
case 3:
INST_NAME("NEG Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32(0);
emit_neg32(dyn, ninst, rex, ed, x3, x4);
WBACK;
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
UMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
UMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
SMULH(gd, xRAX, ed);
MULx(xRAX, xRAX, ed);
if(gd!=xRDX) {MOVx_REG(xRDX, gd);}
} else {
SMULL(xRDX, xRAX, ed); //64 <- 32x32
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2);
GETED32(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
if(MODREG) {
MOVw_REG(x4, ed);
ed = x4;
}
UDIVx(x2, x3, ed);
MSUBx(x4, x2, ed, xRAX);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETED32(0);
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
CBZxw_MARK(xRDX);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(div64, -1);
B_NEXT_nocond;
MARK;
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2);
}
}
break;
case 7:
INST_NAME("IDIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2)
GETSED32w(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
SDIVx(x2, x3, wb);
MSUBx(x4, x2, wb, x3);
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
GETED32(0);
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETED32H(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
CBZxw_MARK(xRDX);
MVNx_REG(x2, xRDX);
CBZxw_MARK(x2);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL((void*)idiv64, -1);
B_NEXT_nocond;
MARK;
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2)
}
}
break;
}
break;
default:
DEFAULT;
}
+1
View File
@@ -117,6 +117,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xE3:
INST_NAME("FNINIT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_purgecache(dyn, ninst, x1, x2, x3);
CALL(reset_fpu, -1);
break;
+219
View File
@@ -0,0 +1,219 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
int64_t fixedaddress;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
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);
FADDD(v1, v1, v2);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
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);
FMULD(v1, v1, v2);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
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);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
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);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
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);
FSUBD(v1, v2, v1);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
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);
FSUBD(v1, v1, v2);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
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);
FDIVD(v1, v2, v1);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
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);
FDIVD(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);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
break;
}
}
return addr;
}
+1
View File
@@ -285,6 +285,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst);
break;
default:
DEFAULT;
+16 -10
View File
@@ -206,8 +206,10 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
return;
}
IFX(X_CF) {
LSRxw_REG(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
LSRxw(s1, s1, c);
IFX(X_PEND) {
@@ -252,8 +254,10 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
return;
}
IFX(X_CF) {
ASRxw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
if(c>1) {
ASRxw(s3, s1, c-1);
}
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
ASRxw(s1, s1, c);
IFX(X_PEND) {
@@ -359,11 +363,13 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
return;
}
IFX(X_CF) {
LSRxw_REG(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, (c>1)?s3:s1, 0, 1);
}
LSRxw(s1, s1, c);
ORRxw_REG_LSL(s1, s1, s2, (rex.w?64:32)-c);
LSRxw(s3, s1, c);
ORRxw_REG_LSL(s1, s3, s2, (rex.w?64:32)-c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -413,8 +419,8 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int3
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
}
LSLxw(s1, s1, c);
ORRxw_REG_LSR(s1, s1, s2, (rex.w?64:32)-c);
LSLxw(s3, s1, c);
ORRxw_REG_LSR(s1, s3, s2, (rex.w?64:32)-c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
+1 -1
View File
@@ -296,7 +296,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
ANDw_mask(s3, s3, 0b011011, 000010); // 0xE0
ANDw_mask(s3, s3, 0b011011, 0b000010); // 0xE0
LSRw(s3, s3, 5);
MOV64x(s4, (uintptr_t)GetParityTab());
LDRw_REG_LSL2(s4, s4, s3);
+206 -1
View File
@@ -29,7 +29,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
@@ -56,6 +56,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
@@ -77,12 +78,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRB(x4, x1, wback);
CBNZx_MARKLOCK(x4);
}
DMB_ISH();
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -94,6 +97,27 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x0F:
@@ -105,6 +129,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
@@ -145,6 +170,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
}
DMB_ISH();
break;
case 0xC1:
@@ -152,6 +178,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
MOVxw_REG(x1, ed);
@@ -183,6 +210,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
MOVxw_REG(gd, x1);
}
DMB_ISH();
break;
case 0xC7:
@@ -190,6 +218,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
DMB_ISH();
MARKLOCK;
LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2);
@@ -205,6 +234,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRDX, x3);
MOV32w(x1, 0);
MARK3;
DMB_ISH();
BFIw(xFlags, x1, F_ZF, 1);
break;
@@ -218,6 +248,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -229,6 +260,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x66:
@@ -237,6 +269,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -430,15 +463,180 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
}
DMB_ISH();
break;
default:
DEFAULT;
}
break;
case 0x80:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_add8c(dyn, ninst, x1, u8, x2, x4);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 1: //OR
INST_NAME("OR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_or8c(dyn, ninst, x1, u8, x2, x4);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 2: //ADC
INST_NAME("ADC Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 3: //SBB
INST_NAME("SBB Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 4: //AND
INST_NAME("AND Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_and8c(dyn, ninst, x1, u8, x2, x4);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 5: //SUB
INST_NAME("SUB Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 6: //XOR
INST_NAME("XOR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
GETEB(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
LDAXRB(x1, wback);
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
EBBACK;
break;
case 7: //CMP
INST_NAME("CMP Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
if(u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
default:
DEFAULT;
}
DMB_ISH();
break;
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -615,6 +813,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
}
DMB_ISH();
break;
case 0x87:
@@ -628,6 +827,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(ed, x1);
} else {
GETGD;
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -640,6 +840,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRxw_U12(x1, ed, 0);
STRxw_U12(gd, ed, 0);
MARK2;
DMB_ISH();
MOVxw_REG(gd, x1);
}
break;
@@ -651,6 +852,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0: // INC Ed
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
@@ -673,10 +875,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
DMB_ISH();
break;
case 1: //DEC Ed
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
@@ -699,6 +903,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
DMB_ISH();
break;
default:
DEFAULT;
+43 -11
View File
@@ -49,7 +49,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t gd, ed;
uint8_t wback;
uint8_t u8;
uint64_t u64;
uint64_t u64, j64;
int v0, v1;
int q0;
int d0, d1;
@@ -214,9 +214,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cLS); //Less than or equal
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x5E:
INST_NAME("DIVSD Gx, Ex");
@@ -234,9 +240,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cGE); //Greater than or equal
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x70:
@@ -282,25 +294,45 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPD(v1, v0);
} else {
FCMPD(v0, v1);
}
FCMPD(v0, v1);
switch(u8&7) {
case 0: CSETMx(x2, cEQ); break; // Equal
case 1: CSETMx(x2, cMI); break; // Less than
case 2: //CSETMx(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
CSETMx(x2, cPL); CSINVx(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
case 1: CSETMx(x2, cCC); break; // Less than
case 2: CSETMx(x2, cLS); break; // Less or equal
case 3: CSETMx(x2, cVS); break; // NaN
case 4: CSETMx(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: CSETMx(x2, cNE); break; // Not Equal or unordered
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMx(x2, cVC); break; // not NaN
}
VMOVQDfrom(v0, 0, x2);
break;
case 0xD0:
INST_NAME("ADDSUBPS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
q0 = fpu_get_scratch(dyn);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
TABLE64(x2, (uintptr_t)&addsubps);
VLDR128_U12(q0, x2, 0);
VFMLAQS(v0, v1, q0);
break;
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXD(v0, v1);
x87_restoreround(dyn, ninst, u8);
VFCVTNSQD(v0, v0); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
break;
case 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
+45 -13
View File
@@ -184,17 +184,28 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x52:
INST_NAME("RSQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
FMOVS_8(d0, 0b01110000);
FSQRTS(v0, v1);
FDIVS(d0, d0, v0);
FSQRTS(d1, v1);
FDIVS(d0, d0, d1);
VMOVeS(v0, 0, d0, 0);
break;
case 0x53:
INST_NAME("RCPSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
d0 = fpu_get_scratch(dyn);
FMOVS_8(d0, 0b01110000); //1.0f
FDIVS(d0, d0, v1);
VMOVeS(v0, 0, d0, 0);
break;
@@ -248,9 +259,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 0);
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cLS); //Less than or equal
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
@@ -267,9 +284,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 0);
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cGE); //Greater than or equal
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x6F:
@@ -352,6 +375,20 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
break;
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
CLZxw(gd, x1); // x2 gets leading 0 == LZCNT
TSTxw_REG(gd, gd);
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex, Ib");
@@ -359,20 +396,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPS(v1, v0);
} else {
FCMPS(v0, v1);
}
FCMPS(v0, v1);
switch(u8&7) {
case 0: CSETMw(x2, cEQ); break; // Equal
case 1: CSETMw(x2, cMI); break; // Less than
case 2: //CSETMw(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
CSETMw(x2, cPL); CSINVw(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
case 1: CSETMw(x2, cCC); break; // Less than
case 2: CSETMw(x2, cLS); break; // Less or equal
case 3: CSETMw(x2, cVS); break; // NaN
case 4: CSETMw(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: CSETMw(x2, cNE); break; // Not Equal or unordered
case 5: CSETMw(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMw(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: CSETMw(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMw(x2, cVC); break; // not NaN
}
VMOVQSfrom(v0, 0, x2);
+134 -9
View File
@@ -25,10 +25,12 @@
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "custommem.h"
#include "bridge.h"
void arm_fstp(x64emu_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);
@@ -51,6 +53,7 @@ void arm_fyl2x(x64emu_t* emu)
void arm_ftan(x64emu_t* emu)
{
ST0.d = tan(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fpatan(x64emu_t* emu)
{
@@ -79,6 +82,7 @@ void arm_fyl2xp1(x64emu_t* emu)
void arm_fsincos(x64emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_frndint(x64emu_t* emu)
{
@@ -92,10 +96,12 @@ void arm_fscale(x64emu_t* emu)
void arm_fsin(x64emu_t* emu)
{
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fcos(x64emu_t* emu)
{
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fbld(x64emu_t* emu, uint8_t* ed)
@@ -108,8 +114,8 @@ void arm_fild64(x64emu_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(x64emu_t* emu, uint8_t* ed)
@@ -120,8 +126,8 @@ void arm_fbstp(x64emu_t* emu, uint8_t* ed)
void arm_fistp64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if((uint64_t)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))
@@ -143,7 +149,7 @@ void arm_fld(x64emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).ref = ST0.q;
STld(0).uref = ST0.q;
}
void arm_ud(x64emu_t* emu)
@@ -185,6 +191,125 @@ void arm_fprem1(x64emu_t* emu)
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void arm_aesimc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void arm_aesmc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void arm_aesdlast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
void arm_aeselast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void arm_aesd(x64emu_t* emu, int xmm)
{
arm_aesdlast(emu, xmm);
arm_aesimc(emu, xmm);
}
void arm_aese(x64emu_t* emu, int xmm)
{
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
#define XMM0 0
#define XMM8 16
#define X870 8
@@ -320,13 +445,13 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
if(!addr)
if(!addr || !getProtection(addr))
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = *(uintptr_t*)a1;
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(addr<0x10000) // too low, that is suspicious
if(!addr || !getProtection(addr))
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
+7
View File
@@ -29,6 +29,13 @@ void arm_fsave(x64emu_t* emu, uint8_t* ed);
void arm_frstor(x64emu_t* emu, uint8_t* ed);
void arm_fprem1(x64emu_t* emu);
void arm_aesd(x64emu_t* emu, int xmm);
void arm_aese(x64emu_t* emu, int xmm);
void arm_aesdlast(x64emu_t* emu, int xmm);
void arm_aeselast(x64emu_t* emu, int xmm);
void arm_aesimc(x64emu_t* emu, int xmm);
void arm_ud(x64emu_t* emu);
// Get an FPU scratch reg
+36 -13
View File
@@ -462,12 +462,20 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
MOVZw(x1, 0);
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
// POP EFLAGS
POP1(xFlags);
MOV32w(x1, 0x3F7FD7);
ANDx_REG(xFlags, xFlags, x1);
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0);
SET_DFNONE(x1);
// POP RSP
POP1(x3);
// POP SS
POP1(x2);
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS]));
// set new RSP
MOVx_REG(xRSP, x3);
// Ret....
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
BR(x2);
@@ -741,7 +749,7 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
if(ret!=0) {
// --- set values
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
// loop all cache entries
for (int i=0; i<8; ++i)
@@ -772,7 +780,7 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
if(!ret) // nothing to do
return;
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// loop all cache entries
@@ -806,7 +814,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// found, setup and grab the value
dyn->x87cache[ret] = st;
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a) {
@@ -851,7 +859,7 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
return;
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// Update
@@ -879,7 +887,7 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// Update
@@ -908,7 +916,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(dyn->x87cache[i]==st) {
// refresh the value
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a<0) {
@@ -932,7 +940,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// found, setup and grab the value
dyn->x87cache[ret] = st;
dyn->x87reg[ret] = fpu_get_reg_x87(dyn);
ADDx_U12(s1, xEmu, offsetof(x64emu_t, mmx87));
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->x87stack;
if(a<0) {
@@ -953,9 +961,9 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1); MAYUSE(s2);
LDRH_U12(s1, xEmu, offsetof(x64emu_t, cw));
RBITw(s2, s1); // round is on bits 10-11 on x86,
LSRw(s2, s2, 20); // but we want the reverse of that
LDRw_U12(s1, xEmu, offsetof(x64emu_t, round));
UBFXw(s2, s1, 1, 1); // bit 1 of round in bit 0 (zero extented) of s2
BFIw(s2, s1, 1, 1); // bit 0 of round in bit 1 of s2
MRS_fpcr(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
@@ -1006,7 +1014,7 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx87[a]));
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx[a]));
return ret;
#else
(void)dyn; (void)a;
@@ -1039,7 +1047,7 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
MESSAGE(LOG_DUMP, "\tPurge MMX Cache ------\n");
++old;
}
VSTR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
VSTR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
fpu_free_reg(dyn, dyn->mmxcache[i]);
dyn->mmxcache[i] = -1;
}
@@ -1057,7 +1065,7 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
#if STEP > 1
for (int i=0; i<8; ++i)
if(dyn->mmxcache[i]!=-1) {
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
}
#else
(void)dyn;
@@ -1106,6 +1114,21 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
return 0;
#endif
}
// forget neon register for a SSE reg, create the entry if needed
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a)
{
(void) ninst;
#if STEP > 1
if(dyn->ssecache[a]==-1)
return;
VSTR128_U12(dyn->ssecache[a], xEmu, offsetof(x64emu_t, xmm[a]));
fpu_free_reg(dyn, dyn->ssecache[a]);
dyn->ssecache[a] = -1;
#else
(void)dyn; (void)a;
#endif
return;
}
// purge the SSE cache for XMM0..XMM7 (to use before function native call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
{
+83 -26
View File
@@ -66,7 +66,25 @@
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
LDRw_U12(x1, wback, fixedaddress); \
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
#define GETED32(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSED32w(D) if((nextop&0xC0)==0xC0) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
@@ -78,8 +96,16 @@
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
#define GETED32H(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
#define GETEDW(hint, ret, D) if(MODREG) { \
#define GETEDW(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
MOVxw_REG(ret, ed); \
wback = 0; \
@@ -88,6 +114,15 @@
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
#define GETED32W(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress);}
// Write back ed in wback (if wback not 0)
@@ -106,6 +141,25 @@
ed = x1; \
}
#define WBACKO(O) if(wback) {STRxw_REG(ed, wback, O);}
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDOx(O, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
LDRx_REG(x1, wback, O); \
ed = x1; \
}
#define GETSEDOw(O, D) if((nextop&0xC0)==0xC0) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
LDRSW_REG(x1, wback, O); \
wb = ed = x1; \
}
//FAKEELike GETED, but doesn't get anything
#define FAKEED if(!MODREG) { \
addr = fakeed(dyn, addr, ninst, nextop); \
@@ -258,18 +312,18 @@
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
#define MARK dyn->insts[ninst].mark = dyn->arm_size
#define GETMARK dyn->insts[ninst].mark
#define MARK2 dyn->insts[ninst].mark2 = dyn->arm_size
#define GETMARK2 dyn->insts[ninst].mark2
#define MARK3 dyn->insts[ninst].mark3 = dyn->arm_size
#define GETMARK3 dyn->insts[ninst].mark3
#define MARKF dyn->insts[ninst].markf = dyn->arm_size
#define GETMARKF dyn->insts[ninst].markf
#define MARKSEG dyn->insts[ninst].markseg = dyn->arm_size
#define GETMARKSEG dyn->insts[ninst].markseg
#define MARKLOCK dyn->insts[ninst].marklock = dyn->arm_size
#define GETMARKLOCK dyn->insts[ninst].marklock
// Branch to MARK if cond (use j64)
#define B_MARK(cond) \
@@ -376,11 +430,11 @@
j64 = GETMARKLOCK-(dyn->arm_size); \
CBNZx(reg, j64)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
#define IFX(A) if((dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3) \
@@ -535,12 +589,12 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x64.need_flags)
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x64.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
@@ -725,6 +779,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_purge07cache STEPNAME(sse_purge07cache)
#define fpu_pushcache STEPNAME(fpu_pushcache)
@@ -865,6 +920,8 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a);
// 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);
// forget neon register for a SSE reg, create the entry if needed
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
// purge the XMM0..XMM7 cache (before function call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
@@ -893,7 +950,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+8 -4
View File
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box64context.h"
@@ -14,6 +15,7 @@
#include "box64stack.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynablock.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
@@ -45,7 +47,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INIT;
while(ok) {
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
if((dyn->insts[ninst].x64.barrier==1)) {
dyn->last_ip = 0;
NEW_BARRIER_INST;
}
@@ -90,17 +92,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INST_EPILOG;
if(dyn->insts && dyn->insts[ninst+1].x64.barrier) {
if(dyn->insts[ninst+1].x64.barrier) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(dyn->insts[ninst+1].x64.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
}
}
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
#if STEP == 0
if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM && !IsInHotPage(addr+3))
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 && (
@@ -113,6 +116,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
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));
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
+10 -2
View File
@@ -5,8 +5,16 @@
#define SETFLAGS(A, B)
#define READFLAGS(A)
#define EMIT(A)
#define JUMP(A) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define JUMP(A) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
#define NEW_INST \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_arm64_t*)realloc(dyn->insts, sizeof(instruction_arm64_t)*dyn->cap*2); \
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm64_t)*dyn->cap); \
dyn->cap *= 2; \
} \
++dyn->size
#define INST_EPILOG
#define INST_NAME(name)
#define DEFAULT \
+1 -4
View File
@@ -6,12 +6,9 @@
#define EMIT(A)
#define READFLAGS(A) dyn->insts[ninst].x64.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x64.set_flags = A; dyn->insts[ninst].x64.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x64.jmp = A
#define BARRIER(A) dyn->insts[ninst].x64.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x64.barrier = A
#define NEW_INST \
dyn->insts[ninst].x64.addr = ip; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;
#define INST_EPILOG
#define INST_EPILOG
#define INST_NAME(name)
+3 -1
View File
@@ -4,8 +4,9 @@
#include "dynarec_private.h"
typedef struct x64emu_s x64emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instruction_arm_s {
typedef struct instruction_arm64_s {
instruction_x64_t x64;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
@@ -50,6 +51,7 @@ typedef struct dynarec_arm_s {
uintptr_t* sons_x64; // the x64 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
dynablock_t* dynablock;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+81 -46
View File
@@ -124,7 +124,9 @@ int CalcLoadAddr(elfheader_t* head)
head->stackalign = head->PHEntries[i].p_align;
}
if(head->PHEntries[i].p_type == PT_TLS) {
head->tlsaddr = head->PHEntries[i].p_vaddr;
head->tlssize = head->PHEntries[i].p_memsz;
head->tlsfilesize = head->PHEntries[i].p_filesz;
head->tlsalign = head->PHEntries[i].p_align;
// force alignement...
if(head->tlsalign>1)
@@ -183,7 +185,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
start &= ~balign;
if( (head->e_type == ET_DYN) ||
(((bstart>=start) && (bstart<=end)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
(((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
{
// merge
ok = 1;
@@ -287,12 +289,20 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf64_Phdr * e = &head->PHEntries[i];
char* dest = (char*)e->p_paddr + head->delta;
printf_log(LOG_DEBUG, "Loading block #%zu @%p (0x%lx/0x%lx)\n", i, dest, e->p_filesz, e->p_memsz);
fseeko64(f, e->p_offset, SEEK_SET);
if(e->p_filesz) {
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%ld)\n", i, e->p_filesz);
return 1;
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%lx/0x%lx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
void* p = (void*)-1;
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
}
if(p!=dest) {
printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
fseeko64(f, e->p_offset, SEEK_SET);
if(e->p_filesz) {
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz);
return 1;
}
}
}
#ifdef DYNAREC
@@ -369,21 +379,24 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
int t = ELF64_R_TYPE(rel[i].r_info);
Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rel[i].r_info)];
const char* symname = SymName(h, sym);
int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2) && t==R_X86_64_COPY) {
*offs = sym->st_value + h->delta;
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
return 1;
if(t==R_X86_64_COPY && symname && !strcmp(symname, name)) {
int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
*offs = sym->st_value + h->delta;
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
return 1;
}
}
}
return 0;
}
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rel *rel)
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rel *rel)
{
int ret_ok = 0;
for (int i=0; i<cnt; ++i) {
int t = ELF64_R_TYPE(rel[i].r_info);
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rel[i].r_info)];
@@ -425,6 +438,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
case R_X86_64_PC32:
if (!offs) {
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_PC32 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
}
offs = (offs - (uintptr_t)p);
if(!offs)
@@ -434,12 +448,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
case R_X86_64_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
offs = sym->st_value;
end = offs + sym->st_size;
if(sym->st_size) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
}
@@ -451,7 +465,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
end = globend;
}
if (!offs) {
if(strcmp(symname, "__gmon_start__"))
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
@@ -493,6 +507,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
case R_X86_64_64:
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
// return -1;
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+*(uint64_t*)p));
@@ -533,7 +548,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
printf_log(LOG_INFO, "Warning, don't know how to handle rel #%d %s (%p)\n", i, DumpRelType(ELF64_R_TYPE(rel[i].r_info)), p);
}
}
return 0;
return bindnow?ret_ok:0;
}
struct tlsdesc
@@ -551,8 +566,9 @@ EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu)
}
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf64_Rela *rela, int* need_resolv)
{
int ret_ok = 0;
for (int i=0; i<cnt; ++i) {
int t = ELF64_R_TYPE(rela[i].r_info);
Elf64_Sym *sym = &head->DynSym[ELF64_R_SYM(rela[i].r_info)];
@@ -562,7 +578,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
elfheader_t* h_tls = head;
elfheader_t* h_tls = NULL;//head;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
@@ -642,7 +658,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
end = globend;
}
if (!offs) {
if(strcmp(symname, "__gmon_start__"))
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
@@ -659,12 +675,14 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
|| !tmp
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
|| !need_resolv
|| bindnow
) {
if (!offs) {
if(bind==STB_WEAK) {
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_JUMP_SLOT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
}
// return -1;
} else {
@@ -686,6 +704,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
case R_X86_64_64:
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
// return -1;
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_64 @%p with sym=%s (ver=%d/%s) addend=0x%lx (%p -> %p)\n",
@@ -696,9 +715,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
case R_X86_64_TPOFF64:
// Negated offset in static TLS block
{
if(h_tls)
if(!symname || !symname[0]) {
h_tls = head;
offs = sym->st_value;
else {
} else {
h_tls = NULL;
if(local_maplib)
h_tls = GetGlobalSymbolElf(local_maplib, symname, version, vername);
if(!h_tls)
@@ -706,7 +727,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
}
if(h_tls) {
delta = *(int64_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%ld -> %ld+%ld+%ld, size=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int64_t)offs, rela[i].r_addend, end-offs);
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs);
@@ -727,7 +748,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
offs = getElfIndex(my_context, h_tls);
}
if(p) {
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", "R_X86_64_DTPMOD64", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s %s @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", "R_X86_64_DTPMOD64", p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_X86_64_DTPMOD64 Slot Offset is NULL \n", symname);
@@ -743,7 +764,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
}
// return -1;
} else {
if(h_tls)
if(!symname || symname[0]=='\0' || bind==STB_LOCAL)
offs = sym->st_value;
if(p) {
int64_t tlsoffset = offs; // it's not an offset in elf memory
@@ -770,42 +791,42 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
printf_log(LOG_INFO, "Warning, don't know of to handle rela #%d %s on %s\n", i, DumpRelType(ELF64_R_TYPE(rela[i].r_info)), symname);
}
}
return 0;
return bindnow?ret_ok:0;
}
int RelocateElf(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
if(head->rel) {
int cnt = head->relsz / head->relent;
DumpRelTable(head, cnt, (Elf64_Rel *)(head->rel + head->delta), "Rel");
printf_log(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->rel + head->delta)))
printf_dump(LOG_DEBUG, "Applying %d Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->rel + head->delta)))
return -1;
}
if(head->rela) {
int cnt = head->relasz / head->relaent;
DumpRelATable(head, cnt, (Elf64_Rela *)(head->rela + head->delta), "RelA");
printf_log(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL))
printf_dump(LOG_DEBUG, "Applying %d Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL))
return -1;
}
return 0;
}
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
int need_resolver = 0;
if(head->pltrel) {
int cnt = head->pltsz / head->pltent;
if(head->pltrel==DT_REL) {
DumpRelTable(head, cnt, (Elf64_Rel *)(head->jmprel + head->delta), "PLT");
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, local_maplib, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta)))
printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) for %s\n", cnt, head->name);
if(RelocateElfREL(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rel *)(head->jmprel + head->delta)))
return -1;
} else if(head->pltrel==DT_RELA) {
DumpRelATable(head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), "PLT");
printf_log(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, local_maplib, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver))
printf_dump(LOG_DEBUG, "Applying %d PLT Relocation(s) with Addend for %s\n", cnt, head->name);
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->jmprel + head->delta), &need_resolver))
return -1;
}
if(need_resolver) {
@@ -815,11 +836,11 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, elfheader_t* head)
if(head->pltgot) {
*(uintptr_t*)(head->pltgot+head->delta+16) = pltResolver;
*(uintptr_t*)(head->pltgot+head->delta+8) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16));
printf_dump(LOG_DEBUG, "PLT Resolver injected in plt.got at %p\n", (void*)(head->pltgot+head->delta+16));
} else if(head->got) {
*(uintptr_t*)(head->got+head->delta+16) = pltResolver;
*(uintptr_t*)(head->got+head->delta+8) = (uintptr_t)head;
printf_log(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16));
printf_dump(LOG_DEBUG, "PLT Resolver injected in got at %p\n", (void*)(head->got+head->delta+16));
}
}
}
@@ -1018,7 +1039,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
uname(1) man page description of the -i option). For more details of this token
expansion, see “System Specific Shared Objects”
*/
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu)
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu)
{
DumpDynamicRPath(h);
// update RPATH first
@@ -1079,7 +1100,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
// TODO: Add LD_LIBRARY_PATH and RPATH handling
if(AddNeededLib(maplib, neededlibs, deplib, local, nlibs, cnt, box64, emu)) {
if(AddNeededLib(maplib, neededlibs, deplib, local, bindnow, nlibs, cnt, box64, emu)) {
printf_log(LOG_INFO, "Error loading one of needed lib\n");
if(!allow_missing_libs)
return 1; //error...
@@ -1118,6 +1139,20 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
context->deferedInitList[context->deferedInitSz++] = h;
return;
}
// Refresh no-file part of TLS in case default value changed
if(h->tlsfilesize) {
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
tlsdatasize_t* ptr;
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL)
if(ptr->tlssize==my_context->tlssize) {
// refresh in tlsdata too
dest = (char*)(ptr->tlsdata+ptr->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
}
}
printf_log(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
if(h->initentry)
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
+2
View File
@@ -73,7 +73,9 @@ struct elfheader_s {
uint64_t memsz;
uint64_t stacksz;
size_t stackalign;
uintptr_t tlsaddr;
uint64_t tlssize;
uint64_t tlsfilesize;
size_t tlsalign;
int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
+1
View File
@@ -31,6 +31,7 @@
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
#define GETGX opgx=GetGx(emu, rex, nextop)
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
#define GETEM32(D) opem=GetEm32O(emu, rex, nextop, D, 0)
#define GETGM opgm=GetGm(emu, rex, nextop)
#define ED oped
#define GD opgd
+9 -7
View File
@@ -218,12 +218,12 @@ void CloneEmu(x64emu_t *newemu, const x64emu_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;
@@ -327,14 +327,15 @@ uint64_t GetRBP(x64emu_t *emu)
{
return R_RBP;
}
void SetFS(x64emu_t *emu, uint16_t v)
/*void SetFS(x64emu_t *emu, uint16_t v)
{
emu->segs[_FS] = v;
emu->segs_serial[_FS] = 0;
}
uint16_t GetFS(x64emu_t *emu)
{
return emu->segs[_FS];
}
}*/
void ResetFlags(x64emu_t *emu)
@@ -353,7 +354,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
if(trace_emm) {
// do emm reg if needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "mm%d:%016lx", i, emu->mmx87[i].q);
sprintf(tmp, "mm%d:%016lx", i, emu->mmx[i].q);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
@@ -370,7 +371,7 @@ const char* DumpCPURegs(x64emu_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);
sprintf(tmp, "ST%d=%f", i, ST(i).d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
@@ -465,7 +466,8 @@ void EmuCall(x64emu_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_RBX = old_rbx;
R_RDI = old_rdi;
+3 -2
View File
@@ -33,8 +33,9 @@ typedef struct x64emu_s {
// sse
sse_regs_t xmm[16];
// 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;
+77 -12
View File
@@ -46,6 +46,11 @@ int Run(x64emu_t *emu, int step)
if(emu->quit)
return 0;
if(R_RIP==0) {
emu->quit = 1;
printf_log(LOG_INFO, "Ask to run at NULL, quit silently\n");
return 0;
}
//ref opcode: http://ref.x64asm.net/geek32.html#xA1
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, (void*)R_RSP);
@@ -158,6 +163,9 @@ x64emurun:
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x36: /* SS: (ignored) */
break;
case 0x38:
nextop = F8;
GETEB(0);
@@ -299,6 +307,15 @@ x64emurun:
else
GD->q[0] = imul32(emu, ED->dword[0], (uint32_t)tmp64s);
break;
case 0x6C: /* INSB DX */
case 0x6D: /* INSL DX */
case 0x6E: /* OUTSB DX */
case 0x6F: /* OUTSL DX */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
GOCOND(0x70
, tmp8s = F8S; CHECK_FLAGS(emu);
@@ -496,7 +513,10 @@ x64emurun:
case 0x8C: /* MOV Ed, Seg */
nextop = F8;
GETED(0);
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
if(MODREG)
ED->q[0] = emu->segs[((nextop&0x38)>>3)];
else
ED->word[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8D: /* LEA Gd,M */
nextop = F8;
@@ -1004,7 +1024,12 @@ x64emurun:
}
}
break;
case 0xC2: /* RETN Iw */
tmp16u = F16;
R_RIP = Pop(emu);
R_RSP += tmp16u;
STEP
break;
case 0xC3: /* RET */
R_RIP = Pop(emu);
STEP
@@ -1050,12 +1075,23 @@ x64emurun:
x64Int3(emu);
if(emu->quit) goto fini;
break;
case 0xCD: /* INT n */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xCF: /* IRET */
R_RIP = Pop(emu);
emu->segs[_CS] = Pop(emu);
emu->segs[_CS] = Pop(emu)&0xffff;
emu->segs_serial[_CS] = 0;
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
tmp64u = Pop(emu); //RSP
emu->segs[_SS] = Pop(emu)&0xffff;
emu->segs_serial[_SS] = 0;
R_RSP= tmp64u;
RESET_FLAGS(emu);
goto fini; // exit, to recompute CS if needed
break;
@@ -1213,7 +1249,15 @@ x64emurun:
R_RIP += tmp8s;
STEP
break;
case 0xE4: /* IN AL, XX */
case 0xE5: /* IN EAX, XX */
case 0xE6: /* OUT XX, AL */
case 0xE7: /* OUT XX, EAX */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_RIP);
@@ -1231,7 +1275,15 @@ x64emurun:
R_RIP += tmp32s;
STEP
break;
case 0xEC: /* IN AL, DX */
case 0xED: /* IN EAX, DX */
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, EAX */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xF0: /* LOCK prefix */
if(RunF0(emu, rex)) {
unimp = 1;
@@ -1241,6 +1293,12 @@ x64emurun:
goto fini;
break;
case 0xF4: /* HLT */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xF5: /* CMC */
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
@@ -1354,10 +1412,16 @@ x64emurun:
SET_FLAG(F_CF);
break;
case 0xFA: /* CLI */
CLEAR_FLAG(F_IF); //not really handled...
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xFB: /* STI */
SET_FLAG(F_IF);
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xFC: /* CLD */
CLEAR_FLAG(F_DF);
@@ -1411,16 +1475,16 @@ x64emurun:
STEP
break;
case 3: /* CALL FAR Ed */
if(nextop>0xC0) {
if(MODREG) {
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
} else {
Push16(emu, R_CS);
Push(emu, R_CS);
Push(emu, R_RIP);
R_RIP = ED->dword[0];
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]); // check CS?
R_CS = (ED+1)->word[0];
goto fini; // exit loop to recompute new CS...
}
@@ -1430,14 +1494,14 @@ x64emurun:
STEP
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
if(MODREG) {
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
} else {
R_RIP = ED->q[0];
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]); //check CS?
R_CS = (ED+1)->word[0];
goto fini; // exit loop to recompute CS...
}
@@ -1462,6 +1526,7 @@ x64emurun:
fini:
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
if(unimp) {
R_RIP = emu->old_ip;
emu->quit = 1;
+45 -4
View File
@@ -48,6 +48,18 @@ int Run0F(x64emu_t *emu, rex_t rex)
case 0x05: /* SYSCALL */
x64Syscall(emu);
break;
case 0x06: /* CLTS */
// this is a privilege opcode...
R_RIP-=2;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
break;
case 0x08: /* INVD */
case 0x09: /* WBINVD */
// this is a privilege opcode...
R_RIP-=2;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
break;
case 0x0B: /* UD2 */
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
@@ -69,13 +81,13 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETEX(0);
GETGX;
memcpy(GX, EX, 16); // unaligned, so carreful
GX->u128 = EX->u128;
break;
case 0x11: /* MOVUPS Ex,Gx */
nextop = F8;
GETEX(0);
GETGX;
memcpy(EX, GX, 16); // unaligned, so carreful
EX->u128 = GX->u128;
break;
case 0x12:
nextop = F8;
@@ -142,6 +154,14 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
break;
case 0x20: /* MOV REG, crX */
case 0x21: /* MOV REG, drX */
case 0x22: /* MOV cxR, REG */
case 0x23: /* MOV drX, REG */
// this is a privilege opcode...
R_RIP-=2;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
break;
case 0x28: /* MOVAPS Gx,Ex */
nextop = F8;
@@ -1156,8 +1176,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
GX->ud[i]=(tmp8s)?0xffffffff:0;
}
break;
case 0xC4: /* PINSRW Gm,Ew,Ib */
case 0xC3: /* MOVNTI Ed, Gd */
nextop = F8;
GETED(0);
GETGD;
if(rex.w)
ED->q[0] = GD->q[0];
else {
if(MODREG)
ED->q[0] = GD->dword[0];
else
ED->dword[0] = GD->dword[0];
}
break;
case 0xC4: /* PINSRW Gm,Ew,Ib */
nextop = F8;
GETED(0);
GETGM;
@@ -1271,6 +1303,15 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
break;
case 0xD7: /* PMOVMSKB Gd,Em */
nextop = F8;
GETEM(0);
GETGD;
GD->dword[0] = 0;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80)
GD->dword[0] |= (1<<i);
break;
case 0xD8: /* PSUBUSB Gm,Em */
nextop = F8;
GETEM(0);
+152 -29
View File
@@ -191,6 +191,13 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
break;
case 0xB6: /* MOVZX Gd,Eb */
nextop = F8;
GETEB_OFFS(0, tlsdata);
GETGD;
GD->q[0] = EB->byte[0];
break;
default:
return 1;
}
@@ -224,34 +231,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
case 0x66:
opcode = F8;
while(opcode>=0x40 && opcode<=0x4F) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x0F:
opcode = F8;
switch(opcode) {
case 0xD6: /* MOVQ Ex,Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->q[0] = GX->q[0];
if(MODREG)
EX->q[1] = 0;
break;
default:
return 1;
}
break;
default:
return 1;
}
break;
return Run6664(emu, rex);
case 0x80: /* GRP Eb,Ib */
nextop = F8;
@@ -406,7 +386,150 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
}
break;
default:
case 0xF7: /* GRP3 Ed(,Id) */
nextop = F8;
tmp8u = (nextop>>3)&7;
GETED_OFFS((tmp8u<2)?4:0, tlsdata);
if(rex.w) {
switch(tmp8u) {
case 0:
case 1: /* TEST Ed,Id */
tmp64u = F32S64;
test64(emu, ED->q[0], tmp64u);
break;
case 2: /* NOT Ed */
ED->q[0] = not64(emu, ED->q[0]);
break;
case 3: /* NEG Ed */
ED->q[0] = neg64(emu, ED->q[0]);
break;
case 4: /* MUL RAX,Ed */
mul64_rax(emu, ED->q[0]);
break;
case 5: /* IMUL RAX,Ed */
imul64_rax(emu, ED->q[0]);
break;
case 6: /* DIV Ed */
div64(emu, ED->q[0]);
break;
case 7: /* IDIV Ed */
idiv64(emu, ED->q[0]);
break;
}
} else {
switch(tmp8u) {
case 0:
case 1: /* TEST Ed,Id */
tmp32u = F32;
test32(emu, ED->dword[0], tmp32u);
break;
case 2: /* NOT Ed */
if(MODREG)
ED->q[0] = not32(emu, ED->dword[0]);
else
ED->dword[0] = not32(emu, ED->dword[0]);
break;
case 3: /* NEG Ed */
if(MODREG)
ED->q[0] = neg32(emu, ED->dword[0]);
else
ED->dword[0] = neg32(emu, ED->dword[0]);
break;
case 4: /* MUL EAX,Ed */
mul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 5: /* IMUL EAX,Ed */
imul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 6: /* DIV Ed */
div32(emu, ED->dword[0]);
//emu->regs[_AX].dword[1] = 0; // already put high regs to 0
//emu->regs[_DX].dword[1] = 0;
break;
case 7: /* IDIV Ed */
idiv32(emu, ED->dword[0]);
//emu->regs[_AX].dword[1] = 0;
//emu->regs[_DX].dword[1] = 0;
break;
}
}
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GETED_OFFS(0, tlsdata);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
if(rex.w)
ED->q[0] = inc64(emu, ED->q[0]);
else {
if(MODREG)
ED->q[0] = inc32(emu, ED->dword[0]);
else
ED->dword[0] = inc32(emu, ED->dword[0]);
}
break;
case 1: /* DEC Ed */
if(rex.w)
ED->q[0] = dec64(emu, ED->q[0]);
else {
if(MODREG)
ED->q[0] = dec32(emu, ED->dword[0]);
else
ED->dword[0] = dec32(emu, ED->dword[0]);
}
break;
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
Push(emu, R_RIP);
R_RIP = tmp64u;
break;
case 3: /* CALL FAR Ed */
if(nextop>0xC0) {
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
} else {
Push16(emu, R_CS);
Push(emu, R_RIP);
R_RIP = ED->dword[0];
R_CS = (ED+1)->word[0];
return 0; // exit loop to recompute new CS...
}
break;
case 4: /* JMP NEAR Ed */
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]);
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
} else {
R_RIP = ED->q[0];
R_CS = (ED+1)->word[0];
return 0; // exit loop to recompute CS...
}
break;
case 6: /* Push Ed */
tmp64u = ED->q[0]; // rex.w ignored
Push(emu, tmp64u); // avoid potential issue with push [esp+...]
break;
default:
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
default:
return 1;
}
return 0;
+30 -3
View File
@@ -47,7 +47,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
@@ -225,7 +225,14 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
else
GW->word[0] = EW->word[0];
break;
case 0x8C: /* MOV Ed, Seg */
nextop = F8;
GETEW(0);
if(rex.w)
EW->q[0] = emu->segs[((nextop&0x38)>>3)];
else
EW->word[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8D: /* LEA Gw,M */
nextop = F8;
GETED(0);
@@ -236,7 +243,27 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
GD->word[0] = (uint16_t)(uintptr_t)ED;
break;
case 0x90: /* NOP */
case 0x90: /* NOP or XCHG R8d, AX*/
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97: /* XCHG reg,AX */
tmp8u = _AX+(opcode&7)+(rex.b<<3);
if(tmp8u!=_AX) {
if(rex.w) {
tmp64u = R_RAX;
R_RAX = emu->regs[tmp8u].q[0];
emu->regs[tmp8u].q[0] = tmp64u;
} else {
tmp16u = R_AX;
R_AX = emu->regs[tmp8u].word[0];
emu->regs[tmp8u].word[0] = tmp16u;
}
}
break;
break;
case 0x98: /* CBW */
+481 -1
View File
@@ -22,6 +22,27 @@
#include "modrm.h"
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
int Run660F(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
@@ -33,9 +54,53 @@ int Run660F(x64emu_t *emu, rex_t rex)
int32_t tmp32s;
uint32_t tmp32u;
uint64_t tmp64u;
float tmpf;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1, *opex2;
mmx87_regs_t *opem, *opgm;
// AES opcodes constants
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
opcode = F8;
@@ -248,6 +313,27 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0x08: /* PSIGNB Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
GX->sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
break;
case 0x09: /* PSIGNW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i)
GX->sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
break;
case 0x0A: /* PSIGND Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
break;
case 0x0B: /* PMULHRSW Gx, Ex */
nextop = F8;
GETEX(0);
@@ -258,6 +344,49 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0x14: /* BLENDVPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
if(emu->xmm[0].ud[i]&0x80000000)
GX->ud[i] = EX->ud[i];
}
break;
case 0x17: // PTEST GX, EX
nextop = F8;
GETEX(0);
GETGX;
CONDITIONAL_SET_FLAG(!(GX->u128&EX->u128), F_ZF);
CONDITIONAL_SET_FLAG(!((~GX->u128)&EX->u128), F_CF);
break;
case 0x1C: /* PABSB Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i) {
GX->sb[i] = abs(EX->sb[i]);
}
break;
case 0x1D: /* PABSW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i) {
GX->sw[i] = abs(EX->sw[i]);
}
break;
case 0x1E: /* PABSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
GX->sd[i] = abs(EX->sd[i]);
}
break;
case 0x20: /* PMOVSXBW Gx, Ex */
nextop = F8;
GETEX(0);
@@ -301,14 +430,158 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->sq[i] = EX->sd[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]>EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0x3A: /* PMAXSD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]<EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0xDB: /* AESIMC Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
//STATE ← InvMixColumns( STATE );
if (EX == GX) {
for(int i=0; i<16; ++i)
eax1.ub[i] = EX->ub[i];
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX->ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX->ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
} else {
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
GX->ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
GX->ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
}
}
break;
case 0xDC: /* AESENC Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = subbytes[eax1.ub[i]];
//STATE ← MixColumns( STATE );
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
GX->ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
GX->ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
case 0xDD: /* AESENCLAST Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
GX->ub[i] = subbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
case 0xDE: /* AESDEC Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = invsubbytes[eax1.ub[i]];
//STATE ← InvMixColumns( STATE );
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX->ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX->ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
case 0xDF: /* AESDECLAST Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
GX->ub[i] = invsubbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
default:
return 1;
}
break;
case 0x3A: // these are some SSE3 opcodes
case 0x3A: // these are some SSE3 & SSE4.x opcodes
opcode = F8;
switch(opcode) {
case 0x0A: // ROUNDSS Gx, Ex, u8
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8; // ignoring bit 3 interupt thingy
if(tmp8u&4)
tmp8u = (emu->mxcsr>>13)&3;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest:
GX->f[0] = floor(EX->f[0]+0.5);
break;
case ROUND_Down:
GX->f[0] = floor(EX->f[0]);
break;
case ROUND_Up:
GX->f[0] = ceil(EX->f[0]);
break;
case ROUND_Chop:
GX->f[0] = EX->f[0];
break;
}
break;
case 0x0B: // ROUNDSD Gx, Ex, u8
nextop = F8;
GETEX(1);
@@ -334,6 +607,16 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0x0E: /* PBLENDW Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for (int i=0; i<8; ++i) {
if(tmp8u&(1<<i))
GX->uw[i] = EX->uw[i];
}
break;
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GETEX(1);
@@ -350,6 +633,78 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0x17: // EXTRACTPS ED, GX, u8
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
ED->dword[0] = GX->ud[tmp8u&3];
if(MODREG && rex.w) ED->dword[1] = 0;
break;
case 0x20: // PINSRB GX, ED, u8
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
GX->ub[tmp8u&0xf] = ED->byte[0];
break;
case 0x21: // INSERTPS GX, EX, u8
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
for(int i=0; i<4; ++i)
if(tmp8u&(1<<i))
GX->ud[i] = 0;
break;
case 0x22: // PINSRD GX, ED, u8
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
if(rex.w)
GX->q[tmp8u&0x1] = ED->q[0];
else
GX->ud[tmp8u&0x3] = ED->dword[0];
break;
case 0x40: /* DPPS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmpf = 0.0f;
for(int i=0; i<4; ++i)
if(tmp8u&(1<<(i+4)))
tmpf += GX->f[i]*EX->f[i];
for(int i=0; i<4; ++i)
GX->f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
break;
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
nextop = F8;
GETEX(1);
GETGX;
tmp32u = F8;
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= tmp32u;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= tmp32u;
break;
default:
return 1;
}
@@ -798,6 +1153,18 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
break;
case 0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] += GX->d[1];
if(EX==GX) {
GX->d[1] = GX->d[0];
} else {
GX->d[1] = EX->d[0] + EX->d[1];
}
break;
case 0x7E: /* MOVD Ed, Gx */
nextop = F8;
GETED(0);
@@ -965,7 +1332,104 @@ int Run660F(x64emu_t *emu, rex_t rex)
GETGW;
GW->word[0] = EB->byte[0];
break;
case 0xB7: /* MOVZX Gw,Ew */
nextop = F8;
GETEW(0);
GETGW;
GW->word[0] = EW->word[0];
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ew,Ib */
CHECK_FLAGS(emu);
GETEW(0);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 5: /* BTS Ew, Ib */
CHECK_FLAGS(emu);
GETEW(0);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->q[0] ^= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
EW->word[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
break;
case 6: /* BTR Ew, Ib */
CHECK_FLAGS(emu);
GETEW(0);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
break;
case 7: /* BTC Ew, Ib */
CHECK_FLAGS(emu);
GETEW(0);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
}
break;
default:
return 1;
}
break;
case 0xBB: /* BTC Ew,Gw */
CHECK_FLAGS(emu);
nextop = F8;
@@ -1116,6 +1580,22 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->q[1] = eax1.q[1];
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* BSWAP reg16 */
tmp8u = (opcode&7)+(rex.b<<3);
if(rex.w) {
emu->regs[tmp8u].q[0] = __builtin_bswap64(emu->regs[tmp8u].q[0]);
} else {
emu->regs[tmp8u].word[0] = __builtin_bswap16(emu->regs[tmp8u].word[0]);
}
break;
case 0xD1: /* PSRLW Gx, Ex */
nextop = F8;
GETEX(0);
+28
View File
@@ -27,6 +27,7 @@ int Run6664(x64emu_t *emu, rex_t rex)
uint8_t opcode;
uint8_t nextop;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx;
uintptr_t tlsdata = GetFSBaseEmu(emu);
opcode = F8;
@@ -39,6 +40,33 @@ int Run6664(x64emu_t *emu, rex_t rex)
switch(opcode) {
case 0x0F:
opcode = F8;
switch(opcode) {
case 0xD6: /* MOVQ Ex,Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->q[0] = GX->q[0];
if(MODREG)
EX->q[1] = 0;
break;
default:
return 1;
}
break;
case 0x89: /* MOV Ew,Gw */
nextop = F8;
GETEW_OFFS(0, tlsdata);
GETGW;
if(rex.w)
EW->q[0] = GW->q[0];
else
EW->word[0] = GW->word[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GETEW_OFFS(0, tlsdata);
+65 -52
View File
@@ -27,10 +27,11 @@ int Run66F0(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
uint16_t tmp16u2;
uint16_t tmp16u, tmp16u2;
int32_t tmp32s;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2;
reg64_t *oped;
reg64_t *oped, *opgd;
opcode = F8;
// REX prefix before the F0 are ignored
@@ -40,7 +41,45 @@ int Run66F0(x64emu_t *emu, rex_t rex)
opcode = F8;
}
if(rex.w) return RunF0(emu, rex);
switch(opcode) {
case 0x0F:
nextop = F8;
switch(nextop) {
case 0xB1: /* CMPXCHG Ew,Gw */
nextop = F8;
GETEW(0);
GETGW;
#ifdef DYNAREC
do {
tmp16u = arm64_lock_read_h(EW);
cmp16(emu, R_AX, tmp16u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_h(EW, GW->word[0]);
} else {
R_AX = tmp16u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp16(emu, R_AX, EW->word[0]);
if(ACCESS_FLAG(F_ZF)) {
EW->word[0] = GW->word[0];
} else {
R_AX = EW->word[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
}
break;
case 0x81: /* GRP Ew,Iw */
case 0x83: /* GRP Ew,Ib */
@@ -49,55 +88,7 @@ int Run66F0(x64emu_t *emu, rex_t rex)
tmp64s = (opcode==0x83)?(F8S):(F16S);
tmp64u = (uint64_t)tmp64s;
#ifdef DYNAREC
if(rex.w) {
switch((nextop>>3)&7) {
case 0: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 1: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = or64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 2: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = adc64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 3: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sbb64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 4: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = and64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 5: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sub64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 6: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = xor64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
else
switch((nextop>>3)&7) {
case 0: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = add16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 1: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = or16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 2: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = adc16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 3: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sbb16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 4: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = and16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 5: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sub16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 6: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = xor16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
switch((nextop>>3)&7) {
case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;
case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break;
case 2: ED->q[0] = adc64(emu, ED->q[0], tmp64u); break;
case 3: ED->q[0] = sbb64(emu, ED->q[0], tmp64u); break;
case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break;
case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break;
case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
@@ -106,8 +97,30 @@ int Run66F0(x64emu_t *emu, rex_t rex)
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
else
switch((nextop>>3)&7) {
case 0: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = add16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 1: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = or16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 2: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = adc16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 3: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sbb16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 4: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = and16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 5: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sub16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 6: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = xor16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
switch((nextop>>3)&7) {
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
+7
View File
@@ -29,6 +29,7 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
int8_t tmp8s;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
uint64_t tmp64u;
reg64_t *oped, *opgd;
@@ -237,6 +238,12 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
R_RIP += tmp8s;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_RIP);
R_RIP += tmp32s;
break;
case 0xF7: /* GRP3 Ed(,Id) */
nextop = F8;
tmp8u = (nextop>>3)&7;
+14
View File
@@ -65,6 +65,20 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0x6F: /* MOVQ Gm, Em */
nextop = F8;
GETEM32(0);
GETGM;
GM->q = EM->q;
break;
case 0x7F: /* MOVQ Em, Gm */
nextop = F8;
GETEM32(0);
GETGM;
EM->q = GM->q;
break;
default:
return 1;
}
+28 -6
View File
@@ -32,14 +32,21 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
{
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
if(init) {
Push64(emu, GetRBP(emu)); // set frame pointer
SetRBP(emu, GetRSP(emu)); // save RSP
SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP
PushExit(emu);
SetRDX(emu, (uint64_t)my_context->envv);
SetRSI(emu, (uint64_t)my_context->argv);
SetRDI(emu, (uint64_t)my_context->argc);
R_RIP=(uint64_t)*init;
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
DynaRun(emu);
if(emu->error) // any error, don't bother with more
return 0;
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 0;
}
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
@@ -55,9 +62,11 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
DynaRun(emu);
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 1; // finished!
if(!emu->quit) {
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 1; // finished!
}
return 0;
}
@@ -1000,6 +1009,11 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
}
#endif
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
if(R_RIP==0) {
printf_log(LOG_NONE, "Running at NULL address\n");
pthread_mutex_unlock(&my_context->mutex_trace);
return;
}
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
uint64_t a = *(uint64_t*)(ip+3);
if(a==0) {
@@ -1241,7 +1255,7 @@ mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->mmx87[m&0x07];
return &emu->mmx[m&0x07];
} else return (mmx87_regs_t*)GetECommon(emu, rex, m, delta);
}
@@ -1269,6 +1283,14 @@ sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
}
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->mmx[(m&0x07)];
} else return (mmx87_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
}
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
{
@@ -1289,7 +1311,7 @@ mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
(void)rex;
uint8_t m = (v&0x38)>>3;
return &emu->mmx87[m&7];
return &emu->mmx[m&7];
}
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
+1
View File
@@ -94,6 +94,7 @@ reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
#define GetGw GetGd
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v);
void UpdateFlags(x64emu_t *emu);
+3
View File
@@ -185,6 +185,7 @@ int RunD9(x64emu_t *emu, rex_t rex)
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
break;
case 0xFC: /* FRNDINT */
ST0.d = fpu_round(emu, ST0.d);
@@ -196,9 +197,11 @@ int RunD9(x64emu_t *emu, rex_t rex)
break;
case 0xFE: /* FSIN */
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
break;
case 0xFF: /* FCOS */
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
break;
+2 -2
View File
@@ -163,11 +163,11 @@ int RunDB(x64emu_t *emu, rex_t rex)
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).ref = ST0.q;
STld(0).uref = ST0.q;
break;
case 7: /* FSTP tbyte */
GETED(0);
if(ST0.q!=STld(0).ref)
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, ED);
else
memcpy(ED, &STld(0).ld, 10);
+4 -4
View File
@@ -152,8 +152,8 @@ int RunDF(x64emu_t *emu, rex_t rex)
tmp64s = ED->sq[0];
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 */
GETED(0);
@@ -162,8 +162,8 @@ int RunDF(x64emu_t *emu, rex_t rex)
break;
case 7: /* FISTP i64 */
GETED(0);
if(STll(0).ref==ST(0).sq)
ED->sq[0] = STll(0).ll;
if(STll(0).sref==ST(0).sq)
ED->sq[0] = STll(0).sq;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
ED->sq[0] = 0x8000000000000000LL;
+212 -1
View File
@@ -30,7 +30,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
uint8_t tmp8u, tmp8u2; (void)tmp8u2;
int32_t tmp32s; (void)tmp32s;
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
@@ -405,6 +405,187 @@ int RunF0(x64emu_t *emu, rex_t rex)
#endif
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ed,Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 5: /* BTS Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
#ifdef DYNAREC
if(rex.w) {
tmp8u&=63;
do {
tmp64u = arm64_lock_read_dd(ED);
if(tmp64u & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
tmp32s = 0;
} else {
tmp64u ^= (1LL<<tmp8u);
tmp32s = arm64_lock_write_dd(ED, tmp64u);
CLEAR_FLAG(F_CF);
}
} while(tmp32s);
} else {
tmp8u&=31;
do {
tmp32u = arm64_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32s = 0;
} else {
tmp32u ^= (1<<tmp8u);
tmp32s = arm64_lock_write_d(ED, tmp32u);
CLEAR_FLAG(F_CF);
}
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->q[0] ^= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->dword[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
#ifdef DYNAREC
if(rex.w) {
do {
tmp8u&=63;
tmp64u = arm64_lock_read_dd(ED);
if(tmp64u & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
tmp64u ^= (1LL<<tmp8u);
tmp32s = arm64_lock_write_dd(ED, tmp64u);
} else {
tmp32s = 0;
CLEAR_FLAG(F_CF);
}
} while(tmp32s);
} else {
tmp8u&=31;
do {
tmp32u = arm64_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm64_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 7: /* BTC Ed, Ib */
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
#ifdef DYNAREC
if(rex.w) {
tmp8u&=63;
do {
tmp64u = arm64_lock_read_dd(ED);
if(tmp64u & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
tmp64u ^= (1LL<<tmp8u);
tmp32s = arm64_lock_write_dd(ED, tmp64u);
} while(tmp32s);
} else {
tmp8u&=31;
do {
tmp32u = arm64_lock_read_d(ED);
if(tmp32u & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm64_lock_write_d(ED, tmp32u);
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
}
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GETED(0);
@@ -523,6 +704,36 @@ int RunF0(x64emu_t *emu, rex_t rex)
case 0x66:
return Run66F0(emu, rex); // more opcode F0 66 and 66 F0 is the same
case 0x80: /* GRP Eb,Ib */
nextop = F8;
GETEB(1);
tmp8u = F8;
#ifdef DYNAREC
switch((nextop>>3)&7) {
case 0: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = add8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 1: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = or8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 2: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = adc8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 3: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = sbb8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 4: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = and8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 5: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = sub8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 6: do { tmp8u2 = arm64_lock_read_b(EB); tmp8u2 = xor8(emu, tmp8u2, tmp8u);} while(arm64_lock_write_b(EB, tmp8u2)); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
+14 -4
View File
@@ -212,16 +212,16 @@ int RunF20F(x64emu_t *emu, rex_t rex)
case 0xC2: /* CMPSD Gx, Ex, Ib */
nextop = F8;
GETEX(0);
GETEX(1);
GETGX;
tmp8u = F8;
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 4: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || (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;
case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break;
case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break;
@@ -229,6 +229,16 @@ int RunF20F(x64emu_t *emu, rex_t rex)
GX->q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
break;
case 0xD0: /* ADDSUBPS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] -= EX->f[0];
GX->f[1] += EX->f[1];
GX->f[2] -= EX->f[2];
GX->f[3] += EX->f[3];
break;
case 0xD6: /* MOVDQ2Q Gm, Ex */
nextop = F8;
GETEX(0);
+39 -3
View File
@@ -238,6 +238,24 @@ int RunF30F(x64emu_t *emu, rex_t rex)
memcpy(EX, GX, 16); // unaligned...
break;
case 0xB8: /* POPCNT Gd,Ed */
nextop = F8;
GETED(0);
GETGD;
if(rex.w)
GD->q[0] = __builtin_popcountl(ED->q[0]);
else
GD->q[0] = __builtin_popcount(ED->dword[0]);
RESET_FLAGS(emu);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
CLEAR_FLAG(F_ZF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CONDITIONAL_SET_FLAG(GD->q[0]==0, F_ZF);
break;
case 0xBC: /* TZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
@@ -273,6 +291,24 @@ int RunF30F(x64emu_t *emu, rex_t rex)
}
}
break;
case 0xBD: /* LZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
tmp64u = ED->q[0];
tmp8u = (tmp64u)?__builtin_clzl(tmp64u):64;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CONDITIONAL_SET_FLAG(tmp8u==64, F_CF);
} else {
tmp32u = ED->dword[0];
tmp8u = (tmp32u)?__builtin_clz(tmp32u):32;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CONDITIONAL_SET_FLAG(tmp8u==32, F_CF);
}
GD->q[0] = tmp8u;
break;
case 0xC2: /* CMPSS Gx, Ex, Ib */
nextop = F8;
@@ -282,10 +318,10 @@ int RunF30F(x64emu_t *emu, rex_t rex)
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 4: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || (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;
case 6: tmp8s=isnan(GX->f[0]) || isnan(EX->f[0]) || isgreater(GX->f[0], EX->f[0]); break;
case 7: tmp8s=!isnan(GX->f[0]) && !isnan(EX->f[0]); break;
+104 -33
View File
@@ -36,13 +36,16 @@
typedef struct x64_sigaction_s x64_sigaction_t;
typedef struct x64_stack_s x64_stack_t;
int mkdir(const char *path, mode_t mode);
extern int mkdir(const char *path, mode_t mode);
extern int fchmodat (int __fd, const char *__file, mode_t __mode, int __flag);
//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
ssize_t my_readlink(x64emu_t* emu, void* path, void* buf, size_t sz);
int my_stat(x64emu_t *emu, void* filename, void* buf);
int my_lstat(x64emu_t *emu, void* filename, void* buf);
int my_fstat(x64emu_t *emu, int fd, void* buf);
int my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact);
int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss);
@@ -72,10 +75,13 @@ scwrap_t syscallwrap[] = {
//{ 2, __NR_open, 3 }, // flags need transformation
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
//{ 4, __NR_stat, 2 }, // Need to align struct stat
//{ 5, __NR_fstat, 2},
//{ 6, __NR_lstat, 2},
{ 8, __NR_lseek, 3},
//{ 9, __NR_mmap, 6}, // wrapped to track mmap
//{ 10, __NR_mprotect, 3}, // same
//{ 11, __NR_munmap, 2}, // same
{ 5, __NR_fstat, 2},
{ 12, __NR_brk, 1},
//{ 13, __NR_rt_sigaction, 4}, // wrapped to use my_ version
{ 14, __NR_rt_sigprocmask, 4},
{ 16, __NR_ioctl, 3},
@@ -90,18 +96,32 @@ scwrap_t syscallwrap[] = {
{ 23, __NR_select, 5},
#endif
//{ 25, __NR_mremap, 5}, // wrapped to track protection
{ 35, __NR_nanosleep, 2},
{ 39, __NR_getpid, 0},
{ 41, __NR_socket, 3},
{ 42, __NR_connect, 3},
{ 43, __NR_accept, 3},
{ 44, __NR_sendto, 6},
{ 45, __NR_recvfrom, 6},
{ 46, __NR_sendmsg, 3},
{ 47, __NR_recvmsg, 3},
{ 53, __NR_socketpair, 4},
#ifdef __NR_vfork
{56, __NR_vfork, 0},
#endif
#ifdef __NR_fork
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
#endif
{ 61, __NR_wait4, 4},
{ 66, __NR_semctl, 4},
{ 73, __NR_flock, 2},
#ifdef __NR_getdents
{ 78, __NR_getdents, 3},
#endif
{ 79, __NR_getcwd, 2},
#ifdef __NR_rename
{ 82, __NR_rename, 2},
#endif
#ifdef __NR_mkdir
{ 83, __NR_mkdir, 2},
#endif
@@ -112,6 +132,8 @@ scwrap_t syscallwrap[] = {
{ 96, __NR_gettimeofday, 2},
{ 97, __NR_getrlimit, 2},
{ 101, __NR_ptrace, 4},
{ 118, __NR_getresuid, 3},
{ 120, __NR_getresgid, 3},
{ 125, __NR_capget, 2},
{ 126, __NR_capset, 2},
{ 127, __NR_rt_sigpending, 2},
@@ -124,6 +146,8 @@ scwrap_t syscallwrap[] = {
{ 201, __NR_time, 1},
#endif
{ 202, __NR_futex, 6},
{ 203, __NR_sched_setaffinity, 3},
{ 204, __NR_sched_getaffinity, 3},
{ 217, __NR_getdents64, 3},
{ 220, __NR_semtimedop, 4},
{ 228, __NR_clock_gettime, 2},
@@ -135,10 +159,21 @@ scwrap_t syscallwrap[] = {
#endif
{ 254, __NR_inotify_add_watch, 3},
{ 255, __NR_inotify_rm_watch, 2},
{ 257, __NR_openat, 4},
{ 274, __NR_get_robust_list, 3},
{ 294, __NR_inotify_init1, 1},
{ 298, __NR_perf_event_open, 5},
{ 309, __NR_getcpu, 3}, // need wrapping?
{ 315, __NR_sched_getattr, 4},
{ 318, __NR_getrandom, 3},
{ 319, __NR_memfd_create, 2},
#ifdef __NR_statx
// TODO: implement fallback if __NR_statx is not defined
{ 332, __NR_statx, 4},
#endif
#ifdef __NR_fchmodat4
{ 434, __NR_fchmodat4, 4},
#endif
};
struct mmap_arg_struct {
@@ -248,42 +283,48 @@ void EXPORT x64Syscall(x64emu_t *emu)
}
switch (s) {
case 0: // sys_read
R_EAX = (uint32_t)read((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
*(int64_t*)&R_RAX = read((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
break;
case 1: // sys_write
R_EAX = (uint32_t)write((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
*(int64_t*)&R_RAX = write((int)R_EDI, (void*)R_RSI, (size_t)R_RDX);
break;
case 2: // sys_open
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_RDI, of_convert(R_ESI), R_EDX);};
//R_EAX = (uint32_t)open((void*)R_EDI, of_convert(R_ESI), R_EDX);
R_EAX = (uint32_t)my_open(emu, (void*)R_RDI, of_convert(R_ESI), R_EDX);
//*(int64_t*)&R_RAX = open((void*)R_EDI, of_convert(R_ESI), R_EDX);
*(int64_t*)&R_RAX = my_open(emu, (void*)R_RDI, of_convert(R_ESI), R_EDX);
break;
case 3: // sys_close
R_EAX = (uint32_t)close((int)R_EDI);
*(int64_t*)&R_RAX = close((int)R_EDI);
break;
case 4: // sys_stat
R_EAX = (uint32_t)my_stat(emu, (void*)R_RDI, (void*)R_RSI);
*(int64_t*)&R_RAX = my_stat(emu, (void*)R_RDI, (void*)R_RSI);
break;
case 5: // sys_fstat
*(int64_t*)&R_RAX = my_fstat(emu, (int)R_EDI, (void*)R_RSI);
break;
case 6: // sys_lstat
*(int64_t*)&R_RAX = my_lstat(emu, (void*)R_RDI, (void*)R_RSI);
break;
case 9: // sys_mmap
R_RAX = (uintptr_t)my_mmap64(emu, (void*)R_RDI, R_RSI, (int)R_EDX, (int)R_R10d, (int)R_R8d, R_R9);
break;
case 10: // sys_mprotect
R_EAX = (uint32_t)my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
*(int64_t*)&R_RAX = my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
break;
case 11: // sys_munmap
R_EAX = (uint32_t)my_munmap(emu, (void*)R_RDI, R_RSI);
*(int64_t*)&R_RAX = my_munmap(emu, (void*)R_RDI, R_RSI);
break;
case 13: // sys_rt_sigaction
R_EAX = (uint32_t)my_sigaction(emu, (int)R_EDI, (const x64_sigaction_t *)R_RSI, (x64_sigaction_t *)R_RDX/*, (size_t)R_R10*/);
*(int64_t*)&R_RAX = my_sigaction(emu, (int)R_EDI, (const x64_sigaction_t *)R_RSI, (x64_sigaction_t *)R_RDX/*, (size_t)R_R10*/);
break;
#ifndef __NR_access
case 21: // sys_access
R_EAX = (uint32_t)access((void*)R_RDI, R_ESI);
*(int64_t*)&R_RAX = access((void*)R_RDI, R_ESI);
break;
#endif
#ifndef __NR_pipe
case 22:
R_EAX = (uint32_t)pipe((void*)R_RDI);
*(int64_t*)&R_RAX = pipe((void*)R_RDI);
break;
#endif
#ifndef __NR_select
@@ -294,6 +335,14 @@ void EXPORT x64Syscall(x64emu_t *emu)
case 25: // sys_mremap
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
break;
#ifndef __NR_vfork
case 56: // vfork
{
int64_t r = vfork();
R_RAX = r;
}
break;
#endif
#ifndef __NR_fork
case 57:
R_RAX = fork();
@@ -310,24 +359,29 @@ void EXPORT x64Syscall(x64emu_t *emu)
}
break;
#endif
#ifndef __NR_rename
case 82: // sys_rename
*(int64_t*)&R_RAX = rename((void*)R_RDI, (void*)R_RSI);
break;
#endif
#ifndef __NR_mkdir
case 83: // sys_mkdir
R_EAX = (uint32_t)mkdir((void*)R_RDI, R_ESI);
*(int64_t*)&R_RAX = mkdir((void*)R_RDI, R_ESI);
break;
#endif
#ifndef __NR_unlink
case 87: //sys_unlink
R_EAX = (uint32_t)unlink((void*)R_RDI);
*(int64_t*)&R_RAX = unlink((void*)R_RDI);
break;
#endif
case 89: // sys_readlink
R_RAX = (ssize_t)my_readlink(emu,(void*)R_RDI, (void*)R_RSI, (size_t)R_RDX);
break;
case 131: // sys_sigaltstack
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
*(int64_t*)&R_RAX = my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
break;
case 158: // sys_arch_prctl
R_EAX = (uint32_t)my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
*(int64_t*)&R_RAX = my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
break;
#ifndef __NR_time
case 201: // sys_time
@@ -339,13 +393,18 @@ void EXPORT x64Syscall(x64emu_t *emu)
R_EAX = (int)syscall(__NR_inotify_init1, 0);
break;
#endif
#ifndef __NR_fchmodat4
case 434:
*(int64_t*)R_RAX = fchmodat((int)R_EDI, (void*)R_RSI, (mode_t)R_RDX, (int)R_R10d);
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
return;
}
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
printf_log(LOG_DEBUG, " => 0x%lx\n", R_RAX);
}
#define stack(n) (R_RSP+8+n)
@@ -357,7 +416,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
uintptr_t EXPORT my_syscall(x64emu_t *emu)
{
uint32_t s = R_EDI;;
uint32_t s = R_EDI;
printf_dump(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
@@ -381,37 +440,45 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
}
switch (s) {
case 0: // sys_read
return (uint32_t)read(R_ESI, (void*)R_RDX, R_ECX);
return (uint64_t)read(R_ESI, (void*)R_RDX, R_ECX);
case 1: // sys_write
return (uint32_t)write(R_ESI, (void*)R_RDX, R_ECX);
return (uint64_t)write(R_ESI, (void*)R_RDX, R_ECX);
case 2: // sys_open
return my_open(emu, (char*)R_RSI, of_convert(R_EDX), R_ECX);
case 3: // sys_close
return (uint32_t)close(R_ESI);
return (uint64_t)(int64_t)close(R_ESI);
case 4: // sys_stat
return (uint32_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
return (uint64_t)(int64_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
case 5: // sys_fstat
return (uint64_t)(int64_t)my_fstat(emu, (int)R_ESI, (void*)R_RDX);
case 6: // sys_lstat
return (uint64_t)(int64_t)my_lstat(emu, (void*)R_RSI, (void*)R_RDX);
case 9: // sys_mmap
return (uintptr_t)my_mmap64(emu, (void*)R_RSI, R_RDX, (int)R_RCX, (int)R_R8d, (int)R_R9, i64(0));
case 10: // sys_mprotect
return (uint32_t)my_mprotect(emu, (void*)R_RSI, R_RDX, (int)R_ECX);
return (uint64_t)(int64_t)my_mprotect(emu, (void*)R_RSI, R_RDX, (int)R_ECX);
case 11: // sys_munmap
return (uint32_t)my_munmap(emu, (void*)R_RSI, R_RDX);
return (uint64_t)(int64_t)my_munmap(emu, (void*)R_RSI, R_RDX);
case 13: // sys_rt_sigaction
return (uint32_t)my_sigaction(emu, (int)R_ESI, (const x64_sigaction_t *)R_RDX, (x64_sigaction_t *)R_RCX/*, (size_t)R_R8*/);
return (uint64_t)(int64_t)my_sigaction(emu, (int)R_ESI, (const x64_sigaction_t *)R_RDX, (x64_sigaction_t *)R_RCX/*, (size_t)R_R8*/);
#ifndef __NR_access
case 21: // sys_access
return (uint32_t)access((void*)R_RSI, R_EDX);
return (uint64_t)(int64_t)access((void*)R_RSI, R_EDX);
#endif
#ifndef __NR_pipe
case 22:
return (uint32_t)pipe((void*)R_RSI);
return (uint64_t)(int64_t)pipe((void*)R_RSI);
#endif
#ifndef __NR_select
case 23: // sys_select
return (uint32_t)select(R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
return (uint64_t)(int64_t)select(R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
#endif
case 25: // sys_mremap
return (uintptr_t)my_mremap(emu, (void*)R_RSI, R_RDX, R_RCX, R_R8d, (void*)R_R9);
#ifndef __NR_vfork
case 56: // vfork
return vfork();
#endif
#ifndef __NR_fork
case 57:
return fork();
@@ -428,18 +495,18 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
#endif
#ifndef __NR_mkdir
case 83: // sys_mkdir
return (uint32_t)mkdir((void*)R_RSI, R_EDX);
return (uint64_t)(int64_t)mkdir((void*)R_RSI, R_EDX);
#endif
#ifndef __NR_unlink
case 87: //sys_unlink
return (uint32_t)unlink((void*)R_RSI);
return (uint64_t)(int64_t)unlink((void*)R_RSI);
#endif
case 89: // sys_readlink
return (uintptr_t)my_readlink(emu,(void*)R_RSI, (void*)R_RDX, (size_t)R_RCX);
case 131: // sys_sigaltstack
return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
return (uint64_t)(int64_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
case 158: // sys_arch_prctl
return (uint32_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX);
return (uint64_t)(int64_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX);
#ifndef __NR_time
case 201: // sys_time
return (uintptr_t)time((void*)R_RSI);
@@ -448,6 +515,10 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
case 253:
return (int)syscall(__NR_inotify_init1, 0);
#endif
#ifndef __NR_fchmodat4
case 434:
return (int)fchmodat((int)R_ESI, (void*)R_RDX, (mode_t)R_RCX, (int)R_R8d);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
emu->quit = 1;
+9 -6
View File
@@ -136,23 +136,26 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
int my_arch_prctl(x64emu_t *emu, int code, void* addr)
{
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
switch(code) {
case ARCH_GET_GS:
*(void**)addr = GetSegmentBase(emu->segs[_GS]);
return 0;
case ARCH_SET_GS:
if(emu->segs[_GS]!=(0xa<<3)) {
pthread_once(&thread_key_once3, thread_key_alloc3);
emu->segs[_GS] = 0xa<<3;
if(!default_gs)
default_gs = 0xa<<3;
}
pthread_once(&thread_key_once3, thread_key_alloc3);
if(emu->segs[_GS]!=(0xa<<3))
emu->segs[_GS] = 0xa<<3; // should not move!
emu->segs_serial[_GS] = 0;
my_context->segtls[3].base = (uintptr_t)addr;
my_context->segtls[3].limit = 0;
my_context->segtls[3].present = 1;
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
return 0;
case ARCH_GET_FS:
*(void**)addr = GetSegmentBase(emu->segs[_FS]);
return 0;
}
// other are unsupported
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
+25 -9
View File
@@ -21,7 +21,7 @@ void fpu_do_free(x64emu_t* emu, int i)
void reset_fpu(x64emu_t* emu)
{
memset(emu->mmx87, 0, sizeof(emu->mmx87));
memset(emu->x87, 0, sizeof(emu->x87));
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
emu->cw = 0x37F;
emu->sw.x16 = 0x0000;
@@ -177,8 +177,8 @@ void D2LD(void* d, void* ld)
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
int32_t exp80 = s.ud[1]&0x7ff00000;
int32_t exp80final = (exp80>>20);
int64_t mant80 = s.q&0x000fffffffffffffL;
int64_t mant80final = (mant80 << 11);
uint64_t mant80 = s.q&0x000fffffffffffffL;
uint64_t mant80final = (mant80 << 11);
if(exp80final==0x7ff) {
// NaN and Infinite
exp80final = 0x7fff;
@@ -294,7 +294,11 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
{
xsave32_t *p = (xsave32_t*)ed;
// should save flags & all
emu->sw.f.F87_TOP = emu->top&7;
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
emu->sw.f.F87_TOP = top;
p->ControlWord = emu->cw;
p->StatusWord = emu->sw.x16;
uint8_t tags = 0;
@@ -310,7 +314,7 @@ void fpu_fxsave32(x64emu_t* emu, void* ed)
p->MxCsr_Mask = 0;
// copy FPU/MMX regs...
for(int i=0; i<8; ++i)
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
// copy SSE regs
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
}
@@ -319,7 +323,11 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
{
xsave64_t *p = (xsave64_t*)ed;
// should save flags & all
emu->sw.f.F87_TOP = emu->top&7;
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
emu->sw.f.F87_TOP = top;
p->ControlWord = emu->cw;
p->StatusWord = emu->sw.x16;
uint8_t tags = 0;
@@ -333,7 +341,7 @@ void fpu_fxsave64(x64emu_t* emu, void* ed)
p->MxCsr_Mask = 0;
// copy FPU/MMX regs...
for(int i=0; i<8; ++i)
memcpy(&p->FloatRegisters[i].q[0], &emu->mmx87[0], sizeof(emu->mmx87[0]));
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
// copy SSE regs
memcpy(&p->XmmRegisters[0], &emu->xmm[0], sizeof(emu->xmm));
}
@@ -347,9 +355,13 @@ void fpu_fxrstor32(x64emu_t* emu, void* ed)
uint8_t tags = p->TagWord;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
// copy SSE regs
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
}
@@ -363,9 +375,13 @@ void fpu_fxrstor64(x64emu_t* emu, void* ed)
uint8_t tags = p->TagWord;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx87[i], &p->FloatRegisters[i].q[0], sizeof(emu->mmx87[0]));
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
// copy SSE regs
memcpy(&emu->xmm[0], &p->XmmRegisters[0], sizeof(emu->xmm));
}
+3 -3
View File
@@ -14,9 +14,9 @@ typedef struct x64emu_s x64emu_t;
#define LN2 0.69314718055994531
#define LG2 0.3010299956639812
#define ST0 emu->mmx87[emu->top]
#define ST1 emu->mmx87[(emu->top+1)&7]
#define ST(a) emu->mmx87[(emu->top+(a))&7]
#define ST0 emu->x87[emu->top]
#define ST1 emu->x87[(emu->top+1)&7]
#define ST(a) emu->x87[(emu->top+(a))&7]
#define STld(a) emu->fpu_ld[(emu->top+(a))&7]
#define STll(a) emu->fpu_ll[(emu->top+(a))&7]
+3
View File
@@ -82,6 +82,7 @@ typedef struct box64context_s {
char* fullpath;
char* box64path; // path of current box64 executable
char* box86path; // path of box86 executable (if present)
uint64_t stacksz;
size_t stackalign;
@@ -103,6 +104,7 @@ typedef struct box64context_s {
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
bridge_t *system; // other bridges
uintptr_t vsyscall; // vsyscall bridge value
uintptr_t vsyscalls[3]; // the 3 x86 VSyscall pseudo bridges (mapped at 0xffffffffff600000+)
dlprivate_t *dlprivate; // dlopen library map
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
kh_symbolmap_t *glmymap; // link to the mysymbolmap of libGL
@@ -121,6 +123,7 @@ typedef struct box64context_s {
#endif
pthread_mutex_t mutex_tls;
pthread_mutex_t mutex_thread;
pthread_mutex_t mutex_bridge;
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
+2
View File
@@ -17,6 +17,8 @@ uintptr_t AddAutomaticBridge(x64emu_t* emu, bridge_t* bridge, wrapper_t w, void*
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
uintptr_t AddVSyscall(bridge_t* bridge, int num);
int hasAlternate(void* addr);
void* getAlternate(void* addr);
void addAlternate(void* addr, void* alt);
+1 -3
View File
@@ -45,10 +45,8 @@ uint32_t getProtection(uintptr_t addr);
void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(uintptr_t addr, size_t size);
void protectDBnolock(uintptr_t addr, size_t size);
void unprotectDB(uintptr_t addr, size_t size);
void lockDB();
void unlockDB();
int isprotectedDB(uintptr_t addr, size_t size);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
+10
View File
@@ -13,6 +13,15 @@ extern int box64_dynarec_dump;
extern int box64_dynarec_trace;
extern int box64_dynarec_forced;
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
extern int box64_dynarec_bigblock;
extern int box64_dynarec_strongmem;
#ifdef ARM64
extern int arm64_asimd;
extern int arm64_aes;
extern int arm64_pmull;
extern int arm64_crc32;
extern int arm64_atomics;
#endif
#endif
extern int dlsym_error; // log dlsym error
#ifdef HAVE_TRACE
@@ -23,6 +32,7 @@ extern uintptr_t trace_start, trace_end;
extern char* trace_func;
#endif
extern int allow_missing_libs;
extern int box64_prefer_wrapped;
extern int box64_steam;
extern int box64_wine;
extern int box64_nopulse; // disabling the use of wrapped pulseaudio
+6 -1
View File
@@ -9,7 +9,7 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db);
void FreeDynablock(dynablock_t* db, int need_lock);
void MarkDynablock(dynablock_t* db);
//return 1 if Dynareblock is empty
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
@@ -29,4 +29,9 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
// for use in signal handler
void cancelFillBlock();
int IsInHotPage(uintptr_t addr);
void AddHotPage(uintptr_t addr);
#endif //__DYNABLOCK_H_
+1
View File
@@ -4,6 +4,7 @@
typedef struct dynablock_s dynablock_t;
typedef struct x64emu_s x64emu_t;
void CancelBlock64();
void* FillBlock64(dynablock_t* block, uintptr_t addr);
#endif //__DYNAREC_ARM_H_
+3 -3
View File
@@ -24,13 +24,13 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
void FreeElfMemory(elfheader_t* head);
int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, box64context_t *box64, x64emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RunElfInit(elfheader_t* h, x64emu_t *emu);
+1
View File
@@ -14,6 +14,7 @@ int FileExist(const char* filename, int flags);
char* ResolveFile(const char* filename, path_collection_t* paths);
// 1: if file is an x86 elf, 0: if not (or not found)
int FileIsX86ELF(const char* filename);
int FileIsX64ELF(const char* filename);
#if defined(RPI) || defined(RK3399) || defined(RK3326)
+3 -3
View File
@@ -2,11 +2,11 @@
#define _GLOBAL_SYMBOLS_H_
//GTK stuff
//void my_checkGlobalGdkDisplay();
//void my_setGlobalGThreadsInit();
void my_checkGlobalGdkDisplay();
void my_setGlobalGThreadsInit();
//void** my_GetGTKDisplay();
//void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
// NCurse / TInfo
void my_checkGlobalTInfo();
+338
View File
@@ -0,0 +1,338 @@
#ifndef __GTKCLASS_H__
#define __GTKCLASS_H__
#include <stdint.h>
#include <stddef.h>
#include "globalsymbols.h"
typedef struct box64context_s box64context_t;
typedef struct bridge_s bridge_t;
typedef struct my_GValue_s
{
size_t g_type;
union {
int v_int;
int64_t v_int64;
uint64_t v_uint64;
float v_float;
double v_double;
void* v_pointer;
} data[2];
} my_GValue_t;
typedef struct my_GObjectClass_s
{
size_t g_type_class;
void* construct_properties;
void* (*constructor) (int type, uint32_t n_construct_properties, void* construct_properties);
void (*set_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*get_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*dispose) (void* object);
void (*finalize) (void* object);
void (*dispatch_properties_changed) (void* object, uint32_t n_pspecs, void* pspecs);
void (*notify) (void* object, void* pspec);
void (*constructed) (void* object);
uint32_t flags;
void* pdummy[6];
} my_GObjectClass_t;
typedef struct my_GtkObjectClass_s
{
my_GObjectClass_t parent_class;
void (*set_arg) (void* object, void* arg, uint32_t arg_id);
void (*get_arg) (void* object, void* arg, uint32_t arg_id);
void (*destroy) (void* object);
} my_GtkObjectClass_t;
typedef struct my_GtkWidgetClass_s
{
my_GtkObjectClass_t parent_class;
uint32_t activate_signal;
uint32_t set_scroll_adjustments_signal;
void (*dispatch_child_properties_changed) (void* widget, uint32_t n_pspecs, void* pspecs);
void (* show) (void* widget);
void (* show_all) (void* widget);
void (* hide) (void* widget);
void (* hide_all) (void* widget);
void (* map) (void* widget);
void (* unmap) (void* widget);
void (* realize) (void* widget);
void (* unrealize) (void* widget);
void (* size_request) (void* widget, void* requisition);
void (* size_allocate) (void* widget, void* allocation);
void (* state_changed) (void* widget, int previous_state);
void (* parent_set) (void* widget, void* previous_parent);
void (* hierarchy_changed) (void* widget, void* previous_toplevel);
void (* style_set) (void* widget, void* previous_style);
void (* direction_changed) (void* widget, int previous_direction);
void (* grab_notify) (void* widget, int was_grabbed);
void (* child_notify) (void* widget, void* pspec);
int (* mnemonic_activate) (void* widget, int group_cycling);
void (* grab_focus) (void* widget);
int (* focus) (void* widget, int direction);
int (* event) (void* widget, void* event);
int (* button_press_event) (void* widget, void* event);
int (* button_release_event) (void* widget, void* event);
int (* scroll_event) (void* widget, void* event);
int (* motion_notify_event) (void* widget, void* event);
int (* delete_event) (void* widget, void* event);
int (* destroy_event) (void* widget, void* event);
int (* expose_event) (void* widget, void* event);
int (* key_press_event) (void* widget, void* event);
int (* key_release_event) (void* widget, void* event);
int (* enter_notify_event) (void* widget, void* event);
int (* leave_notify_event) (void* widget, void* event);
int (* configure_event) (void* widget, void* event);
int (* focus_in_event) (void* widget, void* event);
int (* focus_out_event) (void* widget, void* event);
int (* map_event) (void* widget, void* event);
int (* unmap_event) (void* widget, void* event);
int (* property_notify_event) (void* widget, void* event);
int (* selection_clear_event) (void* widget, void* event);
int (* selection_request_event) (void* widget, void* event);
int (* selection_notify_event) (void* widget, void* event);
int (* proximity_in_event) (void* widget, void* event);
int (* proximity_out_event) (void* widget, void* event);
int (* visibility_notify_event) (void* widget, void* event);
int (* client_event) (void* widget, void* event);
int (* no_expose_event) (void* widget, void* event);
int (* window_state_event) (void* widget, void* event);
void (* selection_get) (void* widget, void* selection_data, uint32_t info, uint32_t time_);
void (* selection_received) (void* widget, void* selection_data, uint32_t time_);
void (* drag_begin) (void* widget, void* context);
void (* drag_end) (void* widget, void* context);
void (* drag_data_get) (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_);
void (* drag_data_delete) (void* widget, void* context);
void (* drag_leave) (void* widget, void* context,uint32_t time_);
int (* drag_motion) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
int (* drag_drop) (void* widget, void* context, int32_t x, int32_t y, uint32_t time_);
void (* drag_data_received) (void* widget, void* context, int32_t x, int32_t y, void* selection_data, uint32_t info, uint32_t time_);
int (* popup_menu) (void* widget);
int (* show_help) (void* widget, int help_type);
void*(*get_accessible) (void* widget);
void (*screen_changed) (void* widget, void* previous_screen);
int (*can_activate_accel) (void* widget, uint32_t signal_id);
int (*grab_broken_event) (void* widget, void* event);
void (* composited_changed) (void* widget);
int (* query_tooltip) (void* widget, int32_t x, int32_t y, int keyboard_tooltip, void* tooltip);
void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void);
} my_GtkWidgetClass_t;
typedef struct my_GtkContainerClass_s
{
my_GtkWidgetClass_t parent_class;
void (*add) (void* container, void* widget);
void (*remove) (void* container, void* widget);
void (*check_resize) (void* container);
void (*forall) (void* container, int include_internals, void* callback, void* callback_data);
void (*set_focus_child) (void* container, void* widget);
int (*child_type) (void* container);
void* (*composite_name) (void* container, void* child);
void (*set_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
void (*get_child_property) (void* container, void* child, uint32_t property_id, void* value, void* pspec);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkContainerClass_t;
typedef struct my_GtkActionClass_s
{
my_GObjectClass_t parent_class;
void (* activate) (void* action);
int menu_item_type;
int toolbar_item_type;
void* (* create_menu_item) (void* action);
void* (* create_tool_item) (void* action);
void (* connect_proxy) (void* action, void* proxy);
void (* disconnect_proxy) (void* action, void* proxy);
void* (* create_menu) (void* action);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkActionClass_t;
typedef struct my_GtkMiscClass_s
{
my_GtkWidgetClass_t parent_class;
} my_GtkMiscClass_t;
typedef struct my_GtkLabelClass_s
{
my_GtkMiscClass_t parent_class;
void (* move_cursor) (void* label, int step, int count, int extend_selection);
void (* copy_clipboard) (void* label);
void (* populate_popup) (void* label, void* menu);
int (*activate_link) (void* label, void* uri);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkLabelClass_t;
typedef struct my_GtkTreeViewClass_s
{
my_GtkContainerClass_t parent_class;
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
void (* row_activated) (void* tree_view, void* path, void* column);
int (* test_expand_row) (void* tree_view, void* iter, void* path);
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
void (* row_expanded) (void* tree_view, void* iter, void* path);
void (* row_collapsed) (void* tree_view, void* iter, void* path);
void (* columns_changed) (void* tree_view);
void (* cursor_changed) (void* tree_view);
int (* move_cursor) (void* tree_view, int step, int count);
int (* select_all) (void* tree_view);
int (* unselect_all) (void* tree_view);
int (* select_cursor_row) (void* tree_view, int start_editing);
int (* toggle_cursor_row) (void* tree_view);
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
int (* select_cursor_parent) (void* tree_view);
int (* start_interactive_search) (void* tree_view);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkTreeViewClass_t;
typedef struct my_GtkBinClass_s
{
my_GtkContainerClass_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkBinClass_t;
typedef struct my_GtkWindowClass_s {
my_GtkBinClass_t parent_class;
void (* set_focus) (void* window, void* focus);
int (* frame_event) (void* window, void* event);
void (* activate_focus) (void* window);
void (* activate_default) (void* window);
void (* move_focus) (void* window, int direction);
void (*keys_changed) (void* window);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkWindowClass_t;
typedef struct my_MetaFramesClass_s
{
my_GtkWindowClass_t parent_class;
} my_MetaFramesClass_t;
typedef struct my_GtkTableClass_s
{
my_GtkContainerClass_t parent_class;
} my_GtkTableClass_t;
typedef struct my_GtkFixedClass_s
{
my_GtkContainerClass_t parent_class;
} my_GtkFixedClass_t;
// GTypeValueTable
typedef struct my_GTypeValueTable_s {
void (*value_init) (void* value);
void (*value_free) (void* value);
void (*value_copy) (void* src_value, void* dest_value);
void* (*value_peek_pointer) (void* value);
void* collect_format;
void* (*collect_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
void* lcopy_format;
void* (*lcopy_value) (void* value, uint32_t n_collect_values, void* collect_values, uint32_t collect_flags);
} my_GTypeValueTable_t;
// GTypeInfo
typedef void (*GBaseInitFunc) (void* g_class);
typedef void (*GBaseFinalizeFunc) (void* g_class);
typedef void (*GClassInitFunc) (void* g_class, void* class_data);
typedef void (*GClassFinalizeFunc) (void* g_class, void* class_data);
typedef void (*GInstanceInitFunc) (void* instance, void* g_class);
typedef struct my_GTypeInfo_s {
uint16_t class_size;
GBaseInitFunc base_init;
GBaseFinalizeFunc base_finalize;
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
void* class_data;
uint16_t instance_size;
uint16_t n_preallocs;
GInstanceInitFunc instance_init;
my_GTypeValueTable_t* value_table;
} my_GTypeInfo_t;
// GtkTypeInfo
typedef GBaseInitFunc GtkClassInitFunc;
typedef GInstanceInitFunc GtkObjectInitFunc;
typedef struct my_GtkTypeInfo_s {
void* type_name;
uint32_t object_size;
uint32_t class_size;
GtkClassInitFunc class_init_func;
GtkObjectInitFunc object_init_func;
void* reserved_1;
void* reserved_2;
GtkClassInitFunc base_class_init_func;
} my_GtkTypeInfo_t ;
my_GTypeValueTable_t* findFreeGTypeValueTable(my_GTypeValueTable_t* fcts);
my_GTypeInfo_t* findFreeGTypeInfo(my_GTypeInfo_t* fcts, size_t parent);
my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, size_t parent);
void InitGTKClass(bridge_t *bridge);
void FiniGTKClass();
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget) \
GTKCLASS(GtkContainer) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel) \
GTKCLASS(GtkMisc) \
GTKCLASS(GtkTreeView) \
GTKCLASS(GtkBin) \
GTKCLASS(GtkWindow) \
GTKCLASS(GtkTable) \
GTKCLASS(GtkFixed) \
GTKCLASS(MetaFrames) \
#define GTKCLASS(A) void Set##A##ID(size_t id);
GTKCLASSES()
#undef GTKCLASS
void SetGTypeName(void* f);
void AutoBridgeGtk(void*(*ref)(size_t), void(*unref)(void*));
void* wrapCopyGTKClass(void* cl, size_t type);
void* unwrapCopyGTKClass(void* klass, size_t type);
typedef struct my_signal_s {
uint64_t sign; // signature
void* data;
uintptr_t c_handler;
uintptr_t destroy;
} my_signal_t;
// some random sign to identify a my_signal_t
#define SIGN 0xFB3405EB4510AA00LL
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
void my_signal_delete(my_signal_t* sig);
int my_signal_is_valid(void* sig);
int my_signal_cb(void* a, void* b, void* c, void* d);
void my_add_signal_offset(size_t klass, uint32_t offset, int n);
#endif //__GTKCLASS_H__
Loaded 100 of 663 files, more files were not shown because too many files have changed in this diff. Show more