Compare commits

..
414 Commits
Author SHA1 Message Date
ptitSeb 666861419d Bumped to v0.2.0 2022-11-17 14:21:42 +01:00
Jai A P 52d6c5ac88 Fix PKGBUILDS (#452) 2022-11-16 15:51:18 +01:00
ptitSeb 5b89a2375a [DYNAREC] Fixed RCR and RCL opcodes 2022-11-16 15:11:19 +01:00
ptitSeb c0d19de08d Added one more GLES extension to wrapped libGL 2022-11-15 16:43:34 +01:00
ptitSeb 27d85a737c Added a few more wrapped function to libcrypto 2022-11-15 16:31:26 +01:00
ptitSeb 277f542304 Better handling of rolling logs 2022-11-15 12:58:40 +01:00
ptitSeb 517a5b6844 [DYNAREC] Pre-allocate more instructions on FillBlock64 2022-11-15 12:58:15 +01:00
ptitSeb d4f98902a0 Added 1 wrapped function to libX11 2022-11-15 12:57:24 +01:00
ptitSeb eb289e8542 Added 1 extension to wrapped libGL 2022-11-15 12:57:20 +01:00
ptitSeb 06754daf87 Added a bunch of libGL and libGLES2 extensions 2022-11-15 00:27:43 +01:00
ptitSeb ee509f6350 Small fixes and improvement to memory protection handling 2022-11-14 21:06:33 +01:00
ptitSeb 6a7c6cba12 Added BOX64_CRASHHANDLER env. var. 2022-11-14 21:05:32 +01:00
ptitSeb 129f5e93fa Added some synonim for libpango-1 and libcairo 2022-11-14 14:57:33 +01:00
ptitSeb 629312b382 Set TLS size to be a 64K page on all cases 2022-11-14 14:57:00 +01:00
ptitSeb d31524691b Improved ROLLING_LOG and improved getcontext/setcontext handling of floating points 2022-11-13 19:31:28 +01:00
ptitSeb ff6ec86f1c Added 1 wrapped function for libmpg123 2022-11-13 17:58:24 +01:00
ptitSeb 0c55facdd9 Added wrapped (empty) libvdpau 2022-11-13 17:27:53 +01:00
ptitSeb d9e1f91735 Added SDL_ResetKeyboard wrapped function 2022-11-13 17:17:54 +01:00
ptitSeb 9f037fef60 [DYNAREC] Optimisations and fixes on a few x87 opcodes (fixes Piczle Cross Adventure on Steam) 2022-11-13 17:08:16 +01:00
ptitSeb 0bc7100ea8 Print the ROLLING_LOG on the Ask to run at NULL error 2022-11-13 17:07:06 +01:00
ptitSeb 8698a58a60 Cosmetic change on my_dl_iterate_phdr callback 2022-11-13 17:05:49 +01:00
ptitSeb a8151de2cb Optimized getDB, setProtection and freeProtection 2022-11-13 17:05:03 +01:00
ptitSeb 7a9005dae6 Added 1 vulkan extension 2022-11-13 10:27:10 +01:00
ptitSeb a77f8bf203 Added wrapped libgstgl-1.0 with a few functions 2022-11-13 09:51:12 +01:00
ptitSeb efc7877ffd Changed steam-pressure-vessel wrapping to include system libs first 2022-11-13 09:50:45 +01:00
ptitSeb 3cb7632dc8 Also use size when selecting symbol for R_X86_64_COPY and R_X86_64_GLOB_DAT relocations 2022-11-13 00:04:26 +01:00
ptitSeb cde8e54b51 Fixed wrapped function signature for vkCmdSetScissorWithCount, 2022-11-12 22:37:42 +01:00
ptitSeb 8ce1a2d605 Fix an issue with dynarec build when running without dynarec 2022-11-11 20:55:02 +01:00
ptitSeb d09379990b x86_64 build don't need CreateCPUInfoFile 2022-11-11 19:50:12 +01:00
ptitSeb 136318f98a Actualy fix x86_64 build 2022-11-11 19:48:37 +01:00
ptitSeb 1775844f45 Fix x86_64 build 2022-11-11 19:07:03 +01:00
ptitSeb 987a663094 Improved cpu cores detection and reporting 2022-11-11 18:08:19 +01:00
ptitSeb 107dbd5645 Fixed some fuse wrapped functions (better AppImage compatibility) 2022-11-11 15:40:15 +01:00
ptitSeb bebd8f3c1a Added fuse_main_real wrapped function 2022-11-10 12:16:02 +01:00
ptitSeb 3be1e33339 [DYNAREC] Fixed alternate address not always taken into account by Dynarec 2022-11-02 22:09:54 +01:00
ptitSeb 91348f22be Fixed a small memory leak with Dynarec 2022-11-02 22:09:20 +01:00
ptitSeb c9279061fa [ANDROID] Build fix 2022-11-01 20:34:36 +01:00
ptitSeb 5bfe397c63 Added libudev.so.1 dependancy for wrapped libudev.so.0 2022-11-01 20:34:24 +01:00
ptitSeb a202640da4 Update README_CN.md 2022-11-01 12:19:28 +01:00
ptitSeb 08fcdfa0fb Updated README.md with new sponsors
Thanks for keeping this project alive !
2022-11-01 12:18:55 +01:00
ptitSeb 51fb706781 Added llrintl wrapped function (for #419) 2022-11-01 10:49:39 +01:00
ptitSeb 92ed70f029 Added XftNameUnparse wrapped function (for #424) 2022-11-01 10:43:51 +01:00
ptitSeb 067b28be41 Added a few libflac wrapped function (for #425) 2022-11-01 10:42:13 +01:00
ptitSeb 81b7fc519c Addedsyscall 24 (for #429) 2022-11-01 10:39:05 +01:00
ptitSeb 24cc0c8422 Detect when program is linked with glibc 2.34+ to workaround the default libc libs to load 2022-11-01 10:37:44 +01:00
ptitSeb 8459ea0d31 Remove dynablocklist (#438)
* [DYNAREC] Removed dynablock sons handling
* [DYNAREC] Removed dynablocklist, and attached dynablocks to the jumptable
* [DYNAREC] Changed handling of HotPage (part of Protection now)
* [DYNAREC] Fixed some performance issues (especially with heavily threaded programs)
2022-10-31 12:05:04 +01:00
ptitSeb 494c245b59 [DYNAREC] Reprotect bridge when emu is running 2022-10-30 16:34:01 +01:00
ptitSeb d87f0ea728 Added some more wrapped function to libX11 (for #436) 2022-10-29 23:07:12 +02:00
ptitSeb dbdfc13a23 Fixed a signature in tbbmallocproxy wrapped lib 2022-10-29 22:40:57 +02:00
ptitSeb c19730f5e2 Re-disabled the abort when quitting, seems stable now 2022-10-29 22:36:31 +02:00
ptitSeb 446e735825 [DYNAREC] Small change to use alloca instead of customMalloc 2022-10-29 22:34:59 +02:00
ptitSeb 0e47d1269c Malloc override (#437)
* Add some malloc override mecanism, but missing c++ function overriding
* Add c++ new/delete redirection too
* Added support for libtbbmalloc_proxy
2022-10-29 22:32:47 +02:00
ptitSeb 7dc5359c2b Added support for MOVBE extension ([DYNAREC] too) 2022-10-29 17:24:06 +02:00
ptitSeb e394903ccf Better fix, again, for dlsym(RTLD_NEXT, ...) 2022-10-29 16:49:25 +02:00
ptitSeb 98bb78ae3a Optimized custom pthread_once 2022-10-29 16:49:13 +02:00
ptitSeb defe5ce594 Better fix for dlsym(RTLD_NEXT, ...) 2022-10-29 16:26:29 +02:00
ptitSeb 713e3fa89d Don't enable steamwebhelper yet 2022-10-29 15:26:14 +02:00
ptitSeb 73f813279a Fixed FT_Outline_Decompose wrapped function 2022-10-29 15:24:58 +02:00
ptitSeb 0063cad60d Added a few x11 wrapped function (for #436) 2022-10-29 12:43:37 +02:00
ptitSeb 3bb3f618b9 Fix for dlsym(RTLD_NEXT, ...) 2022-10-29 12:43:28 +02:00
ptitSeb 53195e3a25 Small imrpovment to custom phtread_once 2022-10-29 12:43:03 +02:00
ptitSeb 09103aa52e [DYNAREC] Fixed a potential issue with free range of dynablock 2022-10-29 10:16:52 +02:00
ptitSeb ee63a9f368 Imrpoved Bridges, again 2022-10-29 09:41:46 +02:00
ptitSeb 9a73c15b84 Added 66 0F 38 10 opcode ({DYNAREC] too) 2022-10-29 09:02:35 +02:00
ptitSeb b50dec9d92 Added a few more wrapped libfuse functions 2022-10-29 08:52:25 +02:00
ptitSeb 9f8feb622e [DYNAREC] More log when using BOX64_NODYNAREC 2022-10-28 20:48:46 +02:00
ptitSeb db156b41fb [DYNAREC] Fixed F3 0F 5B opcode 2022-10-28 20:48:16 +02:00
ptitSeb 374583bb48 [DYNAREC] Fixed an emitter 2022-10-28 20:47:52 +02:00
ptitSeb 5d3c218b1b [DYNAREC] Added 66 F0 0F B1 opcode 2022-10-28 15:11:18 +02:00
ptitSeb f34427e772 [DYNAREC] Added 66 87 opcode 2022-10-28 15:10:51 +02:00
ptitSeb a1666986c6 [DYNAREC] Added (F2/F3) AD ocpodes 2022-10-28 15:10:20 +02:00
ptitSeb b669177c83 Added 66 0F 7D opcode 2022-10-28 11:35:03 +02:00
ptitSeb 1678d2b97a Re-enabled the abort if exit is too long, seems to be still needed 2022-10-27 19:53:49 +02:00
ptitSeb 3564f41c48 Wrapping of GtkTextView and GtkContainer classes for Gtk3 2022-10-27 19:36:11 +02:00
ptitSeb 72314a33ab Added posix_spawn_file_actions_addclose wrapped function 2022-10-27 19:35:38 +02:00
ptitSeb 9289b29504 Try to get a cleaner exit 2022-10-27 19:02:25 +02:00
ptitSeb de115b87df Fixed some issue with bridge memory protection handling 2022-10-27 18:42:39 +02:00
ptitSeb cfeb0626cc Added BOX64_SHOWBT env. var. to have a backtrace on segfault 2022-10-27 18:42:07 +02:00
ptitSeb 3f2c4ed794 Fixed dlopen that should increment refcount even with RTLD_NOLOAD 2022-10-27 16:11:19 +02:00
ptitSeb 978256179b Improved handling of execve and posix_spawn, especialy with arv[0] is not the expected value 2022-10-27 14:04:41 +02:00
ptitSeb 742af765ba Some fixes to execv and posic_spawn wrapped functions 2022-10-26 20:49:41 +02:00
ptitSeb 035d0aebc1 Added libudev.so synonym of libudev.so.1 2022-10-26 20:19:00 +02:00
ptitSeb a5dbd58200 Added one more gtk3 wrapped function 2022-10-26 20:14:29 +02:00
ptitSeb 9073e1d47e [DYNAREC] Fixed 0F BA opcodes 2022-10-26 19:40:26 +02:00
ptitSeb ed1078dadf Try to improve the shell detection, again (for #433) 2022-10-26 17:16:53 +02:00
ptitSeb 83dbd728ef Added syscalls 7 and 112 2022-10-26 16:59:20 +02:00
ptitSeb 31a6149b0f Actually fixed (this time) syscall 78 2022-10-26 15:51:43 +02:00
ptitSeb 3d274fdfd9 Fixed an issue with syscall 78 2022-10-26 15:33:00 +02:00
ptitSeb 8f3ec680c7 Added syscall to BOX64_ROLLING_LOG too 2022-10-26 15:31:44 +02:00
ptitSeb 612e94be9d More flexibility for BOX64_ROLLING_LOG 2022-10-26 14:20:39 +02:00
ptitSeb 7a95c78ba0 Fixed non-dynarec build 2022-10-26 14:19:33 +02:00
ptitSeb 5a2a546090 Fix non-dynarec build 2022-10-26 14:10:12 +02:00
ptitSeb baf6fc8987 Added BOX64_ROLLING_LOG support to __stack_chk_fail 2022-10-26 13:58:20 +02:00
ptitSeb bf75d6496f Made a custom implementation of pthread_once 2022-10-26 13:48:28 +02:00
ptitSeb fb7f134c06 Fixed 64 F3 0F 5A ocpode (still for #432) 2022-10-25 18:39:32 +02:00
ptitSeb 067dcbc0f7 [DYNAREC] Added BIGBLOCK=3 level 2022-10-25 18:34:38 +02:00
ptitSeb 280bc969ce Added 64 F3 0F 5A opcode (for #432) 2022-10-25 17:12:38 +02:00
ptitSeb 010b8a79cb Added xkb_compose_state_reset wrapped function (for #431) 2022-10-25 14:25:19 +02:00
ptitSeb 4ec39ae323 Added xkb_compose_state_get_status wrapped function (for #431) 2022-10-25 11:01:00 +02:00
ptitSeb ec7c654451 Changed elf signature detection to accomodate for AppImage 2022-10-25 10:49:20 +02:00
ptitSeb 6022a61b3c Added xkb_compose_state_feed wrapped function (for #431) 2022-10-25 10:03:13 +02:00
ptitSeb 975b489007 Added a few more libxkbcommon wrapped functions (for #431) 2022-10-25 09:47:01 +02:00
ptitSeb f8f1859a05 [DYNAREC] Better (defered) flag handling in dynarec (gives between 5% and 10% speedup) 2022-10-24 20:19:09 +02:00
ptitSeb 92f2a44b28 Small fixes with unaligned pthread_cond_t 2022-10-24 18:24:50 +02:00
ptitSeb 7585a984b2 [DYNAREC] Rewrote unused acro, in case it used later 2022-10-24 18:23:35 +02:00
ptitSeb 789bf9c220 Added xkb_compose_table_new_from_locale wrapped function (for #431) 2022-10-24 17:01:46 +02:00
ptitSeb 2e9bc93e1f [DYNAREC] Use customMalloc for internal dynarec stuff (fixed starbound) 2022-10-24 14:30:51 +02:00
ptitSeb e2a993a425 custom Alloc now allocate memory rounded up to 8bytes align 2022-10-24 11:40:22 +02:00
ptitSeb d0b5c79b81 Use box_strdup instead of realpath for the string allocation to be safe 2022-10-24 11:39:33 +02:00
ptitSeb 95622ca964 Forgot a bunch of other box_ malloc/realloc/calloc/free use 2022-10-23 19:19:30 +02:00
ptitSeb 76b63de754 [DYNAREC] Forget this realloc->box_realloc 2022-10-23 18:05:13 +02:00
ptitSeb 58cdb1bda2 Refactored, again, elfloader symbol fetching (ported from box86) 2022-10-22 20:57:31 +02:00
ptitSeb a530f56511 [DYNAREC] Small change on how add_next/get_closest_next works 2022-10-22 17:28:35 +02:00
ptitSeb bf6e74ad8e [DYNAREC] Added BOX64_DYNAREC_SAFEFLAGS 2022-10-22 16:13:55 +02:00
ptitSeb c2253dafc0 This fixed factorio for me, but it's not clear why 2022-10-22 12:27:05 +02:00
ptitSeb 389d159c7a [DYNAREC] Added 66 0F 7C opcode 2022-10-22 11:11:39 +02:00
ptitSeb 21161ae38e [DYNAREC] Added DE opcodes 2022-10-22 10:23:24 +02:00
ptitSeb aa074d7121 Fixed an issue with last lib refactor (fixed EtG, and all SDL2 based stuff and more probably) 2022-10-21 18:47:45 +02:00
ptitSeb 99d04e93a2 [DYNAREC] Initialize dynmap, it's cleaner 2022-10-19 23:01:10 +02:00
ptitSeb d6b9df6ca2 Small refactor and simplification of library_t structure and box64context_t 2022-10-19 22:59:19 +02:00
ptitSeb 4fbeca0aa3 Forgot to return the value in wrapped __libc_start_main (for #427) 2022-10-19 21:51:11 +02:00
Alfred E. Neumayer f19b89b263 src: asm: Rename lr & fp registers to their x-equivalents (#426)
Older GCC versions (like on Ubuntu Touch) don't recognize the aliases.
Fixes building box64 with older toolchains.
2022-10-17 22:21:33 +02:00
ptitSeb 0a908d78ca Added XftFontOpenName vrapped function (for #424) 2022-10-11 22:09:56 +02:00
ptitSeb f2b8b06280 Fixed and improved Shell script detection 2022-10-10 23:30:51 +02:00
Eric Wiessner (KI7POL) 0cc04e5253 Create X64WINE.md (#423) 2022-10-10 08:15:31 +02:00
ptitSeb 5e9a9b9867 Added 64 66 0F 11 opcode (for #418) 2022-10-09 20:32:41 +02:00
ptitSeb 68826baf3b [DYNAREC] Small optim for 0F C6 opcode 2022-10-01 23:44:55 +02:00
ptitSeb cc26096c28 [DYNAREC] Fixed and optimized 0F BA opcodes 2022-10-01 23:31:49 +02:00
Jonathan Keller 1c110080a8 fix overzealous replace in wrappers pathnames (#415)
Wrapper filenames were generated by replacing ".c" with "_private.h".
Unfortunately this matched anywhere in the string, causing problems if
the path contained a directory containing the substring ".c". For
instance, if box64 is compiled in a '.cache' directory (as AUR helpers
like to do, see #144), the directory name was inadvertently mangled
into '_private.hache'.

Fix this by restricting the match to the end of the string.
2022-09-30 20:28:46 +02:00
ptitSeb 7b67bbe698 Added PCLMULQDQ ([DYNAREC] Too, using PMULL if present) extension (improve a lot AES-XTS score of Geekbench 5) 2022-09-30 19:13:47 +02:00
ptitSeb 7692371ccb More vulkan wrapped functions 2022-09-29 20:20:17 +02:00
ptitSeb 534eb4ce88 Fixed signal handling 2022-09-29 19:54:38 +02:00
ptitSeb c88b936233 [DYNAREC] Added 64 2B opcode 2022-09-29 15:31:22 +02:00
ptitSeb 32c229215a Improved signal handling and x87 flags (with tests backported from box86) 2022-09-29 11:24:42 +02:00
ptitSeb 9c5cc38c9a [CMAKE] Put name in tests 2022-09-29 10:46:02 +02:00
ptitSeb 12795ea491 Slight better trace for pop r15 2022-09-28 15:13:57 +02:00
ptitSeb c0b143043f Added lzma_auto_decoder wrapped function to liblzma (for #129) 2022-09-28 12:35:03 +02:00
ptitSeb 40b849da23 Improved handling of CF flags in dec/inc opcodes ([DYNAREC] too) (helps Xonotic official linux build) 2022-09-26 10:16:21 +02:00
ptitSeb 4f18bd6293 [DYNAREC] Improved BOX64_NODYNAREC effect, and Interpretor->Dynarec on conditional jump 2022-09-25 21:25:16 +02:00
ptitSeb 702e92d4f4 Added a vulkan extension 2022-09-25 12:08:56 +02:00
ptitSeb 40fa336829 Added a few xcb_randr wrapped functions (for #287) 2022-09-24 08:55:37 +02:00
ptitSeb fa93803b45 Added __pread_chk wrapped function to libc 2022-09-22 18:23:50 +02:00
ptitSeb 7201dbd477 Added wrapped XFreeFontSet function (for #411) 2022-09-21 19:25:10 +02:00
ptitSeb 40248c3e13 Added syscall 267 (for #99 and #100) 2022-09-20 12:28:37 +02:00
ptitSeb f2a0a1b62d Small fix to protection tracking on signal handling 2022-09-19 19:29:39 +02:00
ptitSeb dcb4bbb3e6 More fixes and improvment to bash handling (helps #360) 2022-09-18 19:00:53 +02:00
ptitSeb 21c56e7898 Improved usage of x86_64 bash with BOX64_BASH env var 2022-09-15 14:07:46 +02:00
ptitSeb 7c74e7be35 Added F0 86 ocpode ([DYNAREC] too) (for #406) 2022-09-15 10:43:25 +02:00
ptitSeb bf5ec1eb57 Fixed a USAGE.md issue (for #405) 2022-09-14 13:07:12 +02:00
ptitSeb 342241a24d Improved thread_self stack size detection 2022-09-13 16:17:37 +02:00
ptitSeb d047dcb983 Attempt at fixing wrapped __vfwprintf_chk (for #404) 2022-09-12 16:35:35 +02:00
ptitSeb 0fc310f1c4 Aded 1 wrapped function libxkbcommon 2022-09-12 15:13:56 +02:00
ptitSeb c6e14a562b Added vfwprintf and __vfwprintf_chk wrapped function (for #404) 2022-09-12 15:05:24 +02:00
ptitSeb a3f6a7ddbc Added one more function to libX11 2022-09-12 14:07:57 +02:00
ptitSeb c8c09d7e09 Try to improve syscall rt_sigaction handling 2022-09-12 13:56:51 +02:00
ptitSeb 411163c73f Added some wrapped function to libgio, libgdk3 and libxi 2022-09-12 13:55:45 +02:00
ptitSeb b25aa07e11 Smalls fixes to USAGE.md 2022-09-12 11:52:27 +02:00
ptitSeb bc72a506c1 Added many wrapped function to libva and friends 2022-09-11 16:01:41 +02:00
ptitSeb 8451c62b44 Added a few more wrapped libnss3 functions 2022-09-11 14:50:44 +02:00
ptitSeb 1f3729822a Some more wrapping on AtkUtils 2022-09-11 14:27:21 +02:00
ptitSeb a27283aa9b Added syscall 297 2022-09-11 14:27:02 +02:00
ptitSeb 1eb1bd6800 Added empty wrapped libva and friends 2022-09-10 22:09:14 +02:00
ptitSeb cda4af3403 Added some more GL/GLES extensions 2022-09-10 21:46:03 +02:00
ptitSeb 93ea5bacb7 Added localtime64 and localtime64_r in case they exists 2022-09-10 18:48:37 +02:00
ptitSeb 841c5c22e0 Fixed an issue with dlsym(RTLD_NEXT, ...) not always finding the symbols 2022-09-10 18:24:31 +02:00
ptitSeb 511446846f Added empty wrapped libfreebl3 2022-09-10 12:41:53 +02:00
ptitSeb a79bf97b48 Added a few more extensions to wrapped libGL 2022-09-10 12:36:42 +02:00
ptitSeb a78d5e2636 Added a few libnss3 wrapped functions 2022-09-10 12:32:24 +02:00
ptitSeb b6d2e3fb55 Added special case for pthread_kill because behaviour changed with glibc 2.34 2022-09-10 11:28:22 +02:00
ptitSeb 43850ac856 Added wprintw wrapped function to ncurses and ncurses6 lib (for #401) 2022-09-08 10:04:30 +02:00
ptitSeb 532b1697a6 When running x86_64 bash, using x86_64 bash to run script automaticaly (for #402) 2022-09-08 09:59:58 +02:00
ptitSeb a3f63a12f9 [DYNAREC] Improve memory protection tracking (help #361) 2022-09-04 15:21:32 +02:00
ptitSeb b2dfe64cea Limit all libc mmap to 47bits max 2022-09-04 15:20:29 +02:00
ptitSeb ff7dc072d1 Make StrongMem emulation level 2 stronger 2022-09-04 15:19:17 +02:00
ptitSeb b185afa29f Fixed x86/x86_64 binary detection (for #399) 2022-08-31 08:48:54 +02:00
ptitSeb 742742fd48 small improvment to x64/x86 signature detection 2022-08-30 10:25:09 +02:00
ptitSeb 5f6104a9d3 Added 1 libxi wrapped function 2022-08-28 18:12:21 +02:00
ptitSeb 787198b30e Added 1 wrapped function to gtk3 2022-08-28 17:58:29 +02:00
ptitSeb 3490c63259 Fixed gtk_get_major/minor/micro version wrapped function to gtk2 2022-08-28 17:29:32 +02:00
ptitSeb 8077d7bb0b Added gtk_get_major/minor/micro version wrapped function to gtk2 2022-08-28 17:27:33 +02:00
ptitSeb b2c8c227ec Added a few more FAudio wrapped functions 2022-08-28 14:26:47 +02:00
ptitSeb ca8ff5fda9 Added some CERT function to wrapped libnss3 (for #375) 2022-08-13 12:39:44 +02:00
ptitSeb a6f2d96557 Fixed a warning 2022-08-11 19:43:36 +02:00
wannacu 948205e6f9 Add SW64 base support (#382)
* Add SW64 base support

* Add a few syscalls
2022-08-11 11:14:13 +02:00
ptitSeb d90b6b7e51 Fixed issue with last RIP handling refactor 2022-08-10 23:50:09 +02:00
ptitSeb e3e1ee313b Some cleanup 2022-08-10 22:39:58 +02:00
ptitSeb dc5c049ed9 Added D9 D8..DF opcodes ([DYNAREC] too) (for #361) 2022-08-09 23:04:14 +02:00
ptitSeb 642260bdb6 Chenged Interpretor so RIP is updated on opcode success (better precision for Signal) 2022-08-06 16:10:17 +02:00
ptitSeb bafa85e772 Fixed a warning 2022-08-06 16:10:17 +02:00
ptitSeb 4f102a43fa Also use __libc_memalign instead of posix_memalign 2022-08-06 16:10:17 +02:00
ptitSeb 2ac265d529 All box internal memory alloc use __libc_ internal one (except on Android, using libc one gather from dlsym) 2022-08-06 16:10:17 +02:00
João Henrique e261270eb8 Backport SDL_DYNAPI_entry wrapper from box86. (#374)
* Backport SDL_DYNAPI_entry wrapper from box86.

* Correct SDL_DYNAPI_entry prototype.

Second argument is of pointer type, not integer.
2022-08-06 13:56:51 +02:00
ptitSeb d08bd0c619 Added a new extension to wrapped libGL 2022-07-31 09:13:10 +02:00
ptitSeb cc833341e4 Small improvment in signal handling 2022-07-30 18:51:51 +02:00
ptitSeb add0081b50 Added some wayland wrapped libs (partial) 2022-07-30 17:02:18 +02:00
ptitSeb 46fb9d6df1 Small changed to wrapped exit function 2022-07-30 16:44:05 +02:00
ptitSeb e324942a07 Fixed wrapped gtk_tree_store_new function 2022-07-30 16:18:28 +02:00
ptitSeb b853012cb6 Small improvment to BOX64_ROLLING_LOG=1 2022-07-30 16:08:41 +02:00
ptitSeb d64d7db5f5 Better trace for readlink 2022-07-30 15:50:51 +02:00
ptitSeb d19a076f1e Added a few more wrapped nns3 and nspr4 functions 2022-07-30 15:40:52 +02:00
ptitSeb 5ad314ba5a Added wrapping of GtkTextViewClass in gtk2 2022-07-30 15:22:17 +02:00
ptitSeb c7473dd7c9 Added wrapped g_signal_override_class_handler function 2022-07-30 15:05:05 +02:00
ptitSeb abb9ab1bb6 Fixed CERT_PKIXVerifyCert that can have a well hiden callback... 2022-07-30 14:56:46 +02:00
ptitSeb 8bc9baefd6 Added BOX64_ROLLING_LOG=1 for a 'Just in Time LOG=2' on signal 2022-07-30 14:18:53 +02:00
ptitSeb 0fe835e087 Improve obstack support (for #352) 2022-07-30 11:50:51 +02:00
ptitSeb e8ed41c763 Improve support of MyAlign for printf type (for #356) 2022-07-30 11:44:20 +02:00
ptitSeb d9cd0604cc Added an empty wrapped libsoftokn3 (for #365) 2022-07-30 10:42:43 +02:00
ptitSeb afb2cc4a99 Fixed syscall 332 (for #361) 2022-07-30 10:04:10 +02:00
ptitSeb a72751914d Added 2 SDL2 wrapped function (for #364) 2022-07-28 18:25:39 +02:00
ptitSeb 9e3c5b1bf2 Added syscall 60 (for #363) 2022-07-28 09:38:50 +02:00
ptitSeb bf77789076 Merge branch 'main' of https://github.com/ptitSeb/box64 into main 2022-07-27 21:43:09 +02:00
ptitSeb 1b0d063cff Added SDL_GameControllerFromPlayerIndex wrapped function to sdl2 2022-07-27 21:42:58 +02:00
ptitSeb 24f8f47f76 Forgot those from previous commit 2022-07-27 21:41:46 +02:00
ptitSeb 7745457f9b Quick hack to align pthread_cond_t if needed (for #362) 2022-07-27 15:33:02 +02:00
ptitSeb 660bbae9a8 Added a few GLES wrapped function (for #362) 2022-07-27 15:19:00 +02:00
ptitSeb c071e9b051 Improved wrapping of libatk 2022-07-27 14:48:43 +02:00
ptitSeb 1c1bab8d6b Added F2 0F 7D opcode 2022-07-25 16:53:48 +02:00
ptitSeb 8beb818100 Added a few more Atk wrapped functions 2022-07-24 20:48:05 +02:00
ptitSeb 1ff0a7c4e7 Added 66 0F D0 opcode 2022-07-24 20:41:37 +02:00
ptitSeb 49991a3341 Added a mostly empty wrapped libatomic 2022-07-24 20:36:24 +02:00
ptitSeb 88af5ea07c Added a few libdrm wrapped functions 2022-07-24 19:41:45 +02:00
ptitSeb 63fbd64eb8 Wrapped one more GL extension 2022-07-24 19:38:34 +02:00
ptitSeb 8337fd306a Added many gbm wrapped functions 2022-07-24 19:37:26 +02:00
ptitSeb 7df6dbeafb Added a few more libGL wrapped extensions 2022-07-24 19:24:59 +02:00
ptitSeb bf2d6b8999 More work on wrapping for gtk3 and friends 2022-07-24 19:09:21 +02:00
ptitSeb 5528cb9f16 Added syscall 128 2022-07-24 14:00:47 +02:00
ptitSeb d8bc6dcc1b Added 1 more symbol to wrapped libc 2022-07-24 14:00:33 +02:00
ptitSeb c0ebc4cbb0 Some work around chromium / libcef / electron / nw (still not ok) 2022-07-23 20:06:28 +02:00
ptitSeb e3b6d6e6b2 Disabling steamwebhelper again, it was eanbled by mystake 2022-07-23 18:23:04 +02:00
ptitSeb a50b10b869 Added GL_EXT_window_rectangles wrapped extension to libGL 2022-07-17 17:52:32 +02:00
ptitSeb 183704ab95 Added one more syscall 2022-07-17 16:10:17 +02:00
ptitSeb e654ed980a Better log for waitpid 2022-07-17 16:09:49 +02:00
ptitSeb a4eb35371f Better signal function handler log 2022-07-17 15:26:04 +02:00
ptitSeb 0931f95e65 Fixed a typo 2022-07-17 12:45:13 +02:00
ptitSeb 83997e1125 Added '+' in FILE_TRACE_NAME to append trace 2022-07-17 12:43:35 +02:00
ptitSeb 555a1184e4 Better trace for getenv and setenv 2022-07-17 12:41:38 +02:00
ptitSeb f6b31f65ac Fixed a few more warnings 2022-07-17 09:25:49 +02:00
ptitSeb fc67b208ad Fixed a few warnings 2022-07-17 09:19:58 +02:00
ptitSeb b6f83007eb Added a few GLES wrapped functions 2022-07-16 22:15:28 +02:00
ptitSeb 6e82268704 [DYNAREC] Improved handlinf of RIP value 2022-07-16 21:57:55 +02:00
ptitSeb 4142cc296b tls parameter of clone libc function needs special treatment (not done yet) 2022-07-16 21:47:26 +02:00
ptitSeb e98b1e6716 Added a few syscalls 2022-07-16 21:46:23 +02:00
ptitSeb fda8b96063 [DYNAREC] Fixed 0F 09 Opcode 2022-07-16 21:35:34 +02:00
ptitSeb bb8e11e08d Improved 0F 0B opcode (SIGILL at ip, not ip+2) 2022-07-16 21:34:33 +02:00
ptitSeb aee1fe1004 [DYNAREC] Improved pred_sz computation 2022-07-16 21:33:56 +02:00
ptitSeb fbcd77a1a7 [DYNAREC] Improved trace a bit 2022-07-16 21:33:05 +02:00
ptitSeb 90f58dbcbe Improve trace a bit 2022-07-16 21:32:38 +02:00
ptitSeb 729d19ab24 Better trace for recvmsg 2022-07-16 21:31:35 +02:00
ptitSeb ca9a1b6666 [DYNAREC] Fixed 0F 09/0B opcodes 2022-07-16 21:30:13 +02:00
ptitSeb 08aa003335 [DYNAREC] Fixed defered carry flags for ADC 64bits 2022-07-16 21:29:14 +02:00
ptitSeb b0a56e2790 Improved wrapping of MetaFrames in gtk2 2022-07-16 17:03:36 +02:00
ptitSeb 01f589885f Added a few missing SDL2_TTF wrapped functions (for Silicon Zero) 2022-07-16 15:22:05 +02:00
ptitSeb 038c940e8e Fix sigaction syscall 2022-07-15 14:14:56 +02:00
ptitSeb 20067c02bc Added wrapped gtk3 and gdk3 (from box86) 2022-07-15 14:10:18 +02:00
ptitSeb efa3fa3aed Added wrapped libxshlfence 2022-07-15 11:05:22 +02:00
ptitSeb e0908ced14 Added more function so x86_64 bash can work (a copy is in tests folder) 2022-07-15 09:56:00 +02:00
ptitSeb 3068ca8908 Added 2 more wrapped function to libm (help Surviving Mars) 2022-07-14 21:24:04 +02:00
ptitSeb 88406332d2 Added a bunch of vulkan functions wrappers 2022-07-14 18:32:15 +02:00
ptitSeb 6cb9561d96 Changed a bit how wrapped libc clone works 2022-07-14 16:26:38 +02:00
ptitSeb 3135ba57cd Use a bigger TLSData by default with forcing emulated gtk 2022-07-14 16:26:10 +02:00
ptitSeb 96420b959a Added a couple of wrapped freetype functions (for Hacknet) 2022-07-14 15:06:01 +02:00
ptitSeb 15bda0af27 A few more fontconfig and freetype wrapped functions 2022-07-14 12:41:58 +02:00
ptitSeb a076e9b0a8 Don't prefer emulated libs for 64bits process on pressure_vessel for now (like for 32bits process) 2022-07-14 09:39:03 +02:00
ptitSeb 0cb4fa67f1 Fixed BOX86_ENVx handling (for #347) 2022-07-14 08:52:45 +02:00
ptitSeb bf79be222c Added __fwprintf_chk wrapped function (for KSP) 2022-07-11 19:59:24 +02:00
ptitSeb 1bb27f2b80 Added a workaround for missing __gxx_personality_v0 function (for #349) 2022-07-11 19:55:27 +02:00
ptitSeb 96dae29f4d Added __wcsncat_chk wrapped function 2022-07-11 16:19:30 +02:00
ptitSeb 4e0df627df Added a few NV vulkan extensions (for #348) 2022-07-11 14:10:52 +02:00
ptitSeb 15411c7c9e Added BOX64_ENV to create env. var. at load time (for #347) 2022-07-11 13:51:05 +02:00
ptitSeb b4c389c374 Double the min size of TLS data to 8k (help Keep Talking and Nobody Explode, and probably other too) 2022-07-10 15:48:58 +02:00
ptitSeb 44aeead296 [DYNAREC] More color for DYNAREC_DUMP=2 2022-07-10 15:48:43 +02:00
ptitSeb 5e0d4800d9 More previous bytes on Unimplemented Opcode message 2022-07-10 10:56:52 +02:00
ptitSeb e1a8e8d82d Small change in one of dlsym_error log 2022-07-10 10:56:12 +02:00
ptitSeb 4ae714089d Added one more wrapped function to vulkan 2022-07-09 21:36:52 +02:00
ptitSeb 3894da6242 Added more gstreamer wrapped functions 2022-07-09 19:19:47 +02:00
ptitSeb 2f74e6ebf8 Added (empty) wrapped libgcrypt.so.20 2022-07-09 18:38:12 +02:00
ptitSeb c1aeb2244c Fixed potential issue with new loaded lib comparison 2022-07-09 17:48:51 +02:00
ptitSeb d231851734 Changed various log level for libdl file open error 2022-07-09 16:52:20 +02:00
ptitSeb c4a68bcd43 [DYNAREC] Fixed some x87 issues (fixing issues with ut2004) 2022-07-09 16:18:37 +02:00
ptitSeb 1add5dac3e Added a version of libstdc++.so.5 (as it's difficult to find that version now) 2022-07-09 14:43:15 +02:00
ptitSeb ec3786f862 Various improvement and some workaround to support musl binary (for #324) 2022-07-09 11:58:35 +02:00
ptitSeb 0e761801de Restored workaround for Linux GOG installer on SBCs 2022-07-07 21:29:47 +02:00
theofficialgman 39f70c0956 change order of matrix (to preview better under checkmark dropdown (#346) 2022-07-05 22:14:13 +02:00
theofficialgman 0674636243 add 18.04 for tegra-x1 github actions (#345)
remove from ubuntu-latest as well
2022-07-05 22:01:01 +02:00
ptitSeb ea89d85845 Added __wcscat_chk wrapped function (for #343) 2022-07-04 08:11:18 +02:00
ptitSeb 0f3884afde Fixed 64 F2 0F 10 and 64 66 0F 2E opcodes (for #298) 2022-07-04 08:07:53 +02:00
ptitSeb 7b3d4c6359 Fixed a warning 2022-07-04 08:06:35 +02:00
ptitSeb f9a8fa3854 Added a workaround if pthread_cond_clockwait is not supported (for #342) 2022-07-04 07:58:09 +02:00
ptitSeb 575c86551e Added a workaround if pthread_cond_clockwait is not supported (for #342) 2022-07-04 07:53:33 +02:00
ptitSeb 57bbac4923 [DYNAREC] Disable 64 66 0F 2E opcode, something is wrong and it SIGILL (for #298) 2022-07-03 22:52:08 +02:00
ptitSeb 7f8167e4e2 Added bit29 of EDX for CPUID 0x80000001 leaf (for Xonotic v0.8.5) 2022-07-03 16:14:34 +02:00
ptitSeb ebce5998de Added 66 F0 0F C1 opcode ([DYNAREC] too) (for FRAMED Collection on Steam) 2022-07-03 15:49:23 +02:00
ptitSeb 672a41a79c Added support for R_X86_64_IRELATIVE reloc, along with a test for it (for #303) 2022-07-03 14:14:17 +02:00
ptitSeb 48b881f491 Added wrapped pthread_cond_clockwait (for #303) 2022-07-03 13:55:21 +02:00
ptitSeb a6f0525a4c Added 64 66 0F 2E/2F ocodes ([DYNAREC] too) (for #298) 2022-07-03 13:35:17 +02:00
ptitSeb d9707926fa [DYNAREC] Added most 67 00-3C opcodes 2022-07-03 13:19:57 +02:00
ptitSeb e38c663dea Added 67 38-3D opcodes (for #323) 2022-07-03 10:58:41 +02:00
ptitSeb b1873b21b6 Added syscall 324 (for #327) 2022-07-03 10:50:04 +02:00
ptitSeb 4c4d3dc9e7 Fixed a warning 2022-07-03 10:49:40 +02:00
ptitSeb c7e6777cc1 Merge pull request #294 from stiltr/misc-fixes
Add wrapped functions needed for 'ls -l'.
2022-07-03 10:42:40 +02:00
ptitSeb 5336524129 [DYNAREC] Add a mecanism to remember fixed address accessed with LOCK, so MOV to/from them use a Memory Barrier automaticaly 2022-07-03 00:07:14 +02:00
ptitSeb de30d37ba9 Reworked TLS to limit resizing, as it tends to break Unity3D games 2022-07-03 00:06:19 +02:00
ptitSeb e2b6e32fe9 Show some value around RSP when a Signal is dumped 2022-07-03 00:05:32 +02:00
ptitSeb f2573a5c02 [DYNAREC] Fixed an issue with unwinding x86 address from signal 2022-07-02 11:40:23 +02:00
ptitSeb 96f8873f2c Added syscall 231 (for #333) 2022-07-01 10:33:06 +02:00
ptitSeb b3919fe819 Merge pull request #336 from wannacu/main
Align address when call mprotect
2022-07-01 09:23:46 +02:00
wannacu 9eeaaf0a03 Align address when call mprotect 2022-07-01 15:18:05 +08:00
ptitSeb 9328ba79d1 Fixed a regression preventing wine-preloader to work correctly 2022-06-30 18:38:29 +02:00
ptitSeb 0c7168648f Added syscall 270 (for #333) 2022-06-30 17:58:34 +02:00
ptitSeb 26f8a756cb Merge pull request #334 from martinmanyhats/pagesize64k
Enable 64k page size
2022-06-30 14:13:53 +02:00
ptitSeb 4174442558 Added syscall 27 (for #333) 2022-06-30 14:05:36 +02:00
Martin Reed 452a390325 Enable 64k page size eg Ampere A1. 2022-06-30 10:45:21 +00:00
ptitSeb 9fcb6e1f38 Added one libssl wrapped functions (for #331) 2022-06-29 13:34:23 +02:00
ptitSeb 826f9cf2f3 Added 2 libssl wrapped functions (for #331) 2022-06-29 08:15:12 +02:00
ptitSeb c18fbfa106 Fixed printf_log for __cx_pure_virtual function 2022-06-28 20:27:08 +02:00
ptitSeb cd695f735b Added one libssl wrapped functions with reverse callback (for #331) 2022-06-28 20:25:57 +02:00
ptitSeb 0e3cd11a55 Added one more libssl wrapped functions (for #331) 2022-06-28 19:47:31 +02:00
ptitSeb 1236c16c83 Added one libssl wrapped functions (for #331) 2022-06-28 19:42:08 +02:00
ptitSeb 66a47329db Added one libcrypto wrapped functions (for #331) 2022-06-28 19:27:37 +02:00
ptitSeb 322f18926e Added one libssl wrapped functions (for #331) 2022-06-28 19:17:47 +02:00
ptitSeb 5bbc241168 Added a few more libssl wrapped functions (for #331) 2022-06-28 19:08:17 +02:00
ptitSeb 83925633e0 Fixed some potential issue for eroneous execv call (fixes some infinite looping AppImage) 2022-06-26 18:21:04 +02:00
ptitSeb 42943eab95 Removed blockempty call in freeProtection, as the call is slow, at the expanse of more memory that stay allocated for traking purpose, except when whole block is free 2022-06-26 14:29:20 +02:00
ptitSeb 66bf32bafa Also changed the other wrapped __Xstat(64) function to accept a NULL buffer 2022-06-26 11:18:44 +02:00
ptitSeb aa42913ece Fixed wrapped __xtsat call with NULL buffer (helps Surviving Mars) 2022-06-26 11:07:52 +02:00
ptitSeb e4e8a46424 Improved a bit HotPage handling (might help Terraria and RimWorld, maybe other) 2022-06-26 10:50:10 +02:00
ptitSeb dfe894a39b Added one more FAudio wrapped function (for Terraria) 2022-06-26 10:49:39 +02:00
ptitSeb c80feac629 Added SDL_LoadFile wrapped function (helps Terraria) 2022-06-26 10:45:51 +02:00
ptitSeb 71c1ca3eb6 Added a couple of wrapped function to libssl and libcrypto (for #330) 2022-06-25 18:20:36 +02:00
ptitSeb ffc99aa52e [DYNAREC] Remove assert, the test is not relevent anymore 2022-06-25 16:58:32 +02:00
ptitSeb 4b10506691 [DYNAREC] Fixed an issue with fillPredecessor that would undersize the predecessor array (should help #328, maybe other) 2022-06-25 13:54:15 +02:00
ptitSeb 57f1f82d76 [DYNAREC] Added CPU Dump on Signal to help debugging (only if signal inside a DynaBlock for now) 2022-06-25 13:51:53 +02:00
ptitSeb 53f84817ba [DYNAREC] Fixed a typo when turning off Dynarec 2022-06-25 13:51:22 +02:00
ptitSeb 221527e0e1 [DYNAREC] Added BRK emitter, to help debugging 2022-06-25 13:50:44 +02:00
ptitSeb 501ab2bbe8 Rollback the signal/return address change limit 2022-06-21 10:05:06 +02:00
ptitSeb f78c5a2b18 [DYNAREC] Fixed some complex x87 opcode, like FSINCOS (fixed bad camera in Unigine Heaven linux version) 2022-06-19 22:10:01 +02:00
ptitSeb 962c3c25b6 Various small debugging improvments 2022-06-19 21:18:05 +02:00
ptitSeb ae6d6d753a Do not prefer emulated on 32bits pressure vessels for now (helps winegstreamer lib) 2022-06-19 21:17:41 +02:00
ptitSeb 3e764fdc45 Change process name (hidding box64, helps mesa find the correct hack for some binaries) 2022-06-19 20:50:15 +02:00
ptitSeb f52ee794db Merge pull request #326 from Jai-JAP/patch-1
Fix grammar
2022-06-19 17:52:07 +02:00
Jai A P 34ece330f3 Update main.c 2022-06-19 21:15:23 +05:30
ptitSeb 7adaf39f1a Better handling of LD_PRELOAD libraries 2022-06-19 15:28:13 +02:00
ptitSeb 6392550208 More work on libfuse (some AppImage now runs) 2022-06-11 19:11:27 +02:00
ptitSeb 98d705ed9b [DYNAREC] added 67 8B opcode 2022-06-11 16:44:41 +02:00
ptitSeb a356eb7abf Added 67 83 opcode ([DYNAREC] too) (for #323) 2022-06-11 16:42:05 +02:00
ptitSeb e950872ec9 [DYNAREC] Fixed (or least avoid SIGILL) for DD /1 opcode 2022-06-11 15:47:35 +02:00
ptitSeb ab1fdbfead Fixed a potential crash with previous commit 2022-06-11 14:48:56 +02:00
ptitSeb 7ac8d7de22 Added support to load different libs with same name from different folders (for #299) 2022-06-11 13:40:54 +02:00
ptitSeb f012e02b35 Added 67 C7 opcode ([DYNAREC] too) (for #323) 2022-06-11 13:22:05 +02:00
ptitSeb 1ffbb7bf6b Added __cxa_pure_virtual wrapped function (for #299) 2022-06-11 10:53:09 +02:00
ptitSeb 72927195fd Added wrapped __wprintf_chk and wprintf (for #311) 2022-06-11 10:29:46 +02:00
ptitSeb e29326d8d0 Merge pull request #321 from archanox/patch-1
Fix typos and arch type string
2022-06-08 11:24:08 +02:00
Pierce Andjelkovic b7bf1955b7 Fix typos and arch type string 2022-06-08 18:31:34 +10:00
ptitSeb 1057b88ba7 Fixed some issue with TLS data not beeing updated correctly after ElfInit (fixes Steam version of Ion Fury) 2022-06-06 17:02:41 +02:00
ptitSeb de21088bc4 Added one more GL extension 2022-06-06 17:01:58 +02:00
ptitSeb d8698cdc84 Fixed an issue with GetNoSelfSymbolStartEnd function that would find in self first 2022-06-05 16:54:16 +02:00
ptitSeb 1ae1906637 Added syscall 317 2022-06-05 16:29:09 +02:00
ptitSeb 5a0fc820d4 Added some GLES wrapped functions 2022-06-05 12:22:35 +02:00
ptitSeb a1f51ad7dc Added 1 more wrapped function to libfontconfig 2022-06-05 12:22:07 +02:00
ptitSeb fbb89dcf10 Added some failsafe on unwind 2022-06-05 12:21:40 +02:00
ptitSeb 736552a559 Added preliminary support for wrapped libEGL 2022-06-05 12:01:04 +02:00
ptitSeb 162abb0a32 Fixed a regression with last dynarec refactor (for #318) 2022-06-05 10:52:38 +02:00
ptitSeb a2cd8b72dc Run elf init if __libc_start_main init param is NULL (for #315) 2022-05-30 21:43:00 +02:00
ptitSeb 11aca3f0aa Better version of F2/F3 0F 1E opcode 2022-05-30 21:42:17 +02:00
ptitSeb c312ca45bd More work on FAudio (Salt And Sanctuary seems to work fine now) 2022-05-28 22:27:32 +02:00
ptitSeb f1dc84afef [DYNAREC] Fixed a rare case of crash when crrent block is invalid 2022-05-28 22:26:39 +02:00
ptitSeb 7cafe8311e [DYNAREC] Fixed regression on 66 C1 /7 opcode 2022-05-28 20:52:35 +02:00
ptitSeb 9513053f74 [DYNAREC] Various small fixes and improvments to a few opcodes 2022-05-26 18:41:14 +02:00
ptitSeb bfea73d5d8 [DYNAREC] Fix an issue with LOCK ADD Ew, Iw opcode 2022-05-26 18:02:11 +02:00
ptitSeb 2ae1713ac1 Added XGetTextProperty wrapped function 2022-05-26 14:13:09 +02:00
ptitSeb fb2047853c Fixed XRenderComposite wrapped function signature 2022-05-26 13:33:20 +02:00
ptitSeb 3dec81b9eb First attempt to get a static build (not working for now, don't use it) 2022-05-22 17:49:54 +02:00
ptitSeb b0fa2f5ec0 Added wrapped fstat64 (for #309) 2022-05-21 20:10:14 +02:00
ptitSeb 6c367f4a29 Fixed the workaround for gog installer on PI & RK3399 SBC beeing slow to start 2022-05-21 13:01:23 +02:00
ptitSeb c8d4d3b69e Fixed wrapped lib dependancies not loading 2022-05-10 13:55:31 +02:00
ptitSeb a0234eed48 Merge pull request #306 from ryanfortner/patch-1
docs: add instructions for Debian-based Linux
2022-05-10 07:45:55 +02:00
Ryan Fortner 8cc3b54bcd Fix link 2022-05-09 22:23:24 -04:00
Ryan Fortner d8630d5bdc Update COMPILE.md 2022-05-09 22:18:08 -04:00
Ryan Fortner 82118c854c docs: add instructions for Debian-based Linux 2022-05-09 22:16:12 -04:00
ptitSeb b1b558d244 Small change to avoid wlib_t declaration in wrappedlibs.h (from box86) 2022-05-09 20:11:03 +02:00
ptitSeb 6ef734960a Some refactor on wrapped lib handling, to limit calloc/free used and get more straight forward usage of native wrapped functions (ported from box86) 2022-05-09 18:06:52 +02:00
ptitSeb 244e3eafdf Small fixes to the symbol name to avoid overriding by libs 2022-05-09 18:05:51 +02:00
ptitSeb 59e367a88e Added and fixed opcodes 66 0F 38 38..3F ([DYNAREC] too) (for #299) 2022-05-03 09:57:47 +02:00
Trevor Stiles 681f0ef111 Merge branch 'main' into misc-fixes 2022-05-01 00:12:40 -07:00
ptitSeb 098317ed29 Updated README 2022-05-01 09:02:41 +02:00
ptitSeb 30cc36abca Removed some debug leftover 2022-05-01 08:38:26 +02:00
ptitSeb 58090c2c32 Fixed fstat, fstatat and lstat wrapper signature (for #295) 2022-05-01 07:58:19 +02:00
ptitSeb 008f5913e9 Added fake libunwind wrapping 2022-04-30 14:28:11 +02:00
ptitSeb 349736b0a5 Added a few wrapped functions to libc 2022-04-30 12:29:18 +02:00
Trevor Stiles 42e926e27c Add wrapped functions needed for 'ls -l'. 2022-04-28 00:26:29 -07:00
ptitSeb 80be548b64 Added wrapped stat (for #293) 2022-04-27 10:41:50 +02:00
ptitSeb bb22be4f4f Added some libfuse wrapping (AppImage is not working yet) 2022-04-26 18:35:28 +02:00
ptitSeb fab4c72285 [DYNAREC] Fixed some issue with XMM cache and Native calls (fixed Zoom title bitmap distortion) 2022-04-25 11:35:40 +02:00
ptitSeb 9bb42fc5bf Small fixes for a few sse opcodes 2022-04-25 11:20:09 +02:00
ptitSeb 5d93fc58b3 [DYNAREC] A small optim of FCOMI macro when OF, AF or SF are needed 2022-04-25 11:19:38 +02:00
ptitSeb ab633484cd Improved BOX64_LOAD_ADDR env. var. to help having reproducible runs 2022-04-24 17:29:22 +02:00
ptitSeb 5e69a69b8d Improved initial stack build 2022-04-24 15:14:11 +02:00
ptitSeb 50a9aef179 Fixed a potential issue with stack overwritten on sigaction call 2022-04-24 15:14:06 +02:00
ptitSeb 13bc7d17bf [DYNAREC] Ignore 26 Prefix (for #290) 2022-04-23 13:26:27 +02:00
ptitSeb d8c328ec09 [DYNAREC] Ignore 36 prefix for 66 prefixed opcodes (for #290) 2022-04-23 09:19:31 +02:00
ptitSeb 2a4c1d0aac Do not use alloca here, it's not temporary storage 2022-04-18 22:50:52 +02:00
ptitSeb 6c4b88123a Added some wrapped libs and functions 2022-04-18 15:40:53 +02:00
ptitSeb b78f3a8216 [DYNAREC] No need to save op1 and op2 for defered flag computation on logic operations 2022-04-18 13:55:54 +02:00
ptitSeb 8f93b18469 [DYNAREC] Simpler writing for this test 2022-04-18 13:50:29 +02:00
ptitSeb a66725adc4 [DYNAREC] Small optim on flags barrier handling 2022-04-18 13:43:09 +02:00
ptitSeb 8d9d5f3fc3 [DYNAREC] Added F0 21 opcode 2022-04-17 17:18:49 +02:00
ptitSeb 9699198bcc [DYNAREC] Added 66 0F 3A DF opcode 2022-04-17 12:03:06 +02:00
ptitSeb aa163b5010 [DYNAREC] Added 66 0F 51 opcode 2022-04-17 11:05:29 +02:00
ptitSeb aacc392049 [DYNAREC] Better handling of opcodes with 66 F0 prefixes 2022-04-17 10:55:03 +02:00
ptitSeb 74b99b52ee [DYNAREC] Added 0F AE /7 opcode 2022-04-17 10:36:52 +02:00
ptitSeb c7b573dcff [DYNAREC] Added 66 0F 3A 20 opcode 2022-04-17 10:13:51 +02:00
ptitSeb 5b03a1e218 [DYNAREC] Added 66 F0 FF and F0 08 opcodes 2022-04-17 10:13:22 +02:00
ptitSeb 77db70f9b5 [DYNAREC] Added F8/F9 opcodes 2022-04-17 10:12:35 +02:00
ptitSeb 0379d02d8c Start of a new dev. cycle 2022-04-17 09:33:44 +02:00
419 changed files with 24292 additions and 8335 deletions

No files matched your search

+10 -2
View File
@@ -27,10 +27,18 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3288, TEGRAX1, PHYTIUM, SD845]
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3288, PHYTIUM, SD845]
type: [Release, Trace]
os: [ubuntu-latest]
include:
- platform: TEGRAX1
type: Release
os: ubuntu-18.04
- platform: TEGRAX1
type: Trace
os: ubuntu-18.04
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box64 Repository"
uses: actions/checkout@v2
+1
View File
@@ -55,6 +55,7 @@ dkms.conf
build/
build*/
.vscode
.cache
.gdb_history
src/git_head.h
backup/
+87 -23
View File
@@ -14,13 +14,15 @@ option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based devi
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
option(RV64 "Set to ON if targeting an RISCV RV64G based device" ${RV64})
option(RV64 "Set to ON if targeting an RISC-V RV64GC based device" ${RV64})
option(PPC64LE "Set to ON if targeting an PowerPC 64 LE based device" ${PPC64LE})
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
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})
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
if(LARCH64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
@@ -49,10 +51,19 @@ endif()
if(M1 OR LARCH64)
set(PAGE16K ON CACHE BOOL "")
endif()
if(SW64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(PAGE8K ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
option(PAGE8K "Set to ON if host device have PageSize of 8K (instead of 4K)" ${PAGE8K})
option(PAGE16K "Set to ON if host device have PageSize of 16K (instead of 4K)" ${PAGE16K})
option(PAGE64K "Set to ON if host device have PageSize of 64K (instead of 4K)" ${PAGE64K})
option(STATICBUILD "Set to ON to have a static build (Warning, not working)" ${STATICBUILD})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
@@ -120,22 +131,32 @@ elseif(LARCH64)
set(CMAKE_ASM_FLAGS "-pipe -march=loongarch64")
elseif(RV64)
add_definitions(-DRV64)
add_definitions(-pipe -march=rv64g)
set(CMAKE_ASM_FLAGS "-pipe -march=rv64g")
add_definitions(-pipe -march=rv64gc)
set(CMAKE_ASM_FLAGS "-pipe -march=rv64gc")
elseif(PPC64LE)
add_definitions(-DPPC64LE)
elseif(LX2160A)
add_definitions(-DLX2160A)
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto")
elseif(SW64)
add_definitions(-DSW64)
elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
if(PAGE8K)
add_definitions(-DPAGE8K)
endif()
if(PAGE16K)
add_definitions(-DPAGE16K)
endif()
if(PAGE64K)
add_definitions(-DPAGE64K)
endif()
if(NOGIT)
add_definitions(-DNOGIT)
endif()
@@ -202,6 +223,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/box64context.c"
"${BOX64_ROOT}/src/build_info.c"
"${BOX64_ROOT}/src/custommem.c"
"${BOX64_ROOT}/src/mallochook.c"
"${BOX64_ROOT}/src/steam.c"
"${BOX64_ROOT}/src/dynarec/dynarec.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
@@ -268,6 +290,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
"${BOX64_ROOT}/src/wrapped/wrappedatk.c"
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX64_ROOT}/src/wrapped/wrappedatomic.c"
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
@@ -280,9 +303,12 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedfaudio.c"
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreebl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped/wrappedgbm.c"
"${BOX64_ROOT}/src/wrapped/wrappedgconf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgcrypt.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdk3.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedgio2.c"
@@ -296,10 +322,12 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstaudio.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstreamer.c"
"${BOX64_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstvideo.c"
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtk3.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
@@ -312,6 +340,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
@@ -334,6 +363,11 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibusb1.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibuuid.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibva.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvadrm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvawayland.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvax11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvdpau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvorbis.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
@@ -368,6 +402,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
"${BOX64_ROOT}/src/wrapped/wrappedmpg123.c"
"${BOX64_ROOT}/src/wrapped/wrappednotify.c"
"${BOX64_ROOT}/src/wrapped/wrappednsl.c"
"${BOX64_ROOT}/src/wrapped/wrappednspr4.c"
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
@@ -388,6 +423,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsecret1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsoftokn3.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
@@ -398,11 +434,16 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
"${BOX64_ROOT}/src/wrapped/wrappedunwind.c"
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedwaylandclient.c"
"${BOX64_ROOT}/src/wrapped/wrappedwaylandcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedwaylandegl.c"
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
@@ -411,11 +452,12 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedldapr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlber.c"
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
)
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
foreach(A ${WRAPPEDS})
string(REPLACE ".c" "_private.h" B ${A})
string(REGEX REPLACE ".c$" "_private.h" B ${A})
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
endforeach()
@@ -457,6 +499,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.c"
"${BOX64_ROOT}/src/dynarec/arm64/arm64_printer.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_jmpnext.c"
"${BOX64_ROOT}/src/dynarec/arm64/arm64_prolog.S"
"${BOX64_ROOT}/src/dynarec/arm64/arm64_epilog.S"
@@ -482,11 +525,12 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_db.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dc.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dd.c"
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_de.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_de.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_df.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_660f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6664.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f20f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f30f.c"
)
@@ -543,7 +587,11 @@ set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
#add_dependencies(${BOX64} PRINTER)
#target_link_libraries(${BOX64} c m dl rt pthread resolv)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
if(STATICBUILD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-static -Wl,--no-as-needed -Wl,--whole-archive -Wl,--allow-multiple-definition -lm -ldl -lrt -lpthread -lresolv -lc -Wl,-defsym,_DYNAMIC=0 -pthread")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
endif()
if(DYNAREC)
target_link_libraries(${BOX64} dynarec)
endif()
@@ -580,6 +628,7 @@ if(NOT _x86 AND NOT _x86_64)
RUNTIME DESTINATION bin)
configure_file(system/box64.conf.cmake system/box64.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
@@ -625,82 +674,82 @@ 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}
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test02 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(bootSyscallC ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test03 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(printf ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test04 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(args ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test05 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(maths1 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test06 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(threadsStart ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile06.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test07 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(trig ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test08 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(pi ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test09 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(fork ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test10 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(cppThreads ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test11 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(tlsData ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test12 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(fpu ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test13 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(contexts ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile13.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(test14 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
#add_test(conditionalThreads ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile14.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test15 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(linkingIndirectNoversion ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test16 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(linkingIndirectVersion ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
@@ -722,7 +771,22 @@ add_test(backtrace ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref19.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test20 -D TEST_OUTPUT=tmpfile20.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
+28
View File
@@ -1,3 +1,31 @@
v0.2.0
======
* Wrapped more vulkan function, dxvk 2.0 now works
* Added support for overriden malloc/free functions
* Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size)
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
* Added BOX64_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
* Added BOX64_BASH to setup x86_64 bash binary, so shell script can be run in x86_64 world
* Added BOX64_ROLLING_LOG to have details log only on crash
* Work on alignment for some of pthread structures
* More wrapped libraries in the gtk family
* Some fixes on the Dynarec x87 code (fixing a bunch of games like ut2004 or Piczle Puzzle)
* Improved TLS Size handling (Unity3D games now works)
* More PageSize Compile options
* Improved `execv` family of function to have better box64 integration
* Added support for wrapped libfuse so AppImage works
* Adjusted the binfmt integration so AppImage are automaticaly picked
* Improved FAudio, SDL2, GL (and more) wrapping
* More wrapped libs, like libEGL.so, to helps emulated Qt4/5 libs to load
* Improved Signal Handling and memory protection traking
* Some signature fixes to some wrapped functions (in libc)
* Added more syscalls
* Added a lot of new opcodes to the ARM64 Dynarec
=> Lot's of new games stat working, to name a few: Surviving Mars, Piczle Cross Adventure (using Proton experimental), UT2004, Obduction, Machinarium, Silicon Zero, Hacknet, Absolute Drift, Art of Rally, Dota2
=> Some apps also runs now, like TeamSpeak 3 Client and Server or Discord
=> The bash integration is usefull for device with no binfmt integration or for script that check the machine it's running on
v0.1.8
======
* Added an option to get generated -NAN on SSE2 operation
+15 -3
View File
@@ -1,5 +1,17 @@
Compiling
Compiling/Installing
----
#### Debian-based Linux
You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to install precompiled box64 debs, updated every 24 hours.
```
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
wget -O- https://ryanfortner.github.io/box64-debs/KEY.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/box64-debs-archive-keyring.gpg
sudo apt update && sudo apt install box64 -y
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
#### for RK3399
Using a 64bit OS:
@@ -117,7 +129,7 @@ If it's the first install, you also need:
sudo systemctl restart systemd-binfmt
```
#### for RISCV
#### for RISC-V
Using a 64bit OS:
@@ -125,7 +137,7 @@ Using a 64bit OS:
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRV64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
make -j`nproc`
sudo make install
```
If it's the first install, you also need:
+6 -7
View File
@@ -61,9 +61,7 @@ Note that many installer (mojo setup based) will fall back to "x86" when detecti
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).
So, not all Unity games work and can require a high OpenGL profile, but many actualy work now.
Running Unity games should just works, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, wich is not supported on many ARM integrated GPU.
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 starts then quits before showing anything.
----
@@ -71,7 +69,7 @@ Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA
Notes about GTK programs
----
GTK libraries are now wrapped on box64, bu only gtk2, not gtk3 (contrary to box86).
GTK libraries are now wrapped on box64, both gtk2 and gtk3.
----
@@ -86,14 +84,15 @@ So, no Steam for now on box64.
Notes about Wine
----
Wine64 is supported on box64. Proton should also work. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively)
Wine64 is supported on box64. Proton should also work. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
Note that the new 32bits PE in 64bits process that the Wine time in currently implementing in Wine 7.+ is not yet supported. I tested Wine 7.5 64bits and it worked, but more recent version will probably just not work yet.
----
Notes about Vulkan
----
Box64 wraps Vulkan libraries, but note that it as only been tested with a RX550 card, some extensions may be missing depending on your graphics card.
Box64 wraps Vulkan libraries, but note that it as only been tested with a RX550 card, so some extensions may be missing depending on your graphics card.
----
@@ -104,7 +103,7 @@ I want to thank everyone who has contributed to box64 development.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.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/))
+1 -1
View File
@@ -109,7 +109,7 @@ Box64 包裝 Vulkan 庫。但請注意,它僅使用 RX550 卡進行了測試
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* 硬件捐赠和LoongArch迁移:[xiaoji](https://www.linuxgame.cn)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+42 -4
View File
@@ -11,6 +11,12 @@ Controls the Verbosity level of the logs
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3: DUMP : All DEBUG plus DUMP of all ELF Info.
#### BOX64_ROLLING_LOG
Show last few wrapped function call when a Signal is caught
* 0: No last function call printed (Default.)
* 1: Last 16 wrapped functions calls printed when a signal is printed. Incompatible with BOX64_LOG>1 (may need BOX64_SHOWSEGV=1 also)
* N: Last N wrapped functions calls printed when a signal is printed. Incompatible with BOX64_LOG>1 (may need BOX64_SHOWSEGV=1 also)
#### BOX64_NOBANNER
Disables Box64 printing its version and build
* 0 : Enable printing its banner. (Default.)
@@ -31,6 +37,7 @@ Enables/Disables the logging of `dlsym` errors.
#### BOX64_TRACE_FILE
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
End the filename with `+` to have thetrace appended instead of overwriten
Use `stderr` to use this instead of default `stdout`
#### BOX64_TRACE
@@ -83,6 +90,11 @@ Show Segfault signal even if a signal handler is present
* 0 : Don"t force show the SIGSEGV analysis (Default.)
* 1 : Show SIGSEGV detail, even if a signal handler is present
#### BOX64_SHOWBT
Show some Backtrace (Nativ e and Emulated) whgen a signal (SEGV, ILL or BUS) is caught
* 0 : Don"t show backtraces (Default.)
* 1 : Show Backtrace detail (for native, box64 is rename as the x86_64 binary run)
#### BOX64_X11THREADS
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
* 0 : Don't force call XInitThreads. (Default.)
@@ -124,22 +136,30 @@ Forbid dynablock creation in the interval specified (helpfull for debugging beha
Enables/Disables Box64's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps, but only for blocks in elf memory)
* 3 : Build Dynarec block bigger (don't stop when block overlaps, for all type of memory)
#### BOX64_DYNAREC_STRONGMEM
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model (enabled with dota2 is detected)
#### BOX64_DYNAREC_X87DOUBLE
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (faster)
* 0 : Try to use float when possible for x87 emulation (default, faster)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
#### BOX64_DYNAREC_FASTNAN
Enable/Disable generation of -NAN
* 0 : Generate -NAN like on x86 (Default.)
* 1 : Don't do anything special with NAN, to go as fast as possible (was default before this option exsted)
* 0 : Generate -NAN like on x86
* 1 : Don't do anything special with NAN, to go as fast as possible (default)
#### BOX64_DYNAREC_SAFEFLAGS
Handling of flags on CALL/RET opcodes
* 0 : Treat CALL/RET as if it never needs any flags (faster but not advised)
* 1 : most of RET will need flags, most of CALLS will not (Default)
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
#### BOX64_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
@@ -170,6 +190,11 @@ Box64 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
#### BOX64_CRASHHANDLER
Box64 will use a dummy crashhandler.so library
* 0 : Use Emulated crashhandler.so library if needed
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut for steam and dota2)
#### BOX64_NOPULSE
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
@@ -185,6 +210,19 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX64_BASH
Define x86_64 bash to launch script
* yyyy
Will use yyyy as x86_64 bash to launch script. yyyy needs to be a full path to a valid x86_64 version of bash
#### BOX64_ENV
* XXX=yyyy
will add XXX=yyyy env. var.
#### BOX64_ENV1
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX64_JITGDB
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
+177
View File
@@ -0,0 +1,177 @@
# Installing Wine64
Running Wine64/Wine with Box64/Box86 allows x64/x86 Windows programs to run on 64-bit ARM Linux devices.
- Box64 needs `wine-amd64` to be installed **manually** on ARM64 (aarch64) devices. This will run 64-bit Windows programs (aka x86_64).
- Box86 needs `wine-i386` to be installed **manually** on ARM32 (armhf) devices (or on ARM64 with multiarch or chroot). This will run 32-bit Windows programs (aka x86).
- _Note that `wine:arm64` and `wine:armhf` will not work with Box64/Box86. Your device's package manager might try to install those if you ask it to install wine._
See installation steps below (in the [Examples](#examples) section).
## Overview
The general procedure for installing Wine64 & Wine for Box64 & Box86 is to...
- Download all the install files for the version of Wine you wish to install
- Unzip or dpkg the install files into one folder
- Move that folder to the directory that you wish Wine to run from (often `~/wine/` by default)
- Go to `/usr/local/bin` and make symlinks or scripts that will point to your main wine binaries.
- Boot wine to create a new wineprefix.
- Download winetricks (which is just a complicated bash script), make it executable, then copy it to `/usr/local/bin`.
## Examples
### Installing Wine64 & Wine for Box64 & Box86 on Raspberry Pi OS from WineHQ .deb files
_Links from the [WineHQ repo](https://dl.winehq.org/wine-builds/debian/dists/)_
This install method allows you to install different versions of Wine64/Wine. You may install any version/branch of Wine that you wish.
```
# NOTE: Can only run on aarch64 (since box64 can only run on aarch64)
# box64 runs wine-amd64, box86 runs wine-i386.
### User-defined Wine version variables ################
# - Replace the variables below with your system's info.
# - Note that we need the amd64 version for Box64 even though we're installing it on our ARM processor.
# - Note that we need the i386 version for Box86 even though we're installing it on our ARM processor.
# - Wine download links from WineHQ: https://dl.winehq.org/wine-builds/
local branch="devel" #example: devel, staging, or stable (wine-staging 4.5+ requires libfaudio0:i386)
local version="7.1" #example: "7.1"
local id="debian" #example: debian, ubuntu
local dist="bullseye" #example (for debian): bullseye, buster, jessie, wheezy, ${VERSION_CODENAME}, etc
local tag="-1" #example: -1 (some wine .deb files have -1 tag on the end and some don't)
########################################################
# Clean up any old wine instances
wineserver -k # stop any old wine installations from running
rm -rf ~/.cache/wine # remove any old wine-mono/wine-gecko install files
rm -rf ~/.local/share/applications/wine # remove any old program shortcuts
# Backup any old wine installs
rm -rf ~/wine-old 2>/dev/null; mv ~/wine ~/wine-old 2>/dev/null
rm -rf ~/.wine-old 2>/dev/null; mv ~/.wine ~/.wine-old 2>/dev/null
sudo mv /usr/local/bin/wine /usr/local/bin/wine-old 2>/dev/null
sudo mv /usr/local/bin/wine64 /usr/local/bin/wine-old 2>/dev/null
sudo mv /usr/local/bin/wineboot /usr/local/bin/wineboot-old 2>/dev/null
sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old 2>/dev/null
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old 2>/dev/null
# Wine download links from WineHQ: https://dl.winehq.org/wine-builds/
LNKA="https://dl.winehq.org/wine-builds/${id}/dists/${dist}/main/binary-amd64/" #amd64-wine links
DEB_A1="wine-${branch}-amd64_${version}~${dist}${tag}_amd64.deb" #wine64 main bin
DEB_A2="wine-${branch}_${version}~${dist}${tag}_amd64.deb" #wine64 support files (required for wine64 / can work alongside wine_i386 main bin)
#DEB_A3="winehq-${branch}_${version}~${dist}${tag}_amd64.deb" #shortcuts & docs
LNKB="https://dl.winehq.org/wine-builds/${id}/dists/${dist}/main/binary-i386/" #i386-wine links
DEB_B1="wine-${branch}-i386_${version}~${dist}${tag}_i386.deb" #wine_i386 main bin
DEB_B2="wine-${branch}_${version}~${dist}${tag}_i386.deb" #wine_i386 support files (required for wine_i386 if no wine64 / CONFLICTS WITH wine64 support files)
#DEB_B3="winehq-${branch}_${version}~${dist}${tag}_i386.deb" #shortcuts & docs
# Install amd64-wine (64-bit) alongside i386-wine (32-bit)
echo -e "Downloading wine . . ."
wget -q ${LNKA}${DEB_A1}
wget -q ${LNKA}${DEB_A2}
wget -q ${LNKB}${DEB_B1}
echo -e "Extracting wine . . ."
dpkg-deb -x ${DEB_A1} wine-installer
dpkg-deb -x ${DEB_A2} wine-installer
dpkg-deb -x ${DEB_B1} wine-installer
echo -e "Installing wine . . ."
mv wine-installer/opt/wine* ~/wine
# Download wine dependencies
# - these packages are needed for running box86/wine-i386 on a 64-bit RPiOS via multiarch
sudo dpkg --add-architecture armhf && sudo apt-get update # enable multi-arch
sudo apt-get install -y libasound2:armhf libc6:armhf libglib2.0-0:armhf libgphoto2-6:armhf libgphoto2-port12:armhf \
libgstreamer-plugins-base1.0-0:armhf libgstreamer1.0-0:armhf libldap-2.4-2:armhf libopenal1:armhf libpcap0.8:armhf \
libpulse0:armhf libsane1:armhf libudev1:armhf libusb-1.0-0:armhf libvkd3d1:armhf libx11-6:armhf libxext6:armhf \
libasound2-plugins:armhf ocl-icd-libopencl1:armhf libncurses6:armhf libncurses5:armhf libcap2-bin:armhf libcups2:armhf \
libdbus-1-3:armhf libfontconfig1:armhf libfreetype6:armhf libglu1-mesa:armhf libglu1:armhf libgnutls30:armhf \
libgssapi-krb5-2:armhf libkrb5-3:armhf libodbc1:armhf libosmesa6:armhf libsdl2-2.0-0:armhf libv4l-0:armhf \
libxcomposite1:armhf libxcursor1:armhf libxfixes3:armhf libxi6:armhf libxinerama1:armhf libxrandr2:armhf \
libxrender1:armhf libxxf86vm1 libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
# This list found by downloading...
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel-i386_7.1~bullseye-1_i386.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/winehq-devel_7.1~bullseye-1_i386.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel_7.1~bullseye-1_i386.deb
# then `dpkg-deb -I package.deb`. Read output, add `:armhf` to packages in dep list, then try installing them on Pi aarch64.
# - these packages are needed for running box64/wine-amd64 on RPiOS (box64 only runs on 64-bit OS's)
sudo apt-get install -y libasound2:arm64 libc6:arm64 libglib2.0-0:arm64 libgphoto2-6:arm64 libgphoto2-port12:arm64 \
libgstreamer-plugins-base1.0-0:arm64 libgstreamer1.0-0:arm64 libldap-2.4-2:arm64 libopenal1:arm64 libpcap0.8:arm64 \
libpulse0:arm64 libsane1:arm64 libudev1:arm64 libunwind8:arm64 libusb-1.0-0:arm64 libvkd3d1:arm64 libx11-6:arm64 libxext6:arm64 \
ocl-icd-libopencl1:arm64 libasound2-plugins:arm64 libncurses6:arm64 libncurses5:arm64 libcups2:arm64 \
libdbus-1-3:arm64 libfontconfig1:arm64 libfreetype6:arm64 libglu1-mesa:arm64 libgnutls30:arm64 \
libgssapi-krb5-2:arm64 libjpeg62-turbo:arm64 libkrb5-3:arm64 libodbc1:arm64 libosmesa6:arm64 libsdl2-2.0-0:arm64 libv4l-0:arm64 \
libxcomposite1:arm64 libxcursor1:arm64 libxfixes3:arm64 libxi6:arm64 libxinerama1:arm64 libxrandr2:arm64 \
libxrender1:arm64 libxxf86vm1:arm64 libc6:arm64 libcap2-bin:arm64
# This list found by downloading...
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-amd64/wine-devel_7.1~bullseye-1_amd64.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-amd64/wine-devel-amd64_7.1~bullseye-1_amd64.deb
# then `dpkg-deb -I package.deb`. Read output, add `:arm64` to packages in dep list, then try installing them on Pi aarch64.
# These packages are needed for running wine-staging on RPiOS (Credits: chills340)
sudo apt install libstb0 -y
cd ~/Downloads
wget -r -l1 -np -nd -A "libfaudio0_*~bpo10+1_i386.deb" http://ftp.us.debian.org/debian/pool/main/f/faudio/ # Download libfaudio i386 no matter its version number
dpkg-deb -xv libfaudio0_*~bpo10+1_i386.deb libfaudio
sudo cp -TRv libfaudio/usr/ /usr/
rm libfaudio0_*~bpo10+1_i386.deb # clean up
rm -rf libfaudio # clean up
# Install symlinks
sudo ln -s ~/wine/bin/wine /usr/local/bin/wine
sudo ln -s ~/wine/bin/wine64 /usr/local/bin/wine64
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wine64 /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
```
## Installing winetricks
Winetricks is a bash script which makes it easier to install & configure any desired Windows core system software packages which may be dependencies for certain Windows programs. You can either install it with `apt`, or manually using the steps below.
```
sudo apt-get install cabextract -y # winetricks needs this installed
sudo mv /usr/local/bin/winetricks /usr/local/bin/winetricks-old # Backup old winetricks
cd ~/Downloads && wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks # Download
sudo chmod +x winetricks && sudo mv winetricks /usr/local/bin/ # Install
```
Whenever we run winetricks, we must tell Box86 to supress its info banner, otherwise winetricks will crash. Box86's info banner can be suppressed using the `BOX86_NOBANNER=1` environment variable before invoking winetricks (example: `BOX86_NOBANNER=1 winetricks`).
If `apt` installed a desktop menu shortcut for winetricks (or if you make your own desktop shortcut for winetricks) then you may need to edit that shortcut to include Box86's BOX86_NOBANNER=1 env var. With your favorite text editor, edit `/usr/share/applications/winetricks.desktop` and change `Exec=winetricks --gui` to `Exec=env BOX86_NOBANNER=1 winetricks --gui`.
## Example commands
Creating a 64-bit wineprefix:
`wine64 wineboot` or `wine wineboot` (wineprefix is created in `~/.wine/`)
`WINEPREFIX="$HOME/prefix64" wine wineboot` (wineprefix is created in `~/prefix64/`) _Note: You will need to invoke `WINEPREFIX="$HOME/prefix64"` before every command to use this wineprefix._
Creating a 32-bit wineprefix:
`WINEARCH=win32 wine wineboot` (wineprefix is created in `~/.wine/`)
Fore-quitting wine:
`wineserver -k`
Running Wine Configuration:
`winecfg`
Using winetricks:
`winetricks -q corefonts vcrun2010 dotnet20sp1`
_This command will silently install three packages in series: Windows core fonts, VC++ 2010 Runtimes, and .NET 2.0 SP1. `-q` is the "install silent/quiet" command._
Invoking Box86's logging features (with `BOX86_LOG=1` or similar) will cause winetricks to crash.
For a list of all the different Windows packages & libraries that winetricks can help you install, run `winetricks list-all`
## Other notes
### Wineprefixes (and Wine initialization)
When you first run or boot Wine (`wine wineboot`), Wine will create a new user environment within which to install Windows software. This user environment is called a "wineprefix" (or "wine bottle") and is located (by default) in `~/.wine` (note that Linux folders with a `.` in front of them are "hidden" folders). Think of a wineprefix as Wine's virtual 'harddrive' where it installs software and saves settings. Wineprefixes are portable and deletable. For more Wine documentation, see [WineHQ](https://www.winehq.org/documentation).
If you at any point corrupt something inside your default wineprefix, you can start "fresh" by deleting your `~/.wine` directory (with the `rm -rf ~/.wine` command) and boot wine again to create a new default wineprefix.
### Transplanting wineprefixes
If software isn't installing in Wine with Box86, but is installing for you in Wine on a regular x86 Linux computer, you can copy a wineprefix from your x86 Linux computer to the device you're running Box86 on. This is most easily done by tarring the `~/.wine` folder on your x86 Linux computer (`tar -cvf winebottle.tar ~/.wine`), transferring the tar file to your device, then un-tarring the tar file (`tar -xf winebottle.tar`) on your device running Box86 & Wine. Tarring the wineprefix preserves any symlinks that are inside it.
### Swapping out different versions of Wine
Some versions of Wine work better with certain software. It is best to install a version of Wine that is known to work with the software you would like to run. There are three main development branches of Wine you can pick from, referred to as wine-stable, wine-devel, and wine-staging. _Note that the wine-staging branch requires extra installation steps on Raspberry Pi._
Your entire Wine installation can reside within a single folder on your Linux computer. TwisterOS assumes that your Wine installation is located inside the `~/wine/` directory. The actual directory where you put your `wine` folder doesn't matter as long as you have symlinks within the `/usr/local/bin/` directory which point to the `wine` folder so that Linux can find Wine when you type `wine` into the terminal).
You can change which version of Wine you are running simply by renaming your old `wine` and `.wine` folders to something else, then putting a new `wine` folder (containing your new version of Wine) in its place. Running `wine wineboot` again will migrate a wineprefix from an older version of Wine to be usable by the newer version of Wine you just installed. You can check which version of Wine you're running with the `wine --version` command.
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=Debug
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-lx2160a-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
package() {
cd "$srcdir/${pkgname%-lx2160a-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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-lx2160a-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=Debug
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
package() {
cd "$srcdir/${pkgname%-lx2160a-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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=Debug
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=Debug
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -23,7 +23,7 @@ prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=Debug
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -35,10 +35,4 @@ build() {
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
}
+1 -7
View File
@@ -22,7 +22,7 @@ prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -34,10 +34,4 @@ build() {
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
}
+1 -7
View File
@@ -22,7 +22,7 @@ prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=Debug
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
@@ -34,10 +34,4 @@ build() {
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
}
+4 -1
View File
@@ -388,7 +388,10 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("sdl1mixer", "sdl2mixer") \
or match("sdl1net", "sdl2net") \
or match("sdl1ttf", "sdl2ttf") \
or match("libc", "tcmallocminimal"):
or match("libGL", "libEGL") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
or match("tcmallocminimal", "tbbmallocproxy"):
continue
# Note: this test is very (too) simple. If it ever raises, comment
+53 -76
View File
@@ -63,8 +63,8 @@ void free_tlsdatasize(void* p)
if(!p)
return;
tlsdatasize_t *data = (tlsdatasize_t*)p;
free(data->tlsdata);
free(p);
box_free(data->ptr);
box_free(p);
}
void x64Syscall(x64emu_t *emu);
@@ -79,8 +79,6 @@ int unlockMutex()
ret|=(1<<B); \
}
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
GO(my_context->mutex_trace, 7)
#ifdef DYNAREC
GO(my_context->mutex_dyndump, 8)
@@ -100,10 +98,8 @@ void relockMutex(int locks)
relockCustommemMutex(locks);
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
pthread_mutex_trylock(&A); \
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
GO(my_context->mutex_trace, 7)
#ifdef DYNAREC
GO(my_context->mutex_dyndump, 8)
@@ -121,8 +117,6 @@ static void init_mutexes(box64context_t* context)
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, &attr);
@@ -142,6 +136,31 @@ static void atfork_child_box64context(void)
init_mutexes(my_context);
}
void freeCycleLog(box64context_t* ctx)
{
if(cycle_log) {
for(int i=0; i<cycle_log; ++i) {
box_free(ctx->log_call[i]);
box_free(ctx->log_ret[i]);
}
box_free(ctx->log_call);
box_free(ctx->log_ret);
ctx->log_call = NULL;
ctx->log_ret = NULL;
}
}
void initCycleLog(box64context_t* context)
{
if(cycle_log) {
context->log_call = (char**)box_calloc(cycle_log, sizeof(char*));
context->log_ret = (char**)box_calloc(cycle_log, sizeof(char*));
for(int i=0; i<cycle_log; ++i) {
context->log_call[i] = (char*)box_calloc(256, 1);
context->log_ret[i] = (char*)box_calloc(128, 1);
}
}
}
EXPORTDYN
box64context_t *NewBox64Context(int argc)
{
@@ -152,7 +171,9 @@ box64context_t *NewBox64Context(int argc)
}
#endif
// init and put default values
box64context_t *context = my_context = (box64context_t*)calloc(1, sizeof(box64context_t));
box64context_t *context = my_context = (box64context_t*)box_calloc(1, sizeof(box64context_t));
initCycleLog(context);
context->deferedInit = 1;
context->sel_serial = 1;
@@ -163,6 +184,8 @@ box64context_t *NewBox64Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
// create the vsyscalls
@@ -178,7 +201,7 @@ box64context_t *NewBox64Context(int argc)
context->dlprivate = NewDLPrivate();
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
context->argv = (char**)box_calloc(context->argc+1, sizeof(char*));
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
@@ -211,11 +234,13 @@ void FreeBox64Context(box64context_t** context)
if(ctx->maplib)
FreeLibrarian(&ctx->maplib, NULL);
FreeDictionnary(&ctx->versym);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
}
free(ctx->elfs);
box_free(ctx->elfs);
FreeCollection(&ctx->box64_path);
FreeCollection(&ctx->box64_ld_lib);
@@ -227,16 +252,16 @@ void FreeBox64Context(box64context_t** context)
DeleteX64Trace(ctx);
if(ctx->deferedInitList)
free(ctx->deferedInitList);
box_free(ctx->deferedInitList);
free(ctx->argv);
/*box_free(ctx->argv);*/
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
/*for (int i=0; i<ctx->envc; ++i)
box_free(ctx->envv[i]);
box_free(ctx->envv);*/
if(ctx->atfork_sz) {
free(ctx->atforks);
box_free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
@@ -252,8 +277,9 @@ void FreeBox64Context(box64context_t** context)
FreeDLPrivate(&ctx->dlprivate);
free(ctx->fullpath);
free(ctx->box64path);
box_free(ctx->fullpath);
box_free(ctx->box64path);
box_free(ctx->bashpath);
FreeBridge(&ctx->system);
@@ -261,7 +287,7 @@ void FreeBox64Context(box64context_t** context)
freeALProcWrapper(ctx);
if(ctx->stack_clone)
free(ctx->stack_clone);
box_free(ctx->stack_clone);
void* ptr;
@@ -272,7 +298,7 @@ void FreeBox64Context(box64context_t** context)
pthread_key_delete(ctx->tlskey);
if(ctx->tlsdata)
free(ctx->tlsdata);
box_free(ctx->tlsdata);
free_neededlib(&ctx->neededlibs);
@@ -281,8 +307,6 @@ void FreeBox64Context(box64context_t** context)
finiAllHelpers(ctx);
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifndef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
@@ -293,7 +317,9 @@ void FreeBox64Context(box64context_t** context)
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
free(ctx);
freeCycleLog(ctx);
box_free(ctx);
}
int AddElfHeader(box64context_t* ctx, elfheader_t* head) {
@@ -301,7 +327,7 @@ int AddElfHeader(box64context_t* ctx, elfheader_t* head) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
@@ -312,7 +338,7 @@ int AddElfHeader(box64context_t* ctx, elfheader_t* head) {
int AddTLSPartition(box64context_t* context, int tlssize) {
int oldsize = context->tlssize;
context->tlssize += tlssize;
context->tlsdata = realloc(context->tlsdata, context->tlssize);
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
// clean GS segment for current emu
@@ -325,52 +351,3 @@ int AddTLSPartition(box64context_t* context, int tlssize) {
return -context->tlssize; // negative offset
}
void add_neededlib(needed_libs_t* needed, library_t* lib)
{
if(!needed)
return;
for(int i=0; i<needed->size; ++i)
if(needed->libs[i] == lib)
return;
if(needed->size == needed->cap) {
needed->cap += 8;
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
}
needed->libs[needed->size++] = lib;
}
void free_neededlib(needed_libs_t* needed)
{
if(!needed)
return;
needed->cap = 0;
needed->size = 0;
if(needed->libs)
free(needed->libs);
needed->libs = NULL;
}
void add_dependedlib(needed_libs_t* depended, library_t* lib)
{
if(!depended)
return;
for(int i=0; i<depended->size; ++i)
if(depended->libs[i] == lib)
return;
if(depended->size == depended->cap) {
depended->cap += 8;
depended->libs = (library_t**)realloc(depended->libs, depended->cap*sizeof(library_t*));
}
depended->libs[depended->size++] = lib;
}
void free_dependedlib(needed_libs_t* depended)
{
if(!depended)
return;
depended->cap = 0;
depended->size = 0;
if(depended->libs)
free(depended->libs);
depended->libs = NULL;
}
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX64_VERSION_H_
#define BOX64_MAJOR 0
#define BOX64_MINOR 1
#define BOX64_REVISION 8
#define BOX64_MINOR 2
#define BOX64_REVISION 0
#endif //__BOX64_VERSION_H_
+436 -220
View File
File diff suppressed because it is too large. Load diff
+39 -21
View File
@@ -196,7 +196,7 @@
// ADR
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
#define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd))
#define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd)))
// LDR
#define LDR_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt))
@@ -359,6 +359,10 @@
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
// Break
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
#define BRK(imm16) EMIT(BRK_gen(imm16))
// BR and Branches
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
#define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
@@ -679,7 +683,9 @@
// VLDR
#define VMEM_gen(size, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | 0b01<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
// imm14 must be 3-aligned
// imm13 must be 1-aligned
#define VLDR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b01, ((uint32_t)((imm13)>>1))&0xfff, Rn, Ht))
// imm14 must be 2-aligned
#define VLDR32_U12(Dt, Rn, imm14) EMIT(VMEM_gen(0b10, 0b01, ((uint32_t)((imm14)>>2))&0xfff, Rn, Dt))
// imm15 must be 3-aligned
#define VLDR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b01, ((uint32_t)((imm15)>>3))&0xfff, Rn, Dt))
@@ -691,22 +697,22 @@
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
// imm16 must be 4-aligned
#define VSTR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
// (imm14) must be 1-aligned
#define VSTR16_U12(Ht, Rn, imm14) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm14>>1))&0xfff, Rn, Ht))
// (imm13) must be 1-aligned
#define VSTR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm13>>1))&0xfff, Rn, Ht))
#define VMEMUR_vector(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
// signed offset, no alignement!
#define VLDR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
#define VLDR8_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR16_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR32_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR64_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR128_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
// signed offset, no alignement!
#define VSTR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
#define VSTR8_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR16_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR32_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
#define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
#define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
@@ -721,18 +727,18 @@
#define VMEM_REG_gen(size, opc, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | 0b10<<10 | (Rn)<<5 | (Rt))
#define VLDR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR32_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 0, Rn, Dt))
#define VLDR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 1, Rn, Dt))
#define VLDR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 0, Rn, Qt))
#define VLDR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 1, Rn, Qt))
#define VSTR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR32_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Dt))
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Dt))
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Qt))
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Qt))
#define VLDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | 1<<26 | (imm19)<<5 | (Rt))
#define VLDR32_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b00, ((imm19)>>2)&0x7FFFF, Vt))
@@ -1239,6 +1245,11 @@
#define VFRINTISQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 0, 1, Vn, Vd))
#define VFRINTIDQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 1, 1, Vn, Vd))
#define FRINTI_scalar(type, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | 0b111<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINTIS(Sd, Sn) EMIT(FRINTI_scalar(0b00, Sn, Sd))
#define FRINTID(Dd, Dn) EMIT(FRINTI_scalar(0b01, Dn, Dd))
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
@@ -1760,7 +1771,7 @@
#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
// AES extension
#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))
@@ -1769,4 +1780,11 @@
#define AESIMC(Vd, Vn) EMIT(AESMC_gen(1, Vn, Vd))
#define AESMC(Vd, Vn) EMIT(AESMC_gen(0, Vn, Vd))
// PMULL extension is PMULL_128
#define PMULL_gen(Q, size, Rm, Rn, Rd) (0<<31 | (Q)<<30 | 0b001110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b1110<<12 | (Rn)<<5 | (Rd))
#define PMULL(Rd, Rn, Rm) EMIT(PMULL_gen(0, 0b00, Rm, Rn, Rd))
#define PMULL2(Rd, Rn, Rm) EMIT(PMULL_gen(1, 0b00, Rm, Rn, Rd))
#define PMULL_128(Rd, Rn, Rm) EMIT(PMULL_gen(0, 0b11, Rm, Rn, Rd))
#define PMULL2_128(Rd, Rn, Rm) EMIT(PMULL_gen(1, 0b11, Rm, Rn, Rd))
#endif //__ARM64_EMITTER_H__
+2 -2
View File
@@ -30,7 +30,7 @@ arm64_epilog:
ldp d12, d13, [sp, (8 *14)]
ldp d14, d15, [sp, (8 *16)]
add sp, sp, (8 * 18)
ldp lr, fp, [sp], 16 // saved lr
ldp x30, x29, [sp], 16 // saved lr
//end, return...
ret
@@ -49,6 +49,6 @@ arm64_epilog_fast:
ldp d12, d13, [sp, (8 *14)]
ldp d14, d15, [sp, (8 *16)]
add sp, sp, (8 * 18)
ldp lr, fp, [sp], 16 // saved lr
ldp x30, x29, [sp], 16 // saved lr
//end, return...
ret
+12
View File
@@ -16,6 +16,7 @@
.global arm64_lock_read_dq
.global arm64_lock_write_dq
.global arm64_lock_xchg
.global arm64_lock_xchg_d
.global arm64_lock_storeifnull
.global arm64_lock_storeifref
@@ -100,6 +101,17 @@ arm64_lock_xchg_0:
mov x0, x2
ret
arm64_lock_xchg_d:
dmb ish
arm64_lock_xchg_d_0:
// address is x0, value is x1, return old value in x0
ldaxr w2, [x0]
stlxr w3, w1, [x0]
cbnz w3, arm64_lock_xchg_d_0
dmb ish
mov w0, w2
ret
arm64_lock_storeifnull:
dmb ish
arm64_lock_storeifnull_0:
+3
View File
@@ -30,6 +30,9 @@ extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
// Atomicaly exchange value at [p] with val, return old p
extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
extern void* arm64_lock_storeifnull(void*p, void* val);
+1 -1
View File
@@ -20,7 +20,7 @@ arm64_next:
stp x16, x17, [sp, (8 * 8)]
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
mov x2, lr // "from" is in lr, so put in x2
mov x2, x30 // "from" is in lr, so put in x2
add x3, sp, 8*11 // x3 is address to change rip
// call the function
bl LinkNext
+12 -1
View File
@@ -776,7 +776,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
if(isMask(opcode, "10011011U10mmmmm011111nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "%cMULH %s, %s, %s", a.U?'U':'S', Xt[Rd], Wt[Rn], Wt[Rm]);
snprintf(buff, sizeof(buff), "%cMULH %s, %s, %s", a.U?'U':'S', Xt[Rd], Xt[Rn], Xt[Rm]);
return buff;
}
if(isMask(opcode, "f0011011000mmmmm0aaaaannnnnddddd", &a)) {
@@ -1351,6 +1351,17 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "AES%sMC V%d.16B, V%d.16B", sf?"I":"", Rd, Rn);
return buff;
}
// PMULL
if(isMask(opcode, "0Q001110ff1mmmmm111000nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "??", "??", "??", "??", "1D", "2D"};
const char* Z[] = {"8H", "??", "??", "1Q"};
int sz = sf;
const char* Vn = Y[(sz<<1)|a.Q];
const char* Vd = Z[sz];
snprintf(buff, sizeof(buff), "PMULL%s V%d.%s, V%d.%s, V%d.%s", a.Q?"2":"", Rd, Vd, Rn, Vn, Rm, Vn);
return buff;
}
// DMB ISH
if(isMask(opcode, "11010101000000110011nnnn10111111", &a)) {
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
+1 -1
View File
@@ -9,7 +9,7 @@
.global arm64_prolog
arm64_prolog:
//save all 18 used register
stp lr, fp, [sp, -16]! // save lr
stp x30, x29, [sp, -16]! // save lr
sub sp, sp, (8 * 18)
stp x19, x20, [sp, (8 * 0)]
stp x21, x22, [sp, (8 * 2)]
+105 -40
View File
@@ -39,12 +39,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint64_t u64;
uint8_t wback, wb1, wb2, wb;
int64_t fixedaddress;
int lock;
int cacheupd;
opcode = F8;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
MAYUSE(wb);
MAYUSE(lock);
MAYUSE(cacheupd);
switch(opcode) {
case 0x00:
@@ -526,14 +530,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRSW_U12(gd, ed, fixedaddress);
}
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(gd, ed, fixedaddress);
}
}
@@ -648,11 +652,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!dyn->insts[ninst].x64.barrier) \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
B(i32); \
} \
@@ -858,7 +862,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
DMB_ISH();
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
// do the swap with exclusive locking
LDAXRB(x1, ed);
@@ -880,7 +884,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(ed, x1);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
DMB_ISH();
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -925,8 +929,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
BFIx(eb1, gd, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, &lock, 0, 0);
STRB_U12(gd, ed, fixedaddress);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
break;
case 0x89:
@@ -936,10 +944,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp))) {
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
@@ -971,11 +979,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = wback;
}
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, &lock, 0, 0);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier)))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(x4, wback, fixedaddress);
ed = x4;
}
@@ -987,12 +995,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
if(box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier))) {
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || !ninst || box64_dynarec_strongmem>1 || (ninst && dyn->insts[ninst-1].x64.barrier)))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
LDRxw_U12(gd, ed, fixedaddress);
}
break;
@@ -1002,7 +1010,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
STRH_U12(x3, ed, fixedaddress);
}
@@ -1014,7 +1022,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
MOVxw_REG(gd, ed);
}
@@ -1029,7 +1037,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 0, rex, NULL, 0, 0);
LDRH_U12(x1, ed, fixedaddress);
ed = x1;
}
@@ -1043,7 +1051,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
if(ed==xRSP) {
STRx_U12(x2, ed, fixedaddress);
} else {
@@ -1200,7 +1208,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
@@ -1294,12 +1303,33 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xAD:
if(rep) {
INST_NAME("REP LODSD");
} else {
INST_NAME("LODSD");
}
LDRxw_U12(xRAX, xRSI, 0);
BFIw(x2, xFlags, F_DF, 1);
if(rex.w) {
MOV32w(x1, 8);
} else {
MOV32w(x1, 4);
}
EORxw_REG_LSL(x1, x1, x2, rex.w?63:31);
if(rep) {
MULxw(x1, x1, xRCX);
EORw_REG(xRCX, xRCX, xRCX);
}
ADDx_REG(xRSI, xRSI, x1);
break;
case 0xAE:
switch(rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
UBFXw(x1, xRAX, 0, 8);
TBNZ_MARK2(xFlags, F_DF);
@@ -1559,7 +1589,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC2:
INST_NAME("RETN");
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
READFLAGS(X_PEND); // lets play safe here too
if(box64_dynarec_safeflags) {
READFLAGS(X_PEND); // lets play safe here too
}
BARRIER(BARRIER_FLOAT);
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
@@ -1569,7 +1601,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC3:
INST_NAME("RET");
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
if(box64_dynarec_safeflags) {
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
}
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
@@ -1592,10 +1626,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x3, u8);
BFIx(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 0, rex, &lock, 0, 1);
u8 = F8;
MOV32w(x3, u8);
STRB_U12(x3, ed, fixedaddress);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
break;
case 0xC7:
@@ -1606,10 +1644,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_U12(x3, ed, fixedaddress);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
break;
@@ -1640,13 +1682,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
x87_forget(dyn, ninst, x3, x4, 0);
sse_purge07cache(dyn, ninst, x3);
tmp = isSimpleWrapper(*(wrapper_t*)(addr));
if(box64_log<2 && tmp) {
if((box64_log<2 || !cycle_log) && tmp) {
//GETIP(ip+3+8+8); // read the 0xCC
call_n(dyn, ninst, *(void**)(addr+8), tmp);
addr+=8+8;
} else {
GETIP(ip+1); // read the 0xCC
STORE_XEMU_CALL(xRIP);
ADDx_U12(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
CALL_S(x64Int3, -1);
LOAD_XEMU_CALL(xRIP);
addr+=8+8;
@@ -1813,7 +1856,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
GETEDW(x4, x1, 0);
CALL_(rcl32, ed, x4);
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);
WBACK;
break;
case 3:
@@ -1823,7 +1866,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
GETEDW(x4, x1, 0);
CALL_(rcr32, ed, x4);
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);
WBACK;
break;
case 4:
@@ -1863,7 +1906,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
MOV64xw(x4, (rex.w?64:32));
SUBx_REG(x3, x4, x3);
GETEDW(x4, x2, 0);
GETED(0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
RORxw_REG(ed, ed, x3);
@@ -1887,7 +1930,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDW(x4, x2, 0);
GETED(0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
RORxw_REG(ed, ed, x3);
@@ -2001,7 +2044,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xDD:
addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDE:
addr = dynarec64_DE(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDF:
addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
@@ -2014,11 +2059,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
if(Z) {CBNZx(xRCX, i32);} else {CBZx(xRCX, i32);}; \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!dyn->insts[ninst].x64.barrier) \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
Bcond(c__, i32); \
} \
@@ -2077,18 +2122,24 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(BARRIER_FULL);
//BARRIER_NEXT(BARRIER_FULL);
TABLE64(x2, addr);
if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) {
ADDx_U12(x2, xRIP, addr-dyn->last_ip);
} else {
TABLE64(x2, addr);
}
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
sse_purge07cache(dyn, ninst, x3);
if(box64_log<2 && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
if((box64_log<2 || !cycle_log) && dyn->insts[ninst].natcall && (tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2)))) {
//GETIP(ip+3+8+8); // read the 0xCC
call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp);
POP1(xRIP); // pop the return address
dyn->last_ip = addr;
} else {
GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already
STORE_XEMU_CALL(xRIP);
ADDx_U12(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
CALL_S(x64Int3, -1);
LOAD_XEMU_CALL(xRIP);
TABLE64(x3, dyn->insts[ninst].natcall);
@@ -2107,10 +2158,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK;
LOAD_XEMU_REM(); // load remaining register, has they have changed
jump_to_epilog(dyn, 0, xRIP, ninst);
dyn->last_ip = addr;
}
break;
default:
if(ninst && dyn->insts[ninst-1].x64.set_flags) {
if((box64_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x64.set_flags)) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
@@ -2148,7 +2200,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
fpuCacheTransform(dyn, ninst, x1, x2, x3);
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
tmp = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);
if(tmp==4) {
NOP;
@@ -2378,6 +2430,18 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xF8:
INST_NAME("CLC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
BFCx(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
ORRx_mask(xFlags, xFlags, 1, 0, 0); // xFlags | 1
break;
case 0xFC:
INST_NAME("CLD");
@@ -2428,7 +2492,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
PASS2IF((box64_dynarec_safeflags>1) ||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
+127 -93
View File
@@ -39,7 +39,7 @@
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
@@ -52,7 +52,7 @@
if(MODREG) { \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR64_U12(a, ed, fixedaddress); \
}
@@ -72,6 +72,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t wback, wb2;
uint8_t eb1, eb2;
int32_t i32, i32_;
int cacheupd;
int v0, v1;
int q0, q1;
int d0, d1;
@@ -88,6 +89,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
@@ -122,6 +124,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x09:
INST_NAME("WBINVD");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0x0B:
@@ -130,6 +140,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0x0D:
@@ -137,7 +151,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 1:
INST_NAME("PREFETCHW");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
PST_L1_STREAM_U12(ed, fixedaddress);
break;
default: //???
@@ -156,7 +170,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
}
break;
@@ -170,7 +184,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -184,7 +198,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("MOVLPS Gx,Ex");
GETGX(v0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 0, ed);
}
break;
@@ -196,7 +210,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
}
break;
@@ -224,7 +238,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("MOVHPS Gx,Ex");
GETGX(v0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
@@ -236,7 +250,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 1, ed);
}
break;
@@ -248,22 +262,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
PLD_L1_STREAM_U12(ed, fixedaddress);
break;
case 1:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
PLD_L1_KEEP_U12(ed, fixedaddress);
break;
case 2:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
PLD_L2_KEEP_U12(ed, fixedaddress);
break;
case 3:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
PLD_L3_KEEP_U12(ed, fixedaddress);
break;
default:
@@ -289,7 +303,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
@@ -303,7 +317,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -318,7 +332,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -334,7 +348,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
@@ -386,6 +400,31 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SQRDMULH_16(q0, q0, q1);
break;
case 0xF0:
INST_NAME("MOVBE Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) {
REVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
LDRxw_U12(gd, ed, fixedaddress);
REVxw(gd, gd);
}
break;
case 0xF1:
INST_NAME("MOVBE Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
REVxw(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, NULL, 0, 0);
REVxw(x1, gd);
STRxw_U12(x1, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
@@ -424,7 +463,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3); \
CSELxw(gd, ed, gd, YES); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0); \
Bcond(NO, +8); \
LDRxw_U12(gd, ed, fixedaddress); \
if(!rex.w) {MOVw_REG(gd, gd);} \
@@ -452,7 +491,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gd, x1, 3, 1);
} else {
// EX is memory
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, NULL, 0, 0);
LDRx_U12(x1, ed, fixedaddress+0);
LSRx(x1, x1, 31);
BFIx(gd, x1, 0, 1);
@@ -655,7 +694,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VMOVeD(q0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(q0, 1, ed);
}
SQXTUN_8(v0, q0);
@@ -691,7 +730,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeD(q0, 1, v1, 0);
} else {
q0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(q0, 1, ed);
}
VMOVeD(q0, 0, v0, 0);
@@ -712,7 +751,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
if(rex.w) {
VLDR64_U12(v0, ed, fixedaddress);
} else {
@@ -730,7 +769,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeD(v0, 0, v1, 0);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
@@ -798,7 +837,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = F8;
if (u8) {
i32 = -1;
@@ -834,7 +873,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 4:
INST_NAME("PSRAW Ex, Ib");
INST_NAME("PSRAW Em, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8>15) u8=15;
@@ -846,7 +885,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 6:
INST_NAME("PSLLW Ex, Ib");
INST_NAME("PSLLW Em, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8) {
@@ -989,7 +1028,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(ed, ed);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
if(rex.w) {
VSTR64_U12(v0, ed, fixedaddress);
} else {
@@ -1005,7 +1044,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
VMOV(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
@@ -1022,11 +1061,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!dyn->insts[ninst].x64.barrier) \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
B(i32); \
} \
@@ -1055,7 +1094,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} \
BFIx(eb1, x3, eb2, 8); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0); \
STRB_U12(x3, ed, fixedaddress); \
}
@@ -1076,7 +1115,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
@@ -1123,7 +1162,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
@@ -1192,7 +1231,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxsave64):((void*)fpu_fxsave32), -1);
}
@@ -1204,7 +1243,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxrstor64):((void*)fpu_fxrstor32), -1);
}
@@ -1220,11 +1259,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
LDRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
STRw_U12(x4, ed, fixedaddress);
}
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
GETED(0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(arm_clflush, -1, 0);
break;
default:
DEFAULT;
}
@@ -1272,7 +1320,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
@@ -1315,7 +1363,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UBFXxw(gd, eb1, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRB_U12(gd, ed, fixedaddress);
}
break;
@@ -1327,7 +1375,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
UBFXxw(gd, ed, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRH_U12(gd, ed, fixedaddress);
}
break;
@@ -1343,17 +1391,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
u8&=rex.w?0x3f:0x1f;
if(u8) {
LSRxw(x1, ed, u8);
ed = x1;
}
BFIw(xFlags, ed, F_CF, 1);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
break;
case 5:
INST_NAME("BTS Ed, Ib");
@@ -1363,19 +1407,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
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
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
@@ -1391,20 +1430,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
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
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
@@ -1419,18 +1453,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
if(u8) {
LSRxw(x4, ed, u8);
} else {
MOVw_REG(x4, ed);
}
BFIw(xFlags, x4, F_CF, 1);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
@@ -1452,7 +1481,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
@@ -1524,7 +1553,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
SBFXxw(gd, wback, wb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRSBxw_U12(gd, ed, fixedaddress);
}
break;
@@ -1536,7 +1565,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
SXTHxw(gd, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRSHxw_U12(gd, ed, fixedaddress);
}
break;
@@ -1579,7 +1608,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
}
break;
@@ -1592,7 +1621,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
VMOVQHfrom(v0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&3;
VLD1_16(v0, u8, wback);
}
@@ -1606,7 +1635,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = (F8)&3;
VMOVHto(gd, v0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&3;
LDRH_U12(gd, wback, u8*2);
}
@@ -1616,26 +1645,31 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGX(v0, 1);
if(!MODREG)
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
d0 = fpu_get_scratch(dyn);
// first two elements from Gx
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v0, (u8>>(i*2)&3));
}
// second two from Ex
if(MODREG) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
else
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2)&3));
}
u8 = F8;
if(MODREG && v0==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
VDUPQ_32(v0, v0, u8&3);
} else {
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, (u8>>(i*2)&3)*4);
VLD1_32(d0, i, x2);
d0 = fpu_get_scratch(dyn);
// first two elements from Gx
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v0, (u8>>(i*2)&3));
}
// second two from Ex
if(MODREG) {
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2)&3));
}
} else {
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, (u8>>(i*2)&3)*4);
VLD1_32(d0, i, x2);
}
}
VMOVQ(v0, d0);
}
VMOVQ(v0, d0);
break;
case 0xC8:
@@ -1778,7 +1812,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
} else {
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
@@ -1847,7 +1881,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF5:
INST_NAME("PMADDWD Gx, Ex");
INST_NAME("PMADDWD Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
+26 -15
View File
@@ -91,7 +91,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
}
@@ -107,7 +107,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR32_U12(v0, x4, fixedaddress);
}
@@ -129,7 +129,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVQ(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR128_U12(v0, x4, fixedaddress);
}
@@ -145,7 +145,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeD(d0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR64_U12(v0, x4, fixedaddress);
}
@@ -160,7 +160,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeS(q0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR32_U12(v0, x4, fixedaddress);
}
@@ -182,7 +182,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVQ(v0, v1);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR128_U12(v0, ed, fixedaddress);
}
@@ -242,7 +242,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UBFXxw(gd, eb1, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRB_REG(gd, ed, x4);
}
break;
@@ -252,6 +252,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -291,7 +301,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRSW_REG(gd, ed, x4);
}
} else {
@@ -299,7 +309,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRw_REG(gd, ed, x4);
}
}
@@ -500,7 +510,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRB_REG(x4, wback, x4);
ed = x4;
}
@@ -514,7 +524,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
STRxw_REG(gd, ed, x4);
}
break;
@@ -527,7 +537,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRxw_REG(gd, ed, x4);
}
break;
@@ -549,7 +559,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x3, u8);
BFIx(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = F8;
MOV32w(x3, u8);
STRB_REG(x3, ed, x4);
@@ -564,7 +574,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_REG(x3, ed, x4);
@@ -937,7 +947,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(((ninst && dyn->insts[ninst-1].x64.set_flags)
PASS2IF((box64_dynarec_safeflags>1) ||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
+84 -43
View File
@@ -35,19 +35,21 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t gd, ed;
uint8_t wback, wb1;
int64_t fixedaddress;
int lock;
MAYUSE(u8);
MAYUSE(u16);
MAYUSE(u64);
MAYUSE(j64);
MAYUSE(lock);
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x66)) // ignoring CS:, SS: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
// REX prefix before the 66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
@@ -301,26 +303,17 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x69:
INST_NAME("IMUL Gw,Ew,Iw");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 2);
i32 = F16S;
MOV32w(x2, i32);
MULw(x2, x2, x1);
UFLAG_RES(x2);
gd=x2;
GWBACK;
break;
case 0x6B:
INST_NAME("IMUL Gw,Ew,Ib");
if(opcode==0x69) {
INST_NAME("IMUL Gw,Ew,Iw");
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 1);
i32 = F8S;
GETSEW(x1, (opcode==0x69)?2:1);
if(opcode==0x69) i32 = F16S; else i32 = F8S;
MOV32w(x2, i32);
MULw(x2, x2, x1);
UFLAG_RES(x2);
@@ -352,11 +345,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("ADD Ew, Iw");
} else {
INST_NAME("ADD Ew, Ib");
}
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
@@ -443,6 +432,35 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x87:
INST_NAME("(LOCK)XCHG Ew, Gw");
nextop = F8;
if(MODREG) {
GETGD;
GETED(0);
MOVxw_REG(x1, gd);
BFIx(gd, ed, 0, 16);
BFIx(ed, x1, 0, 16);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
DMB_ISH();
TSTx_mask(ed, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, ed);
STLXRH(x3, gd, ed);
CBNZx_MARKLOCK(x3);
B_MARK2_nocond;
MARK;
LDRH_U12(x1, ed, 0);
STRH_U12(gd, ed, 0);
MARK2;
DMB_ISH();
BFIx(gd, x1, 0, 16);
}
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
@@ -453,8 +471,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
STRH_U12(gd, ed, fixedaddress);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
break;
case 0x8B:
@@ -467,7 +489,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
LDRH_U12(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
@@ -639,7 +665,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
LSLw_IMM(ed, ed, u8&0x1f);
EWBACK;
@@ -652,7 +678,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
LSRw_IMM(ed, ed, u8&0x1f);
EWBACK;
@@ -663,11 +689,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
GETSEW(x1, 0);
GETSEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
ASRw_REG(ed, ed, x2);
ASRw(ed, ed, (u8&0x1f));
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
@@ -684,10 +710,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x1, u16);
BFIx(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 2);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
MOV32w(x1, u16);
STRH_U12(x1, ed, fixedaddress);
if(lock || (box64_dynarec_strongmem &&
(dyn->insts[ninst].x64.barrier || box64_dynarec_strongmem>1 || (dyn->insts[ninst+1].x64.barrier || dyn->insts[ninst+1].x64.jmp)))) {
DMB_ISH();
}
}
break;
@@ -701,7 +731,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
ANDw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
@@ -715,7 +745,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x2, 1);
} else {
INST_NAME("ROR Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
ANDw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
@@ -728,7 +758,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
EWBACK;
@@ -738,7 +768,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
EWBACK;
@@ -750,7 +780,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
@@ -767,7 +797,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
@@ -784,7 +814,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
@@ -798,6 +828,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
@@ -847,17 +880,25 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("DIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(div16, -1);
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
UDIVw(x3, x2, ed);
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIx(xRAX, x3, 0, 16);
BFIx(xRDX, x4, 0, 16);
break;
case 7:
INST_NAME("IDIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(idiv16, -1);
GETSEW(x1, 0);
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
SDIVw(x3, x2, ed);
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIx(xRAX, x3, 0, 16);
BFIx(xRDX, x4, 0, 16);
break;
}
break;
+221 -45
View File
@@ -23,13 +23,13 @@
#include "dynarec_arm64_helper.h"
// Get EX as a quad
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
@@ -50,7 +50,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t nextop, u8;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
@@ -82,7 +82,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
@@ -95,7 +95,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -108,7 +108,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 0, ed);
break;
case 0x13:
@@ -120,7 +120,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 0, ed);
break;
case 0x14:
@@ -131,7 +131,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
VMOVeD(v0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
@@ -141,10 +141,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
VMOVeD(v0, 0, v0, 1);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
VMOVeD(v0, 1, v1, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
ADDx_U12(ed, ed, 8);
VLD1_64(v0, 1, ed);
@@ -159,7 +159,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
break;
case 0x17:
@@ -171,7 +171,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 1, ed);
break;
@@ -192,7 +192,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
@@ -206,7 +206,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -323,6 +323,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SQRDMULHQ_16(q0, q0, q1);
break;
case 0x10:
INST_NAME("PBLENDVB Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = sse_get_reg(dyn, ninst, x1, 0, 0);
v1 = fpu_get_scratch(dyn);
if(q0!=q1) {
VSSHRQ_8(v1, v0, 7); // bit[7]-> bit[7..0]
VBICQ(q0, q0, v1);
VANDQ(v1, q1, v1);
VORRQ(q0, q0, v1);
}
break;
case 0x1C:
INST_NAME("PABSB Gx,Ex");
nextop = F8;
@@ -439,14 +454,41 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
UXTL_32(q0, q1); // 32bits->64bits
break;
case 0x38:
INST_NAME("PMINSB Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
SMINQ_8(q0, q0, q1);
break;
case 0x39:
INST_NAME("PMINSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0,1);
GETGX(q0, 1);
SMINQ_32(q0, q0, q1);
break;
case 0x3A:
INST_NAME("PMINUW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
UMINQ_16(q0, q0, q1);
break;
case 0x3B:
INST_NAME("PMINUD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
UMINQ_32(q0, q0, q1);
break;
case 0x3C:
INST_NAME("PMAXSB Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
SMAXQ_8(q0, q0, q1);
break;
case 0x3D:
INST_NAME("PMAXSD Gx, Ex"); // SSE4 opcode!
nextop = F8;
@@ -454,6 +496,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(q0, 1);
SMAXQ_32(q0, q0, q1);
break;
case 0x3E:
INST_NAME("PMAXUW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
UMAXQ_16(q0, q0, q1);
break;
case 0x3F:
INST_NAME("PMAXUD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
UMAXQ_32(q0, q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
@@ -613,6 +669,15 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x20:
INST_NAME("PINSRB Gx, ED, Ib");
nextop = F8;
GETGX(q0, 1);
GETEB(x1, 1);
u8 = F8;
VMOVQBfrom(q0, (u8&15), x1);
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
nextop = F8;
@@ -626,6 +691,74 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
if(arm64_pmull) {
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
switch (u8&0b00010001) {
case 0b00000000:
PMULL_128(q0, q0, q1);
break;
case 0b00010001:
PMULL2_128(q0, q0, q1);
break;
case 0b00000001:
VEXTQ_8(q0, q0, q0, 8); // Swap Up/Lower 64bits parts
PMULL_128(q0, q0, q1);
break;
case 0b00010000:
VEXTQ_8(q0, q0, q0, 8); // Swap Up/Lower 64bits parts
PMULL2_128(q0, q0, q1);
break;
}
} else {
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); //p = NULL
} else {
MOV32w(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
if(ed!=x3) {
MOVx_REG(x3, ed);
}
}
u8 = F8;
MOV32w(x4, u8);
CALL(arm_pclmul, -1);
}
break;
case 0xDF:
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); //p = NULL
} else {
MOV32w(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
if(ed!=x3) {
MOVx_REG(x3, ed);
}
}
u8 = F8;
MOV32w(x4, u8);
CALL(arm_aeskeygenassist, -1);
break;
default:
DEFAULT;
}
@@ -639,7 +772,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0); \
LDRH_U12(x1, ed, fixedaddress); \
ed = x1; \
} \
@@ -660,11 +793,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
LSRx(gd, gd, 63);
BFIx(gd, x1, 1, 1);
break;
case 0x51:
INST_NAME("SQRTPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX_empty(q1);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
// check if any input value was NAN
VFCMEQQD(v0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFSQRTQD(q1, q0);
if(!box64_dynarec_fastnan) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0,0);
GETEX(q0, 0, 0);
GETGX(v0, 1);
VANDQ(v0, v0, q0);
break;
@@ -885,21 +1037,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("PUNPCKHBW Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
GETEX(q1, 0, 0);
VZIP2Q_8(q0, q0, q1);
break;
case 0x69:
INST_NAME("PUNPCKHWD Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
GETEX(q1, 0, 0);
VZIP2Q_16(q0, q0, q1);
break;
case 0x6A:
INST_NAME("PUNPCKHDQ Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
GETEX(q1, 0, 0);
VZIP2Q_32(q0, q0, q1);
break;
case 0x6B:
@@ -922,7 +1074,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
VMOVeD(v0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
@@ -935,7 +1087,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
VMOVeD(v0, 1, v1, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
ADDSx_U12(x1, ed, 8);
VLD1_64(v0, 1, x1);
}
@@ -961,7 +1113,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
@@ -1035,7 +1187,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
} else {
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = F8;
if (u8) {
for (int i=0; i<4; ++i) {
@@ -1244,6 +1396,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VCMEQQ_32(v0, v0, q0);
break;
case 0x7C:
INST_NAME("HADDPD Gx, Ex");
nextop = F8;
GETGX(q1, 1);
GETEX(q0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
// check if any input value was NAN
// but need to mix low/high part
VTRNQ1_64(v0, q1, q0);
VTRNQ2_64(v1, q1, q0);
VFMAXQD(v0, v0, v1); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFADDPQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
@@ -1253,7 +1429,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX + (nextop&7) + (rex.b<<3);
VMOVQDto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
} else {
@@ -1261,7 +1437,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX + (nextop&7) + (rex.b<<3);
VMOVSto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(v0, ed, fixedaddress);
}
}
@@ -1274,7 +1450,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -1288,7 +1464,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
LDRH_U12(x1, x3, fixedaddress);
@@ -1329,7 +1505,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
@@ -1390,7 +1566,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
@@ -1424,7 +1600,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
UBFXxw(x1, eb1, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRB_U12(x1, ed, fixedaddress);
}
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
@@ -1437,7 +1613,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff>>1, 1, rex, NULL, 0, 0);
LDRH_U12(x1, ed, fixedaddress);
}
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
@@ -1455,7 +1631,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
@@ -1523,7 +1699,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
SBFXw(x1, eb1, eb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRSBw_U12(x1, ed, fixedaddress);
}
BFIx(gd, x1, 0, 16);
@@ -1570,7 +1746,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = xRAX+(nextop&7)+(rex.b<<3);
VMOVQHfrom(v0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&7;
VLD1_16(v0, u8, wback);
}
@@ -1584,7 +1760,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
u8 = (F8)&7;
VMOVHto(gd, v0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&7;
LDRH_U12(gd, wback, u8*2);
}
@@ -1680,7 +1856,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
@@ -1847,7 +2023,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
+25 -4
View File
@@ -31,8 +31,10 @@ 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;
int64_t j64;
int v0, v1;
int64_t fixedaddress;
MAYUSE(j64);
// REX prefix before the 66 are ignored
rex.rex = 0;
@@ -51,7 +53,26 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x0F:
opcode = F8;
switch(opcode) {
/* //Something is wrong, and this gives a SIGILL
case 0x2E:
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETG;
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
grab_segdata(dyn, addr, ninst, x4, _FS);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn); \
VLDR128_REG(v1, ed, x4);
}
FCMPD(v0, v1);
FCOMI(x1, x2);
break;
*/
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
@@ -62,7 +83,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
VSTR64_REG(v0, ed, x4);
}
break;
@@ -87,7 +108,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
} else {
grab_segdata(dyn, addr, ninst, x4, _FS);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(rex.w) {
STRx_REG(gd, ed, x4);
} else {
@@ -111,7 +132,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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(rex.w) {
LDRx_REG(gd, ed, x4);
} else {
+412
View File
@@ -0,0 +1,412 @@
#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_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_66F0(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 opcode = F8;
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j64);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0/66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x09:
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x0F:
opcode = F8;
switch(opcode) {
case 0xB1:
INST_NAME("LOCK CMPXCHG Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
UXTHw(x6, xRAX);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
UXTHw(x1, ed);
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
CMPSxw_REG(x6, x1);
B_MARK(cNE);
BFIx(ed, gd, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK3(cNE);
// Aligned version
MARKLOCK;
LDAXRH(x1, wback);
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRH(x4, gd, wback);
CBNZx_MARKLOCK(x4);
// done
B_MARK_nocond;
// Unaligned version
MARK3;
LDRH_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRB(x4, gd, wback);
CBNZx_MARK3(x4);
STRH_U12(gd, wback, 0);
}
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp32(dyn, ninst, rex, x6, x1, x3, x4, x5);}
BFIx(xRAX, x1, 0, 16);
DMB_ISH();
break;
case 0xC1:
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
UXTHx(x5, gd);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
BFIx(gd, ed, 0, 16);
emit_add16(dyn, ninst, x5, gd, x3, x4);
BFIx(ed, x5, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
ADDxw_REG(x4, x1, x5);
STLXRH(x3, x4, wback);
CBNZx_MARKLOCK(x3);
IFX(X_ALL|X_PEND) {
MOVxw_REG(x2, x1);
emit_add16(dyn, ninst, x2, x5, x3, x4);
}
BFIx(gd, x1, 0, 16);
}
DMB_ISH();
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ew, Iw");} else {INST_NAME("LOCK ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ew, Iw");} else {INST_NAME("LOCK SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_xor16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ew, Iw");} else {INST_NAME("(LOCK) CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x6, (opcode==0x81)?2:1);
(void)wb1;
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(i32) {
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
BFIx(ed, x6, 0, 16);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
}
break;
}
DMB_ISH();
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7)
{
case 0: // INC Ew
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
emit_inc16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_inc16(dyn, ninst, x1, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 1: //DEC Ew
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
emit_dec16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_dec16(dyn, ninst, x1, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+542 -11
View File
@@ -38,18 +38,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2;
int64_t fixedaddress;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
// REX prefix before the 67 are ignored
rex.rex = 0;
@@ -64,6 +68,105 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
switch(opcode) {
case 0x00:
INST_NAME("ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_add8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x01:
INST_NAME("ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x02:
INST_NAME("ADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_add8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x03:
INST_NAME("ADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x04:
INST_NAME("ADD AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_add8c(dyn, ninst, x1, u8, x3, x4);
BFIx(xRAX, x1, 0, 8);
break;
case 0x05:
INST_NAME("ADD EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5);
break;
case 0x08:
INST_NAME("OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_or8(dyn, ninst, x1, x2, x4, x2);
EBBACK;
break;
case 0x09:
INST_NAME("OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x0A:
INST_NAME("OR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_or8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x0B:
INST_NAME("OR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0C:
INST_NAME("OR AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_or8c(dyn, ninst, x1, u8, x3, x4);
BFIx(xRAX, x1, 0, 8);
break;
case 0x0D:
INST_NAME("OR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x0F:
opcode=F8;
@@ -83,7 +186,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
s0 = fpu_get_scratch(dyn);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
@@ -98,10 +201,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); // no rex.b on MMX
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
VMOVeD(v0, 0, v1, 0);
VMOV(v0, v1);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
@@ -114,7 +217,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
VMOV(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
@@ -124,6 +227,403 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x10:
INST_NAME("ADC Eb, Gb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_adc8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x11:
INST_NAME("ADC Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x12:
INST_NAME("ADC Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_adc8(dyn, ninst, x1, x2, x4, x3);
GBBACK;
break;
case 0x13:
INST_NAME("ADC Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_adc32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x14:
INST_NAME("ADC AL, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5);
BFIx(xRAX, x1, 0, 8);
break;
case 0x15:
INST_NAME("ADC EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x1, i64);
emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4);
break;
case 0x18:
INST_NAME("SBB Eb, Gb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_sbb8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x1A:
INST_NAME("SBB Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sbb8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x1C:
INST_NAME("SBB AL, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5);
BFIx(xRAX, x1, 0, 8);
break;
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4);
break;
case 0x20:
INST_NAME("AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_and8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x21:
INST_NAME("AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x22:
INST_NAME("AND Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_and8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x23:
INST_NAME("AND Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_and32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x24:
INST_NAME("AND AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_and8c(dyn, ninst, x1, u8, x3, x4);
BFIx(xRAX, x1, 0, 8);
break;
case 0x25:
INST_NAME("AND EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x28:
INST_NAME("SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_sub8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x29:
INST_NAME("SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x2A:
INST_NAME("SUB Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sub8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x2B:
INST_NAME("SUB Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x2C:
INST_NAME("SUB AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_sub8c(dyn, ninst, x1, u8, x3, x4, x5);
BFIx(xRAX, x1, 0, 8);
break;
case 0x2D:
INST_NAME("SUB EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_sub32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5);
break;
case 0x30:
INST_NAME("XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_xor8(dyn, ninst, x1, x2, x4, x5);
EBBACK;
break;
case 0x31:
INST_NAME("XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x32:
INST_NAME("XOR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_xor8(dyn, ninst, x1, x2, x3, x4);
GBBACK;
break;
case 0x33:
INST_NAME("XOR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x34:
INST_NAME("XOR AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
emit_xor8c(dyn, ninst, x1, u8, x3, x4);
BFIx(xRAX, x1, 0, 8);
break;
case 0x35:
INST_NAME("XOR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x38:
INST_NAME("CMP Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x39:
INST_NAME("CMP Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5);
break;
case 0x3A:
INST_NAME("CMP Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x3B:
INST_NAME("CMP Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_cmp32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x3C:
INST_NAME("CMP AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
UXTBw(x1, xRAX);
if(u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x3D:
INST_NAME("CMP EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
} else
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
WBACK;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
WBACK;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
WBACK;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
WBACK;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
@@ -131,8 +631,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
case 0x8B:
INST_NAME("MOV Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
if(lock) {DMB_ISH();}
LDRxw_U12(gd, ed, fixedaddress);
}
break;
@@ -144,7 +658,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
} else { // mem <= reg
// should a geted32 be created, to use 32bits regs instead of 64bits?
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=gd) {
MOVw_REG(gd, ed);
}
@@ -223,7 +737,24 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xC7:
INST_NAME("MOV Ed, Id");
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_U12(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
@@ -233,11 +764,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!dyn->insts[ninst].x64.barrier) \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
B(i32); \
} \
@@ -302,7 +833,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("NOT Ed");
GETED32(4);
GETED32(0);
MVNxw_REG(ed, ed);
WBACK;
break;
+8 -8
View File
@@ -185,7 +185,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
@@ -198,7 +198,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
@@ -211,7 +211,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
@@ -225,7 +225,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
@@ -240,7 +240,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
@@ -253,7 +253,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, s0, v1);
@@ -266,7 +266,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
@@ -279,7 +279,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, s0, v1);
+32 -25
View File
@@ -31,6 +31,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int v1, v2;
int s0;
@@ -71,6 +72,8 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
// should set C1 to 0
break;
@@ -79,6 +82,24 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FNOP");
break;
case 0xD8:
INST_NAME("FSTPNCE ST0, ST0");
x87_do_pop(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FSTPNCE ST0, STx");
// copy the cache value for st0 to stx
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
@@ -252,21 +273,17 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xFC:
INST_NAME("FRNDINT");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1);
/*
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
u8 = x87_setround(dyn, ninst, x1, x2, x3);
VCVT_S32_F64(x1, v1); // limit to 32bits....
VCVT_F64_S32(v1, x1);
FRINTID(v1, v1);
x87_restoreround(dyn, ninst, u8);
*/
#endif
break;
case 0xFD:
INST_NAME("FSCALE");
@@ -294,14 +311,6 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE2:
case 0xE3:
case 0xE6:
@@ -319,7 +328,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = v1;
else
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
if(!ST_IS_F(0)) {
FCVT_D_S(v1, s0);
@@ -334,7 +343,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(s0, ed, fixedaddress);
break;
case 3:
@@ -346,7 +355,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(s0, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
@@ -354,7 +363,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
@@ -365,14 +374,12 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
STRH_U12(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
UBFXw(x1, x1, 10, 2); // extract round
STRw_U12(x1, xEmu, offsetof(x64emu_t, round));
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
@@ -381,7 +388,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
wb1 = 1;
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
+7 -7
View File
@@ -190,7 +190,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
SXTL_32(v1, s0);
SCVTFDD(v1, v1);
@@ -202,7 +202,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
@@ -234,7 +234,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
@@ -266,7 +266,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
@@ -293,7 +293,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
// the FLD is immediatly followed by an FSTP
LDRx_U12(x5, ed, 0);
@@ -302,7 +302,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; //0xDB
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
@@ -316,7 +316,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("FSTP tbyte");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
+8 -8
View File
@@ -182,7 +182,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FADDD(v1, v1, v2);
break;
@@ -190,7 +190,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
break;
@@ -198,7 +198,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
@@ -207,7 +207,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
@@ -217,7 +217,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FSUBD(v1, v1, v2);
break;
@@ -225,7 +225,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
break;
@@ -233,7 +233,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
@@ -241,7 +241,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 3, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
break;
+15 -8
View File
@@ -83,6 +83,8 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xDF:
INST_NAME("FSTP ST0, STx");
// copy the cache value for st0 to stx
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
@@ -157,15 +159,20 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v1, ed, fixedaddress);
break;
case 1:
INST_NAME("FISTTP i64, ST0");
v1 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
// those are ARM 8.5 opcode!
FRINT64ZD(s0, v1);
#else
FRINTRRD(s0, v1, 3); // not ideal, might averflow and not set 0x8000000000000000 correctly
#endif
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
@@ -173,13 +180,13 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
@@ -187,7 +194,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_frstor, -1);
break;
@@ -195,14 +202,14 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_fsave, -1);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
if(dyn->n.x87stack) {
+284
View File
@@ -0,0 +1,284 @@
#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 "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
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)
{
(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("FADDP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMULP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOMP ST0, STx"); //yep
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
break;
case 0xD9:
INST_NAME("FCOMPP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUBRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUBP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIVRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIVP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
return 0;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v2, v1);
break;
}
}
return addr;
}
+8 -8
View File
@@ -151,7 +151,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRSHw_U12(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
SCVTFSw(v1, x1);
@@ -162,7 +162,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -197,7 +197,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -233,7 +233,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -269,21 +269,21 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
INST_NAME("FBLD ST0, tbytes");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbld, -1);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
LDRx_U12(x1, wback, fixedaddress);
SCVTFDx(v1, x1);
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbst, -1);
x87_do_pop(dyn, ninst, x3);
@@ -292,7 +292,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
+3 -36
View File
@@ -28,8 +28,6 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -60,14 +58,11 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
MOV64xw(s3, c);
ORRxw_REG(s1, s1, s3);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -95,8 +90,6 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -127,14 +120,11 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
MOV64xw(s3, c);
EORxw_REG(s1, s1, s3);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -162,8 +152,6 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -197,14 +185,11 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV64xw(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_PEND) {} else {MOV64xw(s3, c);}
MOV64xw(s3, c);
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
} else {
@@ -235,8 +220,6 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -268,8 +251,6 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -301,8 +282,6 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -334,8 +313,6 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -367,8 +344,6 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -403,8 +378,6 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -440,8 +413,6 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -519,8 +490,6 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -598,8 +567,6 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
+2 -2
View File
@@ -77,7 +77,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags==X_PEND))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<0x1000) {
@@ -201,7 +201,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags==X_PEND))
{
// special case when doing math on RSP and only PEND is needed: ignoring it!
if(c>=0 && c<0x1000) {
+110 -253
View File
@@ -30,10 +30,12 @@ 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, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
uint8_t wback, wb1, wb2, eb1, eb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
@@ -71,7 +73,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_add8(dyn, ninst, x1, x2, x4, x3);
BFIx(wback, x1, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x4, x3);
@@ -90,7 +92,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -100,6 +102,34 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DMB_ISH();
break;
case 0x08:
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if(rex.rex) {
wback = xRAX + (nextop&7) + (rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
UBFXw(x1, wback, wb2*8, 8);
emit_or8(dyn, ninst, x1, x2, x4, x3);
BFIx(wback, x1, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_or8(dyn, ninst, x1, x2, x4, x3);
STLXRB(x4, x1, wback);
CBNZx_MARKLOCK(x4);
}
DMB_ISH();
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -110,7 +140,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -152,7 +182,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(xRAX, x2, 0, 8);
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
// Aligned version
MARKLOCK;
LDAXRB(x2, wback);
@@ -186,7 +216,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRAX, x1);
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK3(cNE);
// Aligned version
@@ -230,7 +260,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(gd, x1);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
@@ -261,7 +291,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
DMB_ISH();
MARKLOCK;
LDAXPxw(x2, x3, wback);
@@ -287,6 +317,26 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_and32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -297,7 +347,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -308,233 +358,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x66:
opcode = F8;
switch(opcode) {
case 0x09:
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
DMB_ISH();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
DMB_ISH();
break;
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Iw");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Iw");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ew, Iw");} else {INST_NAME("LOCK ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ew, Iw");} else {INST_NAME("LOCK SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_xor16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ew, Iw");} else {INST_NAME("(LOCK) CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x6, (opcode==0x81)?2:1);
(void)wb1;
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(i32) {
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
BFIx(ed, x6, 0, 16);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
}
break;
}
DMB_ISH();
break;
default:
DEFAULT;
}
break;
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0x80:
nextop = F8;
@@ -549,7 +373,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -569,7 +393,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -590,7 +414,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -611,7 +435,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -631,7 +455,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -651,7 +475,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -671,7 +495,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -717,7 +541,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_add32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -747,7 +571,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -767,7 +591,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -787,7 +611,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -806,7 +630,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_and32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -825,7 +649,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -855,7 +679,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_xor32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -882,6 +706,39 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DMB_ISH();
break;
case 0x86:
INST_NAME("LOCK XCHG Eb, Gb");
// Do the swap
nextop = F8;
if(MODREG) {
GETGB(x4);
if(rex.rex) {
ed = xRAX+(nextop&7)+(rex.b<<3);
eb1 = ed;
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3);
eb2 = ((ed&4)>>2);
}
UBFXw(x1, eb1, eb2*8, 8);
// do the swap 14 -> ed, 1 -> gd
BFIx(gb1, x1, gb2*8, 8);
BFIx(eb1, x4, eb2*8, 8);
} else {
DMB_ISH();
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
// do the swap with exclusive locking
LDAXRB(x1, ed);
// do the swap 14 -> strb(ed), 1 -> gd
STLXRB(x3, x4, ed);
CBNZx_MARKLOCK(x3);
DMB_ISH();
BFIx(gb1, x1, gb2*8, 8);
}
break;
case 0x87:
INST_NAME("LOCK XCHG Ed, Gd");
nextop = F8;
@@ -894,7 +751,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
GETGD;
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
@@ -923,7 +780,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
@@ -951,7 +808,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
+12 -12
View File
@@ -23,13 +23,13 @@
#include "dynarec_arm64_helper.h"
// Get Ex as a double, not a quad (warning, x2 get used)
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
VLDR64_U12(a, ed, fixedaddress); \
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
VLDR64_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
@@ -82,7 +82,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress); // upper part reseted
}
break;
@@ -96,7 +96,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
d0 = sse_get_reg(dyn, ninst, x1, ed, 1);
VMOVeD(d0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
@@ -110,7 +110,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
VMOVeD(v0, 1, v0, 0);
@@ -343,7 +343,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
VLDR128_U12(v1, ed, fixedaddress);
}
@@ -413,7 +413,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
+31 -22
View File
@@ -23,13 +23,23 @@
#include "dynarec_arm64_helper.h"
// Get Ex as a single, not a quad (warning, x2 get used)
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
VLDR32_U12(a, ed, fixedaddress); \
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
VLDR32_U12(a, ed, fixedaddress); \
}
// Get EX as a quad
#define GETEXQ(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
@@ -75,7 +85,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeS(v0, 0, q0, 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(v0, ed, fixedaddress);
}
break;
@@ -83,12 +93,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
VMOVeS(q0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(v0, ed, fixedaddress);
}
break;
@@ -98,7 +108,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
}
@@ -112,7 +122,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
}
@@ -236,9 +246,9 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0);
break;
case 0x5B:
INST_NAME("CVTPS2DQ Gx, Ex");
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
GETEX(d0, 0, 0);
GETEXQ(d0, 0, 0);
GETGX_empty(v0);
VFCVTZSQS(v0, d0);
break;
@@ -297,21 +307,20 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x6F:
INST_NAME("MOVDQU Gx,Ex");// no alignment constraint on NEON here, so same as MOVDQA
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x70:
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
GETEX(v1, 0, 1);
GETEXQ(v1, 0, 1);
GETGX(v0, 1);
u8 = F8;
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
@@ -339,7 +348,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FMOVD(v0, v1);
} else {
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
@@ -351,7 +360,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
@@ -415,7 +424,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VEORQ(v0, v0, v0); // usefull?
VMOV(v0, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
@@ -428,7 +437,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
v1 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v1, ed, fixedaddress);
}
GETGX_empty(v0);
+109 -21
View File
@@ -157,6 +157,11 @@ void arm_ud(x64emu_t* emu)
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
}
void arm_priv(x64emu_t* emu)
{
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
}
void arm_fsave(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -267,30 +272,29 @@ void arm_aesdlast(x64emu_t* emu, int xmm)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static 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,
};
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]];
@@ -308,6 +312,46 @@ void arm_aese(x64emu_t* emu, int xmm)
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
void arm_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
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];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void arm_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void arm_clflush(x64emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
#define XMM0 0
@@ -351,6 +395,7 @@ int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm)
dyn->n.fpuused[EMM0 + emm] = 1;
dyn->n.neoncache[EMM0 + emm].t = NEON_CACHE_MM;
dyn->n.neoncache[EMM0 + emm].n = emm;
dyn->n.news |= (1<<(EMM0 + emm));
return EMM0 + emm;
}
// Get an XMM quad reg
@@ -365,6 +410,7 @@ int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
dyn->n.fpuused[i] = 1;
dyn->n.neoncache[i].t = t;
dyn->n.neoncache[i].n = xmm;
dyn->n.news |= (1<<i);
return i;
}
// Reset fpu regs counter
@@ -585,7 +631,7 @@ int isCacheEmpty(dynarec_arm_t* dyn, int ninst) {
}
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int i2 = dyn->insts[ninst].x64.jmp_insts;
if(i2<0)
return 1;
@@ -632,6 +678,48 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
return ret;
}
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
return 0;
}
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int ret = 0;
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
return ret;
}
void neoncacheUnwind(neoncache_t* cache)
{
if(cache->swapped) {
+5 -1
View File
@@ -34,9 +34,13 @@ 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_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void arm_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void arm_clflush(x64emu_t* emu, void* p);
void arm_ud(x64emu_t* emu);
void arm_priv(x64emu_t* emu);
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
@@ -68,7 +72,7 @@ void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
// FPU Cache transformation (for loops)
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int i1);
int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
+117 -30
View File
@@ -27,10 +27,13 @@
#include "dynarec_arm64_helper.h"
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int *l, int s, int delta)
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
int lock = l?((l==LOCK_LOCK)?1:2):0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
@@ -54,6 +57,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
*fixaddress = tmp;
}
} else {
switch(lock) {
case 1: addLockAddress(tmp); break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV64x(ret, tmp);
}
} else {
@@ -73,13 +80,16 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
GETIP(addr+delta);
ADDx_U12(ret, xRIP, tmp);
} else if(tmp+addr+delta<0x1000000000000LL) { // 3 opcodes to load immediate is cheap enough
tmp += addr+delta;
MOV64x(ret, tmp);
MOV64x(ret, tmp+addr+delta);
} else {
MOV64x(ret, tmp);
GETIP(addr+delta);
ADDx_REG(ret, ret, xRIP);
}
switch(lock) {
case 1: addLockAddress(addr+delta+tmp); break;
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
}
@@ -156,10 +166,13 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta)
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
int lock = l?((l==LOCK_LOCK)?1:2):0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
@@ -183,6 +196,10 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
*fixaddress = tmp;
}
} else {
switch(lock) {
case 1: addLockAddress(tmp); break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV64x(ret, tmp);
}
} else {
@@ -197,6 +214,10 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
MOV32w(ret, tmp);
GETIP(addr+delta);
ADDw_REG(ret, ret, xRIP);
switch(lock) {
case 1: addLockAddress(addr+delta+tmp); break;
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
if(ret==hint) {
@@ -382,30 +403,30 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
}
uintptr_t tbl = getJumpTable64();
MAYUSE(tbl);
TABLE64(x2, tbl);
UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x3, x2, x3);
TABLE64(x3, tbl);
UBFXx(x2, xRIP, 48, JMPTABL_SHIFT);
LDRx_REG_LSL3(x3, x3, x2);
UBFXx(x2, xRIP, 32, JMPTABL_SHIFT);
LDRx_REG_LSL3(x3, x3, x2);
UBFXx(x2, xRIP, 16, JMPTABL_SHIFT);
LDRx_REG_LSL3(x3, x3, x2);
UBFXx(x2, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x3, x2);
} else {
uintptr_t p = getJumpTableAddress64(ip);
MAYUSE(p);
TABLE64(x2, p);
TABLE64(x3, p);
GETIP_(ip);
LDRx_U12(x3, x2, 0);
LDRx_U12(x2, x3, 0);
}
if(reg!=x1) {
MOVx_REG(x1, xRIP);
}
CLEARIP();
#ifdef HAVE_TRACE
//MOVx(x2, 15); no access to PC reg
//MOVx(x3, 15); no access to PC reg
#endif
BLR(x3); // save LR...
BLR(x2); // save LR...
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
@@ -804,7 +825,7 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
if(next) {
// need to check if a ST_F need local promotion
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[i])>=0) {
FCVT_S_D(0, dyn->n.x87reg[i]);
FCVT_D_S(0, dyn->n.x87reg[i]);
VSTR64_REG_LSL3(0, s1, s3); // save the value
} else {
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3); // save the value
@@ -882,7 +903,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int populate, int s1, int s2, i
ret = i;
// found, setup and grab the value
dyn->n.x87cache[ret] = st;
dyn->n.x87reg[ret] = fpu_get_reg_x87(dyn, t, st);
dyn->n.x87reg[ret] = fpu_get_reg_x87(dyn, NEON_CACHE_ST_D, st);
if(populate) {
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
@@ -939,7 +960,12 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
ADDw_U12(s2, s2, st);
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
}
VLDR64_REG_LSL3(dyn->n.x87reg[ret], s1, s2);
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F) {
FCVT_D_S(31, dyn->n.x87reg[ret]);
VSTR64_REG_LSL3(31, s1, s2);
} else {
VSTR64_REG_LSL3(dyn->n.x87reg[ret], s1, s2);
}
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
}
@@ -953,6 +979,10 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(ret==-1) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
#if STEP == 1
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F)
neoncache_promote_double(dyn, ninst, st);
#endif
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
@@ -980,6 +1010,10 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(dyn->n.x87cache[i]==st) {
// refresh the value
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
#if STEP == 1
if(dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F)
neoncache_promote_double(dyn, ninst, st);
#endif
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
int a = st - dyn->n.x87stack;
@@ -1042,7 +1076,8 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1); MAYUSE(s2);
LDRw_U12(s1, xEmu, offsetof(x64emu_t, round));
LDRw_U12(s1, xEmu, offsetof(x64emu_t, cw));
BFXILw(s1, s1, 10, 2);
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
@@ -1227,10 +1262,10 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
++old;
}
VSTR128_U12(dyn->n.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
if(!next) {
fpu_free_reg(dyn, dyn->n.ssecache[i].reg);
dyn->n.ssecache[i].v = -1;
}
}
if(!next) {
fpu_free_reg(dyn, dyn->n.ssecache[i].reg);
dyn->n.ssecache[i].v = -1;
}
}
if(old!=-1) {
@@ -1250,16 +1285,16 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
int start = not07?8:0;
// only SSE regs needs to be push back to xEmu
// only SSE regs needs to be push back to xEmu (needs to be "write")
int n=0;
for (int i=start; i<16; i++)
if(dyn->n.ssecache[i].v!=-1)
if((dyn->n.ssecache[i].v!=-1) && (dyn->n.ssecache[i].write))
++n;
if(!n)
return;
MESSAGE(LOG_DUMP, "\tPush XMM Cache (%d)------\n", n);
for (int i=start; i<16; ++i)
if(dyn->n.ssecache[i].v!=-1) {
if((dyn->n.ssecache[i].v!=-1) && (dyn->n.ssecache[i].write)) {
VSTR128_U12(dyn->n.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
}
MESSAGE(LOG_DUMP, "\t------- Push XMM Cache (%d)\n", n);
@@ -1268,7 +1303,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
int start = not07?8:0;
// only SSE regs needs to be pop back from xEmu
// only SSE regs needs to be pop back from xEmu (don't need to be "write" this time)
int n=0;
for (int i=start; i<16; i++)
if(dyn->n.ssecache[i].v!=-1)
@@ -1476,7 +1511,7 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
cache->neoncache[i].v = 0;
}
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
int i2 = dyn->insts[ninst].x64.jmp_insts;
@@ -1607,6 +1642,58 @@ void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
#endif
}
static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int j64;
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return;
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = 0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
if(dyn->f.pending!=SF_SET && dyn->f.pending!=SF_SET_PENDING)
go = 1;
break;
case SF_SET_PENDING:
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
break;
case SF_PENDING:
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
else
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
break;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
go = 1;
if(go) {
if(dyn->f.pending!=SF_PENDING) {
LDRw_U12(s1, xEmu, offsetof(x64emu_t, df));
j64 = (GETMARK3)-(dyn->native_size);
CBZw(s1, j64);
}
CALL_(UpdateFlags, -1, 0);
MARK3;
}
#endif
}
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) {
if(cacheupd&1)
fpuCacheTransform(dyn, ninst, s1, s2, s3);
if(cacheupd&2)
flagsCacheTransform(dyn, ninst, s1);
}
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
+119 -94
View File
@@ -32,6 +32,9 @@
#define PK64(a) *(uint64_t*)(addr+a)
#define PKip(a) *(uint8_t*)(ip+a)
//LOCK_* define
#define LOCK_LOCK (int*)1
// GETGD get x64 register in gd
#define GETGD gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3)
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
@@ -39,7 +42,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -47,7 +50,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
LDRx_U12(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -55,7 +58,7 @@
ed = xEAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL,0, D); \
LDRw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -65,7 +68,7 @@
wb = x1; \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
@@ -73,7 +76,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -83,7 +86,7 @@
wb = x1; \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
@@ -92,7 +95,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
@@ -100,7 +103,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
}
@@ -110,7 +113,7 @@
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
@@ -119,7 +122,7 @@
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
}
@@ -129,14 +132,12 @@
#define WBACKx if(wback) {STRx_U12(ed, wback, fixedaddress);}
// Write back ed in wback (if wback not 0)
#define WBACKw if(wback) {STRw_U12(ed, wback, fixedaddress);}
// Send back wb to either ed or wback
#define SBACK(wb) if(wback) {STRxw(wb, wback, fixedaddress);} else {MOVxw_REG(ed, wb);}
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDO(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); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
LDRxw_REG(x1, wback, O); \
ed = x1; \
}
@@ -146,7 +147,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
LDRx_REG(x1, wback, O); \
ed = x1; \
}
@@ -156,7 +157,7 @@
wb = x1; \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
LDRSW_REG(x1, wback, O); \
wb = ed = x1; \
}
@@ -175,7 +176,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -187,7 +188,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -199,7 +200,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRSHx_U12(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
@@ -224,7 +225,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRB_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
@@ -243,7 +244,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, D); \
ADDx_REG(x3, wback, i); \
if(wback!=x3) wback = x3; \
LDRB_U12(i, wback, fixedaddress); \
@@ -264,11 +265,30 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRSBx_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETEB will use i for ed, and can use r3 for wback.
#define GETEB32(i, D) if(MODREG) { \
if(rex.rex) { \
wback = xRAX+(nextop&7)+(rex.b<<3); \
wb2 = 0; \
} else { \
wback = (nextop&7); \
wb2 = (wback>>2)*8; \
wback = xRAX+(wback&3); \
} \
UBFXx(i, wback, wb2, 8); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRB_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_U12(ed, wback, fixedaddress);} else {BFIx(wback, ed, wb2, 8);}
//GETGB will use i for gd
@@ -386,10 +406,18 @@
#define CBNZx_MARK3(reg) \
j64 = GETMARK3-(dyn->native_size); \
CBNZx(reg, j64)
// Branch to MARK3 if reg is not 0 (use j64)
#define CBNZw_MARK3(reg) \
j64 = GETMARK3-(dyn->native_size); \
CBNZw(reg, j64)
// Branch to MARK3 if reg is 0 (use j64)
#define CBZx_MARK3(reg) \
j64 = GETMARK3-(dyn->native_size); \
CBZx(reg, j64)
// Branch to MARK3 if reg is 0 (use j64)
#define CBZw_MARK3(reg) \
j64 = GETMARK3-(dyn->native_size); \
CBZw(reg, j64)
// Test bit N of A and branch to MARK3 if not set
#define TBZ_MARK3(A, N) \
j64 = GETMARK3-(dyn->native_size); \
@@ -447,11 +475,11 @@
j64 = GETMARKLOCK-(dyn->native_size); \
CBNZx(reg, j64)
#define IFX(A) if((dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
#define IFX(A) if((dyn->insts[ninst].x64.gen_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.gen_flags&(X_PEND) || !dyn->insts[ninst].x64.gen_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.gen_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.gen_flags==(A) || dyn->insts[ninst].x64.gen_flags==(B) || dyn->insts[ninst].x64.gen_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.gen_flags&(A) && !(dyn->insts[ninst].x64.gen_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3) \
@@ -469,9 +497,19 @@
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
MOV32w(s2, 0b01000101); \
IFX(X_OF|X_AF|X_SF|X_PEND) { \
MOV32w(s2, 0b100011010101); \
BICw_REG(xFlags, xFlags, s2); \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
MOV32w(s2, 0b01000101); \
} \
} else { \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
MOV32w(s2, 0b01000101); \
BICw_REG(xFlags, xFlags, s2); \
} \
} \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
/*s2 already set */ /* unordered */ \
CSELw(s1, s2, s1, cVS); \
@@ -481,60 +519,43 @@
ORRw_REG(xFlags, xFlags, s1); \
} \
SET_DFNONE(s1); \
IFX(X_OF|X_PEND) { \
BFCw(xFlags, F_OF, 1); \
} \
IFX(X_AF|X_PEND) { \
BFCw(xFlags, F_AF, 1); \
} \
IFX(X_SF|X_PEND) { \
BFCw(xFlags, F_SF, 1); \
} \
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STP_REGS(A, B) STPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
#define LDP_REGS(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STORE_XEMU_REGS(A) \
STORE_REG(RAX); \
STORE_REG(RCX); \
STORE_REG(RDX); \
STORE_REG(RBX); \
STORE_REG(RSP); \
STORE_REG(RBP); \
STORE_REG(RSI); \
STORE_REG(RDI); \
STORE_REG(R8); \
STORE_REG(R9); \
STORE_REG(R10); \
STORE_REG(R11); \
STORE_REG(R12); \
STORE_REG(R13); \
STORE_REG(R14); \
STORE_REG(R15); \
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
STP_REGS(RAX, RCX); \
STP_REGS(RDX, RBX); \
STP_REGS(RSP, RBP); \
STP_REGS(RSI, RDI); \
STP_REGS(R8, R9); \
STP_REGS(R10, R11); \
STP_REGS(R12, R13); \
STP_REGS(R14, R15); \
if(A==xRIP) { \
STPx_S7_offset(xFlags, xRIP, xEmu, offsetof(x64emu_t, eflags)); \
} else { \
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));} \
}
#define LOAD_REG(A) LDRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define LOAD_XEMU_REGS(A) \
LOAD_REG(RAX); \
LOAD_REG(RCX); \
LOAD_REG(RDX); \
LOAD_REG(RBX); \
LOAD_REG(RSP); \
LOAD_REG(RBP); \
LOAD_REG(RSI); \
LOAD_REG(RDI); \
LOAD_REG(R8); \
LOAD_REG(R9); \
LOAD_REG(R10); \
LOAD_REG(R11); \
LOAD_REG(R12); \
LOAD_REG(R13); \
LOAD_REG(R14); \
LOAD_REG(R15); \
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {LDRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
#define LOAD_XEMU_REGS(A) \
LDP_REGS(RAX, RCX); \
LDP_REGS(RDX, RBX); \
LDP_REGS(RSP, RBP); \
LDP_REGS(RSI, RDI); \
LDP_REGS(R8, R9); \
LDP_REGS(R10, R11); \
LDP_REGS(R12, R13); \
LDP_REGS(R14, R15); \
if(A==xRIP) { \
LDPx_S7_offset(xFlags, xRIP, xEmu, offsetof(x64emu_t, eflags)); \
} else { \
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {LDRx_U12(A, xEmu, offsetof(x64emu_t, ip));} \
}
#define STORE_XEMU_MINIMUM(A) \
STORE_REG(RAX); \
@@ -575,6 +596,10 @@
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
#ifndef MAYSETFLAGS
#define MAYSETFLAGS()
#endif
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
@@ -590,23 +615,21 @@
SET_DFOK(); \
}
#endif
// SF_MAYSET doesn't change the flags status cache
// it also doesn't consume any needed flags
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->f.pending!=SF_SET \
&& (B==SF_SUBSET || B==SF_SUBSET_PENDING) \
&& (dyn->insts[ninst].x64.need_flags&(~((A)|((B==SF_SUBSET_PENDING)?X_PEND:0))))) \
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A)|X_PEND)); \
if(dyn->insts[ninst].x64.need_flags) switch(B) { \
&& ((B)&SF_SUB) \
&& (dyn->insts[ninst].x64.gen_flags&(~(A)))) \
READFLAGS(((dyn->insts[ninst].x64.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x64.gen_flags)&(~(A)));\
if(dyn->insts[ninst].x64.gen_flags) switch(B) { \
case SF_SUBSET: \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SUBSET_PENDING: \
case SF_SET_PENDING: \
dyn->f.pending = (dyn->insts[ninst].x64.need_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
dyn->f.pending = (dyn->insts[ninst].x64.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
break; \
case SF_MAYSET: break; \
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
@@ -618,12 +641,12 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.need_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x64.need_flags)
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
@@ -707,6 +730,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_F0 STEPNAME(dynarec64_F0)
#define dynarec64_660F STEPNAME(dynarec64_660F)
#define dynarec64_6664 STEPNAME(dynarec64_6664)
#define dynarec64_66F0 STEPNAME(dynarec64_66F0)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
@@ -826,13 +850,13 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
#define fpuCacheTransform STEPNAME(fpuCacheTransform)
#define CacheTransform STEPNAME(CacheTransform)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
/* setup r2 to address pointed by */
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s);
@@ -953,12 +977,12 @@ void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
#if STEP < 2
#define CHECK_CACHE() 0
#else
#define CHECK_CACHE() fpuCacheNeedsTransform(dyn, ninst)
#define CHECK_CACHE() (cacheupd = CacheNeedsTransform(dyn, ninst))
#endif
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
@@ -1028,11 +1052,12 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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_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_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);
uintptr_t dynarec64_F0(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_660F(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_6664(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_66F0(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_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
+11
View File
@@ -0,0 +1,11 @@
#include <stdint.h>
#include "arm64_emitter.h"
#define EMIT(A) *block = (A); ++block
void CreateJmpNext(void* addr, void* next)
{
uint32_t* block = (uint32_t*)addr;
LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
BR(x2);
}
+6 -7
View File
@@ -6,16 +6,15 @@
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
#define MESSAGE(A, ...)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define READFLAGS(A) \
dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
if(B!=SF_MAYSET) { \
dyn->insts[ninst].x64.state_flags = B; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0; \
}
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = B; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
@@ -23,7 +22,7 @@
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_native_t*)realloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2); \
dyn->insts = (instruction_native_t*)customRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t)*dyn->cap); \
dyn->cap *= 2; \
} \
+1 -2
View File
@@ -7,8 +7,7 @@
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
if(ninst && isInstClean(dyn, ninst)) { \
dyn->last_ip = 0; \
++dyn->sons_size; \
if(dyn->last_ip!=ip) dyn->last_ip = 0; \
} \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
+6 -7
View File
@@ -9,17 +9,13 @@
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst && isInstClean(dyn, ninst)) { \
dyn->last_ip = 0; \
dyn->sons_x64[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_native[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block); \
++dyn->sons_size; \
if(dyn->last_ip!=ip) dyn->last_ip = 0; \
}
#define INST_EPILOG
#define INST_NAME(name) \
if(box64_dynarec_dump) {\
printf_x64_instruction(my_context->dec, &dyn->insts[ninst].x64, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), set=%X, use=%X, need=%X", \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X", \
(box64_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->native_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
@@ -28,9 +24,12 @@
dyn->insts[ninst].x64.state_flags, \
dyn->f.pending, \
dyn->f.dfnone, \
dyn->insts[ninst].x64.may_set?"may":"set", \
dyn->insts[ninst].x64.set_flags, \
dyn->insts[ninst].x64.gen_flags, \
dyn->insts[ninst].x64.use_flags, \
dyn->insts[ninst].x64.need_flags); \
dyn->insts[ninst].x64.need_before, \
dyn->insts[ninst].x64.need_after); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
+8 -7
View File
@@ -5,6 +5,7 @@
typedef struct x64emu_s x64emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
@@ -18,15 +19,15 @@ typedef struct dynablock_s dynablock_t;
typedef union neon_cache_s {
int8_t v;
struct {
unsigned int t:4; // reg type
unsigned int n:4; // reg number
uint8_t t:4; // reg type
uint8_t n:4; // reg number
};
} neon_cache_t;
typedef union sse_cache_s {
int8_t v;
struct {
unsigned int reg:7;
unsigned int write:1;
uint8_t reg:7;
uint8_t write:1;
};
} sse_cache_t;
typedef struct neoncache_s {
@@ -99,11 +100,9 @@ typedef struct dynarec_arm_s {
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x64; // the x64 address of potential dynablock sons
void** sons_native; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
@@ -113,6 +112,8 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
void CreateJmpNext(void* addr, void* next);
#define GO_TRACE() \
GETIP_(ip); \
MOVx_REG(x1, xRIP); \
+102 -380
View File
@@ -3,6 +3,7 @@
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/mman.h>
#include "debug.h"
#include "box64context.h"
@@ -19,6 +20,7 @@
#include "dynablock_private.h"
#include "dynarec_private.h"
#include "elfloader.h"
#include "bridge.h"
#include "dynarec_native.h"
#include "native_lock.h"
@@ -37,111 +39,37 @@ uint32_t X31_hash_code(void* addr, int len)
return (uint32_t)h;
}
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
}
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
ret->minstart = text;
ret->maxend = text+textsz-1;
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
}
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
return ret;
}
void FreeDynablock(dynablock_t* db, int need_lock)
{
if(db) {
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->parent, db->father, db->sons_size, db->gone);
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x64_addr;
if(addr>=startdb && addr<enddb)
native_lock_xchg(&db->parent->direct[addr-startdb], 0); // secured write
}
// remove jumptable
setJumpTableDefault64(db->x64_addr);
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)native_lock_xchg(&db->sons[i], 0);
FreeDynablock(son, 0);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
free(db->sons);
free(db->instsize);
}
free(db);
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
FreeDynarecMap(db, (uintptr_t)db->actual_block, db->size);
customFree(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i], 1);
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->need_test)
return; // already done
dynarec_log(LOG_DEBUG, "MarkDynablock %p with %d son(s) %p-%p\n", db, db->sons_size, db->x64_addr, db->x64_addr+db->x64_size-1);
dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1);
db->need_test = 1;
setJumpTableDefault64(db->x64_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault64(db->sons[i]->x64_addr);
setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block);
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz-1;
return 0;
}
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
{
if(start1 > end2 || start2 > end1)
@@ -149,81 +77,38 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
return 1;
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
static int MarkedDynablock(dynablock_t* db)
{
if(db) {
if(db->need_test)
return 1; // already done
}
return 0;
}
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
// Mark will try to find *any* blocks that intersect the range to mark
if(!dynablocks)
if(!db)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t sizedb = dynablocks->textsz;
dynablock_t *db;
dynarec_log(LOG_DEBUG, "MarkDirectDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)startdb, (void*)sizedb);
for(uintptr_t i = 0; i<sizedb; ++i)
if((db=dynablocks->direct[i]))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x64_addr, (void*)db->x64_size);
if(!MarkedDynablock(db))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
}
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
if(!db)
return 1;
if(dynablocks->direct) {
dynablock_t* db;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)native_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db, 1);
);
kh_destroy(dynablocks, blocks);
// check emptyness
for(uintptr_t i=0; i<dynablocks->textsz; ++i)
if(dynablocks->direct[i])
return 0;
return 1;
int need_lock = my_context?1:0;
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1)) {
FreeDynablock(db, need_lock);
return 0;
}
return 1;
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p\n", (void*)addr, (void*)addr+size-1);
if(dynablocks->direct) {
uintptr_t new_addr = dynablocks->minstart;
uintptr_t new_size = dynablocks->maxend - new_addr + 1;
MarkDirectDynablock(dynablocks, addr, size);
// the blocks check before
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), addr, size);
}
}
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
{
@@ -234,63 +119,30 @@ dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
const uintptr_t s = (uintptr_t)db->block;
const uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
return db;
)
return NULL;
}
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
dynablock_t *AddNewDynablock(uintptr_t addr)
{
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
dynablock_t* block;
#if 0
// check if memory as the correct flags
int prot = getProtection(addr);
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if (!*created)
return block;
#endif
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(native_lock_storeifnull(&dynablocks->direct, p)!=p)
free(p); // someone already create the direct array, too late...
}
// create and add new block
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)native_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
pthread_mutex_unlock(&my_context->mutex_dyndump);
free(block);
*created = 0;
return tmp;
}
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
*created = 1;
pthread_mutex_lock(&my_context->mutex_dyndump);
return block;
}
@@ -307,39 +159,28 @@ void cancelFillBlock()
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
}
// nope, lets do the long way
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
if(hasAlternate((void*)addr))
return NULL;
dynablock_t* block = getDB(addr);
if(block || !create)
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
block = getDB(addr); // just in case
if(block) {
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
return block;
}
block = AddNewDynablock(addr);
// fill the block
block->x64_addr = (void*)addr;
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
if(need_lock)
@@ -347,175 +188,59 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
return NULL;
}
void* ret = FillBlock64(block, filladdr);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
void* old = (void*)native_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
if(old!=block && old) {// put it back in place, strange things are happening here!
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
// doing nothing else, the block has not be writen
}
free(block);
customFree(block);
block = NULL;
}
// check size
if(block && block->x64_size) {
if(dynablocks->minstart>addr)
dynablocks->minstart = addr;
if(block && (block->x64_size || (!block->x64_size && !block->done))) {
int blocksz = block->x64_size;
if(dynablocks->maxend<addr+blocksz) {
dynablocks->maxend = addr+blocksz;
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz-1)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->minstart>addr)
dblist->minstart = addr;
}
}
if(blocksz>my_context->max_db_size)
my_context->max_db_size = blocksz;
// fill-in jumptable
addJumpTableIfDefault64(block->x64_addr, block->block);
for(int i=0; i<block->sons_size; ++i) {
addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
block->sons[i]->done = 1;
if(!addJumpTableIfDefault64(block->x64_addr, block->block)) {
FreeDynablock(block, 1);
block = getDB(addr);
} else {
if(block->x64_size)
block->done = 1; // don't validate the block if the size is null, but keep the block
}
block->done = 1;
}
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", GetTID(), created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0);
return block;
}
#define MAX_HOTPAGE 64
#define HOTPAGE_STEP 64
static int volatile hotpage_count[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage[MAX_HOTPAGE] = {0};
static uintptr_t volatile hotpage_size[MAX_HOTPAGE] = {0};
static volatile int hotpages = 0;
int IsInHotPage(uintptr_t addr) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if((hotpage_count[i]>0) && (addr>=hotpage[i]) && (addr<hotpage[i]+0x1000*(hotpage_size[i]+1))) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
__sync_synchronize();
return 1;
}
}
return 0;
}
int AreaInHotPage(uintptr_t start, uintptr_t end) {
if(!hotpages)
return 0;
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(hotpage_count[i]>0)
if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
--hotpage_count[i];
if(!hotpage_count[i]) {
--hotpages;
hotpage_size[i] = 0;
dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
}
return 1;
}
}
return 0;
}
void AddHotPage(uintptr_t addr) {
addr&=~0xfff;
// look for same address
for(int i=0; i<MAX_HOTPAGE; ++i) {
if(addr>=hotpage[i] && addr<hotpage[i]+0x1000*(hotpage_size[i]+1)) {
if(!hotpage_count[i])
++hotpages;
hotpage_count[i] = HOTPAGE_STEP;
__sync_synchronize();
return;
}
if(addr==hotpage[i]+0x1000*(hotpage_size[i]+1)) {
++hotpage_size[i];
hotpage_count[i] = HOTPAGE_STEP;
__sync_synchronize();
return;
}
if(addr+0x1000==hotpage[i]) {
++hotpage_size[i];
hotpage[i] = addr;
hotpage_count[i] = HOTPAGE_STEP;
__sync_synchronize();
return;
}
}
// look for empty spot / minium
int mincnt = hotpage_count[0];
int minidx = 0;
for(int i=1; i<MAX_HOTPAGE; ++i)
if(hotpage_count[i]<mincnt) {
mincnt = hotpage_count[i];
minidx = i;
}
if(hotpage_count[minidx]) {
static int cnt = 0;
if(cnt<50) {
dynarec_log(LOG_NONE, "Warning, not enough Hotpage, replacing %p(%p/%d) with %p\n", (void*)hotpage[minidx], (void*)(0x1000*(hotpage_size[minidx]+1)), hotpage_count[minidx], (void*)addr);
++cnt;
if(cnt==50) // stop spamming console with message...
dynarec_log(LOG_NONE, " will stop warning about not enough Hotpage now\n");
}
hotpage_size[minidx] = 0;
} else
++hotpages;
hotpage[minidx] = addr;
hotpage_count[minidx] = HOTPAGE_STEP;
__sync_synchronize();
}
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
dynablock_t *father = (db && db->father)?db->father:db;
if(father && father->done && db->block && father->need_test) {
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, (void*)addr);
return NULL;
}
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) with %d son(s) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->sons_size, (void*)addr);
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
return NULL;
}
if(AreaInHotPage((uintptr_t)father->x64_addr, (uintptr_t)father->x64_addr + father->x64_size - 1)) {
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with %d son(s) for %p because it's in a hotpage\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->sons_size, (void*)addr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && IntervalIntersects(
(uintptr_t)father->x64_addr,
(uintptr_t)father->x64_addr+father->x64_size-1,
(uintptr_t)(*current)->x64_addr,
(uintptr_t)(*current)->x64_addr+(*current)->x64_size-1))
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father, 0);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
db = internalDBGetBlock(emu, addr, addr, create, 0);
} else {
father->need_test = 0;
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->hash, father->sons_size, (void*)addr);
protectDB((uintptr_t)father->x64_addr, father->x64_size);
db->need_test = 0;
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
@@ -526,26 +251,23 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
dynablock_t *father = (db && db->father)?db->father:db;
if(father && father->done && db->block && father->need_test) {
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
if(hash!=father->hash) {
father->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father, 0);
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
db = internalDBGetBlock(emu, addr, filladdr, create, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x64_addr, father->x64_size);
db->need_test = 0;
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
addJumpTableIfDefault64(father->x64_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
addJumpTableIfDefault64(db->x64_addr, db->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
+5 -17
View File
@@ -1,16 +1,14 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct instsize_s {
unsigned int x64:4;
unsigned int nat:4;
unsigned char x64:4;
unsigned char nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
void* block;
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
int size;
void* x64_addr;
uintptr_t x64_size;
@@ -20,18 +18,8 @@ typedef struct dynablock_s {
uint8_t gone;
uint8_t dummy;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
instsize_t* instsize;
void* jmpnext; // a branch jmpnext code when block is marked
} dynablock_t;
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
uintptr_t maxend; // max address end for anyblock on this blocklist
uintptr_t minstart; // min start address for block overlapping this blocklist
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+8 -34
View File
@@ -20,22 +20,7 @@
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#endif
#ifdef DYNAREC
#ifdef ARM64
void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void arm64_epilog() EXPORTDYN;
#define native_prolog arm64_prolog
#define native_epilog arm64_epilog
#elif defined(LA464)
void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void la464_epilog() EXPORTDYN;
#define native_prolog la464_prolog
#define native_epilog la464_epilog
#else
#error Unsupported architecture
#endif
#include "dynarec_next.h"
#endif
#ifdef DYNAREC
@@ -46,12 +31,11 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
#ifdef HAVE_TRACE
if(!addr) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
}
#endif
dynablock_t* current = NULL;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
dynablock_t* block = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
@@ -60,7 +44,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
R_RIP = addr; // but also new RIP!
*x3 = addr; // and the RIP in x27 register
printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
block = DBGetBlock(emu, addr, 1);
}
if(!block) {
#ifdef HAVE_TRACE
@@ -121,23 +105,18 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
while(!emu->quit) {
dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
native_prolog(emu, block->block);
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -201,22 +180,17 @@ int DynaRun(x64emu_t* emu)
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* current = NULL;
dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);;
current = block;
while(!emu->quit) {
dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
Run(emu, 1);
block = DBGetBlock(emu, R_RIP, 1, &current);
current = block;
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, emu);
// block is here, let's run it!
native_prolog(emu, block->block);
block = NULL;
}
if(emu->fork) {
int forktype = emu->fork;
+159 -207
View File
@@ -23,21 +23,22 @@
#include "dynarec_native.h"
#include "dynarec_arch.h"
#include "dynarec_next.h"
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uintptr_t a = *(uintptr_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%s%p: Exit x64emu%s\n", (box64_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Exit x64emu%s\n", (box64_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (box64_dynarec_dump>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box64_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box64_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (void*)a, (box64_dynarec_dump>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%s%p: %s", (box64_dynarec_dump>1)?"\e[1m":"", ip, DecodeX64Trace(dec, inst->addr));
dynarec_log(LOG_NONE, "%s%p: %s", (box64_dynarec_dump>1)?"\e[01;33m":"", ip, DecodeX64Trace(dec, inst->addr));
} else {
dynarec_log(LOG_NONE, "%s%p: ", (box64_dynarec_dump>1)?"\e[1m":"", ip);
dynarec_log(LOG_NONE, "%s%p: ", (box64_dynarec_dump>1)?"\e[01;33m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
}
@@ -61,12 +62,20 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha
void add_next(dynarec_native_t *dyn, uintptr_t addr) {
if(!box64_dynarec_bigblock)
return;
// exist?
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
// put in a free slot
for(int i=0; i<dyn->next_sz; ++i)
if(!dyn->next[i]) {
dyn->next[i] = addr;
return;
}
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
dyn->next_cap += 64;
dyn->next = (uintptr_t*)customRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -76,13 +85,12 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
++i;
}
return best;
}
@@ -242,7 +250,7 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x64_size,
toadd = 1 + native_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
insts = (instsize_t*)customRealloc(insts, (*cap)*sizeof(instsize_t));
}
while(toadd) {
if(x64_size>15)
@@ -272,8 +280,8 @@ int Table64(dynarec_native_t *dyn, uint64_t val)
// not found, add it
if(idx==-1) {
if(dyn->table64size == dyn->table64cap) {
dyn->table64cap+=4;
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
dyn->table64cap+=16;
dyn->table64 = (uint64_t*)customRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
}
idx = dyn->table64size++;
dyn->table64[idx] = val;
@@ -285,23 +293,23 @@ int Table64(dynarec_native_t *dyn, uint64_t val)
static void fillPredecessors(dynarec_native_t* dyn)
{
int pred_sz = 0;
int pred_sz = 1; // to be safe
// compute total size of predecessor to alocate the array
// first compute the jumps
for(int i=0; i<dyn->size; ++i) {
if(dyn->insts[i].x64.jmp && dyn->insts[i].x64.jmp_insts!=-1) {
++pred_sz;
++dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz;
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
pred_sz++;
dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz++;
}
}
// second the "has_next"
for(int i=0; i<dyn->size; ++i) {
if(i!=dyn->size-1 && dyn->insts[i].x64.has_next && (!i || dyn->insts[i].pred_sz)) {
++pred_sz;
++dyn->insts[i+1].pred_sz;
for(int i=0; i<dyn->size-1; ++i) {
if(dyn->insts[i].x64.has_next) {
pred_sz++;
dyn->insts[i+1].pred_sz++;
}
}
dyn->predecessor = (int*)malloc(pred_sz*sizeof(int));
dyn->predecessor = (int*)customMalloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -309,70 +317,63 @@ static void fillPredecessors(dynarec_native_t* dyn)
p += dyn->insts[i].pred_sz;
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
assert(p==dyn->predecessor+pred_sz);
// fill pred
for(int i=0; i<dyn->size; ++i) {
if(i!=dyn->size-1 && dyn->insts[i].x64.has_next && (!i || dyn->insts[i].pred_sz))
if((i!=dyn->size-1) && dyn->insts[i].x64.has_next)
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x64.jmp && dyn->insts[i].x64.jmp_insts!=-1)
dyn->insts[dyn->insts[i].x64.jmp_insts].pred[dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz++] = i;
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
int j = dyn->insts[i].x64.jmp_insts;
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
static void updateNeed(dynarec_native_t* dyn, int ninst, uint32_t need) {
uint32_t old_need = dyn->insts[ninst].x64.need_flags;
uint32_t new_need = old_need | need;
uint32_t new_use = dyn->insts[ninst].x64.use_flags;
uint32_t old_use = dyn->insts[ninst].x64.old_use;
if((new_need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET) {
new_need &=~X_PEND;
new_need |= X_ALL;
}
uint32_t new_set = 0;
if(dyn->insts[ninst].x64.state_flags & SF_SET)
new_set = dyn->insts[ninst].x64.set_flags;
if(dyn->insts[ninst].x64.state_flags & SF_PENDING)
new_set |= X_PEND;
if((new_need&X_PEND) && (
dyn->insts[ninst].x64.state_flags==SF_SET || dyn->insts[ninst].x64.state_flags==SF_SUBSET)) {
new_need &=~X_PEND;
new_need |=X_ALL;
}
dyn->insts[ninst].x64.need_flags = new_need;
dyn->insts[ninst].x64.old_use = new_use;
if(dyn->insts[ninst].x64.jmp_insts==-1)
new_need |= X_PEND;
// a Flag Barrier will change all need to "Pending", as it clear all flags optimisation
if(new_need && dyn->insts[ninst].x64.barrier&BARRIER_FLAGS)
new_need = X_PEND;
if((new_need == old_need) && (new_use == old_use)) // no changes, bye
return;
if(!(new_need && dyn->insts[ninst].x64.barrier&BARRIER_FLAGS)) {
new_need &=~new_set; // clean needed flag that were suplied
new_need |= new_use; // new need
}
if((new_need == (X_ALL|X_PEND)) && (dyn->insts[ninst].x64.state_flags & SF_SET))
new_need = X_ALL;
//update need to new need on predecessor
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
updateNeed(dyn, dyn->insts[ninst].pred[i], new_need);
}
static void resetNeed(dynarec_native_t* dyn) {
for(int i = dyn->size; i-- > 0;) {
dyn->insts[i].x64.old_use = 0;
dyn->insts[i].x64.need_flags = dyn->insts[i].x64.default_need;
// updateNeed goes backward, from last intruction to top
static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
need |= dyn->insts[ninst].x64.need_after;
if((need&X_PEND) && (dyn->insts[ninst].x64.state_flags==SF_SUBSET)) {
need &=~X_PEND;
need |= X_ALL;
}
if((need&X_PEND) && (dyn->insts[ninst].x64.state_flags==SF_SET)) {
need &=~X_PEND;
need |= dyn->insts[ninst].x64.set_flags; // SF_SET will compute all flags, it's not SUBSET!
}
if((need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET_PENDING) {
need |= X_ALL&~(dyn->insts[ninst].x64.set_flags);
}
dyn->insts[ninst].x64.gen_flags = need&dyn->insts[ninst].x64.set_flags;
if((need&X_PEND) && (dyn->insts[ninst].x64.state_flags&SF_PENDING))
dyn->insts[ninst].x64.gen_flags |= X_PEND;
dyn->insts[ninst].x64.need_after = need;
need = dyn->insts[ninst].x64.need_after&~dyn->insts[ninst].x64.gen_flags;
if(dyn->insts[ninst].x64.may_set)
need |= dyn->insts[ninst].x64.gen_flags; // forward the flags
// Consume X_PEND if relevant
if((need&X_PEND) && (dyn->insts[ninst].x64.set_flags&SF_PENDING))
need &=~X_PEND;
need |= dyn->insts[ninst].x64.use_flags;
if(dyn->insts[ninst].x64.need_before == need)
return ninst - 1;
dyn->insts[ninst].x64.need_before = need;
if(dyn->insts[ninst].x64.barrier&BARRIER_FLAGS) {
need = need?X_PEND:0;
}
int ok = 0;
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i) {
if(dyn->insts[ninst].pred[i] == ninst-1)
ok = 1;
else
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
}
if(!ok)
return ninst - 1;
--ninst;
}
return ninst;
}
__thread void* current_helper = NULL;
@@ -383,13 +384,15 @@ void CancelBlock64()
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->table64);
free(helper->sons_x64);
free(helper->sons_native);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
customFree(helper->next);
customFree(helper->insts);
customFree(helper->instsize);
customFree(helper->predecessor);
customFree(helper->table64);
if(helper->dynablock && helper->dynablock->actual_block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->actual_block, helper->dynablock->size);
else if(helper->dynablock && helper->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->block-sizeof(void*), helper->dynablock->size);
}
uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr);
@@ -397,14 +400,38 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr);
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
size_t sz = 4*sizeof(void*);
void* actual_p = (void*)AllocDynarecMap(block, sz);
void* p = actual_p + sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock64();
return NULL;
}
block->size = sz;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
*(dynablock_t**)actual_p = block;
*(void**)(p+2*sizeof(void*)) = native_epilog;
CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
block->need_test = 0;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
return block;
}
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
block->done = 1;
return (void*)block;
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(block, addr);
}
// protect the 1st page
protectDB(addr, 1);
@@ -414,19 +441,19 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_native_t*)calloc(helper.cap, sizeof(instruction_native_t));
helper.cap = 128;
helper.insts = (instruction_native_t*)customCalloc(helper.cap, sizeof(instruction_native_t));
// pass 0, addresses, x64 jump addresses, overall size of the block
uintptr_t end = native_pass0(&helper, addr);
// no need for next anymore
free(helper.next);
customFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64();
return (void*)block;
return CreateEmptyBlock(block, addr);;
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
@@ -438,17 +465,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
protectDB(addr, end-addr); //end is 1byte after actual end
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// Compute flag_need, without with current barriers
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
uintptr_t j = helper.insts[i].x64.jmp;
if(j<start || j>=end) {
helper.insts[i].x64.jmp_insts = -1;
helper.insts[i].x64.use_flags |= X_PEND;
helper.insts[i].x64.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
@@ -463,75 +486,38 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
// fill predecessors with the jump address
fillPredecessors(&helper);
// check for the optionnal barriers now
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].barrier_maybe) {
// out-of-block jump
if(helper.insts[i].x64.jmp_insts == -1) {
// nothing for now
} else {
// inside block jump
int k = helper.insts[i].x64.jmp_insts;
if(k>i) {
// jump in the future
if(helper.insts[k].pred_sz>1) {
// with multiple flow, put a barrier
helper.insts[k].x64.barrier|=BARRIER_FLAGS;
}
} else {
// jump back
helper.insts[k].x64.barrier|=BARRIER_FLAGS;
}
}
}
}
// check to remove useless barrier, in case of jump when destination doesn't needs flags
/*for(int i=helper.size-1; i>=0; --i) {
int k;
if(helper.insts[i].x64.jmp
&& ((k=helper.insts[i].x64.jmp_insts)>=0)
&& helper.insts[k].x64.barrier&BARRIER_FLAGS) {
//TODO: optimize FPU barrier too
if((!helper.insts[k].x64.need_flags)
||(helper.insts[k].x64.set_flags==X_ALL
&& helper.insts[k].x64.state_flags==SF_SET)
||(helper.insts[k].x64.state_flags==SF_SET_PENDING)) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
helper.insts[k].x64.barrier &= ~BARRIER_FLAGS; // remove flag barrier
}
}
}*/
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
for(int i = helper.size; i-- > 0;) {
int k;
if(helper.insts[i].x64.jmp
&& ((k=helper.insts[i].x64.jmp_insts)>=0)
) {
if(helper.insts[k].x64.barrier&BARRIER_FLAGS)
// jumpto barrier
helper.insts[i].x64.use_flags |= X_PEND;
if(helper.insts[i].x64.barrier&BARRIER_FLAGS && (helper.insts[k].x64.need_flags | helper.insts[k].x64.use_flags))
helper.insts[k].x64.barrier|=BARRIER_FLAGS;
else
helper.insts[i].x64.use_flags |= (helper.insts[k].x64.need_flags | helper.insts[k].x64.use_flags);
}
if(helper.insts[i].x64.barrier&BARRIER_FLAGS)
// immediate barrier
helper.insts[i].x64.use_flags |= X_PEND;
}
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// pass 1, float optimisations, first pass for flags
native_pass1(&helper, addr);
// pass 2, instruction size
native_pass2(&helper, addr);
// keep size of instructions for signal handling
size_t insts_rsize = 0;
{
size_t insts_size = 0;
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
helper.instsize = (instsize_t*)customCalloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
helper.instsize = addInst(helper.instsize, &insts_size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
helper.instsize = addInst(helper.instsize, &insts_size, &cap, 0, 0); // add a "end of block" mark, just in case
insts_rsize = insts_size*sizeof(instsize_t);
}
insts_rsize = (insts_rsize+7)&~7; // round the size...
// ok, now allocate mapped memory, with executable flag on
size_t sz = helper.native_size + helper.table64size*sizeof(uint64_t);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
size_t sz = sizeof(void*) + helper.native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
// dynablock_t* block (arm insts) table64 jmpnext code instsize
void* actual_p = (void*)AllocDynarecMap(block, sz);
void* p = actual_p + sizeof(void*);
void* next = p + helper.native_size + helper.table64size*sizeof(uint64_t);
void* instsize = next + 4*sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock64();
return NULL;
@@ -539,10 +525,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
helper.block = p;
helper.native_start = (uintptr_t)p;
helper.tablestart = helper.native_start + helper.native_size;
if(helper.sons_size) {
helper.sons_x64 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
helper.sons_native = (void**)calloc(helper.sons_size, sizeof(void*));
}
*(dynablock_t**)actual_p = block;
// pass 3, emit (log emit native opcode)
if(box64_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize);
@@ -572,30 +555,31 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(helper.table64size) {
memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
}
// all done...
__clear_cache(p, p+sz); // need to clear the cache before execution...
// keep size of instructions for signal handling
{
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
size_t size = 0;
block->instsize = (instsize_t*)calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
}
memcpy(instsize, helper.instsize, insts_rsize);
block->instsize = instsize;
// ok, free the helper now
free(helper.insts);
customFree(helper.insts);
helper.insts = NULL;
free(helper.table64);
customFree(helper.table64);
helper.table64 = NULL;
customFree(helper.instsize);
helper.instsize = NULL;
customFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = next+sizeof(void*);
*(dynablock_t**)next = block;
*(void**)(next+2*sizeof(void*)) = native_next;
CreateJmpNext(block->jmpnext, next+2*sizeof(void*));
block->need_test = 0;
//block->x64_addr = (void*)start;
block->x64_size = end-start;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abbort if it as
if((block->hash != hash)) {
@@ -609,38 +593,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
return NULL;
//protectDB(addr, end-addr);
}
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x64[i], &created);
if(created) { // avoid breaking a working block!
son->block = helper.sons_native[i];
son->x64_addr = (void*)helper.sons_x64[i];
son->x64_size = end-helper.sons_x64[i];
if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / Native=%p)", son->x64_addr, son->block);}
son->father = block;
son->size = sz + son->block - block->block; // update size count, for debugging
//son->done = 1;
if(!son->parent)
son->parent = block->parent;
sons[sons_size] = son;
++sons_size;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
free(sons);
}
free(helper.sons_x64);
helper.sons_x64 = NULL;
free(helper.sons_native);
helper.sons_native = NULL;
current_helper = NULL;
//block->done = 1;
return (void*)block;
+16 -11
View File
@@ -18,6 +18,7 @@
#include "dynablock.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "elfloader.h"
#include "dynarec_arch.h"
#include "dynarec_helper.h"
@@ -30,18 +31,19 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
{
int ok = 1;
int ninst = 0;
int j64;
uintptr_t ip = addr;
uintptr_t init_addr = addr;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->f.pending = 0;
dyn->f.dfnone = 0;
fpu_reset(dyn);
int reset_n = -1;
dyn->last_ip = (dyn->insts && dyn->insts[0].pred_sz)?0:ip; // RIP is always set at start of block unless there is a predecessor!
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3
// ok, go now
INIT;
while(ok) {
@@ -104,7 +106,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
}
}
reset_n = -1;
} else if(dyn->insts[ninst].pred_sz!=1)
} else if(ninst && (dyn->insts[ninst].pred_sz!=1 || dyn->insts[ninst].pred[0]!=ninst-1))
dyn->last_ip = 0; // reset IP if some jump are comming here
// propagate ST stack state, especial stack pop that are defered
if(dyn->n.stack_pop) {
@@ -123,6 +125,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
dyn->n.swapped = 0;
NEW_INST;
fpu_reset_scratch(dyn);
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
}
#ifdef HAVE_TRACE
if(my_context->dec && box64_dynarec_trace) {
if((trace_end == 0)
@@ -142,7 +147,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
++addr;
pk = PK(0);
}
while(pk==0x3E) { //Branch Taken Hint ignored
while(pk==0x3E || pk==0x26) { //Branch Taken Hint ignored, same for ES: prefix
++addr;
pk = PK(0);
}
@@ -213,23 +218,23 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
if(ok && !isJumpTableDefault64((void*)addr) && (box64_dynarec_bigblock<2))
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
|| (addr>=box64_nodynarec_start && addr<box64_nodynarec_end)))
#else
if(ok && (ninst==dyn->size))
#endif
{
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
if(!box64_dynarec_dump && addr>=box64_nodynarec_start && addr<box64_nodynarec_end)
dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
--ninst;
if(!dyn->insts[ninst].x64.barrier) {
BARRIER(BARRIER_FLOAT);
}
#if STEP == 0
if(dyn->insts[ninst].x64.set_flags)
dyn->insts[ninst].x64.default_need |= X_PEND;
else
dyn->insts[ninst].x64.use_flags |= X_PEND;
dyn->insts[ninst].x64.need_after |= X_PEND;
#endif
++ninst;
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
@@ -242,6 +247,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
return addr;
}
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef __DYNAREC_NEXT_H__
#define __DYNAREC_NEXT_H__
#ifdef ARM64
void arm64_next(void) EXPORTDYN;
void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void arm64_epilog() EXPORTDYN;
#define native_next arm64_next
#define native_prolog arm64_prolog
#define native_epilog arm64_epilog
#elif defined(LA464)
void la464_next(void) EXPORTDYN;
void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void la464_epilog() EXPORTDYN;
#define native_next la464_next
#define native_prolog la464_prolog
#define native_epilog la464_epilog
#else
#error Unsupported architecture
#endif
#endif //__DYNAREC_NEXT_H__
+4 -4
View File
@@ -24,7 +24,6 @@
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
#define SF_MAYSET 8
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
@@ -37,9 +36,10 @@ typedef struct instruction_x64_s {
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
uint8_t default_need;// 0 or X_PEND basically
uint8_t need_flags; // calculated
uint8_t old_use; // calculated
uint8_t may_set; // 1 if the flags may not be set
uint8_t gen_flags; // calculated
uint8_t need_before;// calculated
uint8_t need_after; // calculated
} instruction_x64_t;
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
+1
View File
@@ -15,6 +15,7 @@
#define native_lock_read_dq(A, B, C) arm64_lock_read_dq(A, B, C)
#define native_lock_write_dq(A, B, C) arm64_lock_write_dq(A, B, C)
#define native_lock_xchg(A, B) arm64_lock_xchg(A, B)
#define native_lock_xchg_d(A, B) arm64_lock_xchg_d(A, B)
#define native_lock_storeifref(A, B, C) arm64_lock_storeifref(A, B, C)
#define native_lock_storeifnull(A, B) arm64_lock_storeifnull(A, B)
+38 -34
View File
@@ -108,6 +108,10 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
*success = 0;
return 0;
}
if(!IsAddressInElfSpace(ehdr, ehdr->ehframehdr)) {
*success = 0;
return 0;
}
unsigned char ehfh_version = *(unsigned char*)ehdr->ehframehdr;
if (ehfh_version != 1) {
*success = 0;
@@ -389,17 +393,17 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
++unwind_constr.reg_count;
size_t tablelen = unwind_constr.reg_count * sizeof(uint64_t);
size_t statuseslen = ((unwind_constr.reg_count+1) >> 1) * sizeof(uint8_t);
unwind_constr.table = (uint64_t*)malloc(tablelen);
unwind_constr.statuses = (uint8_t*)calloc((unwind_constr.reg_count+1) >> 1, sizeof(uint8_t));
unwind_constr.table = (uint64_t*)box_malloc(tablelen);
unwind_constr.statuses = (uint8_t*)box_calloc((unwind_constr.reg_count+1) >> 1, sizeof(uint8_t));
// ~~undefined is 0: no initialization needed~~ still initialize the first 17 to same_val
for (int i = 0; (i < 17) && (i <= unwind_constr.reg_count); ++i) {
SET_STATUS(unwind_constr, i, REGSTATUS_same_val);
}
curstacksize = 0;
uint64_t **table_stack = (uint64_t**)malloc(maxstacksize * sizeof(uint64_t*));
uint64_t **table_stack = (uint64_t**)box_malloc(maxstacksize * sizeof(uint64_t*));
for (uint64_t i = 0; i < maxstacksize; ++i) {
table_stack[i] = (uint64_t*)malloc(tablelen);
table_stack[i] = (uint64_t*)box_malloc(tablelen);
}
cur_inst = initCIEinstr;
uintptr_t cur_pointed_addr = pc_begin;
@@ -537,10 +541,10 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
printf_log(LOG_DEBUG, "Trying to restore register 0x%02lX while in the intial CFIs\n", (uint64_t)reg); \
FAILED
#define FAILED \
free(unwind_constr.statuses); \
free(unwind_constr.table); \
for (uint64_t i = 0; i < maxstacksize; ++i) free(table_stack[i]); \
free(table_stack); \
box_free(unwind_constr.statuses); \
box_free(unwind_constr.table); \
for (uint64_t i = 0; i < maxstacksize; ++i) box_free(table_stack[i]); \
box_free(table_stack); \
*success = 0; return 0;
while (cur_inst < endCIEinstr) {
unsigned char inst; READ_U1(inst, cur_inst);
@@ -549,21 +553,21 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
}
#undef FAILED
#undef RESTORE_REG
uint64_t *init_table = (uint64_t*)malloc(tablelen);
uint64_t *init_table = (uint64_t*)box_malloc(tablelen);
memcpy(init_table, unwind_constr.table, tablelen);
uint8_t *init_statuses = (uint8_t*)malloc(statuseslen);
uint8_t *init_statuses = (uint8_t*)box_malloc(statuseslen);
memcpy(init_statuses, unwind_constr.statuses, statuseslen);
cur_inst = cur_addr;
#define RESTORE_REG(reg) \
unwind_constr.table[reg] = init_table[reg]; \
SET_STATUS(unwind_constr, (reg), ((init_statuses[(reg) >> 1] >> (((reg) & 1) << 2)) & 0xF));
#define FAILED \
free(init_statuses); \
free(init_table); \
free(unwind_constr.statuses); \
free(unwind_constr.table); \
for (uint64_t i = 0; i < maxstacksize; ++i) free(table_stack[i]); \
free(table_stack); \
box_free(init_statuses); \
box_free(init_table); \
box_free(unwind_constr.statuses); \
box_free(unwind_constr.table); \
for (uint64_t i = 0; i < maxstacksize; ++i) box_free(table_stack[i]); \
box_free(table_stack); \
*success = 0; return 0;
while ((cur_inst < next_addr) && (cur_pointed_addr <= addr)) {
unsigned char inst; READ_U1(inst, cur_inst);
@@ -573,16 +577,16 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
#undef FAILED
#undef RESTORE_REG
#undef PARSE_INST
free(init_statuses);
free(init_table);
box_free(init_statuses);
box_free(init_table);
for (int i = 0; i < maxstacksize; ++i) {
free(table_stack[i]);
box_free(table_stack[i]);
}
free(table_stack);
box_free(table_stack);
dwarf_unwind_t new_unwind;
new_unwind.reg_count = unwind_constr.reg_count;
new_unwind.regs = calloc(unwind_constr.reg_count, sizeof(uint64_t));
new_unwind.regs = box_calloc(unwind_constr.reg_count, sizeof(uint64_t));
uintptr_t cfa = unwind->regs[cfa_reg];
if (cfa_signed) cfa += cfa_offset.soff;
else cfa += cfa_offset.uoff;
@@ -596,9 +600,9 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
case REGSTATUS_same_val:
if (i >= unwind->reg_count) {
printf_log(LOG_DEBUG, "Invalid register status (value copied from register 0x%02lX)\n", i);
free(unwind_constr.statuses);
free(unwind_constr.table);
free(new_unwind.regs);
box_free(unwind_constr.statuses);
box_free(unwind_constr.table);
box_free(new_unwind.regs);
*success = 0;
return 0;
}
@@ -616,9 +620,9 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
case REGSTATUS_register:
if (unwind_constr.table[i] >= unwind->reg_count) {
printf_log(LOG_DEBUG, "Invalid register status (value copied from register 0x%02lX)\n", unwind_constr.table[i]);
free(unwind_constr.statuses);
free(unwind_constr.table);
free(new_unwind.regs);
box_free(unwind_constr.statuses);
box_free(unwind_constr.table);
box_free(new_unwind.regs);
*success = 0;
return 0;
}
@@ -628,10 +632,10 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
}
}
*success = (GET_STATUS(unwind_constr, return_addr_reg) == REGSTATUS_undefined) ? 0 : ((aug_fields & AUG_SIGHDLER) ? 2 : 1);
free(unwind_constr.statuses);
free(unwind_constr.table);
box_free(unwind_constr.statuses);
box_free(unwind_constr.table);
free(unwind->regs);
box_free(unwind->regs);
unwind->reg_count = new_unwind.reg_count;
unwind->regs = new_unwind.regs;
@@ -654,9 +658,9 @@ uintptr_t get_parent_registers(dwarf_unwind_t *unwind, const elfheader_t *ehdr,
}
dwarf_unwind_t *init_dwarf_unwind_registers(x64emu_t *emu) {
dwarf_unwind_t *unwind_struct = (dwarf_unwind_t*)malloc(sizeof(dwarf_unwind_t));
dwarf_unwind_t *unwind_struct = (dwarf_unwind_t*)box_malloc(sizeof(dwarf_unwind_t));
unwind_struct->reg_count = 17;
unwind_struct->regs = (uint64_t*)malloc(17*sizeof(uint64_t));
unwind_struct->regs = (uint64_t*)box_malloc(17*sizeof(uint64_t));
/* x86_64-abi-0.99.pdf
* Register Name | Number | Abbreviation
* General Purpose Register RAX | 0 | %rax
@@ -711,7 +715,7 @@ dwarf_unwind_t *init_dwarf_unwind_registers(x64emu_t *emu) {
}
void free_dwarf_unwind_registers(dwarf_unwind_t **unwind_struct) {
free((*unwind_struct)->regs);
free(*unwind_struct);
box_free((*unwind_struct)->regs);
box_free(*unwind_struct);
*unwind_struct = NULL;
}
+157 -129
View File
@@ -11,6 +11,7 @@
#include <unistd.h>
#include <errno.h>
#include "custommem.h"
#include "box64version.h"
#include "elfloader.h"
#include "debug.h"
@@ -26,7 +27,6 @@
#include "box64stack.h"
#include "callback.h"
#include "box64stack.h"
#include "custommem.h"
#include "wine_tools.h"
#include "dictionnary.h"
#include "symbols.h"
@@ -54,10 +54,15 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
if(!h)
return NULL;
if ((h->path = realpath(name, NULL)) == NULL) {
h->path = (char*)malloc(1);
if ((h->path = box_realpath(name, NULL)) == NULL) {
h->path = (char*)box_malloc(1);
h->path[0] = '\0';
}
h->mapsymbols = NewMapSymbols();
h->weaksymbols = NewMapSymbols();
h->localsymbols = NewMapSymbols();
return h;
}
@@ -72,19 +77,23 @@ void FreeElfHeader(elfheader_t** head)
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
}*/ // will be free at the end, no need to free it now
#endif
free(h->name);
free(h->path);
free(h->PHEntries);
free(h->SHEntries);
free(h->SHStrTab);
free(h->StrTab);
free(h->Dynamic);
free(h->DynStr);
free(h->SymTab);
free(h->DynSym);
box_free(h->name);
box_free(h->path);
box_free(h->PHEntries);
box_free(h->SHEntries);
box_free(h->SHStrTab);
box_free(h->StrTab);
box_free(h->Dynamic);
box_free(h->DynStr);
box_free(h->SymTab);
box_free(h->DynSym);
FreeMapSymbols(&h->mapsymbols);
FreeMapSymbols(&h->weaksymbols);
FreeMapSymbols(&h->localsymbols);
FreeElfMemory(h);
free(h);
box_free(h);
*head = NULL;
}
@@ -156,12 +165,12 @@ const char* ElfPath(elfheader_t* head)
int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
if(mainbin && head->vaddr==0) {
char* load_addr = getenv("BOX64_LOAD_ADDR");
if(load_addr)
if(sscanf(load_addr, "0x%zx", &offs)!=1)
offs = 0;
if(!head->vaddr && box64_load_addr) {
offs = box64_load_addr;
box64_load_addr += head->memsz;
box64_load_addr = (box64_load_addr+0x10ffffffLL)&~0xffffffLL;
}
int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
if(!offs)
offs = head->vaddr;
if(head->vaddr) {
@@ -169,9 +178,9 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
for (size_t i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
++head->multiblock_n;
head->multiblock_size = (uint64_t*)calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
// and now, create all individual blocks
head->memory = (char*)0xffffffffffffffff;
int n = 0;
@@ -209,8 +218,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
}
head->multiblock_n = n; // might be less in fact
for (int i=0; i<head->multiblock_n; ++i) {
printf_log(LOG_DEBUG, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i]
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
@@ -245,7 +253,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
// vaddr is 0, load everything has a One block
if(!offs && box64_wine)
offs = (uintptr_t)find47bitBlock(head->memsz); // limit to 47bits...
printf_log(LOG_DEBUG, "Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
printf_log(log_level, "Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
void* p = mmap((void*)offs, head->memsz
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
@@ -262,12 +270,12 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
head->memory = p;
memset(p, 0, head->memsz);
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
printf_log(LOG_DEBUG, "Got %p (delta=%p)\n", p, (void*)head->delta);
printf_log(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta);
head->multiblock_n = 1;
head->multiblock_size = (uint64_t*)calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size[0] = head->memsz;
head->multiblock_offs[0] = (uintptr_t)p;
head->multiblock[0] = p;
@@ -283,9 +291,9 @@ void FreeElfMemory(elfheader_t* head)
if(head->multiblock_n) {
for(int i=0; i<head->multiblock_n; ++i)
munmap(head->multiblock[i], head->multiblock_size[i]);
free(head->multiblock);
free(head->multiblock_size);
free(head->multiblock_offs);
box_free(head->multiblock);
box_free(head->multiblock_size);
box_free(head->multiblock_offs);
}
}
@@ -299,7 +307,7 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
void* p = (void*)-1;
if(e->p_memsz==e->p_filesz && !(e->p_align&0xfff)) {
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
}
if(p!=dest) {
printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
@@ -355,8 +363,9 @@ int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
#ifdef DYNAREC
cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
#endif
mprotect(dest, e->p_memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
setProtection((uintptr_t)dest, e->p_memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
uint32_t page_offset = (uintptr_t)dest & (box64_pagesize - 1);
mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
if(e->p_filesz) {
ssize_t r = -1;
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
@@ -373,7 +382,7 @@ int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
return 0;
}
int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, int version, const char* vername)
int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername)
{
if(!h)
return 0;
@@ -385,7 +394,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
int t = ELF64_R_TYPE(rela[i].r_info);
Elf64_Sym *sym = &h->DynSym[ELF64_R_SYM(rela[i].r_info)];
const char* symname = SymName(h, sym);
if(t==R_X86_64_COPY && symname && !strcmp(symname, name)) {
if(t==R_X86_64_COPY && symname && !strcmp(symname, name) && sym->st_size==size) {
int version2 = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
@@ -412,10 +421,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
uint64_t *p = (uint64_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
//uintptr_t tmp = 0;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rel[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -452,14 +463,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
*p += offs;
break;
case R_X86_64_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value;
end = offs + sym->st_size;
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)(offs + head->delta), (void*)globoffs, sym->st_size, symname);
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, offs + head->delta, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname);
}
@@ -472,7 +483,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
printf_log(LOG_NONE, "%s: Global Symbol %s (ver=%d/%s) not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, version, vername?vername:"(none)", 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)");
*p = offs;
@@ -484,11 +495,11 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
uintptr_t old_offs = offs;
uintptr_t old_end = end;
offs = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, defver); // try globaldata symbols first
if(offs==0) {
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername); // get original copy if any
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername); // get original copy if any
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
}
if(!offs) {
offs = old_offs;
@@ -566,7 +577,6 @@ uintptr_t tlsdescUndefweak = 0;
uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
EXPORT uintptr_t _dl_tlsdesc_undefweak(x64emu_t* emu)
{
printf_log(LOG_DEBUG, "_dl_tlsdesc_undefweak, rax=%p\n", (void*)R_RAX);
struct tlsdesc *td = (struct tlsdesc *)R_RAX;
return td->arg;
}
@@ -584,10 +594,12 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
uint64_t *p = (uint64_t*)(rela[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
size_t size = sym->st_size;
elfheader_t* h_tls = NULL;//head;
int version = head->VerSym?((Elf64_Half*)((uintptr_t)head->VerSym+head->delta))[ELF64_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -621,15 +633,23 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
printf_dump(LOG_NEVER, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend));
*p = head->delta+ rela[i].r_addend;
break;
case R_X86_64_IRELATIVE:
{
x64emu_t* emu = thread_get_emu();
EmuCall(emu, head->delta+rela[i].r_addend);
printf_dump(LOG_NEVER, "Apply %s R_X86_64_IRELATIVE @%p (%p -> %p()=%p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend), (void*)(R_RAX));
*p = R_RAX;
}
break;
case R_X86_64_COPY:
globoffs = offs;
globend = end;
offs = end = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, defver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
@@ -641,7 +661,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
break;
case R_X86_64_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR64COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -650,7 +670,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
@@ -665,7 +685,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
printf_log((bind==STB_WEAK)?LOG_INFO:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", 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)");
*p = offs/* + rela[i].r_addend*/; // not addend it seems
@@ -697,7 +717,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
(bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
*p = offs + rela[i].r_addend;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
printf_log(LOG_INFO, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
@@ -709,9 +729,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
break;
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;
if(symname && !strcmp(symname, "__gxx_personality_v0")) {
printf_dump(LOG_NEVER, "Warning: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
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",
(bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
@@ -799,6 +823,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
return bindnow?ret_ok:0;
}
void checkHookedSymbols(lib_t *maplib, elfheader_t* h); // in mallochook.c
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
if(head->rel) {
@@ -815,7 +840,7 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* he
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf64_Rela *)(head->rela + head->delta), NULL))
return -1;
}
checkHookedSymbols(maplib, head);
return 0;
}
@@ -923,22 +948,6 @@ 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)
{
if(box64_dump && h->DynSym) DumpDynSym(h);
int libcef = (strstr(h->name, "libcef.so"))?1:0;
//libcef.so is linked with tcmalloc staticaly, but this cannot be easily supported in box64, so hacking some "unlink" here
const char* avoid_libcef[] = {"malloc", "realloc", "free", "calloc", "cfree",
"__libc_calloc", "__libc_cfree", "__libc_memallign", "__liv_pvalloc",
"__libcrealloc", "__libc_valloc", "__posix_memalign",
"valloc", "pvalloc", "posix_memalign", "malloc_stats", "malloc_usable_size",
/*"mallopt",*/ "localtime_r",
//c++ symbol from libstdc++ too
//"_ZnwmRKSt9nothrow_t", "_ZdaPv", // operator new(unsigned long, std::nothrow_t const&), operator delete[](void*)
//"_Znwm", "_ZdlPv", "_Znam", // operator new(unsigned long), operator delete(void*), operator new[](unsigned long)
//"_ZnwmSt11align_val_t", "_ZnwmSt11align_val_tRKSt9nothrow_t", // operator new(unsigned long, std::align_val_t)
//"_ZnamSt11align_val_t", "_ZnamSt11align_val_tRKSt9nothrow_t", // operator new[](unsigned long, std::align_val_t)
//"_ZdlPvRKSt9nothrow_t", "_ZdaPvSt11align_val_tRKSt9nothrow_t", // more delete operators
//"_ZdlPvmSt11align_val_t", "_ZdaPvRKSt9nothrow_t",
//"_ZdaPvSt11align_val_t", "_ZdlPvSt11align_val_t",
};
printf_dump(LOG_NEVER, "Will look for Symbol to add in SymTable(%zu)\n", h->numSymTab);
for (size_t i=0; i<h->numSymTab; ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -957,6 +966,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
p+=2;
symname = AddDictionnary(my_context->versym, symnameversionned);
const char* vername = AddDictionnary(my_context->versym, p);
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
@@ -971,13 +981,6 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
}
} else {
int to_add = 1;
if(libcef) {
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
to_add = 0;
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
if(!strcmp(symname, avoid_libcef[j]))
to_add = 0;
}
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL)))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
@@ -1005,16 +1008,14 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
size_t sz = h->DynSym[i].st_size;
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname))?1:0;
if(version!=-1) version &= 0x7fff;
const char* vername = GetSymbolVersion(h, version);
int to_add = 1;
if(libcef) {
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
to_add = 0;
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
if(!strcmp(symname, avoid_libcef[j]))
to_add = 0;
if(add_default) {
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
}
int to_add = 1;
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername)))
continue;
printf_dump(LOG_NEVER, "Adding Versionned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
@@ -1024,11 +1025,10 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, version, vername);
} else {
AddWeakSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
AddSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
}
}
}
}
/*
@@ -1054,46 +1054,46 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib
char *rpathref = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
char* rpath = rpathref;
while(strstr(rpath, "$ORIGIN")) {
char* origin = strdup(h->path);
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$ORIGIN"));
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
rpath = tmp;
free(origin);
box_free(origin);
}
while(strstr(rpath, "${ORIGIN}")) {
char* origin = strdup(h->path);
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
p = strstr(rpath, "${ORIGIN}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("${ORIGIN}"));
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
rpath = tmp;
free(origin);
box_free(origin);
}
while(strstr(rpath, "${PLATFORM}")) {
char* platform = strdup("x86_64");
char* platform = box_strdup("x86_64");
char* p = strrchr(platform, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
p = strstr(rpath, "${PLATFORM}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, platform);
strcat(tmp, p+strlen("${PLATFORM}"));
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
rpath = tmp;
free(platform);
box_free(platform);
}
if(strchr(rpath, '$')) {
printf_log(LOG_INFO, "BOX64: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
@@ -1102,7 +1102,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, lib
PrependList(&box64->box64_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
}
if(!h->neededlibs && neededlibs)
@@ -1145,6 +1145,26 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
return 0;
}
void RefreshElfTLS(elfheader_t* h)
{
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) {
// refresh in tlsdata too
dest = (char*)(ptr->data+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);
}
}
}
void MarkElfInitDone(elfheader_t* h)
{
if(h)
h->init_done = 1;
}
void RunElfInit(elfheader_t* h, x64emu_t *emu)
{
if(!h || h->init_done)
@@ -1153,29 +1173,19 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
uintptr_t p = h->initentry + h->delta;
box64context_t* context = GetEmuContext(emu);
// Refresh no-file part of TLS in case default value changed
RefreshElfTLS(h);
// check if in deferedInit
if(context->deferedInit) {
if(context->deferedInitSz==context->deferedInitCap) {
context->deferedInitCap += 4;
context->deferedInitList = (elfheader_t**)realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
context->deferedInitList = (elfheader_t**)box_realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
}
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);
h->init_done = 1;
if(h->initentry)
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
@@ -1188,7 +1198,6 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
}
}
h->init_done = 1;
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
return;
@@ -1209,7 +1218,7 @@ void RunDeferedElfInit(x64emu_t *emu)
context->deferedInitCap = context->deferedInitSz = 0;
for (int i=0; i<Sz; ++i)
RunElfInit(List[i], emu);
free(List);
box_free(List);
}
void RunElfFini(elfheader_t* h, x64emu_t *emu)
@@ -1257,7 +1266,7 @@ uint32_t GetBaseSize(elfheader_t* h)
return h->memsz;
}
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr)
int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
{
if(!h)
return 0;
@@ -1387,7 +1396,7 @@ void* GetTLSPointer(box64context_t* context, elfheader_t* h)
}
if(ptr->tlssize != context->tlssize)
ptr = (tlsdatasize_t*)resizeTLSData(context, ptr);
return ptr->tlsdata+(ptr->tlssize+h->tlsbase);
return ptr->data+h->tlsbase;
}
void* GetDynamicSection(elfheader_t* h)
@@ -1398,7 +1407,7 @@ void* GetDynamicSection(elfheader_t* h)
}
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr)
dynablock_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr)
{
(void)context;
// if we are here, the there is not block in standard "space"
@@ -1408,7 +1417,7 @@ dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t add
}*/
if(box64_dynarec_forced) {
addDBFromAddressRange(addr, 1);
return getDB(addr>>DYNAMAP_SHIFT);
return getDB(addr);
}
//check if address is in an elf... if yes, grant a block (should I warn)
Dl_info info;
@@ -1443,14 +1452,14 @@ GO(4)
// dl_iterate_phdr ...
#define GO(A) \
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)\
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box64 itself*/ \
return 0; \
return RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c) \
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box64 itself*/ \
return 0; \
return (int)RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
}
SUPER()
#undef GO
@@ -1575,6 +1584,25 @@ void ElfAttachLib(elfheader_t* head, library_t* lib)
head->lib = lib;
}
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->mapsymbols;
}
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->weaksymbols;
}
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->localsymbols;
}
typedef struct search_symbol_s{
const char* name;
void* addr;
+5 -4
View File
@@ -1,12 +1,9 @@
#ifndef __ELFLOADER_PRIVATE_H_
#define __ELFLOADER_PRIVATE_H_
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
#endif
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
#include <elf.h>
#include "elfloader.h"
@@ -95,6 +92,10 @@ struct elfheader_s {
library_t *lib;
needed_libs_t *neededlibs;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
};
#define R_X86_64_NONE 0 /* No reloc */
+73 -43
View File
@@ -23,7 +23,7 @@ int LoadSH(FILE *f, Elf64_Shdr *s, void** SH, const char* name, uint32_t type)
if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf64_Sym)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%ld, size=%ld) has size (not multiple of %ld)\n", name, s->sh_offset, s->sh_size, sizeof(Elf64_Sym));
}
*SH = calloc(1, s->sh_size);
*SH = box_calloc(1, s->sh_size);
fseeko64(f, s->sh_offset ,SEEK_SET);
if(fread(*SH, s->sh_size, 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%ld, size=%ld)\n", name, s->sh_offset, s->sh_size);
@@ -46,7 +46,7 @@ int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name)
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
if(n)
LoadSH(f, s+n, what, name, type);
if(type==SHT_SYMTAB || type==SHT_DYNSYM) {
@@ -73,7 +73,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(header.e_ident[EI_CLASS]!=ELFCLASS64) {
if(strstr(name, ".so")) {
// less naging on libs...
printf_log(LOG_DEBUG, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
printf_dump(LOG_DEBUG, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
return NULL;
}
if(header.e_ident[EI_CLASS]==ELFCLASS32) {
@@ -119,8 +119,8 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return NULL;
}
elfheader_t *h = calloc(1, sizeof(elfheader_t));
h->name = strdup(name);
elfheader_t *h = box_calloc(1, sizeof(elfheader_t));
h->name = box_strdup(name);
h->entrypoint = header.e_entry;
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
@@ -129,20 +129,20 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(header.e_shentsize && header.e_shnum) {
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of Sections in 1st Section\n");
// read 1st section header and grab actual number from here
fseeko64(f, header.e_shoff, SEEK_SET);
Elf64_Shdr section;
if(fread(&section, sizeof(Elf64_Shdr), 1, f)!=1) {
free(h);
box_free(h);
printf_log(LOG_INFO, "Cannot read Initial Section Header\n");
return NULL;
}
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_log(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries);
h->SHEntries = (Elf64_Shdr*)calloc(h->numSHEntries, sizeof(Elf64_Shdr));
printf_dump(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries);
h->SHEntries = (Elf64_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf64_Shdr));
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
FreeElfHeader(&h);
@@ -151,14 +151,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
}
if(h->numPHEntries == PN_XNUM) {
printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
// read 1st section header and grab actual number from here
h->numPHEntries = h->SHEntries[0].sh_info;
}
}
printf_log(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries);
h->PHEntries = (Elf64_Phdr*)calloc(h->numPHEntries, sizeof(Elf64_Phdr));
printf_dump(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries);
h->PHEntries = (Elf64_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf64_Phdr));
fseeko64(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
FreeElfHeader(&h);
@@ -168,7 +168,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(header.e_shentsize && header.e_shnum) {
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of String Table in 1st Section\n");
h->SHIdx = h->SHEntries[0].sh_link;
}
if(h->SHIdx > h->numSHEntries) {
@@ -177,7 +177,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return NULL;
}
// load Section table
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx);
printf_dump(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx);
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
FreeElfHeader(&h);
return NULL;
@@ -236,15 +236,15 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
break;
case DT_INIT: // Entry point
h->initentry = ptr;
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
printf_dump(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
break;
case DT_INIT_ARRAY:
h->initarray = ptr;
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
break;
case DT_INIT_ARRAYSZ:
h->initarray_sz = val / sizeof(Elf64_Addr);
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
@@ -252,31 +252,31 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
printf_dump(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
break;
case DT_FINI_ARRAY:
h->finiarray = ptr;
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
break;
case DT_FINI_ARRAYSZ:
h->finiarray_sz = val / sizeof(Elf64_Addr);
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz);
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz);
break;
case DT_VERNEEDNUM:
h->szVerNeed = val;
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
printf_dump(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
break;
case DT_VERNEED:
h->VerNeed = (Elf64_Verneed*)ptr;
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
printf_dump(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
break;
case DT_VERDEFNUM:
h->szVerDef = val;
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
printf_dump(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
break;
case DT_VERDEF:
h->VerDef = (Elf64_Verdef*)ptr;
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
}
}
@@ -286,7 +286,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "Rel Table @%p (0x%zx/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
printf_dump(LOG_DEBUG, "Rel Table @%p (0x%zx/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
}
if(h->rela) {
if(h->relaent != sizeof(Elf64_Rela)) {
@@ -294,7 +294,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "RelA Table @%p (0x%zx/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
printf_dump(LOG_DEBUG, "RelA Table @%p (0x%zx/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
}
if(h->jmprel) {
if(h->pltrel == DT_REL) {
@@ -311,7 +311,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
printf_dump(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
}
if(h->DynStrTab && h->szDynStrTab) {
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
@@ -322,43 +322,43 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
printf_dump(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
h->got_end = h->got + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
printf_dump(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt");
if(ii) {
h->plt = h->SHEntries[ii].sh_addr;
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
printf_dump(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// grab version of symbols
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
if(ii) {
h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
printf_dump(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
}
// grab .text for main code
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
if(ii) {
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->textsz = h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz);
printf_dump(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame");
if(ii) {
h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr");
if(ii) {
h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
@@ -370,19 +370,21 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
const char* GetSymbolVersion(elfheader_t* h, int version)
{
if(!h->VerNeed || (version<2))
if(version<2)
return NULL;
/*if(version==1)
return "*";*/
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
@@ -405,3 +407,31 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index)
}
return NULL;
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerNeed) {
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(!strcmp(h->DynStr+aux->vna_name, vername))
return aux->vna_other;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
if(h->VerDef) {
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
+49 -29
View File
@@ -1,38 +1,42 @@
#define F8 *(uint8_t*)(R_RIP++)
#define F8S *(int8_t*)(R_RIP++)
#define F16 *(uint16_t*)(R_RIP+=2, R_RIP-2)
#define F16S *(int16_t*)(R_RIP+=2, R_RIP-2)
#define F32 *(uint32_t*)(R_RIP+=4, R_RIP-4)
#define F32S *(int32_t*)(R_RIP+=4, R_RIP-4)
#define F8 *(uint8_t*)(addr++)
#define F8S *(int8_t*)(addr++)
#define F16 *(uint16_t*)(addr+=2, addr-2)
#define F16S *(int16_t*)(addr+=2, addr-2)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S *(int32_t*)(addr+=4, addr-4)
#define F32S64 (uint64_t)(int64_t)F32S
#define F64 *(uint64_t*)(R_RIP+=8, R_RIP-8)
#define F64S *(int64_t*)(R_RIP+=8, R_RIP-8)
#define PK(a) *(uint8_t*)(R_RIP+a)
#define F64 *(uint64_t*)(addr+=8, addr-8)
#define F64S *(int64_t*)(addr+=8, addr-8)
#define PK(a) *(uint8_t*)(addr+a)
#ifdef DYNAREC
#define STEP if(step) return 0;
#define STEP2 if(step) {R_RIP = addr; return 0;}
#define STEP3 if(*step) *(step)++;
#else
#define STEP
#define STEP2
#define STEP3
#endif
#define GETED(D) oped=GetEd(emu, rex, nextop, D)
#define GETED32(D) oped=GetEd32O(emu, rex, nextop, D, 0)
#define GETED_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGD opgd=GetGd(emu, rex, nextop)
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
#define GETEB32(D) oped=GetEb32O(emu, rex, nextop, D, 0)
#define GETEB_OFFS(D, O) oped=GetEbO(emu, rex, nextop, D, O)
#define GETGB opgd=GetGb(emu, rex, nextop)
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
#define GETEW32(D) oped=GetEw32O(emu, rex, nextop, D, 0)
#define GETEW_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGW opgd=GetGw(emu, rex, nextop)
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
#define GETEX32(D) opex=GetEx32O(emu, rex, nextop, D, 0)
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
#define GETGX opgx=GetGx(emu, rex, nextop)
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
#define GETEM32(D) opem=GetEm32O(emu, rex, nextop, D, 0)
#define GETGM opgm=GetGm(emu, rex, nextop)
#define GETED(D) oped=GetEd(emu, &addr, rex, nextop, D)
#define GETED32(D) oped=GetEd32O(emu, &addr, rex, nextop, D, 0)
#define GETED_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O)
#define GETGD opgd=GetGd(emu, &addr, rex, nextop)
#define GETEB(D) oped=GetEb(emu, &addr, rex, nextop, D)
#define GETEB32(D) oped=GetEb32O(emu, &addr, rex, nextop, D, 0)
#define GETEB_OFFS(D, O) oped=GetEbO(emu, &addr, rex, nextop, D, O)
#define GETGB opgd=GetGb(emu, &addr, rex, nextop)
#define GETEW(D) oped=GetEw(emu, &addr, rex, nextop, D)
#define GETEW32(D) oped=GetEw32O(emu, &addr, rex, nextop, D, 0)
#define GETEW_OFFS(D, O) oped=GetEdO(emu, &addr, rex, nextop, D, O)
#define GETGW opgd=GetGw(emu, &addr, rex, nextop)
#define GETEX(D) opex=GetEx(emu, &addr, rex, nextop, D)
#define GETEX32(D) opex=GetEx32O(emu, &addr, rex, nextop, D, 0)
#define GETEX_OFFS(D, O) opex=GetExO(emu, &addr, rex, nextop, D, O)
#define GETGX opgx=GetGx(emu, &addr, rex, nextop)
#define GETEM(D) opem=GetEm(emu, &addr, rex, nextop, D)
#define GETEM32(D) opem=GetEm32O(emu, &addr, rex, nextop, D, 0)
#define GETGM opgm=GetGm(emu, &addr, rex, nextop)
#define ED oped
#define GD opgd
#define EB oped
@@ -46,7 +50,7 @@
#define MODREG ((nextop&0xC0)==0xC0)
#define GOCOND(BASE, PREFIX, COND, NOTCOND) \
#define GOCOND(BASE, PREFIX, COND, NOTCOND, POST)\
case BASE+0x0: \
PREFIX \
if(ACCESS_FLAG(F_OF)) { \
@@ -54,6 +58,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x1: \
PREFIX \
@@ -62,6 +67,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x2: \
PREFIX \
@@ -70,6 +76,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x3: \
PREFIX \
@@ -78,6 +85,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x4: \
PREFIX \
@@ -86,6 +94,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x5: \
PREFIX \
@@ -94,6 +103,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x6: \
PREFIX \
@@ -102,6 +112,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x7: \
PREFIX \
@@ -110,6 +121,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x8: \
PREFIX \
@@ -118,6 +130,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0x9: \
PREFIX \
@@ -126,6 +139,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xA: \
PREFIX \
@@ -134,6 +148,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xB: \
PREFIX \
@@ -142,6 +157,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xC: \
PREFIX \
@@ -150,6 +166,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xD: \
PREFIX \
@@ -158,6 +175,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xE: \
PREFIX \
@@ -166,6 +184,7 @@
} else { \
NOTCOND \
} \
POST \
break; \
case BASE+0xF: \
PREFIX \
@@ -174,4 +193,5 @@
} else { \
NOTCOND \
} \
POST \
break;
+9 -9
View File
@@ -89,7 +89,7 @@ x64emu_t *NewX64Emu(box64context_t *context, uintptr_t start, uintptr_t stack, i
{
printf_log(LOG_DEBUG, "Allocate a new X86_64 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
x64emu_t *emu = (x64emu_t*)calloc(1, sizeof(x64emu_t));
x64emu_t *emu = (x64emu_t*)box_calloc(1, sizeof(x64emu_t));
internalX64Setup(emu, context, start, stack, stacksize, ownstack);
@@ -135,7 +135,7 @@ void AddCleanup(x64emu_t *emu, void *p)
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 0;
my_context->cleanups[my_context->clean_sz].a = NULL;
@@ -148,7 +148,7 @@ void AddCleanup1Arg(x64emu_t *emu, void *p, void* a)
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 1;
my_context->cleanups[my_context->clean_sz].a = a;
@@ -178,7 +178,7 @@ void CallAllCleanup(x64emu_t *emu)
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
}
my_context->clean_sz = 0;
free(my_context->cleanups);
box_free(my_context->cleanups);
my_context->cleanups = NULL;
}
@@ -197,7 +197,7 @@ void FreeX64Emu(x64emu_t **emu)
internalFreeX64(*emu);
free(*emu);
box_free(*emu);
*emu = NULL;
}
@@ -224,10 +224,9 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
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;
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
newemu->sw = emu->sw;
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
memcpy(&newemu->round, &emu->round, sizeof(emu->round));
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
@@ -441,8 +440,9 @@ void UnimpOpcode(x64emu_t* emu)
R_RIP = emu->old_ip;
int tid = syscall(SYS_gettid);
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
tid, (void*)emu->old_ip, Peek(emu, -1),
printf_log(LOG_NONE, "%04d|%p: Unimplemented Opcode (%02X %02X %02X %02X) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
tid, (void*)emu->old_ip,
Peek(emu, -4), Peek(emu, -3), Peek(emu, -2), Peek(emu, -1),
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7),
Peek(emu, 8), Peek(emu, 9), Peek(emu,10), Peek(emu,11),
+5 -2
View File
@@ -35,12 +35,11 @@ typedef struct x64emu_s {
// fpu / mmx
mmx87_regs_t x87[8];
mmx87_regs_t mmx[8];
uint16_t cw;
x87control_t cw;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
uint32_t mxcsr;
fpu_round_t round;
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
@@ -52,6 +51,9 @@ typedef struct x64emu_s {
multiuint_t op1;
multiuint_t op2;
multiuint_t res;
multiuint_t op1_sav; // for dec/inc defered flags, to be able to compute CF
multiuint_t res_sav;
defered_flags_t df_sav;
uint32_t *x64emu_parity_tab; // helper
#ifdef HAVE_TRACE
reg64_t oldregs[16];
@@ -73,6 +75,7 @@ typedef struct x64emu_s {
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int quitonexit; // quit if exit/_exit is called
int longjmp; // if quit because of longjmp
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint64_t scratch[200];
+73 -18
View File
@@ -65,38 +65,55 @@ x64emu_t* x64emu_fork(x64emu_t* emu, int forktype)
return emu;
}
extern int errno;
void x64Int3(x64emu_t* emu)
static uint64_t F64(uintptr_t* addr) {
uint64_t ret = *(uint64_t*)*addr;
*addr+=8;
return ret;
}
static uint8_t Peek8(uintptr_t addr, uintptr_t offset)
{
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
return *(uint8_t*)(addr+offset);
}
extern int errno;
void x64Int3(x64emu_t* emu, uintptr_t* addr)
{
if(Peek8(*addr, 0)=='S' && Peek8(*addr, 1)=='C') // Signature for "Out of x86 door"
{
R_RIP += 2;
uintptr_t addr = Fetch64(emu);
if(addr==0) {
*addr += 2;
uintptr_t a = F64(addr);
if(a==0) {
R_RIP = *addr;
//printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
emu->quit=1; // normal quit
} else {
RESET_FLAGS(emu);
wrapper_t w = (wrapper_t)addr;
addr = Fetch64(emu);
wrapper_t w = (wrapper_t)a;
a = F64(addr);
R_RIP = *addr;
/* This party can be used to trace only 1 specific lib (but it is quite slow)
elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
int have_trace = 0;
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box64_log>=LOG_DEBUG /*|| have_trace*/) {
if(box64_log>=LOG_DEBUG || cycle_log) {
pthread_mutex_lock(&emu->context->mutex_trace);
int tid = GetTID();
char buff[256] = "\0";
char t_buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
char* buff = cycle_log?my_context->log_call[my_context->current_line]:t_buff;
char* buffret = cycle_log?my_context->log_ret[my_context->current_line]:NULL;
if(buffret) buffret[0] = '\0';
if(cycle_log)
my_context->current_line = (my_context->current_line+1)%cycle_log;
char *tmp;
int post = 0;
int perr = 0;
uint64_t *pu64 = NULL;
uint32_t *pu32 = NULL;
const char *s = NULL;
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
s = GetNativeName((void*)a);
if(a==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", cycle_log?"PltResolver ":" ... ");
} else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ") || !strcmp(s, "open64")) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
@@ -113,6 +130,10 @@ void x64Int3(x64emu_t* emu)
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
perr = 1;
} else if (strstr(s, "readlink")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p, %zd)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (void*)(R_RSI), (size_t)R_RDX);
perr = 1;
} else if (strstr(s, "mkdir")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
@@ -125,18 +146,29 @@ void x64Int3(x64emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
perr = 1;
} else if (!strcmp(s, "write")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
if(R_EDI==2 || R_EDI==3)
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p\"%s\", %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, (char*)R_RSI, R_RDX);
else
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
perr = 1;
} else if (strstr(s, "access")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
perr = 1;
} else if (strstr(s, "waitpid")==s) {
pu32 = (uint32_t*)R_RSI;
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %d)", tid, *(void**)(R_RSP), s, R_EDI, pu32, R_EDX);
perr = 1;
post = 6;
} else if (!strcmp(s, "lseek64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
perr = 1;
} else if (!strcmp(s, "lseek")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
perr = 1;
} else if (!strcmp(s, "recvmsg")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_EDX);
perr = 1;
} else if (strstr(s, "puts")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
@@ -148,7 +180,10 @@ void x64Int3(x64emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)R_RSI);
} else if (strstr(s, "getenv")==s) {
tmp = (char*)(R_RDI);
post = 2;
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
} else if (strstr(s, "setenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %d)", tid, *(void**)(R_RSP), s, (char*)R_RDI, (char*)R_RSI, R_EDX);
} else if (!strcmp(s, "poll")) {
struct pollfd* pfd = (struct pollfd*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
@@ -181,6 +216,8 @@ void x64Int3(x64emu_t* emu)
} else if (!strcmp(s, "glGetStringi")) {
post = 2;
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
} else if (!strcmp(s, "_dl_tlsdesc_undefweak")) {
snprintf(buff, 255, "%04d|%p: Calling %s(RAX=%p)", tid, *(void**)(R_RSP), s, (void*)R_RAX);
} else if (!strcmp(s, "glFramebufferTexture2D")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, 0x%x, 0x%x, %u, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d);
} else if (!strcmp(s, "glTexSubImage2D")) {
@@ -209,9 +246,9 @@ void x64Int3(x64emu_t* emu)
} else {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
}
printf_log(LOG_NONE, "%s =>", buff);
if(!cycle_log) printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
w(emu, addr); // some function never come back, so unlock the mutex first!
w(emu, a); // some function never come back, so unlock the mutex first!
pthread_mutex_lock(&emu->context->mutex_trace);
if(post)
switch(post) { // Only ever 2 for now...
@@ -231,15 +268,20 @@ void x64Int3(x64emu_t* emu)
snprintf(buff2, 63, "NULL Surface");
}
break;
case 6: if(pu32) snprintf(buff2, 63, " [0x%x] ", pu32[0]);
break;
}
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==2 && R_EAX==0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
printf_log(LOG_NONE, " return 0x%lX%s%s\n", R_RAX, buff2, buff3);
if(cycle_log)
snprintf(buffret, 127, "0x%lX%s%s", R_RAX, buff2, buff3);
else
printf_log(LOG_NONE, " return 0x%lX%s%s\n", R_RAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
w(emu, addr);
w(emu, a);
}
return;
}
@@ -254,3 +296,16 @@ int GetTID()
{
return syscall(SYS_gettid);
}
void print_cycle_log(int loglevel) {
if(cycle_log) {
printf_log(LOG_INFO, "Last calls\n");
int j = (my_context->current_line+1)%cycle_log;
for (int i=0; i<cycle_log; ++i) {
int k = (i+j)%cycle_log;
if(my_context->log_call[k][0]) {
printf_log(loglevel, "%s => return %s\n", my_context->log_call[k], my_context->log_ret[k]);
}
}
}
}
+30 -12
View File
@@ -89,88 +89,106 @@ uint64_t cmp64 (x64emu_t *emu, uint64_t d, uint64_t s);
uint8_t daa8 (x64emu_t *emu, uint8_t d);
uint8_t das8 (x64emu_t *emu, uint8_t d);
#define CF_SAV() \
if(emu->df>=d_dec8 && emu->df<=d_inc64) { \
emu->df_sav = d_none; \
} else if(emu->df<d_dec8i || emu->df>d_inc64i) {\
emu->df_sav = emu->df; \
emu->op1_sav = emu->op1; \
emu->res_sav = emu->res; \
}
static inline uint8_t dec8(x64emu_t *emu, uint8_t d)
{
CF_SAV();
emu->res.u8 = d - 1;
emu->op1.u8 = d;
emu->df = d_dec8;
emu->df = d_dec8i;
return emu->res.u8;
}
static inline uint16_t dec16(x64emu_t *emu, uint16_t d)
{
CF_SAV();
emu->res.u16 = d - 1;
emu->op1.u16 = d;
emu->df = d_dec16;
emu->df = d_dec16i;
return emu->res.u16;
}
static inline uint32_t dec32(x64emu_t *emu, uint32_t d)
{
CF_SAV();
emu->res.u32 = d - 1;
emu->op1.u32 = d;
emu->df = d_dec32;
emu->df = d_dec32i;
return emu->res.u32;
}
static inline uint64_t dec64(x64emu_t *emu, uint64_t d)
{
CF_SAV();
emu->res.u64 = d - 1;
emu->op1.u64 = d;
emu->df = d_dec64;
emu->df = d_dec64i;
return emu->res.u64;
}
static inline uint8_t inc8(x64emu_t *emu, uint8_t d)
{
CF_SAV();
emu->res.u8 = d + 1;
emu->op1.u8 = d;
emu->df = d_inc8;
emu->df = d_inc8i;
return emu->res.u8;
}
static inline uint16_t inc16(x64emu_t *emu, uint16_t d)
{
CF_SAV();
emu->res.u16 = d + 1;
emu->op1.u16 = d;
emu->df = d_inc16;
emu->df = d_inc16i;
return emu->res.u16;
}
static inline uint32_t inc32(x64emu_t *emu, uint32_t d)
{
if(emu->df == d_shr32) {
/*if(emu->df == d_shr32) {
// workaround for some wine trickery
uint32_t cnt = emu->op2.u32;
if (cnt > 0) {
uint32_t cc = emu->op1.u32 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
}*/
CF_SAV();
emu->res.u32 = d + 1;
emu->op1.u32 = d;
emu->df = d_inc32;
emu->df = d_inc32i;
return emu->res.u32;
}
static inline uint64_t inc64(x64emu_t *emu, uint64_t d)
{
if(emu->df == d_shr64) {
/*if(emu->df == d_shr64) {
// workaround for some wine trickery
uint64_t cnt = emu->op2.u64;
if (cnt > 0) {
uint64_t cc = emu->op1.u64 & (1LL << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
}*/
CF_SAV();
emu->res.u64 = d + 1;
emu->op1.u64 = d;
emu->df = d_inc64;
emu->df = d_inc64i;
return emu->res.u64;
}
#undef CF_SAV
static inline uint8_t or8(x64emu_t *emu, uint8_t d, uint8_t s)
{
+106 -81
View File
@@ -40,33 +40,34 @@ int Run(x64emu_t *emu, int step)
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3;
uintptr_t addr = R_RIP;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int unimp = 0;
if(emu->quit)
return 0;
if(R_RIP==0) {
if(addr==0) {
emu->quit = 1;
printf_log(LOG_INFO, "Ask to run at NULL, quit silently\n");
printf_log(LOG_INFO, "%04d|Ask to run at NULL, quit silently\n", GetTID());
print_cycle_log(LOG_INFO);
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);
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_RSP);
x64emurun:
while(1) {
#ifdef HAVE_TRACE
__builtin_prefetch((void*)R_RIP, 0, 0);
__builtin_prefetch((void*)addr, 0, 0);
emu->prev2_ip = emu->old_ip;
if(my_context->dec && (
(trace_end == 0)
|| ((R_RIP >= trace_start) && (R_RIP < trace_end))) )
PrintTrace(emu, R_RIP, 0);
|| ((addr >= trace_start) && (addr < trace_end))) )
PrintTrace(emu, addr, 0);
#endif
emu->old_ip = R_RIP;
emu->old_ip = addr;
opcode = F8;
@@ -135,26 +136,30 @@ x64emurun:
case 0x0F: /* More instructions */
switch(rep) {
case 1:
if(RunF20F(emu, rex)) {
if(!(addr = RunF20F(emu, rex, addr, &step))) {
unimp = 1;
goto fini;
}
if(step==2) STEP2;
break;
case 2:
if(RunF30F(emu, rex)) {
if(!(addr = RunF30F(emu, rex, addr))) {
unimp = 1;
goto fini;
}
break;
default:
if(Run0F(emu, rex)) {
if(!(addr = Run0F(emu, rex, addr, &step))) {
unimp = 1;
goto fini;
}
if(step==2) STEP2;
break;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
@@ -250,36 +255,44 @@ x64emurun:
GD->sdword[0] = ED->sdword[0]; // meh?
break;
case 0x64: /* FS: prefix */
if(Run64(emu, rex, _FS)) {
if(!(addr = Run64(emu, rex, _FS, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0x65: /* GS: prefix */
if(Run64(emu, rex, _GS)) {
if(!(addr = Run64(emu, rex, _GS, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0x66: /* 16bits prefix */
if(Run66(emu, rex, rep)) {
if(!(addr = Run66(emu, rex, rep, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0x67: /* reduce EASize prefix */
if(Run67(emu, rex, rep)) {
if(!(addr = Run67(emu, rex, rep, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0x68: /* Push Id */
Push(emu, F32S64);
@@ -313,15 +326,14 @@ x64emurun:
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);
, R_RIP += tmp8s;
,
, addr += tmp8s;
,,STEP2
) /* Jxx Ib */
case 0x80: /* GRP Eb,Ib */
@@ -1027,13 +1039,13 @@ x64emurun:
break;
case 0xC2: /* RETN Iw */
tmp16u = F16;
R_RIP = Pop(emu);
addr = Pop(emu);
R_RSP += tmp16u;
STEP
STEP2
break;
case 0xC3: /* RET */
R_RIP = Pop(emu);
STEP
addr = Pop(emu);
STEP2
break;
case 0xC6: /* MOV Eb,Ib */
@@ -1073,19 +1085,19 @@ x64emurun:
break;
case 0xCC: /* INT 3 */
x64Int3(emu);
if(emu->quit) goto fini;
x64Int3(emu, &addr);
if(emu->quit) goto fini; // R_RIP is up to date when returning from x64Int3
addr = R_RIP;
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);
addr = 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
@@ -1094,6 +1106,7 @@ x64emurun:
emu->segs_serial[_SS] = 0;
R_RSP= tmp64u;
RESET_FLAGS(emu);
R_RIP = addr;
goto fini; // exit, to recompute CS if needed
break;
case 0xD0: /* GRP2 Eb,1 */
@@ -1158,145 +1171,160 @@ x64emurun:
R_AL = *(uint8_t*)(R_RBX + R_AL);
break;
case 0xD8: /* x87 opcodes */
if(RunD8(emu, rex)) {
if(!(addr = RunD8(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xD9: /* x87 opcodes */
if(RunD9(emu, rex)) {
if(!(addr = RunD9(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDA: /* x87 opcodes */
if(RunDA(emu, rex)) {
if(!(addr = RunDA(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDB: /* x87 opcodes */
if(RunDB(emu, rex)) {
if(!(addr = RunDB(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDC: /* x87 opcodes */
if(RunDC(emu, rex)) {
if(!(addr = RunDC(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDD: /* x87 opcodes */
if(RunDD(emu, rex)) {
if(!(addr = RunDD(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDE: /* x87 opcodes */
if(RunDE(emu, rex)) {
if(!(addr = RunDE(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xDF: /* x87 opcodes */
if(RunDF(emu, rex)) {
if(!(addr = RunDF(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX && !ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
STEP
addr += tmp8s;
STEP2
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX && ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
STEP
addr += tmp8s;
STEP2
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX)
R_RIP += tmp8s;
STEP
addr += tmp8s;
STEP2
break;
case 0xE3: /* JECXZ */
case 0xE3: /* JRCXZ */
tmp8s = F8S;
if(!R_RCX)
R_RIP += tmp8s;
STEP
addr += tmp8s;
STEP2
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);
R_RIP += tmp32s;
STEP
Push(emu, addr);
addr += tmp32s;
STEP2
break;
case 0xE9: /* JMP Id */
tmp32s = F32S; // jmp is relative
R_RIP += tmp32s;
STEP
addr += tmp32s;
STEP2
break;
case 0xEB: /* JMP Ib */
tmp32s = F8S; // jump is relative
R_RIP += tmp32s;
STEP
addr += tmp32s;
STEP2
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)) {
if(!(addr = RunF0(emu, rex, addr))) {
unimp = 1;
goto fini;
}
if(emu->quit)
if(emu->quit) {
R_RIP = addr;
goto fini;
}
break;
case 0xF4: /* HLT */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
@@ -1414,13 +1442,11 @@ x64emurun:
break;
case 0xFA: /* CLI */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
case 0xFB: /* STI */
// this is a privilege opcode...
--R_RIP;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
STEP;
break;
@@ -1471,32 +1497,30 @@ x64emurun:
break;
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
Push(emu, R_RIP);
R_RIP = tmp64u;
STEP
Push(emu, addr);
addr = tmp64u;
STEP2
break;
case 3: /* CALL FAR Ed */
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 {
Push(emu, R_CS);
Push(emu, R_RIP);
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]); // check CS?
Push(emu, addr);
R_RIP = addr = (uintptr_t)getAlternate((void*)ED->q[0]); // check CS?
R_CS = (ED+1)->word[0];
goto fini; // exit loop to recompute new CS...
}
break;
case 4: /* JMP NEAR Ed */
R_RIP = (uintptr_t)getAlternate((void*)ED->q[0]);
STEP
addr = (uintptr_t)getAlternate((void*)ED->q[0]);
STEP2
break;
case 5: /* JMP FAR Ed */
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;
@@ -1512,7 +1536,6 @@ x64emurun:
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;
@@ -1523,18 +1546,19 @@ x64emurun:
unimp = 1;
goto fini;
}
R_RIP = addr;
}
fini:
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_RIP, (void*)R_RSP, unimp, emu->fork, emu->uc_link, emu->quit);
if(unimp) {
R_RIP = emu->old_ip;
emu->quit = 1;
UnimpOpcode(emu);
}
// fork handling
if(emu->fork) {
addr = R_RIP;
if(step)
return 0;
int forktype = emu->fork;
@@ -1547,6 +1571,7 @@ fini:
else if(emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
addr = R_RIP;
goto x64emurun;
}
return 0;
+40 -21
View File
@@ -28,7 +28,7 @@
#include "modrm.h"
int Run0F(x64emu_t *emu, rex_t rex)
uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
{
uint8_t opcode;
uint8_t nextop;
@@ -46,18 +46,17 @@ int Run0F(x64emu_t *emu, rex_t rex)
switch(opcode) {
case 0x05: /* SYSCALL */
R_RIP = addr;
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;
@@ -73,7 +72,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
__builtin_prefetch((void*)ED, 1, 0);
break;
default: //???
return 1;
return 0;
}
break;
@@ -159,7 +158,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
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;
@@ -306,8 +304,27 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
break;
case 0xF0: /* MOVBE Gd, Ed*/
nextop = F8;
GETGD;
GETED(0);
if(rex.w)
GD->q[0] = __builtin_bswap64(ED->q[0]);
else
GD->q[0] = __builtin_bswap32(ED->dword[0]);
break;
case 0xF1: /* MOVBE Ed, Gd*/
nextop = F8;
GETGD;
GETED(0);
if(rex.w)
ED->q[0] = __builtin_bswap64(GD->q[0]);
else
ED->q[0] = __builtin_bswap32(GD->dword[0]);
break;
default:
return 1;
return 0;
}
break;
@@ -333,7 +350,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
break;
@@ -345,6 +362,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
CHECK_FLAGS(emu);
, if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->q[0] = ED->dword[0];}
, if(!rex.w) GD->dword[1] = 0;
,
) /* 0x40 -> 0x4F CMOVxx Gd,Ed */ // conditional move, no sign
case 0x50: /* MOVMSKPS Gd, Ex */
@@ -648,7 +666,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
for (int i=0; i<4; ++i) EM->uw[i] <<= tmp8u;
break;
default:
return 1;
return 0;
}
break;
case 0x72: /* GRP */
@@ -674,7 +692,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
for (int i=0; i<2; ++i) EM->ud[i] <<= tmp8u;
break;
default:
return 1;
return 0;
}
break;
case 0x73: /* GRP */
@@ -696,7 +714,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
{EM->q <<= tmp8u;}
break;
default:
return 1;
return 0;
}
break;
case 0x74: /* PCMPEQB Gm,Em */
@@ -750,14 +768,15 @@ int Run0F(x64emu_t *emu, rex_t rex)
break;
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, R_RIP += tmp32s;
,
, addr += tmp32s;
,,STEP3
) /* 0x80 -> 0x8F Jxx */
GOCOND(0x90
, nextop = F8; CHECK_FLAGS(emu);
GETEB(0);
, EB->byte[0]=1;
, EB->byte[0]=0;
,
) /* 0x90 -> 0x9F SETxx Eb */
case 0xA2: /* CPUID */
@@ -855,13 +874,13 @@ int Run0F(x64emu_t *emu, rex_t rex)
case 0xAE: /* Grp Ed (SSE) */
nextop = F8;
if((nextop&0xF8)==0xE8) {
return 0; /* LFENCE */
return addr; /* LFENCE */
}
if((nextop&0xF8)==0xF0) {
return 0; /* MFENCE */
return addr; /* MFENCE */
}
if((nextop&0xF8)==0xF8) {
return 0; /* SFENCE */
return addr; /* SFENCE */
}
GETED(0);
switch((nextop>>3)&7) {
@@ -889,7 +908,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
#endif
break;
default:
return 1;
return 0;
}
break;
case 0xAF: /* IMUL Gd,Ed */
@@ -1061,7 +1080,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
break;
case 0xBB: /* BTC Ed,Gd */
@@ -1287,7 +1306,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
break;
default:
return 1;
return 0;
}
break;
case 0xC8:
@@ -1476,7 +1495,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
case 0xE7: /* MOVNTQ Em,Gm */
nextop = F8;
if((nextop&0xC0)==0xC0)
return 1;
return 0;
GETEM(0);
GETGM;
EM->q = GM->q;
@@ -1629,7 +1648,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+34 -20
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run64(x64emu_t *emu, rex_t rex, int seg)
uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -49,6 +49,10 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
rep = opcode-0xF1;
opcode = F8;
}
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
#define GO(B, OP) \
@@ -131,7 +135,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
}
break;
default:
return 1;
return 0;
}
break;
case 0x11:
@@ -155,7 +159,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
EX->ud[0] = GX->ud[0];
break;
default:
return 1;
return 0;
}
break;
@@ -169,10 +173,10 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
EX->q[1] = GX->q[1];
break;
default:
return 1;
return 0;
}
break;
case 0x59:
switch(rep) {
case 2: /* MULSS Gx, Ex */
@@ -183,7 +187,20 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
break;
default:
return 1;
return 0;
}
break;
case 0x5A:
switch(rep) {
case 2: /* CVTSS2SD Gx, Ex */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
GX->d[0] = EX->f[0];
break;
default:
return 0;
}
break;
@@ -197,7 +214,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
break;
default:
return 1;
return 0;
}
break;
@@ -219,7 +236,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
break;
default:
return 1;
return 0;
}
break;
@@ -264,7 +281,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
break;
case 0x66:
return Run6664(emu, rex);
return Run6664(emu, rex, addr);
case 0x80: /* GRP Eb,Ib */
nextop = F8;
@@ -521,36 +538,34 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
break;
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
Push(emu, R_RIP);
R_RIP = tmp64u;
Push(emu, addr);
addr = 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];
Push(emu, addr);
R_RIP = addr = 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]);
addr = (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_RIP = addr = ED->q[0];
R_CS = (ED+1)->word[0];
return 0; // exit loop to recompute CS...
}
@@ -560,7 +575,6 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
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;
@@ -568,7 +582,7 @@ int Run64(x64emu_t *emu, rex_t rex, int seg)
}
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+18 -14
View File
@@ -25,7 +25,7 @@
#include "modrm.h"
int Run66(x64emu_t *emu, rex_t rex, int rep)
uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -105,7 +105,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
case 0x0F: /* more opcdes */
return Run660F(emu, rex);
return Run660F(emu, rex, addr);
case 0x39:
nextop = F8;
@@ -133,7 +133,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
break;
case 0x64: /* FS: */
return Run6664(emu, rex);
return Run6664(emu, rex, addr);
case 0x69: /* IMUL Gw,Ew,Iw */
nextop = F8;
@@ -178,8 +178,8 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
case 0x7e:
case 0x7f:
// just ignore the 66 (and maybe other) prefix and use regular conditional jump
R_RIP--;
return 0;
addr--;
return addr;
case 0x81: /* GRP3 Ew,Iw */
case 0x83: /* GRP3 Ew,Ib */
@@ -607,19 +607,19 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
break;
case 0xD9: /* x87 opcdes */
return Run66D9(emu, rex);
return Run66D9(emu, rex, addr);
case 0xDD: /* x87 opcdes */
return Run66DD(emu, rex);
return Run66DD(emu, rex, addr);
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_RIP);
R_RIP += tmp32s;
Push(emu, addr);
addr += tmp32s;
break;
case 0xF0: /* LOCK: */
return Run66F0(emu, rex);
return Run66F0(emu, rex, addr);
case 0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
@@ -697,11 +697,15 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
case 1: /* DEC Ed */
EW->word[0] = dec16(emu, EW->word[0]);
break;
/*case 6:
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
Push(emu, addr);
addr = tmp64u;
break;
/*case 6:
Push16(emu, EW->word[0]);
break;*/
default:
R_RIP = emu->old_ip;
printf_log(LOG_NONE, "Illegal Opcode %p: 66 %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;
@@ -710,7 +714,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+113 -15
View File
@@ -43,7 +43,7 @@ static uint8_t ff_mult(uint8_t a, uint8_t b)
return retval;
}
int Run660F(x64emu_t *emu, rex_t rex)
uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -347,6 +347,16 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0x10: /* PBLENDVB Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i) {
if(emu->xmm[0].ub[i]&0x80)
GX->ub[i] = EX->ub[i];
}
break;
case 0x14: /* BLENDVPS Gx, Ex */
nextop = F8;
GETEX(0);
@@ -477,6 +487,14 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->q[i] = EX->ud[i];
break;
case 0x38: /* PMINSB Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
if(GX->sb[i]>EX->sb[i])
GX->sb[i] = EX->sb[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GETEX(0);
@@ -490,10 +508,25 @@ int Run660F(x64emu_t *emu, rex_t rex)
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
if(GX->uw[i]<EX->uw[i])
if(GX->uw[i]>EX->uw[i])
GX->uw[i] = EX->uw[i];
break;
case 0x3B: /* PMINUD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->ud[i]>EX->ud[i])
GX->ud[i] = EX->ud[i];
break;
case 0x3C: /* PMAXSB Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
if(GX->sb[i]<EX->sb[i])
GX->sb[i] = EX->sb[i];
break;
case 0x3D: /* PMAXSD Gx, Ex */
nextop = F8;
GETEX(0);
@@ -502,6 +535,22 @@ int Run660F(x64emu_t *emu, rex_t rex)
if(GX->sd[i]<EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0x3E: /* PMAXUW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
if(GX->uw[i]<EX->uw[i])
GX->uw[i] = EX->uw[i];
break;
case 0x3F: /* PMAXUD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->ud[i]<EX->ud[i])
GX->ud[i] = EX->ud[i];
break;
case 0xDB: /* AESIMC Gx, Ex */
nextop = F8;
@@ -606,7 +655,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
break;
@@ -758,6 +807,25 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
break;
case 0x44: /* PCLMULQDQ Gx, Ex, Ib */
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
{
int g = (tmp8u&1)?1:0;
int e = (tmp8u&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
break;
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
nextop = F8;
GETEX(1);
@@ -780,7 +848,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
break;
@@ -790,7 +858,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
GETEW(0);
GETGW;
, if(rex.w) GW->q[0] = EW->q[0]; else GW->word[0] = EW->word[0];
,
,,
) /* 0x40 -> 0x4F CMOVxx Gw,Ew */ // conditional move, no sign
case 0x50: /* MOVMSKPD Gd, Ex */
@@ -1156,7 +1224,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
for (int i=0; i<8; ++i) EX->uw[i] <<= tmp8u;
break;
default:
return 1;
return 0;
}
break;
case 0x72: /* GRP */
@@ -1185,7 +1253,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
for (int i=0; i<4; ++i) EX->ud[i] <<= tmp8u;
break;
default:
return 1;
return 0;
}
break;
case 0x73: /* GRP */
@@ -1237,7 +1305,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
default:
return 1;
return 0;
}
break;
case 0x74: /* PCMPEQB Gx,Ex */
@@ -1287,7 +1355,31 @@ int Run660F(x64emu_t *emu, rex_t rex)
#endif
}
break;
case 0x7D: /* HSUBPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
#ifndef NOALIGN
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
#endif
GX->d[0] -= GX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
#endif
if(EX==GX) {
GX->d[1] = GX->d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX->d[1] = EX->d[0] - EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
#endif
}
break;
case 0x7E: /* MOVD Ed, Gx */
nextop = F8;
GETED(0);
@@ -1550,7 +1642,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
default:
return 1;
return 0;
}
break;
case 0xBB: /* BTC Ew,Gw */
@@ -1718,7 +1810,13 @@ int Run660F(x64emu_t *emu, rex_t rex)
emu->regs[tmp8u].word[0] = __builtin_bswap16(emu->regs[tmp8u].word[0]);
}
break;
case 0xD0: /* ADDSUBPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] -= EX->d[0];
GX->d[1] += EX->d[1];
break;
case 0xD1: /* PSRLW Gx, Ex */
nextop = F8;
GETEX(0);
@@ -1780,7 +1878,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
if(EX->ub[i]&0x80)
GD->dword[0] |= (1<<i);
} else
return 1;
return 0;
break;
case 0xD8: /* PSUBUSB Gx,Ex */
nextop = F8;
@@ -2099,7 +2197,7 @@ int Run660F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+31 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run6664(x64emu_t *emu, rex_t rex)
uintptr_t Run6664(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -43,6 +43,33 @@ int Run6664(x64emu_t *emu, rex_t rex)
case 0x0F:
opcode = F8;
switch(opcode) {
case 0x11: /* MOVUPD Ex, Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
memcpy(EX, GX, 16); // unaligned...
break;
case 0x2E: /* UCOMISD Gx, Ex */
// no special check...
case 0x2F: /* COMISD Gx, Ex */
RESET_FLAGS(emu);
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
if(isnan(GX->d[0]) || isnan(EX->d[0])) {
SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF);
} else if(isgreater(GX->d[0], EX->d[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
} else if(isless(GX->d[0], EX->d[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); SET_FLAG(F_CF);
} else {
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
}
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0xD6: /* MOVQ Ex,Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
@@ -53,7 +80,7 @@ int Run6664(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
break;
@@ -78,7 +105,7 @@ int Run6664(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+4 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run66D9(x64emu_t *emu, rex_t rex)
uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -73,7 +73,7 @@ int Run66D9(x64emu_t *emu, rex_t rex)
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
@@ -87,8 +87,8 @@ int Run66D9(x64emu_t *emu, rex_t rex)
fpu_savenv(emu, (char*)ED, 1);
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+4 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run66DD(x64emu_t *emu, rex_t rex)
uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -73,7 +73,7 @@ int Run66DD(x64emu_t *emu, rex_t rex)
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
@@ -105,8 +105,8 @@ int Run66DD(x64emu_t *emu, rex_t rex)
reset_fpu(emu);
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+47 -5
View File
@@ -25,7 +25,7 @@
#include "modrm.h"
int Run66F0(x64emu_t *emu, rex_t rex)
uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -43,7 +43,7 @@ int Run66F0(x64emu_t *emu, rex_t rex)
opcode = F8;
}
if(rex.w) return RunF0(emu, rex);
if(rex.w) return RunF0(emu, rex, addr);
switch(opcode) {
@@ -78,8 +78,50 @@ int Run66F0(x64emu_t *emu, rex_t rex)
#endif
break;
case 0xC1: /* XADD Gw,Ew */
nextop = F8;
GETEW(0);
GETGW;
#ifdef DYNAREC
if(rex.w) {
do {
tmp64u = native_lock_read_dd(ED);
tmp64u2 = add64(emu, tmp64u, GD->q[0]);
} while(native_lock_write_dd(ED, tmp64u2));
GD->q[0] = tmp64u;
} else {
if(((uintptr_t)ED)&1) {
do {
tmp16u = ED->word[0] & ~0xff;
tmp16u |= native_lock_read_h(ED);
tmp16u2 = add16(emu, tmp16u, GD->word[0]);
} while(native_lock_write_h(ED, tmp16u2&0xff));
ED->word[0] = tmp16u2;
} else {
do {
tmp16u = native_lock_read_h(ED);
tmp16u2 = add16(emu, tmp16u, GD->word[0]);
} while(native_lock_write_h(ED, tmp16u2));
}
GD->word[0] = tmp16u;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp64u = add64(emu, ED->q[0], GD->q[0]);
GD->q[0] = ED->q[0];
ED->q[0] = tmp64u;
} else {
tmp16u = add16(emu, ED->word[0], GD->word[0]);
GD->word[0] = ED->word[0];
ED->word[0] = tmp16u;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
return 0;
}
break;
@@ -293,7 +335,7 @@ int Run66F0(x64emu_t *emu, rex_t rex)
}
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+109 -11
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run67(x64emu_t *emu, rex_t rex, int rep)
uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -98,16 +98,55 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
case 0x0F:
return Run670F(emu, rex, rep);
return Run670F(emu, rex, rep, addr);
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x38:
nextop = F8;
GETEB32(0);
GETGB;
cmp8(emu, EB->byte[0], GB);
break;
case 0x39:
nextop = F8;
GETED32(0);
GETGD;
if(rex.w)
cmp64(emu, ED->q[0], GD->q[0]);
else
cmp32(emu, ED->dword[0], GD->dword[0]);
break;
case 0x3A:
nextop = F8;
GETEB32(0);
GETGB;
cmp8(emu, GB, EB->byte[0]);
break;
case 0x3B:
nextop = F8;
GETED32(0);
GETGD;
if(rex.w)
cmp64(emu, GD->q[0], ED->q[0]);
else
cmp32(emu, GD->dword[0], ED->dword[0]);
break;
case 0x3C:
R_AL = cmp8(emu, R_AL, F8);
break;
case 0x3D:
if(rex.w)
cmp64(emu, R_RAX, F32S64);
else
cmp32(emu, R_EAX, F32);
break;
case 0x66:
return Run6766(emu, rex, rep);
return Run6766(emu, rex, rep, addr);
case 0x80: /* GRP Eb,Ib */
nextop = F8;
@@ -124,6 +163,53 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) {
tmp32s = F32S;
} else {
tmp32s = F8S;
}
if(rex.w) {
tmp64u = (uint64_t)(int64_t)tmp32s;
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 {
tmp32u = (uint32_t)tmp32s;
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->q[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->q[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->q[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->q[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->q[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->q[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->q[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
else
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
}
break;
case 0x88: /* MOV Eb,Gb */
nextop = F8;
@@ -212,36 +298,48 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
}
break;
case 0xC7: /* MOV Ed,Id */
nextop = F8;
GETED32(4);
if(rex.w)
ED->q[0] = F32S64;
else
if(MODREG)
ED->q[0] = F32;
else
ED->dword[0] = F32;
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX && !ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
addr += tmp8s;
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX && ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
addr += tmp8s;
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX)
R_RIP += tmp8s;
addr += tmp8s;
break;
case 0xE3: /* JECXZ Ib */
tmp8s = F8S;
if(!R_ECX)
R_RIP += tmp8s;
addr += tmp8s;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_RIP);
R_RIP += tmp32s;
Push(emu, addr);
addr += tmp32s;
break;
case 0xF7: /* GRP3 Ed(,Id) */
@@ -316,7 +414,7 @@ int Run67(x64emu_t *emu, rex_t rex, int rep)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+4 -4
View File
@@ -25,7 +25,7 @@
#include "modrm.h"
int Run670F(x64emu_t *emu, rex_t rex, int rep)
uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
{
(void)rep;
uint8_t opcode;
@@ -47,7 +47,7 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
// same for now
case 0x2F: /* COMISS Gx, Ex */
if(rep) {
return 1;
return 0;
}
RESET_FLAGS(emu);
nextop = F8;
@@ -80,7 +80,7 @@ int Run670F(x64emu_t *emu, rex_t rex, int rep)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+4 -4
View File
@@ -25,7 +25,7 @@
#include "modrm.h"
int Run6766(x64emu_t *emu, rex_t rex, int rep)
uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
{
// Hmmmm....
(void)rep;
@@ -59,10 +59,10 @@ int Run6766(x64emu_t *emu, rex_t rex, int rep)
switch(opcode) {
case 0x0F: /* more opcodes */
return Run67660F(emu, rex);
return Run67660F(emu, rex, addr);
default:
return 1;
return 0;
}
return 0;
return addr;
}
+3 -3
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int Run67660F(x64emu_t *emu, rex_t rex)
uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t opcode;
uint8_t nextop;
@@ -58,7 +58,7 @@ int Run67660F(x64emu_t *emu, rex_t rex)
break;
default:
return 1;
return 0;
}
return 0;
return addr;
}
+136 -59
View File
@@ -48,7 +48,10 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 0;
} else {
RunElfInit(my_context->elfs[0], emu);
}
MarkElfInitDone(my_context->elfs[0]);
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
Push64(emu, GetRBP(emu)); // set frame pointer
@@ -67,7 +70,7 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 1; // finished!
}
return 0;
return (int)GetEAX(emu);
}
const char* GetNativeName(void* p)
@@ -152,7 +155,7 @@ void UpdateFlags(x64emu_t *emu)
case d_add64:
lo = (emu->op2.u64 & 0xFFFFFFFF) + (emu->op1.u64 & 0xFFFFFFFF);
hi = (lo >> 32) + (emu->op2.u64 >> 32) + (emu->op1.u64 >> 32);
CONDITIONAL_SET_FLAG(hi & 0x100000000, F_CF);
CONDITIONAL_SET_FLAG(hi & 0x100000000L, F_CF);
CONDITIONAL_SET_FLAG(!emu->res.u64, F_ZF);
CONDITIONAL_SET_FLAG(emu->res.u64 & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res.u64 & 0xff), F_PF);
@@ -834,7 +837,7 @@ void UpdateFlags(x64emu_t *emu)
lo = 1 + (emu->op1.u64 & 0xFFFFFFFF) + (emu->op2.u64 & 0xFFFFFFFF);
}
hi = (lo >> 32) + (emu->op1.u64 >> 32) + (emu->op2.u64 >> 32);
CONDITIONAL_SET_FLAG(hi & 0x1000000000000L, F_CF);
CONDITIONAL_SET_FLAG(hi & 0x100000000L, F_CF);
CONDITIONAL_SET_FLAG(!emu->res.u64, F_ZF);
CONDITIONAL_SET_FLAG(emu->res.u64 & 0x8000000000000000LL, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res.u64 & 0xff), F_PF);
@@ -938,6 +941,33 @@ void UpdateFlags(x64emu_t *emu)
case d_unknown:
printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
break;
case d_dec8i:
case d_dec16i:
case d_dec32i:
case d_dec64i:
case d_inc8i:
case d_inc16i:
case d_inc32i:
case d_inc64i:
{
defered_flags_t df = emu->df - (d_dec8i - d_dec8);
if(emu->df_sav!=d_none) {
// compute CF
multiuint_t op1 = emu->op1;
multiuint_t res = emu->res;
emu->df = emu->df_sav;
emu->op1 = emu->op1_sav;
emu->res = emu->res_sav;
emu->df_sav = d_none;
UpdateFlags(emu);
emu->op1 = op1;
emu->res = res;
}
emu->df = df;
}
UpdateFlags(emu);
break;
}
RESET_FLAGS(emu);
}
@@ -959,9 +989,10 @@ const char* getAddrFunctionName(uintptr_t addr)
uintptr_t start = 0;
elfheader_t* elf = FindElfAddress(my_context, addr);
const char* symbname = FindNearestSymbolName(elf, (void*)addr, &start, &sz);
if(!sz) sz=0x100; // arbitrary value...
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
if(symbname[0]=='\0')
sprintf(ret, "%s + 0x%lx", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));
sprintf(ret, "%s + 0x%lx + 0x%lx", ElfName(elf), start - (uintptr_t)GetBaseAddress(elf), addr - start);
else if(addr==start)
sprintf(ret, "%s/%s", ElfName(elf), symbname);
else
@@ -980,6 +1011,7 @@ void printFunctionAddr(uintptr_t nextaddr, const char* text)
uint64_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
if(!sz) sz=0x100; // arbitrary value...
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
if(nextaddr==start)
printf_log(LOG_NONE, " (%s%s:%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname);
@@ -1031,9 +1063,18 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
} else {
printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip));
uint8_t peek = PK(0);
rex_t rex = {0};
if(peek>=0x40 && peek<=0x4f) {
rex.rex = peek;
ip++;
peek = PK(0);
}
if(peek==0xC3 || peek==0xC2 || (peek==0xF3 && PK(1)==0xC3)) {
printf_log(LOG_NONE, " => %p", *(void**)(R_RSP));
printFunctionAddr(*(uintptr_t*)(R_RSP), "=> ");
} else if(peek==0x57 && rex.b) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
printFunctionAddr(ip, "here: ");
} else if(peek==0x55 || peek==0x53) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
printFunctionAddr(ip, "here: ");
@@ -1054,86 +1095,122 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
#endif
reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta)
static uint8_t F8(uintptr_t* addr) {
uint8_t ret = *(uint8_t*)*addr;
*addr+=1;
return ret;
}
static int8_t F8S(uintptr_t* addr) {
int8_t ret = *(int8_t*)*addr;
*addr+=1;
return ret;
}
static uint16_t F16(uintptr_t* addr) {
uint16_t ret = *(uint16_t*)*addr;
*addr+=2;
return ret;
}
static int16_t F16S(uintptr_t* addr) {
int16_t ret = *(int16_t*)*addr;
*addr+=2;
return ret;
}
static uint32_t F32(uintptr_t* addr) {
uint32_t ret = *(uint32_t*)*addr;
*addr+=4;
return ret;
}
static int32_t F32S(uintptr_t* addr) {
int32_t ret = *(int32_t*)*addr;
*addr+=4;
return ret;
}
static uint64_t F64(uintptr_t* addr) {
uint64_t ret = *(uint64_t*)*addr;
*addr+=8;
return ret;
}
reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta)
{
if (m<=7) {
if(m==0x4) {
uint8_t sib = Fetch8(emu);
uintptr_t base = ((sib&0x7)==5)?((uint64_t)(int64_t)Fetch32s(emu)):(emu->regs[(sib&0x7)+(rex.b<<3)].q[0]); // base
uint8_t sib = F8(addr);
uintptr_t base = ((sib&0x7)==5)?((uint64_t)(int64_t)F32S(addr)):(emu->regs[(sib&0x7)+(rex.b<<3)].q[0]); // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
return (reg64_t*)base;
} else if (m==0x5) { //disp32
int32_t base = Fetch32s(emu);
return (reg64_t*)(base+R_RIP+delta);
int32_t base = F32S(addr);
return (reg64_t*)(base+*addr+delta);
}
return (reg64_t*)(emu->regs[m+(rex.b<<3)].q[0]);
} else {
uintptr_t base;
if((m&7)==4) {
uint8_t sib = Fetch8(emu);
uint8_t sib = F8(addr);
base = emu->regs[(sib&0x7)+(rex.b<<3)].q[0]; // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
} else {
base = emu->regs[(m&0x7)+(rex.b<<3)].q[0];
}
base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
base+=(m&0x80)?F32S(addr):F8S(addr);
return (reg64_t*)base;
}
}
reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
{
if (m<=7) {
if(m==0x4) {
uint8_t sib = Fetch8(emu);
base += ((sib&0x7)==5)?((uint64_t)(int64_t)Fetch32s(emu)):(emu->regs[(sib&0x7)+(rex.b<<3)].q[0]); // base
uint8_t sib = F8(addr);
base += ((sib&0x7)==5)?((uint64_t)(int64_t)F32S(addr)):(emu->regs[(sib&0x7)+(rex.b<<3)].q[0]); // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
return (reg64_t*)base;
} else if (m==0x5) { //disp32
base += Fetch32s(emu);
return (reg64_t*)(base+R_RIP+delta);
base += F32S(addr);
return (reg64_t*)(base+*addr+delta);
}
return (reg64_t*)(base + emu->regs[m+(rex.b<<3)].q[0]);
} else {
if((m&7)==4) {
uint8_t sib = Fetch8(emu);
uint8_t sib = F8(addr);
base += emu->regs[(sib&0x7)+(rex.b<<3)].q[0]; // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sq[0] << (sib>>6));
} else {
base += emu->regs[(m&0x7)+(rex.b<<3)].q[0];
}
base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
base+=(m&0x80)?F32S(addr):F8S(addr);
return (reg64_t*)base;
}
}
reg64_t* GetECommon32O(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t base)
{
if (m<=7) {
if(m==0x4) {
uint8_t sib = Fetch8(emu);
base += ((sib&0x7)==5)?((uint64_t)(int64_t)Fetch32s(emu)):(emu->regs[(sib&0x7)+(rex.b<<3)].dword[0]); // base
uint8_t sib = F8(addr);
base += ((sib&0x7)==5)?((uint64_t)(int64_t)F32S(addr)):(emu->regs[(sib&0x7)+(rex.b<<3)].dword[0]); // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sdword[0] << (sib>>6));
return (reg64_t*)base;
} else if (m==0x5) { //disp32
base += Fetch32s(emu);
return (reg64_t*)(base+R_RIP+delta);
base += F32S(addr);
return (reg64_t*)(base+(*addr)+delta);
}
return (reg64_t*)(uintptr_t)(base + emu->regs[m+(rex.b<<3)].dword[0]);
} else {
if((m&7)==4) {
uint8_t sib = Fetch8(emu);
uint8_t sib = F8(addr);
base += emu->regs[(sib&0x7)+(rex.b<<3)].dword[0]; // base
base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<3)]->sdword[0] << (sib>>6));
} else {
base += emu->regs[(m&0x7)+(rex.b<<3)].dword[0];
}
base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu);
base+=(m&0x80)?F32S(addr):F8S(addr);
return (reg64_t*)base;
}
}
reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
{
// rex ignored here
uint8_t m = v&0xC7; // filter Eb
@@ -1144,10 +1221,10 @@ reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
int lowhigh = (m&4)>>2;
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
}
} else return GetECommon(emu, rex, m, delta);
} else return GetECommon(emu, addr, rex, m, delta);
}
reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
// rex ignored here
uint8_t m = v&0xC7; // filter Eb
@@ -1158,34 +1235,34 @@ reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t of
int lowhigh = (m&4)>>2;
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
}
} else return GetECommonO(emu, rex, m, delta, offset);
} else return GetECommonO(emu, addr, rex, m, delta, offset);
}
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)+(rex.b<<3)];
} else return GetECommon(emu, rex, m, delta);
} else return GetECommon(emu, addr, rex, m, delta);
}
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)+(rex.b<<3)];
} else return GetECommonO(emu, rex, m, delta, offset);
} else return GetECommonO(emu, addr, rex, m, delta, offset);
}
reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)+(rex.b<<3)];
} else return GetECommon32O(emu, rex, m, delta, offset);
} else return GetECommon32O(emu, addr, rex, m, delta, offset);
}
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Eb
if(m>=0xC0) {
@@ -1195,12 +1272,12 @@ reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t
int lowhigh = (m&4)>>2;
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
}
} else return GetECommon32O(emu, rex, m, delta, offset);
} else return GetECommon32O(emu, addr, rex, m, delta, offset);
}
#define GetEw GetEd
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
{
(void)rex;
@@ -1220,16 +1297,16 @@ reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
case 7: base = R_BX; break;
}
switch((m>>6)&3) {
case 0: if(m==6) base = Fetch16(emu); break;
case 1: base += Fetch8s(emu); break;
case 2: base += Fetch16s(emu); break;
case 0: if(m==6) base = F16(addr); break;
case 1: base += F8S(addr); break;
case 2: base += F16S(addr); break;
// case 3 is C0..C7, already dealt with
}
return (reg64_t*)base;
}
}
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset)
{
(void)rex;
@@ -1249,62 +1326,62 @@ reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset)
case 7: base = R_BX; break;
}
switch((m>>6)&3) {
case 0: if(m==6) base = Fetch16(emu); break;
case 1: base += Fetch8s(emu); break;
case 2: base += Fetch16s(emu); break;
case 0: if(m==6) base = F16(addr); break;
case 1: base += F8S(addr); break;
case 2: base += F16S(addr); break;
// case 3 is C0..C7, already dealt with
}
return (reg64_t*)(base+offset);
}
}
mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->mmx[m&0x07];
} else return (mmx87_regs_t*)GetECommon(emu, rex, m, delta);
} else return (mmx87_regs_t*)GetECommon(emu, addr, rex, m, delta);
}
sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->xmm[(m&0x07)+(rex.b<<3)];
} else return (sse_regs_t*)GetECommon(emu, rex, m, delta);
} else return (sse_regs_t*)GetECommon(emu, addr, rex, m, delta);
}
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->xmm[(m&0x07)+(rex.b<<3)];
} else return (sse_regs_t*)GetECommonO(emu, rex, m, delta, offset);
} else return (sse_regs_t*)GetECommonO(emu, addr, rex, m, delta, offset);
}
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->xmm[(m&0x07)+(rex.b<<3)];
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
} else return (sse_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset);
}
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->mmx[(m&0x07)];
} else return (mmx87_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
} else return (mmx87_regs_t*)GetECommon32O(emu, addr, rex, m, delta, offset);
}
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
{
return &emu->regs[((v&0x38)>>3)+(rex.r<<3)];
}
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
reg64_t* GetGb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
{
uint8_t m = (v&0x38)>>3;
if(rex.rex)
@@ -1313,7 +1390,7 @@ reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
return (reg64_t*)&emu->regs[m&3].byte[m>>2];
}
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
mmx87_regs_t* GetGm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
{
(void)rex;
@@ -1321,7 +1398,7 @@ mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
return &emu->mmx[m&7];
}
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v)
sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v)
{
uint8_t m = (v&0x38)>>3;
return &emu->xmm[(m&7)+(rex.r<<3)];
+44 -82
View File
@@ -17,44 +17,6 @@ typedef union rex_s {
};
} rex_t;
static inline uint8_t Fetch8(x64emu_t *emu) {return *(uint8_t*)(R_RIP++);}
static inline int8_t Fetch8s(x64emu_t *emu) {return *(int8_t*)(R_RIP++);}
static inline uint16_t Fetch16(x64emu_t *emu)
{
uint16_t val = *(uint16_t*)R_RIP;
R_RIP+=2;
return val;
}
static inline int16_t Fetch16s(x64emu_t *emu)
{
int16_t val = *(int16_t*)R_RIP;
R_RIP+=2;
return val;
}
static inline uint32_t Fetch32(x64emu_t *emu)
{
uint32_t val = *(uint32_t*)R_RIP;
R_RIP+=4;
return val;
}
static inline int32_t Fetch32s(x64emu_t *emu)
{
int32_t val = *(int32_t*)R_RIP;
R_RIP+=4;
return val;
}
static inline uint64_t Fetch64(x64emu_t *emu)
{
uint64_t val = *(uint64_t*)R_RIP;
R_RIP+=8;
return val;
}
static inline int64_t Fetch64s(x64emu_t *emu)
{
int64_t val = *(int64_t*)R_RIP;
R_RIP+=8;
return val;
}
static inline uint8_t Peek(x64emu_t *emu, int offset){return *(uint8_t*)(R_RIP + offset);}
static inline uint64_t Pop(x64emu_t *emu)
@@ -73,61 +35,61 @@ static inline void Push(x64emu_t *emu, uint64_t v)
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta);
reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetECommon32O(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetECommon(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta);
reg64_t* GetECommonO(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetECommon32O(x64emu_t* emu, uintptr_t* addr, rex_t rex, uint8_t m, uint8_t delta, uintptr_t offset);
reg64_t* GetEb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEbO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEdO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEb32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
#define GetEw GetEd
#define GetEw32O GetEd32O
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
reg64_t* GetEw16(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
reg64_t* GetEw16off(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uintptr_t offset);
mmx87_regs_t* GetEm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetEx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetExO(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetEx32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetGd(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
#define GetGw GetGd
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v);
mmx87_regs_t* GetEm32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v);
reg64_t* GetGb(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
mmx87_regs_t* GetGm(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
mmx87_regs_t* GetEm32O(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetGx(x64emu_t *emu, uintptr_t* addr, rex_t rex, uint8_t v);
void UpdateFlags(x64emu_t *emu);
#define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
#define RESET_FLAGS(emu) emu->df = d_none
int Run0F(x64emu_t *emu, rex_t rex);
int Run64(x64emu_t *emu, rex_t rex, int seg);
int Run66(x64emu_t *emu, rex_t rex, int rep);
int Run660F(x64emu_t *emu, rex_t rex);
int Run6664(x64emu_t *emu, rex_t rex);
int Run66D9(x64emu_t *emu, rex_t rex);
int Run66DD(x64emu_t *emu, rex_t rex);
int Run66F0(x64emu_t *emu, rex_t rex);
int Run67(x64emu_t *emu, rex_t rex, int rep);
int Run670F(x64emu_t *emu, rex_t rex, int rep);
int Run6766(x64emu_t *emu, rex_t rex, int rep);
int Run67660F(x64emu_t *emu, rex_t rex);
int RunD8(x64emu_t *emu, rex_t rex);
int RunD9(x64emu_t *emu, rex_t rex);
int RunDA(x64emu_t *emu, rex_t rex);
int RunDB(x64emu_t *emu, rex_t rex);
int RunDC(x64emu_t *emu, rex_t rex);
int RunDD(x64emu_t *emu, rex_t rex);
int RunDE(x64emu_t *emu, rex_t rex);
int RunDF(x64emu_t *emu, rex_t rex);
int RunF0(x64emu_t *emu, rex_t rex);
int RunF20F(x64emu_t *emu, rex_t rex);
int RunF30F(x64emu_t *emu, rex_t rex);
uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step);
uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr);
uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr);
uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t Run6664(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t Run66D9(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t Run66DD(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr);
uintptr_t Run670F(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr);
uintptr_t Run6766(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr);
uintptr_t Run67660F(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunF0(x64emu_t *emu, rex_t rex, uintptr_t addr);
uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step);
uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr);
void x64Syscall(x64emu_t *emu);
void x64Int3(x64emu_t* emu);
void x64Int3(x64emu_t* emu, uintptr_t* addr);
x64emu_t* x64emu_fork(x64emu_t* e, int forktype);
uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg);
+3 -3
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunD8(x64emu_t *emu, rex_t rex)
uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
float f;
@@ -188,8 +188,8 @@ int RunD8(x64emu_t *emu, rex_t rex)
}
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+17 -15
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunD9(x64emu_t *emu, rex_t rex)
uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
int32_t tmp32s;
@@ -60,6 +60,17 @@ int RunD9(x64emu_t *emu, rex_t rex)
case 0xD0: /* FNOP */
break;
case 0xD8: /* FSTPNCE ST0, STx */
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
ST(nextop&7).q = ST0.q;
fpu_do_pop(emu);
break;
case 0xE0: /* FCHS */
ST0.d = -ST0.d;
break;
@@ -210,20 +221,12 @@ int RunD9(x64emu_t *emu, rex_t rex)
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FLD ST0, Ed float */
@@ -262,9 +265,8 @@ int RunD9(x64emu_t *emu, rex_t rex)
break;
case 5: /* FLDCW Ew */
GETEW(0);
emu->cw = EW->word[0];
emu->cw.x16 = EW->word[0];
// do something with cw?
emu->round = (fpu_round_t)((emu->cw >> 10) & 3);
break;
case 6: /* FNSTENV m */
// warning, incomplete
@@ -276,11 +278,11 @@ int RunD9(x64emu_t *emu, rex_t rex)
break;
case 7: /* FNSTCW Ew */
GETEW(0);
EW->word[0] = emu->cw;
EW->word[0] = emu->cw.x16;
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+3 -3
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunDA(x64emu_t *emu, rex_t rex)
uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -94,7 +94,7 @@ int RunDA(x64emu_t *emu, rex_t rex)
case 0xF8:
case 0xF9:
case 0xFD:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
@@ -132,5 +132,5 @@ int RunDA(x64emu_t *emu, rex_t rex)
break;
}
}
return 0;
return addr;
}
+4 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunDB(x64emu_t *emu, rex_t rex)
uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
int32_t tmp32s;
@@ -123,7 +123,7 @@ int RunDB(x64emu_t *emu, rex_t rex)
case 0xE5:
case 0xE6:
case 0xE7:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Ed */
@@ -174,8 +174,8 @@ int RunDB(x64emu_t *emu, rex_t rex)
fpu_do_pop(emu);
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+3 -3
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunDC(x64emu_t *emu, rex_t rex)
uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -139,8 +139,8 @@ int RunDC(x64emu_t *emu, rex_t rex)
ST0.d = *(double*)ED / ST0.d;
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+4 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunDD(x64emu_t *emu, rex_t rex)
uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -107,7 +107,7 @@ int RunDD(x64emu_t *emu, rex_t rex)
case 0xFD:
case 0xFE:
case 0xFF:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
@@ -182,8 +182,8 @@ int RunDD(x64emu_t *emu, rex_t rex)
*(uint16_t*)ED = emu->sw.x16;
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
+4 -4
View File
@@ -22,7 +22,7 @@
#include "modrm.h"
int RunDE(x64emu_t *emu, rex_t rex)
uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr)
{
uint8_t nextop;
reg64_t *oped;
@@ -124,7 +124,7 @@ int RunDE(x64emu_t *emu, rex_t rex)
case 0xDD:
case 0xDE:
case 0xDF:
return 1;
return 0;
default:
switch((nextop>>3)&7) {
@@ -153,8 +153,8 @@ int RunDE(x64emu_t *emu, rex_t rex)
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
return 1;
return 0;
}
}
return 0;
return addr;
}
Loaded 100 of 419 files, more files were not shown because too many files have changed in this diff. Show more