Compare commits

...
250 Commits
Author SHA1 Message Date
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
502 changed files with 18416 additions and 3465 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
+5
View File
@@ -59,3 +59,8 @@ build*/
src/git_head.h
backup/
# LLVMprivateGenerator
/LLVMprivateGenerator/*
!/LLVMprivateGenerator/Makefile
!/LLVMprivateGenerator/main.cpp
!/LLVMprivateGenerator/registered_structs.cpp
+78 -11
View File
@@ -5,11 +5,12 @@ cmake_policy(SET CMP0065 NEW)
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(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(RK3399 OR RPI4ARM64 OR RK3326 OR TEGRAX1)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -50,18 +51,20 @@ 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(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
if(NOGIT)
@@ -69,7 +72,7 @@ if(NOGIT)
endif()
if(HAVE_TRACE)
set(BOX64 box64t)
set(BOX64 box64)
else()
set(BOX64 box64)
endif()
@@ -200,6 +203,9 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.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 +214,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"
@@ -217,6 +224,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.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"
@@ -230,6 +238,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,6 +264,7 @@ 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/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
@@ -274,6 +291,8 @@ set(WRAPPEDS
"${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"
)
@@ -339,7 +358,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"
@@ -403,17 +422,30 @@ 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 +466,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 +581,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!)
+3
View File
@@ -1,3 +1,6 @@
Current Version
======
v0.1.2
======
* OpenSource!
+18 -2
View File
@@ -31,6 +31,22 @@ 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 Other ARM64 Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
@@ -57,11 +73,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*
+110
View File
@@ -0,0 +1,110 @@
# box64
![Official logo](img/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 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 32buts / 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 libsef/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
* For their major financial contribution: FlyingFathead, stormchaser3000
* 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!)
+5
View File
@@ -134,6 +134,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=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=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-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
}
+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
}
+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
+14 -1
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*)context->vsyscalls[0], (void*)0xffffffffff600000);
addAlternate((void*)context->vsyscalls[1], (void*)0xffffffffff600400);
addAlternate((void*)context->vsyscalls[2], (void*)0xffffffffff600800);
// get handle to box64 itself
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
context->dlprivate = NewDLPrivate();
@@ -268,6 +280,7 @@ void FreeBox64Context(box64context_t** context)
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
free_neededlib(&ctx->neededlibs);
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 1
#define BOX64_REVISION 2
#define BOX64_REVISION 4
#endif //__BOX64_VERSION_H_
+9 -6
View File
@@ -432,10 +432,11 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
if(!size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
#ifndef USE_MMAP
pthread_mutex_lock(&mutex_mmap);
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box64_pagesize, size)) {
pthread_mutex_unlock(&mutex_mmap);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
@@ -443,6 +444,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
#else
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(p==(void*)-1) {
pthread_mutex_unlock(&mutex_mmap);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
@@ -708,11 +710,12 @@ void protectDBnolock(uintptr_t addr, uintptr_t size)
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
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))
if(!(prot&PROT_DYNAREC)) {
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;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
}
}
}
@@ -751,8 +754,8 @@ void unprotectDB(uintptr_t addr, size_t size)
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint8_t prot = kh_value(memprot, k)[ii];
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
if(prot&PROT_DYNAREC) {
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
}
+47 -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))
@@ -628,9 +631,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 +997,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 +1429,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 +1727,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__
+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));
+2 -1
View File
@@ -139,7 +139,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;
+74 -29
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");
@@ -967,7 +970,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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 +998,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 +1388,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 +1957,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;
+79 -8
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
@@ -1307,11 +1337,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 +1365,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 +1393,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 +1541,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 +1641,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;
+215 -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,206 @@ 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(dyn->insts &&
((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;
}
+18 -3
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:
@@ -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:
+307 -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,107 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SXTL_32(q0, q1); // 32bits->64bits
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 +525,16 @@ 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;
VMOVQSfrom(q0, (u8&3), ed);
break;
default:
DEFAULT;
}
@@ -377,6 +558,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 +658,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 +1289,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 +1388,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 +1469,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 +1537,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 +1740,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);
+3
View File
@@ -157,6 +157,9 @@ 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)
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;
+13 -7
View File
@@ -206,7 +206,9 @@ 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);
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 0, 1);
}
LSRxw(s1, s1, c);
@@ -252,7 +254,9 @@ 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);
if(c>1) {
ASRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 0, 1);
}
ASRxw(s1, s1, c);
@@ -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);
if(c>1) {
LSRxw(s3, s1, c-1);
}
BFIw(xFlags, s3, 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);
+180 -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;
@@ -96,6 +96,24 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
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);
}
break;
case 0x0F:
nextop = F8;
switch(nextop) {
@@ -436,6 +454,167 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x80:
nextop = F8;
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;
}
break;
case 0x81:
case 0x83:
nextop = F8;
+18 -6
View File
@@ -288,19 +288,31 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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 0: CSETMx(x2, cEQ); CSELx(x2, xZR, x2, cVS); break; // Equal
case 1: CSETMx(x2, cMI); CSELx(x2, xZR, x2, cVS); break; // Less than
case 2: CSETMx(x2, cLE); CSELx(x2, xZR, x2, cVS); 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
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, cLT); 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 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
+33 -9
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;
@@ -352,6 +363,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");
@@ -365,14 +390,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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 0: CSETMw(x2, cEQ); CSELw(x2, xZR, x2, cVS); break; // Equal
case 1: CSETMw(x2, cMI); CSELw(x2, xZR, x2, cVS); break; // Less than
case 2: CSETMw(x2, cLE); CSELw(x2, xZR, x2, cVS); 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
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, cLT); 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);
+132 -8
View File
@@ -25,10 +25,11 @@
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "custommem.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 +52,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 +81,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 +95,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 +113,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 +125,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 +148,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 +190,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 +444,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;
}
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)
{
+24 -2
View File
@@ -66,7 +66,7 @@
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; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
@@ -106,6 +106,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); \
@@ -725,6 +744,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 +885,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 +915,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);
+1 -1
View File
@@ -100,7 +100,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3))
if(!ok && !need_epilog && !dyn->insts && getProtection(addr+3)&~PROT_CUSTOM)
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
+58 -31
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)
@@ -369,21 +371,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 +430,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)
@@ -451,7 +457,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 +499,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 +540,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 +558,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)];
@@ -642,7 +650,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 +667,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 +696,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 +707,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 +719,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);
@@ -770,42 +783,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 +828,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 +1031,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 +1092,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 +1131,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)
+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;
+76 -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...
}
+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 */
+448 -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,140 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->sq[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 +589,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 +615,75 @@ 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;
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;
}
@@ -965,7 +1299,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 +1547,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;
+12 -5
View File
@@ -55,9 +55,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 +1002,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 +1248,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);
}
@@ -1289,7 +1296,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)
+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;
+11 -1
View File
@@ -212,7 +212,7 @@ 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;
@@ -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);
+36
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;
+102 -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
@@ -124,6 +144,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 +157,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 +281,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 +333,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 +357,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 +391,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 +414,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 +438,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 +493,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 +513,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;
+6 -6
View File
@@ -136,18 +136,18 @@ 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;
+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);
+7
View File
@@ -13,6 +13,12 @@ extern int box64_dynarec_dump;
extern int box64_dynarec_trace;
extern int box64_dynarec_forced;
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
#ifdef ARM64
extern int arm64_asimd;
extern int arm64_aes;
extern int arm64_pmull;
extern int arm64_crc32;
#endif
#endif
extern int dlsym_error; // log dlsym error
#ifdef HAVE_TRACE
@@ -23,6 +29,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
+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)
+1 -1
View File
@@ -24,7 +24,7 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
+1 -1
View File
@@ -12,7 +12,7 @@ typedef struct needed_libs_s needed_libs_t;
library_t *NewLibrary(const char* path, box64context_t* box64);
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu);
int ReloadLibrary(library_t* lib, x64emu_t* emu);
void InactiveLibrary(library_t* lib);
void Free1Library(library_t **lib, x64emu_t* emu);
+35 -6
View File
@@ -35,6 +35,20 @@ typedef struct {
sysv_varargs->reg_save_area=A->reg_save_area; \
sysv_varargs->overflow_arg_area=A->overflow_arg_area;
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
sysv_varargs->gp_offset=(6-((N<6)?N:6))*8;\
sysv_varargs->fp_offset=(6*8); \
sysv_varargs->reg_save_area=SCRATCH; \
sysv_varargs->overflow_arg_area=STACK; \
{ \
uint64_t *p = (uint64_t*)SCRATCH; \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
}
#elif defined(__aarch64__)
// aarch64: 8 64bits general regs and 8 128bits float regs
@@ -54,14 +68,28 @@ typedef struct va_list {
sysv_varargs.__vr_offs=(8*16); \
sysv_varargs.__stack=A;
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
sysv_varargs.__stack=A->overflow_arg_area; \
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
#define CONVERT_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=-(6*8)+A->gp_offset; \
sysv_varargs.__vr_offs=-(8*16)+(A->fp_offset-X64_VA_MAX_REG); \
sysv_varargs.__stack=A->overflow_arg_area; \
sysv_varargs.__gr_top=A->reg_save_area + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=A->reg_save_area + X64_VA_MAX_XMM;
#define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \
va_list sysv_varargs; \
sysv_varargs.__gr_offs=(8*(2+((N<6)?N:6))); \
sysv_varargs.__vr_offs=0; \
sysv_varargs.__stack=STACK; \
sysv_varargs.__gr_top=SCRATCH + X64_VA_MAX_REG; \
sysv_varargs.__vr_top=SCRATCH + X64_VA_MAX_XMM; \
{ \
uint64_t *p = (uint64_t*)SCRATCH; \
p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \
p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \
memcpy(&p[6], emu->xmm, 8*16); \
}
#elif defined(__powerpc64__)
// TODO, is this correct?
#define CREATE_SYSV_VALIST(A) \
@@ -109,6 +137,7 @@ struct x64_stat64 { /* x86_64 arm64 */
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
} __attribute__((packed)); /* 144 */ /* 128 */
void AlignStat64(const void* source, void* dest);
void UnalignStat64(const void* source, void* dest);
// defined in wrapperlibc.c
+3 -3
View File
@@ -150,12 +150,12 @@ typedef struct {
#else
longdouble_t ld;
#endif
uint64_t ref;
uint64_t uref;
} fpu_ld_t;
typedef struct {
int64_t ll;
int64_t ref;
int64_t sq;
int64_t sref;
} fpu_ll_t;
typedef union {
+2 -2
View File
@@ -34,8 +34,8 @@ void SetRSI(x64emu_t *emu, uint64_t v);
void SetRBP(x64emu_t *emu, uint64_t v);
void SetRSP(x64emu_t *emu, uint64_t v);
void SetRIP(x64emu_t *emu, uint64_t v);
void SetFS(x64emu_t *emu, uint16_t v);
uint16_t GetFS(x64emu_t *emu);
//void SetFS(x64emu_t *emu, uint16_t v);
//uint16_t GetFS(x64emu_t *emu);
uint64_t GetRSP(x64emu_t *emu);
uint64_t GetRBP(x64emu_t *emu);
void ResetFlags(x64emu_t *emu);
+8 -8
View File
@@ -46,7 +46,7 @@ static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *free
if (lib->depended.libs[i] == maplib->libraries[j]) break;
}
if (j == maplib->libsz) {
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
printf_log(LOG_DEBUG, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
continue;
}
if (freed[j] == 1) {
@@ -288,7 +288,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
return 0;
}
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, library_t* lib, box64context_t* box64, x64emu_t* emu)
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu)
{
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
@@ -300,22 +300,22 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
} else {
// it's an emulated lib,
// load dependancies and launch init sequence
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box64, emu)) {
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
const char* libs[] = {"libGL.so.1"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box64, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box64, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box64, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box64, emu);
}
// finalize the lib
if(FinalizeLibrary(lib, local?maplib:NULL, emu)) {
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
return 1;
}
@@ -327,7 +327,7 @@ int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* depli
}
EXPORTDYN
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char** paths, int npath, box64context_t* box64, x64emu_t* emu)
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box64context_t* box64, x64emu_t* emu)
{
if(!neededlibs) {
neededlibs = alloca(sizeof(needed_libs_t));
@@ -344,7 +344,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
int idx_end = neededlibs->size;
// add dependant libs and init them
for (int i=idx; i<idx_end; ++i)
if(AddNeededLib_init(maplib, neededlibs, deplib, local, neededlibs->libs[i], box64, emu)) {
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box64, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
if(!allow_missing_libs) return 1;
}
+86 -9
View File
@@ -26,7 +26,7 @@
#include "wrappedlibs.h"
// create the native lib list
#define GO(P, N) int wrapped##N##_init(library_t* lib, box64context_t *box64); \
void wrapped##N##_fini(library_t* lib);\
void wrapped##N##_fini(library_t* lib); \
int wrapped##N##_get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local); \
int wrapped##N##_getnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local);
#include "library_list.h"
@@ -79,12 +79,52 @@ int NbDot(const char* name)
return ret;
}
void NativeLib_CommonInit(library_t *lib) {
lib->priv.w.bridge = NewBridge();
lib->symbolmap = kh_init(symbolmap);
lib->wsymbolmap = kh_init(symbolmap);
lib->mysymbolmap = kh_init(symbolmap);
lib->wmysymbolmap = kh_init(symbolmap);
lib->stsymbolmap = kh_init(symbolmap);
lib->symbol2map = kh_init(symbol2map);
lib->datamap = kh_init(datamap);
lib->wdatamap = kh_init(datamap);
lib->mydatamap = kh_init(datamap);
}
void EmuLib_Fini(library_t* lib)
{
kh_destroy(mapsymbols, lib->priv.n.mapsymbols);
kh_destroy(mapsymbols, lib->priv.n.localsymbols);
}
void NativeLib_FinishFini(library_t* lib)
{
if(lib->priv.w.lib)
dlclose(lib->priv.w.lib);
lib->priv.w.lib = NULL;
if(lib->priv.w.altprefix)
free(lib->priv.w.altprefix);
if(lib->priv.w.neededlibs) {
for(int i=0; i<lib->priv.w.needed; ++i)
free(lib->priv.w.neededlibs[i]);
free(lib->priv.w.neededlibs);
}
FreeBridge(&lib->priv.w.bridge);
}
int WrappedLib_defget(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) {
uintptr_t addr = 0;
uintptr_t size = 0;
if (!getSymbolInMaps(lib, name, 0, &addr, &size, version, vername, local)) {
return 0;
}
if(!addr && !size)
return 0;
*offs = addr;
*sz = size;
return 1;
}
int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
{
// symbols...
@@ -104,6 +144,18 @@ int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz,
}
return 0;
}
int WrappedLib_defgetnoweak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local) {
uintptr_t addr = 0;
uintptr_t size = 0;
if (!getSymbolInMaps(lib, name, 1, &addr, &size, version, vername, local)) {
return 0;
}
if(!addr && !size)
return 0;
*offs = addr;
*sz = size;
return 1;
}
int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local)
{
uintptr_t start, end;
@@ -151,7 +203,7 @@ static void initNativeLib(library_t *lib, box64context_t* context) {
lib->getlocal = NativeLib_GetLocal;
lib->type = 0;
// Call librarian to load all dependant elf
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, thread_get_emu())) {
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, 0, (const char**)lib->priv.w.neededlibs, lib->priv.w.needed, context, thread_get_emu())) {
printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name);
return;
}
@@ -265,18 +317,19 @@ library_t *NewLibrary(const char* path, box64context_t* context)
}
}
int notwrapped = FindInCollection(lib->name, &context->box64_emulated_libs);
int precise = (path && path[0]=='/')?1:0;
// check if name is libSDL_sound-1.0.so.1 but with SDL2 loaded, then try emulated first...
if(!notwrapped && !strcmp(lib->name, "libSDL_sound-1.0.so.1") && my_context->sdl2lib)
notwrapped = 1;
// And now, actually loading a library
// look for native(wrapped) libs first
if(!notwrapped)
if(!notwrapped && !precise)
initNativeLib(lib, context);
// then look for a native one
if(lib->type==-1)
initEmulatedLib(path, lib, context);
// still not loaded but notwrapped indicated: use wrapped...
if(lib->type==-1 && notwrapped)
if(lib->type==-1 && notwrapped && !precise)
initNativeLib(lib, context);
// nothing loaded, so error...
if(lib->type==-1)
@@ -303,7 +356,7 @@ int AddSymbolsLibrary(lib_t *maplib, library_t* lib, x64emu_t* emu)
}
return 0;
}
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu)
{
if(!lib)
return 0;
@@ -313,11 +366,14 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
lib->priv.n.finalized = 1;
elfheader_t *elf_header = my_context->elfs[lib->priv.n.elf_index];
// finalize relocations
if(RelocateElf(my_context->maplib, local_maplib, elf_header)) {
if(RelocateElf(my_context->maplib, local_maplib, bindnow, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
return 1;
}
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
if(RelocateElfPlt(my_context->maplib, local_maplib, bindnow, elf_header)) {
printf_log(LOG_NONE, "Error: relocating Plt symbols in elf %s\n", lib->name);
return 1;
}
#ifdef HAVE_TRACE
if(trace_func) {
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL)) {
@@ -371,11 +427,12 @@ int ReloadLibrary(library_t* lib, x64emu_t* emu)
}
// can close the file now
fclose(f);
if(RelocateElf(lib->context->maplib, lib->maplib, elf_header)) {
// should bindnow be store in a per/library basis?
if(RelocateElf(lib->context->maplib, lib->maplib, 0, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
return 1;
}
RelocateElfPlt(lib->context->maplib, lib->maplib, elf_header);
RelocateElfPlt(lib->context->maplib, lib->maplib, 0, elf_header);
// init (will use PltRelocator... because some other libs are not yet resolved)
RunElfInit(elf_header, emu);
}
@@ -425,6 +482,8 @@ void Free1Library(library_t **lib, x64emu_t* emu)
kh_destroy(datamap, (*lib)->mydatamap);
if((*lib)->mysymbolmap)
kh_destroy(symbolmap, (*lib)->mysymbolmap);
if((*lib)->wmysymbolmap)
kh_destroy(symbolmap, (*lib)->wmysymbolmap);
if((*lib)->stsymbolmap)
kh_destroy(symbolmap, (*lib)->stsymbolmap);
if((*lib)->symbol2map)
@@ -648,6 +707,24 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
return 1;
}
if(!noweak) {
// check in wmysymbolmap
khint_t k = kh_get(symbolmap, lib->wmysymbolmap, name);
if (k!=kh_end(lib->wmysymbolmap)) {
char buff[200];
if(lib->altmy)
strcpy(buff, lib->altmy);
else
strcpy(buff, "my_");
strcat(buff, name);
symbol = dlsym(lib->priv.w.box64lib, buff);
if(!symbol) {
printf_log(LOG_NONE, "Warning, function %s not found\n", buff);
} else
AddOffsetSymbol(lib->context->maplib, symbol, name);
*addr = AddBridge(lib->priv.w.bridge, kh_value(lib->wmysymbolmap, k), symbol, 0, name);
*size = sizeof(void*);
return 1;
}
k = kh_get(symbolmap, lib->wsymbolmap, name);
if (k!=kh_end(lib->wsymbolmap)) {
symbol = dlsym(lib->priv.w.lib, name);
+1
View File
@@ -68,6 +68,7 @@ typedef struct library_s {
kh_symbolmap_t *symbolmap;
kh_symbolmap_t *wsymbolmap;
kh_symbolmap_t *mysymbolmap;
kh_symbolmap_t *wmysymbolmap;
kh_symbolmap_t *stsymbolmap;
kh_symbol2map_t *symbol2map;
kh_datamap_t *datamap;
+16 -10
View File
@@ -52,13 +52,14 @@ GO("libXau.so.6", libxau)
GO("libXdmcp.so.6", libxdmcp)
GO("libX11-xcb.so.1", libx11xcb)
GO("libxcb.so.1", libxcb)
//GO("libxcb-xfixes.so.0", libxcbxfixes)
//GO("libxcb-shape.so.0", libxcbshape)
//GO("libxcb-shm.so.0", libxcbshm)
//GO("libxcb-randr.so.0", libxcbrandr)
//GO("libxcb-image.so.0", libxcbimage)
//GO("libxcb-keysyms.so.1", libxcbkeysyms)
//GO("libxcb-xtest.so.0", libxcbxtest)
GO("libxcb-xfixes.so.0", libxcbxfixes)
GO("libxcb-shape.so.0", libxcbshape)
GO("libxcb-shm.so.0", libxcbshm)
GO("libxcb-randr.so.0", libxcbrandr)
GO("libxcb-image.so.0", libxcbimage)
GO("libxcb-keysyms.so.1", libxcbkeysyms)
GO("libxcb-xtest.so.0", libxcbxtest)
GO("libxcb-glx.so.0", libxcbglx)
//GO("libxcb-dri2.so.0", libxcbdri2)
//GO("libxcb-dri3.so.0", libxcbdri3)
//GO("libxcb-present.so.0", libxcbpresent)
@@ -67,6 +68,8 @@ GO("libXt.so.6", libxt)
GO("libXcomposite.so.1", libxcomposite)
GO("libXdamage.so.1", libxdamage)
GO("libXmu.so.6", libxmu)
GO("libxkbcommon.so.0", xkbcommon)
GO("libxkbcommon-x11.so.0", xkbcommonx11)
GO("libz.so.1", libz)
GO("libopenal.so.1", openal)
GO("libopenal.so.0", openal)
@@ -140,8 +143,9 @@ GO("libpanel.so.5", libpanel)
GO("libncurses.so.6", libncurses6)
GO("libtinfo.so.6", libtinfo6)
GO("libtcmalloc_minimal.so.4", tcmallocminimal)
//GO("libmpg123.so.0", mpg123)
GO("libmpg123.so.0", mpg123)
GO("libgnutls.so.30", gnutls)
GO("libpcre.so.3", libpcre)
GO("libcups.so.2", libcups)
//GO("d3dadapter9.so.1", d3dadapter9)
//GO("libvulkan.so.1", vulkan)
@@ -153,9 +157,11 @@ GO("libxml2.so.2", xml2)
//GO("liblber-2.4.so.2", lber)
//GO("libnsl.so.1", nsl)
//GO("liblcms2.so.2", lcms2)
//GO("libkrb5.so.3", krb5)
//GO("libgssapi_krb5.so.2", gssapikrb5)
GO("libkrb5.so.3", krb5)
GO("libgssapi_krb5.so.2", gssapikrb5)
GO("libgssapi.so.3", gssapi)
//GO("libtiff.so.5", libtiff)
//GO("libfuse.so.2", libfuse)
GO("ld-linux-x86-64.so.2", ldlinux)
+20
View File
@@ -710,6 +710,26 @@ void UnalignStat64(const void* source, void* dest)
x64st->st_ctim = st->st_ctim;
}
void AlignStat64(const void* source, void* dest)
{
struct stat *st = (struct stat*) dest;
struct x64_stat64 *x64st = (struct x64_stat64*)source;
st->st_dev = x64st->st_dev;
st->st_ino = x64st->st_ino;
st->st_mode = x64st->st_mode;
st->st_nlink = x64st->st_nlink;
st->st_uid = x64st->st_uid;
st->st_gid = x64st->st_gid;
st->st_rdev = x64st->st_rdev;
st->st_size = x64st->st_size;
st->st_blksize = x64st->st_blksize;
st->st_blocks = x64st->st_blocks;
st->st_atim = x64st->st_atim;
st->st_mtim = x64st->st_mtim;
st->st_ctim = x64st->st_ctim;
}
typedef union __attribute__((packed)) x64_epoll_data {
void *ptr;
int fd;
+1
View File
@@ -132,6 +132,7 @@ SDL1_RWops_t* RWNativeStart(x64emu_t* emu, SDL1_RWops_t* ops)
SDL1_RWops_t* newrw = Alloc();
newrw->type = BOX64RW;
newrw->hidden.my.orig = ops;
newrw->hidden.my.custom_free = (sdl1_freerw)emu->context->sdl1freerw;
// create wrapper
#define GO(A, W) \
newrw->A = my_emulated_##A;
+87 -71
View File
@@ -264,10 +264,14 @@ static void sigstack_key_alloc() {
pthread_key_create(&sigstack_key, sigstack_destroy);
}
uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...)
{
if(fnc==0 || fnc==1) {
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_IGN":"SIG_DFL");
if(fnc==0) {
printf_log(LOG_NONE, "Unhandled signal caught, aborting\n");
abort();
}
return 0;
}
#ifdef HAVE_TRACE
@@ -303,10 +307,45 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
}
va_end (va);
EmuCall(emu, fnc); // avoid DynaCall for now
int oldquitonlongjmp = emu->quitonlongjmp;
emu->quitonlongjmp = 2;
//EmuCall(emu, fnc); // avoid DynaCall for now
DynaCall(emu, fnc);
if(nargs>6)
R_RSP+=((nargs-6)*4);
emu->quitonlongjmp = oldquitonlongjmp;
if(emu->longjmp) {
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
emu->longjmp = 0;
if(sigcontext) {
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
sigcontext->uc_mcontext.gregs[X64_R9] = R_R9;
sigcontext->uc_mcontext.gregs[X64_R10] = R_R10;
sigcontext->uc_mcontext.gregs[X64_R11] = R_R11;
sigcontext->uc_mcontext.gregs[X64_R12] = R_R12;
sigcontext->uc_mcontext.gregs[X64_R13] = R_R13;
sigcontext->uc_mcontext.gregs[X64_R14] = R_R14;
sigcontext->uc_mcontext.gregs[X64_R15] = R_R15;
sigcontext->uc_mcontext.gregs[X64_RAX] = R_RAX;
sigcontext->uc_mcontext.gregs[X64_RCX] = R_RCX;
sigcontext->uc_mcontext.gregs[X64_RDX] = R_RDX;
sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI;
sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI;
sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP;
sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
// flags
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64;
// get segments
sigcontext->uc_mcontext.gregs[X64_CSGSFS] = ((uint64_t)(R_CS)) | (((uint64_t)(R_GS))<<16) | (((uint64_t)(R_FS))<<32);
} else {
printf_log(LOG_NONE, "Warning, longjmp in signal but no sigcontext to change\n");
}
}
if(exit)
*exit = emu->exit;
@@ -374,42 +413,6 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
}
void my_sighandler(int32_t sig)
{
int Locks = unlockMutex();
printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
// save values
x64emu_t *emu = thread_get_emu();
uintptr_t restorer = my_context->restorer[sig];
uintptr_t old_regs[16] = {0};
uintptr_t old_ip = emu->ip.q[0];
uint64_t old_flags = emu->eflags.x64;
for(int i=0; i<16; ++i)
old_regs[i] = emu->regs[i].q[0];
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
if(new_ss) {
// no alternate stack, so signal RSP needs to match thread RSP!
R_RSP = (uintptr_t)(new_ss->ss_sp+new_ss->ss_size-32);
}
int exits = 0;
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
// restore regs
emu->ip.q[0] = old_ip;
emu->eflags.x64 = old_flags;
for(int i=0; i<16; ++i)
emu->regs[i].q[0] = old_regs[i];
if(exits) {
relockMutex(Locks);
exit(ret);
}
// what about the restored regs?
if(restorer)
RunFunctionHandler(&exits, restorer, 0);
relockMutex(Locks);
}
#ifdef DYNAREC
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
{
@@ -435,7 +438,7 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
}
#endif
void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
{
int Locks = unlockMutex();
@@ -444,13 +447,13 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
uintptr_t restorer = my_context->restorer[sig];
// get that actual ESP first!
x64emu_t *emu = thread_get_emu();
uintptr_t *frame = (uintptr_t*)R_RSP;
uintptr_t frame = R_RSP;
#if defined(DYNAREC) && defined(__aarch64__)
ucontext_t *p = (ucontext_t *)ucntx;
void * pc = (void*)p->uc_mcontext.pc;
dynablock_t* db = (dynablock_t*)cur_db;//FindDynablockFromNativeAddress(pc);
if(db) {
frame = (uintptr_t*)p->uc_mcontext.regs[10+_SP];
frame = (uintptr_t)p->uc_mcontext.regs[10+_SP];
}
#else
(void)ucntx; (void)cur_db;
@@ -460,9 +463,9 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
int used_stack = 0;
if(new_ss) {
if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
frame = (uintptr_t*)emu->regs[_SP].q[0];
frame = (uintptr_t)emu->regs[_SP].q[0];
} else {
frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
frame = (uintptr_t)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
used_stack = 1;
new_ss->ss_flags = SS_ONSTACK;
}
@@ -471,7 +474,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
// TODO: do I need to really setup 2 stack frame? That doesn't seems right!
// setup stack frame
// try to fill some sigcontext....
frame -= sizeof(x64_ucontext_t)/sizeof(uintptr_t);
frame -= sizeof(x64_ucontext_t);
x64_ucontext_t *sigcontext = (x64_ucontext_t*)frame;
// get general register
sigcontext->uc_mcontext.gregs[X64_R8] = R_R8;
@@ -488,9 +491,9 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
sigcontext->uc_mcontext.gregs[X64_RDI] = R_RDI;
sigcontext->uc_mcontext.gregs[X64_RSI] = R_RSI;
sigcontext->uc_mcontext.gregs[X64_RBP] = R_RBP;
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
sigcontext->uc_mcontext.gregs[X64_RSP] = R_RSP;
sigcontext->uc_mcontext.gregs[X64_RBX] = R_RBX;
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;//emu->old_ip; // old_ip should be more accurate as the "current" IP, but it's not always up-to-date
// flags
sigcontext->uc_mcontext.gregs[X64_EFL] = emu->eflags.x64;
// get segments
@@ -555,8 +558,8 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17;
else if(sig==SIGSEGV) {
if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) {
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0010; // execution flag issue (probably)
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:0x0010; // execution flag issue (probably), unless it's a #GP(0)
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR || (info->si_errno==0x1234) || (uintptr_t)info->si_addr==0)?13:14;
} else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue
if(labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16)
@@ -588,12 +591,16 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
GO(RBP);
#undef GO
// set stack pointer
R_RSP = (uintptr_t)frame;
R_RSP = frame;
// set frame pointer
R_RBP = sigcontext->uc_mcontext.gregs[X64_RBP];
int exits = 0;
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
int ret;
if (simple)
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig);
else
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info, sigcontext);
// restore old value from emu
#define GO(A) R_##A = old_##A
GO(RAX);
@@ -643,7 +650,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
GO(FS);
#undef GO
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n");
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p\n", (void*)R_RIP);
if(old_code)
*old_code = -1; // re-init the value to allow another segfault at the same place
if(used_stack) // release stack
@@ -692,7 +699,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
exit(ret);
}
if(restorer)
RunFunctionHandler(&exits, 0, restorer, 0);
RunFunctionHandler(&exits, NULL, restorer, 0);
if(used_stack) // release stack
new_ss->ss_flags = 0;
relockMutex(Locks);
@@ -701,7 +708,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
{
// sig==SIGSEGV || sig==SIGBUS || sig==SIGILL here!
int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_INFO:LOG_NONE;
int log_minimum = (my_context->is_sigaction[sig] && sig==SIGSEGV)?LOG_DEBUG:LOG_INFO;
ucontext_t *p = (ucontext_t *)ucntx;
void* addr = (void*)info->si_addr; // address that triggered the issue
void* rsp = NULL;
@@ -791,7 +798,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
static void* glitch_pc = NULL;
static void* glitch_addr = NULL;
static int glitch_prot = 0;
if(addr && pc && db) {
if(addr && pc /*&& db*/) {
if((glitch_pc!=pc || glitch_addr!=addr || glitch_prot!=prot)) {
// probably a glitch due to intensive multitask...
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x, retrying\n", pc, addr, db, prot);
@@ -834,6 +841,9 @@ exit(-1);
const char* x64name = NULL;
const char* elfname = NULL;
x64emu_t* emu = thread_get_emu();
// Adjust RIP for special case of NULL function run
if(sig==SIGSEGV && R_RIP==0x1 && (uintptr_t)info->si_addr==0x0)
R_RIP = 0x0;
x64pc = R_RIP;
rsp = (void*)R_RSP;
#if defined(__aarch64__) && defined(DYNAREC)
@@ -887,7 +897,7 @@ exit(-1);
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code);
#endif
if(sig==SIGILL)
printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7]);
printf_log(log_minimum, " opcode=%02X %02X %02X %02X %02X %02X %02X %02X (%02X %02X %02X %02X %02X)\n", ((uint8_t*)pc)[0], ((uint8_t*)pc)[1], ((uint8_t*)pc)[2], ((uint8_t*)pc)[3], ((uint8_t*)pc)[4], ((uint8_t*)pc)[5], ((uint8_t*)pc)[6], ((uint8_t*)pc)[7], ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4]);
else if(sig==SIGBUS)
printf_log(log_minimum, " x86opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)x64pc)[0], ((uint8_t*)x64pc)[1], ((uint8_t*)x64pc)[2], ((uint8_t*)x64pc)[3], ((uint8_t*)x64pc)[4], ((uint8_t*)x64pc)[5], ((uint8_t*)x64pc)[6], ((uint8_t*)x64pc)[7]);
else
@@ -895,10 +905,7 @@ exit(-1);
}
relockMutex(Locks);
if(my_context->signals[sig] && my_context->signals[sig]!=1) {
if(my_context->is_sigaction[sig])
my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
else
my_sighandler(sig);
my_sigactionhandler_oldcode(sig, my_context->is_sigaction[sig]?0:1, info, ucntx, &old_code, db);
return;
}
// no handler (or double identical segfault)
@@ -918,7 +925,7 @@ void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx)
void* db = NULL;
#endif
my_sigactionhandler_oldcode(sig, info, ucntx, NULL, db);
my_sigactionhandler_oldcode(sig, 0, info, ucntx, NULL, db);
}
void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
@@ -927,7 +934,7 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
void* db = NULL;
siginfo_t info = {0};
info.si_signo = sig;
info.si_errno = 0;
info.si_errno = (sig==SIGSEGV)?0x1234:0; // MAark as a sign this is a #GP(0) (like privileged instruction)
info.si_code = code;
info.si_addr = addr;
const char* x64name = NULL;
@@ -939,8 +946,8 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code)
elfname = ElfName(elf);
}
printf_log(LOG_INFO, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=%d\n", sig, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr, code);
my_sigactionhandler_oldcode(sig, &info, &ctx, NULL, db);
printf_log(/*LOG_INFO*/LOG_DEBUG, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=%d\n", sig, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr, code);
my_sigactionhandler_oldcode(sig, 0, &info, &ctx, NULL, db);
}
EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler)
@@ -955,14 +962,20 @@ EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler)
my_context->signals[signum] = (uintptr_t)handler;
my_context->is_sigaction[signum] = 0;
my_context->restorer[signum] = 0;
if(handler!=NULL && handler!=(sighandler_t)1) {
handler = my_sighandler;
}
my_context->onstack[signum] = 0;
if(signum==SIGSEGV || signum==SIGBUS || signum==SIGILL)
return 0;
return signal(signum, handler);
if(handler!=NULL && handler!=(sighandler_t)1) {
struct sigaction newact = {0};
struct sigaction oldact = {0};
newact.sa_flags = 0x04;
newact.sa_sigaction = my_sigactionhandler;
sigaction(signum, &newact, &oldact);
return oldact.sa_handler;
} else
return signal(signum, handler);
}
EXPORT sighandler_t my___sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal")));
EXPORT sighandler_t my_sysv_signal(x64emu_t* emu, int signum, sighandler_t handler) __attribute__((alias("my_signal"))); // not completly exact
@@ -993,7 +1006,8 @@ int EXPORT my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
my_context->is_sigaction[signum] = 0;
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
newact.sa_handler = my_sighandler;
newact.sa_flags|=0x04;
newact.sa_sigaction = my_sigactionhandler;
} else
newact.sa_handler = act->_u._sa_handler;
}
@@ -1046,7 +1060,8 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
my_context->is_sigaction[signum] = 0;
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
newact.k_sa_handler = my_sighandler;
newact.sa_flags|=0x4;
newact.k_sa_handler = (void*)my_sigactionhandler;
} else {
newact.k_sa_handler = act->_u._sa_handler;
}
@@ -1088,7 +1103,8 @@ int EXPORT my_syscall_rt_sigaction(x64emu_t* emu, int signum, const x64_sigactio
if(act->_u._sa_handler!=NULL && act->_u._sa_handler!=(sighandler_t)1) {
my_context->signals[signum] = (uintptr_t)act->_u._sa_handler;
my_context->is_sigaction[signum] = 0;
newact.sa_handler = my_sighandler;
newact.sa_sigaction = my_sigactionhandler;
newact.sa_flags|=0x4;
} else {
newact.sa_handler = act->_u._sa_handler;
}
@@ -1264,7 +1280,7 @@ void init_signal_helper(box64context_t* context)
{
// setup signal handling
for(int i=0; i<MAX_SIGNAL; ++i) {
context->signals[i] = 1; // SIG_DFL
context->signals[i] = 0; // SIG_DFL
}
struct sigaction action = {0};
action.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
+11 -3
View File
@@ -197,7 +197,8 @@ x64emu_t* thread_get_emu()
size_t stack_size;
void *stack_addr;
if(!pthread_attr_getstack(&attr, &stack_addr, &stack_size))
stacksize = stack_size;
if(stack_size)
stacksize = stack_size;
pthread_attr_destroy(&attr);
}
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
@@ -363,8 +364,11 @@ EXPORT int my_pthread_attr_getstacksize(x64emu_t* emu, pthread_attr_t* attr, siz
{
(void)emu;
void* addr;
return pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
int ret = pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
if(!*size)
*size = 2*1024*1024;
//return pthread_attr_getstacksize(getAlignedAttr(attr), size);
return ret;
}
EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr)
{
@@ -464,7 +468,7 @@ void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
SetupX64Emu(emuthread);
SetFS(emuthread, GetFS(emu));
//SetFS(emuthread, GetFS(emu));
et->emu = emuthread;
et->fnc = (uintptr_t)f;
et->arg = arg;
@@ -835,6 +839,10 @@ pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
}
pthread_mutex_t* ret = GetMutex(k);
#ifndef __PTHREAD_MUTEX_HAVE_PREV
#define __PTHREAD_MUTEX_HAVE_PREV 1
#endif
if(init) {
if(am->sign == SIGNMTX) {
int kind = ((int*)am->m)[3+__PTHREAD_MUTEX_HAVE_PREV]; // extract kind from original mutex
+93 -14
View File
@@ -9,6 +9,12 @@
#include <signal.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#ifdef DYNAREC
#ifdef ARM64
#include <linux/auxvec.h>
#include <asm/hwcap.h>
#endif
#endif
#include "build_info.h"
#include "debug.h"
@@ -38,6 +44,12 @@ int box64_dynarec_dump = 0;
int box64_dynarec_forced = 0;
uintptr_t box64_nodynarec_start = 0;
uintptr_t box64_nodynarec_end = 0;
#ifdef ARM64
int arm64_asimd = 0;
int arm64_aes = 0;
int arm64_pmull = 0;
int arm64_crc32 = 0;
#endif
#else //DYNAREC
int box64_dynarec = 0;
#endif
@@ -56,6 +68,7 @@ int box64_dynarec_trace = 0;
int x11threads = 0;
int x11glx = 1;
int allow_missing_libs = 0;
int box64_prefer_wrapped = 0;
int fix_64bit_inodes = 0;
int box64_zoom = 0;
int box64_steam = 0;
@@ -66,7 +79,7 @@ int box64_novulkan = 0;
char* libGL = NULL;
uintptr_t fmod_smc_start = 0;
uintptr_t fmod_smc_end = 0;
uint32_t default_gs = 0;
uint32_t default_gs = 0xa<<3;
int jit_gdb = 0;
int box64_tcmalloc_minimal = 0;
@@ -115,6 +128,39 @@ void my_child_fork()
}
}
#ifdef DYNAREC
void GatherDynarecExtensions()
{
if(box64_dynarec==0) // no need to check if no dynarec
return;
#ifdef ARM64
unsigned long hwcap = real_getauxval(AT_HWCAP);
if(!hwcap) // no HWCap: provide a default...
hwcap = HWCAP_ASIMD;
// first, check all needed extensions, lif half, edsp and fastmult
if((hwcap&HWCAP_ASIMD) == 0) {
printf_log(LOG_INFO, "Missing ASMID cpu support, disabling Dynarec\n");
box64_dynarec=0;
return;
}
if(hwcap&HWCAP_CRC32)
arm64_crc32 = 1;
if(hwcap&HWCAP_PMULL)
arm64_pmull = 1;
if(hwcap&HWCAP_AES)
arm64_aes = 1;
printf_log(LOG_INFO, "Dynarec for ARM64, with extension: ASIMD");
if(arm64_aes)
printf_log(LOG_INFO, " AES");
if(arm64_crc32)
printf_log(LOG_INFO, " CRC32");
if(arm64_pmull)
printf_log(LOG_INFO, " PMULL");
printf_log(LOG_INFO, " PageSize:%d\n", box64_pagesize);
#endif
}
#endif
EXPORTDYN
void LoadLogEnv()
@@ -345,7 +391,7 @@ void LoadLogEnv()
p = getenv("BOX64_JITGDB");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
if(p[0]>='0' && p[0]<='0'+2)
jit_gdb = p[0]-'0';
}
if(jit_gdb)
@@ -354,6 +400,9 @@ void LoadLogEnv()
box64_pagesize = sysconf(_SC_PAGESIZE);
if(!box64_pagesize)
box64_pagesize = 4096;
#ifdef DYNAREC
GatherDynarecExtensions();
#endif
}
EXPORTDYN
@@ -423,7 +472,7 @@ int GatherEnv(char*** dest, const char** env, const char* prog)
(*dest)[idx++] = strdup("BOX64_PATH=.:bin");
}
if(!ld_path) {
(*dest)[idx++] = strdup("BOX64_LD_LIBRARY_PATH=.:lib");
(*dest)[idx++] = strdup("BOX64_LD_LIBRARY_PATH=.:lib:lib64");
}
// add "_=prog" at the end...
if(prog) {
@@ -448,7 +497,8 @@ void PrintHelp() {
printf(" '-h'|'--help' to print box64 help and quit\n");
printf("You can also set some environment variables:\n");
printf(" BOX64_PATH is the box64 version of PATH (default is '.:bin')\n");
printf(" BOX64_LD_LIBRARY_PATH is the box64 version LD_LIBRARY_PATH (default is '.:lib')\n");
printf(" BOX64_LD_LIBRARY_PATH is the box64 version LD_LIBRARY_PATH (default is '.:lib:lib64')\n");
printf(" BOX64_PREFER_WRAPPED if box64 will use wrapped libs even if the lib is specified with absolute path\n");
printf(" BOX64_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info (level 3 is level 2 + BOX64_DUMP)\n");
printf(" BOX64_DUMP with 0/1 to dump elf infos\n");
printf(" BOX64_NOBANNER with 0/1 to enable/disable the printing of box64 version and build at start\n");
@@ -506,16 +556,24 @@ void LoadEnvVars(box64context_t *context)
printf_log(LOG_INFO, "\n");
}
}
if(getenv("BOX64_PREFER_WRAPPED")) {
if (strcmp(getenv("BOX64_PREFER_WRAPPED"), "1")==0) {
box64_prefer_wrapped = 1;
printf_log(LOG_INFO, "BOX64: Prefer Wrapped libs\n");
}
}
if(getenv("BOX64_NOSIGSEGV")) {
if (strcmp(getenv("BOX64_NOSIGSEGV"), "1")==0)
if (strcmp(getenv("BOX64_NOSIGSEGV"), "1")==0) {
context->no_sigsegv = 1;
printf_log(LOG_INFO, "BOX64: Disabling handling of SigSEGV\n");
}
}
if(getenv("BOX64_NOSIGILL")) {
if (strcmp(getenv("BOX64_NOSIGILL"), "1")==0)
if (strcmp(getenv("BOX64_NOSIGILL"), "1")==0) {
context->no_sigill = 1;
printf_log(LOG_INFO, "BOX64: Disabling handling of SigILL\n");
}
}
// check BOX64_PATH and load it
LoadEnvPath(&context->box64_path, ".:bin", "BOX64_PATH");
@@ -817,7 +875,16 @@ int main(int argc, const char **argv, const char **env) {
my_context->argv[0] = strdup(prog);
else
my_context->argv[0] = ResolveFile(prog, &my_context->box64_path);
// check if box86 is present
{
my_context->box86path = strdup(my_context->box64path);
char* p = strrchr(my_context->box86path, '6'); // get the 6 of box64
p[0] = '8'; p[1] = '6'; // change 64 to 86
if(!FileExist(my_context->box86path, IS_FILE)) {
free(my_context->box86path);
my_context->box86path = NULL;
}
}
const char* prgname = strrchr(prog, '/');
if(!prgname)
prgname = prog;
@@ -894,12 +961,24 @@ int main(int argc, const char **argv, const char **env) {
}
elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->argv[0], 1);
if(!elf_header) {
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch natively instead\n", my_context->argv[0]);
int x86 = my_context->box86path?FileIsX86ELF(my_context->argv[0]):0;
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->argv[0], x86?"using box86":"natively");
fclose(f);
free_contextargv();
FreeBox64Context(&my_context);
FreeCollection(&ld_preload);
return execvp(argv[1], (char * const*)(argv+1));
if(x86) {
// duplicate the array to change 1st arg as box86
const char** newargv = (const char**)calloc(argc+1, sizeof(char*));
newargv[0] = my_context->box86path;
FreeBox64Context(&my_context);
for(int i=1; i<argc; ++i)
newargv[i] = argv[i];
return execvp(newargv[0], (char * const*)newargv);
} else {
FreeBox64Context(&my_context);
return execvp(argv[1], (char * const*)(argv+1));
}
printf_log(LOG_NONE, "Failed to execvp: error is %s\n", strerror(errno));
}
AddElfHeader(my_context, elf_header);
@@ -1018,26 +1097,26 @@ int main(int argc, const char **argv, const char **env) {
}
// pre-load lib if needed
if(ld_preload.size) {
if(AddNeededLib(NULL, NULL, NULL, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) {
if(AddNeededLib(NULL, NULL, NULL, 0, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) {
printf_log(LOG_INFO, "Warning, cannot pre-load a lib\n");
}
}
FreeCollection(&ld_preload);
// Call librarian to load all dependant elf
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, my_context, emu)) {
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, 0, my_context, emu)) {
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
FreeBox64Context(&my_context);
return -1;
}
// reloc...
printf_log(LOG_DEBUG, "And now export symbols / relocation for %s...\n", ElfName(elf_header));
if(RelocateElf(my_context->maplib, NULL, elf_header)) {
if(RelocateElf(my_context->maplib, NULL, 0, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", my_context->argv[0]);
FreeBox64Context(&my_context);
return -1;
}
// and handle PLT
RelocateElfPlt(my_context->maplib, NULL, elf_header);
RelocateElfPlt(my_context->maplib, NULL, 0, elf_header);
// defered init
RunDeferedElfInit(emu);
// do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
+1 -1
View File
@@ -167,7 +167,7 @@ void SetupInitialStack(x64emu_t *emu)
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
Push(emu, 0); Push(emu, 26); //AT_HWCAP2(26)=0
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
//Push(emu, ); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
//Push(emu, 0); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
if(!emu->context->auxval_start) // store auxval start if needed
emu->context->auxval_start = (uintptr_t*)R_RSP;
+49 -8
View File
@@ -11,9 +11,9 @@
#include "khash.h"
#include "debug.h"
#include "x64emu.h"
#include "box64context.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "box64context.h"
#endif
KHASH_MAP_INIT_INT64(bridgemap, uintptr_t)
@@ -30,7 +30,6 @@ typedef struct brick_s {
typedef struct bridge_s {
brick_t *head;
brick_t *last; // to speed up
pthread_mutex_t mutex;
kh_bridgemap_t *bridgemap;
} bridge_t;
@@ -48,7 +47,6 @@ bridge_t *NewBridge()
bridge_t *b = (bridge_t*)calloc(1, sizeof(bridge_t));
b->head = NewBrick();
b->last = b->head;
pthread_mutex_init(&b->mutex, NULL);
b->bridgemap = kh_init(bridgemap);
return b;
@@ -69,7 +67,6 @@ void FreeBridge(bridge_t** bridge)
b = n;
}
kh_destroy(bridgemap, (*bridge)->bridgemap);
pthread_mutex_destroy(&(*bridge)->mutex);
free(*bridge);
*bridge = NULL;
}
@@ -86,7 +83,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
int prot = 0;
do {
#endif
pthread_mutex_lock(&bridge->mutex);
pthread_mutex_lock(&my_context->mutex_bridge);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick();
@@ -95,7 +92,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
}
sz = b->sz;
#ifdef DYNAREC
pthread_mutex_unlock(&bridge->mutex);
pthread_mutex_unlock(&my_context->mutex_bridge);
if(box64_dynarec) {
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
if(prot)
@@ -104,7 +101,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
}
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
pthread_mutex_lock(&bridge->mutex);
pthread_mutex_lock(&my_context->mutex_bridge);
#endif
b->sz++;
b->b[sz].CC = 0xCC;
@@ -117,7 +114,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
int ret;
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
pthread_mutex_unlock(&bridge->mutex);
pthread_mutex_unlock(&my_context->mutex_bridge);
#ifdef DYNAREC
if(box64_dynarec)
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
@@ -206,6 +203,50 @@ void* GetNativeFncOrFnc(uintptr_t fnc)
return (void*)b->f;
}
// using the brdige mecanism for the VSyscall
uintptr_t AddVSyscall(bridge_t* bridge, int num)
{
brick_t *b = NULL;
int sz = -1;
#ifdef DYNAREC
int prot = 0;
do {
#endif
pthread_mutex_lock(&my_context->mutex_bridge);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick();
b = b->next;
bridge->last = b;
}
sz = b->sz;
#ifdef DYNAREC
pthread_mutex_unlock(&my_context->mutex_bridge);
if(box64_dynarec) {
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
else // only add DB if there is no protection
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
}
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
pthread_mutex_lock(&my_context->mutex_bridge);
#endif
b->sz++;
b->b[sz].B8 = 0xB8;
b->b[sz].num = num;
b->b[sz]._0F = 0x0F;
b->b[sz]._05 = 0x05;
b->b[sz]._C3 = 0xC3;
pthread_mutex_unlock(&my_context->mutex_bridge);
#ifdef DYNAREC
if(box64_dynarec)
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
#endif
return (uintptr_t)&b->b[sz].CC;
}
#ifdef HAVE_TRACE
KHASH_MAP_INIT_INT64(bridgename, const char*)
static kh_bridgename_t *bridgename;
+6
View File
@@ -15,6 +15,12 @@ typedef union onebridge_s {
uint8_t C3; // C2 or C3 ret
uint16_t N; // N in case of C2 ret
};
struct {
uint8_t B8; // B8 00 11 22 33 mov rax, num
uint32_t num;
uint8_t _0F; uint8_t _05; // 0F 05 syscall
uint8_t _C3; // C3 ret
};
uint64_t dummy[4];
} onebridge_t;
#pragma pack(pop)
+29 -3
View File
@@ -15,7 +15,10 @@
#include "debug.h"
#include "fileutils.h"
static const char* x86sign = "\x7f" "ELF" "\x01" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x03" "\x00";
static const char* x64sign = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x02" "\x00" "\x3e" "\x00";
static const char* x86lib = "\x7f" "ELF" "\x01" "\x01" "\x01" "\x03" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x03" "\x00" "\x03" "\x00";
static const char* x64lib = "\x7f" "ELF" "\x02" "\x01" "\x01" "\x03" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x00" "\x03" "\x00" "\x3e" "\x00";
int FileExist(const char* filename, int flags)
{
@@ -65,14 +68,37 @@ int FileIsX64ELF(const char* filename)
FILE *f = fopen(filename, "rb");
if(!f)
return 0;
char head[sizeof(*x64sign)] = {0};
int sz = fread(head, sizeof(*x64sign), 1, f);
char head[20] = {0};
int sz = fread(head, 20, 1, f);
if(sz!=1) {
fclose(f);
return 0;
}
fclose(f);
if(memcmp(head, x64sign, sizeof(*x64sign))==0)
if(memcmp(head, x64sign, 20)==0)
return 1;
head[7] = x64lib[7]; // this one changes
if(memcmp(head, x64lib, 20)==0)
return 1;
return 0;
}
int FileIsX86ELF(const char* filename)
{
FILE *f = fopen(filename, "rb");
if(!f)
return 0;
char head[20] = {0};
int sz = fread(head, 20, 1, f);
if(sz!=1) {
fclose(f);
return 0;
}
fclose(f);
if(memcmp(head, x86sign, 20)==0)
return 1;
head[7] = x64lib[7];
if(memcmp(head, x86lib, 20)==0)
return 1;
return 0;
}
+1
View File
@@ -53,6 +53,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
| 1<<9 // SSSE3
| 1<<12 // fma
| 1<<13 // cx16 (cmpxchg16)
| 1<<25 // aesni
;
break;
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...
File diff suppressed because it is too large. Load diff
+8
View File
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedalureDEFS_H_
#define __wrappedalureDEFS_H_
#endif // __wrappedalureDEFS_H_
+17
View File
@@ -0,0 +1,17 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedalureTYPES_H_
#define __wrappedalureTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
#define SUPER() ADDED_FUNCTIONS()
#endif // __wrappedalureTYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedalureUNDEFS_H_
#define __wrappedalureUNDEFS_H_
#endif // __wrappedalureUNDEFS_H_
+8
View File
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedalutDEFS_H_
#define __wrappedalutDEFS_H_
#endif // __wrappedalutDEFS_H_
+17
View File
@@ -0,0 +1,17 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.1.0.16) *
*******************************************************************/
#ifndef __wrappedalutTYPES_H_
#define __wrappedalutTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
#define SUPER() ADDED_FUNCTIONS()
#endif // __wrappedalutTYPES_H_
Loaded 100 of 502 files, more files were not shown because too many files have changed in this diff. Show more