Compare commits

...
465 Commits
Author SHA1 Message Date
ptitSeb dae0917c47 Bumped version to v0.4.0 2026-01-03 16:50:53 +01:00
Yang Liu 37a189814c [BOX32][WRAPPER] Fixed XPeekIfEvent wrapping (#3329) 2026-01-03 16:45:04 +01:00
ptitSeb baa962f586 [RCFILE] Better profile for steam, more stable 2026-01-02 18:03:16 +01:00
Yang Liu df37f14729 [RCFILE] Added a profile for Total War: Three Kingdoms (#3328) 2026-01-02 17:54:07 +01:00
ptitSeb 48d5ce7b34 [STEAM] Don't let check requirement to run as it might want to use bwrap while it's not compatible with box64 (for #3321) 2026-01-02 15:04:22 +01:00
Yang Liu 4ed3c02834 [LA64_DYNAREC] Refined more rotate opcodes flags computation (#3327) 2026-01-02 14:43:37 +01:00
ptitSeb bebae710ec [BOX32][WRAPPER] Various box32 fixes 2026-01-02 14:07:23 +01:00
ptitSeb 0254fbdd83 [RCFILE][BOX32] Added secret settings to avoid setting Persona to 32bits on box32 runs 2026-01-01 18:53:10 +01:00
Yang Liu 758a1a9ea5 [LA64_DYNAREC] Small fix to geted and micro-optimization to LEA opcode (#3326) 2026-01-01 18:51:30 +01:00
Yang Liu 7f6e5fca90 Fixed non-dynarec build on dynarec available platforms (#3325) 2025-12-31 12:13:29 +01:00
Yang Liu 866cfe300d [LA64_DYNAREC] Refined RCL8/16/32/64 /imm opcodes (#3324) 2025-12-31 12:12:29 +01:00
Yang Liu ac5a149297 [CMAKE] Fixed an uninstall script warning (#3323) 2025-12-31 11:45:55 +01:00
ptitSeb 4759e2d20d [RV64_DYNAREC] Fixed a regression introduced with 2b070086d1 2025-12-30 18:56:46 +01:00
ptitSeb e0b4a8a48a [ARM64_DYNAREC] Fixed flags hack on CALL/RET/Illegal instruction to not destroy df info if status is unknown (for #3319) 2025-12-30 09:43:30 +01:00
Max Parry 977dcc6c4c [STEAM] Minor refactoring (#3320)
* [STEAM] Minor refactoring

- don't remove the deb files as they are already removed with the `rm -rf ./tmp/`
- don't create ~/steam as it is already bound to be created with `mkdir -p ~/steam/tmp`
- remove superfluous characters in path

* [STEAM] Use Curl over WGet, as it's more common on most systems
2025-12-30 08:05:29 +01:00
ptitSeb a89704c8a7 [RCFILE] Added 1 more game profile 2025-12-29 21:03:46 +01:00
Yang Liu 09bdbcb049 [LA64_DYNAREC] Micro-optimization for emit_test32c (#3318) 2025-12-29 16:43:48 +01:00
ptitSeb c23de7dc9c [RCFILE] Added some more game profiles 2025-12-29 15:59:54 +01:00
Yang Liu 816f807a2d [LA64_DYNAREC] Micro-optimization for emit_shr32c (#3317) 2025-12-29 11:09:04 +01:00
Yang Liu 7e15f0e3d5 [LA64_DYNAREC] Refined rcr8/16 /imm opcodes (#3316) 2025-12-29 08:10:46 +01:00
Yang Liu 1e73fe64e1 [RCFILE] Enable callret for gb6 (#3315) 2025-12-29 08:09:51 +01:00
Yang Liu 32fbdd28ac [LA64_DYNAREC] Added some missing SM=2 store hints (#3314) 2025-12-29 08:09:11 +01:00
ptitSeb 050e0f9f43 [ARM64_DYNAREC] Fixed some DIV IDIV flags issues 2025-12-28 10:05:56 +01:00
ptitSeb 7420c5a088 [INTERP] 0F 09 is a GPF not a Segfault 2025-12-28 09:20:04 +01:00
ptitSeb 9a5a8fedc5 [ARM64_DYNAREC] 0F 09 is a GPF, not a SIGILL 2025-12-27 21:37:54 +01:00
ptitSeb 9d6fcab85f [DYNAREC] Fixed an issue when a jump is internal but endup as a jump out where X_PEND would not be added as needed 2025-12-27 20:54:16 +01:00
Yang Liu 1654964362 [RCFILE] Added a profile for StarCraft II (#3313) 2025-12-27 17:25:32 +01:00
Yang Liu 3b5f3b26f1 [RCFILE] A small improvement for Battle.net client (#3312) 2025-12-27 16:13:13 +01:00
Yang Liu 8e4a17f851 [RCFILE] Removed some obsolete env. var. (#3311)
These are specific to Linux Steam, but they're not needed anymore.
2025-12-27 16:12:41 +01:00
Yang Liu cc117019ff [LA64_DYNAREC] Some refactor and cleanups on rotate opcodes (#3310) 2025-12-27 09:44:19 +01:00
ptitSeb 490350acac [WRAPPER] Various fixes for libGL wrapping ([BOX32] Too) 2025-12-26 18:40:33 +01:00
ptitSeb 90706e7f74 [BOX32][WRAPPER] Improved support for libGLX_nvidia.so and some small other libGL wrapping fixes 2025-12-26 16:38:57 +01:00
ptitSeb 3ac959275f [WRAPPER][LIBGL] more work on libGL wrapping 2025-12-26 16:08:52 +01:00
rajdakin d6651c3615 [BOX64] Fixed all true-positive GCC default warnings (#3309) 2025-12-26 15:44:43 +01:00
ptitSeb 80dafff3c5 [BOX32][WRAPPER] Refactored libGL wrapping 2025-12-26 14:46:33 +01:00
ptitSeb 3eb8e16958 [WRAPPING] Remove some obsolete code 2025-12-26 14:36:45 +01:00
ptitSeb 6a1861572d [WRAPPER] Reworked libGLX_nvidia wrapping 2025-12-26 11:32:57 +01:00
ptitSeb 78a2109344 [WRAPPING][LIBGL] Reworked libGL wrapping with new bridge2 2025-12-26 11:16:57 +01:00
Yang Liu 894285b1db [WRAPPER][BOX32] Minor fix and improvement to XGetICValues (#3306) 2025-12-26 08:27:56 +01:00
ptitSeb 663ae1abda [WRAPPER] Added 1 more symbol to libdbus 2025-12-25 17:03:56 +01:00
Yang Liu fddba78b84 Make sure managed memory blocks are always aligned to 16 bytes (#3305) 2025-12-25 11:15:46 +01:00
ptitSeb 0cec2e8bf8 [VULKAN][WRAPPER] refactored vulkan wrapper to use bridge2 2025-12-24 17:04:18 +01:00
ptitSeb 2557acc3b2 [WRAPPER] Fixed add bridge2 function 2025-12-24 14:27:03 +01:00
ptitSeb a8bb97f7e2 [WRAPPER] Improved bridge with a secondary function (inplace of the name) 2025-12-24 10:04:25 +01:00
ptitSeb 5adfb41a37 [VULKAN][WRAPPER] Removed some GOM in vulkan wrapper 2025-12-24 09:20:21 +01:00
Neltharion dd1420eeba More wrapped symbols for SDL2 (#3297)
* Added new wrappers for SDL2

* fix
2025-12-23 23:09:26 +01:00
Yang Liu b9a9317a73 [LA64_DYNAREC] Small improvments to ALSL printer (#3303) 2025-12-23 15:51:41 +01:00
Yang Liu ac816e90aa [RCFILE][LA64] Added Risk of Rain 2 profile (#3300) 2025-12-23 15:47:36 +01:00
ptitSeb d7f71d7a2f [WRAPPER] Added some more gstreamer wrapped symbols 2025-12-23 08:54:40 +01:00
Yang Liu d15a203bb1 [LA64_DYNAREC] Optimized RCR opcodes (#3299) 2025-12-23 08:54:03 +01:00
Yang Liu 3b9edf0070 [CORE] Refined tracing file header info (#3298)
There are some header info missing in tracing file when using rcfile
2025-12-23 08:11:28 +01:00
Yang Liu 0ae576964c [WRAPPER] Wrapped more gtk3 and related symbols (#3295) 2025-12-22 18:20:57 +01:00
Yang Liu 7086d0e5a2 [WRAPPER] Wrapped 1 more glib2 symbol (#3296)
used by Linux Steam
2025-12-22 18:18:47 +01:00
ptitSeb e912aff5c6 [WRAPPER] Make BOX64_EMULATED_LIBS to also affect gstreamer hacked loading of plugins 2025-12-21 18:29:16 +01:00
ptitSeb f93af92f5d [WRAPPER] Added some more gstreamer wrapped functions 2025-12-21 17:55:02 +01:00
ptitSeb e02c5c325d [WRAPPER][GTK] Fix overloaded signal with offset handling 2025-12-21 17:54:19 +01:00
ptitSeb 06950103a2 [RCFILE] Added a new game profile 2025-12-21 17:53:17 +01:00
ptitSeb 8f736dcdee [TRACE] Show wrapper name if signal happens in a bridge 2025-12-21 17:52:30 +01:00
ptitSeb 9aa5ba1b90 [TRACE] Small simplification on getAddrFunctionName helper function 2025-12-21 17:51:42 +01:00
ptitSeb 30f891aaa6 [ARM64_DYNAREC][TRACE] Print if Native call use simpleWrapper 2025-12-21 17:50:53 +01:00
Yang Liu 57466cf0f0 [LA64_DYNAREC] Fixed a regression in emit_sub32c (#3294) 2025-12-21 13:27:39 +01:00
ptitSeb 2babe3aa89 [WRAPPER] One fix for libunistring wrapping 2025-12-20 17:32:09 +01:00
ptitSeb 0fa0e02844 [WRAPPER] Reworked wrapping of libhogweed.so.6 with wrapperhelper 2025-12-20 16:15:23 +01:00
ptitSeb a983cbe67b [WRAPPER] Reworked libidn2 wrapping with wrapperhelper 2025-12-20 15:00:28 +01:00
ptitSeb f5d468718d [WRAPPER] Reworked libgmp wrapping with wrapperhelper 2025-12-20 14:58:58 +01:00
ptitSeb 62a053bc48 [TRACE] Show dirty when a dynablock is dirty on a signal 2025-12-20 14:51:15 +01:00
ptitSeb 451c7901b4 [WRAPPER] More work on libunistring.so.2 wrapping 2025-12-20 14:48:13 +01:00
ptitSeb 066e7d3aea [WRAPER] Reworked libunistring2 wrapping with wrapperhelper 2025-12-20 13:53:01 +01:00
luoqiaoling 1de324a500 [BOX64] Fixed my_box64signalhandler, convert native signal to x64 (#3292) 2025-12-20 10:25:19 +01:00
ptitSeb 2db33422c6 [RCFILE] Added 1 more game profile 2025-12-20 10:22:58 +01:00
ptitSeb f2660cd3f0 Improved log when PltResolver don't find a symbol 2025-12-19 18:57:29 +01:00
Yang Liu b34b7aca42 [LA64_DYNAREC] Fixed some minor typos of SQRTSD and XCHG opcodes (#3291) 2025-12-19 17:53:11 +01:00
ptitSeb cdf3890a33 [LA64_DYNAREC] Revert 7586bd47cb as it breaks Steam as-is 2025-12-19 17:20:17 +01:00
ptitSeb 14b660e3bb [BOX32]Improve auxval handling 2025-12-19 15:16:27 +01:00
ptitSeb 87d74ebf02 Improve auxval handling (fixing newer AppImage not running) 2025-12-19 15:16:12 +01:00
ptitSeb 3a6653dabf Improved SYS_clone syscal, and improved [TRACE] of some other syscalls 2025-12-19 15:15:33 +01:00
ptitSeb 052db75bd8 [TRACE] Improved trace of execve call/syscall 2025-12-19 15:15:02 +01:00
ptitSeb 25b83a80f0 [README] Put build badge from github workflows 2025-12-19 15:12:53 +01:00
Yang Liu f4ee2cc701 [WRAPPER] Wrapped more symbols for libfreetype (#3290) 2025-12-19 11:36:03 +01:00
Yang Liu 0158102974 [ENV] Fixed race condition of init/uninit of rolling logs (#3289)
I had issues using this feature to trace wps office
2025-12-19 10:30:13 +01:00
Yang Liu 7586bd47cb [LA64_DYNAREC] Refacfored the handling of deferred flags (#3288) 2025-12-19 08:14:58 +01:00
Yang Liu 7f20c20031 [LA64_DYNAREC] Fixed various typos ([RV64_DYNAREC] too) (#3287) 2025-12-17 18:16:33 +01:00
luoqiaoling 2143a88d99 [DYNACHCHE] correct dynacache typo (#3286) 2025-12-17 18:16:21 +01:00
ptitSeb 67c2df0b58 [WRAPPER] Fixed some wrapping issue with libnettle 2025-12-17 16:35:41 +01:00
ptitSeb 24ba5357de [TRACE] Print stack top when 40 53 is traced on 64bits 2025-12-17 16:35:41 +01:00
Yang Liu 57f1b60fb0 [LA64_DYNAREC] Fixed a potential issue of the ADDxREGy macro ([RV64_DYNAREC] too) (#3284) 2025-12-16 17:17:07 +01:00
ptitSeb 5b5b6aca0d [RCFILE] Added more games profile 2025-12-16 14:39:25 +01:00
luoqiaoling b7c386289d [BOX64][INTERP] Fixed idiv boundary tests (#3283)
- related test case: tests/test33
- add test33 to CMakeLists.txt for ctest
2025-12-16 12:11:21 +01:00
Yang Liu b0b2f3c611 [RV64_DYNAREC] Refactored opcode prefix decoding (#3282)
* [RV64_DYNAREC] Refactored opcode prefix decoding

* more
2025-12-16 10:44:33 +01:00
ptitSeb b9af6270d4 [RCFILE] Added a new game profile 2025-12-15 18:47:25 +01:00
Yang Liu 59b35d49e2 [RCFILE] Added a new option BOX64_PROFILE (#3280)
* [RCFILE] Added a new option BOX64_PROFILE

* Warn on unknown
2025-12-15 15:50:40 +01:00
phorcys c68dc6fd7b [LA64_DYNAREC] Add 0F FE /{0,1} LOCK {INC,DEC} Eb. (#3279)
For game FrostPunk 2.
2025-12-15 14:24:39 +01:00
Yang Liu c49ec4417f [LA64_DYNAREC] Ported the BARRIER_FLOAT refactor from Arm64 (#3278) 2025-12-15 12:02:03 +01:00
ptitSeb 8e3fc1e8d8 [BOX32][WRAPPER] Fixed longjmp with val==0 (for #3274) 2025-12-15 10:52:37 +01:00
ptitSeb 5ed336f8ce [WRAPPER] Fixed longjmp with val==0 (for #3274) 2025-12-15 10:52:17 +01:00
ptitSeb ecba89ea31 Improved cpuid handling 2025-12-15 10:51:15 +01:00
Yang Liu 9bf06e9929 [SYSCALL] Added 1 more syscall epoll_pwait2 (#3276) 2025-12-15 09:23:52 +01:00
Yang Liu 4e07b1765d [LA64_DYNAREC] Some improvements to safeflags=2, more to expect (#3273) 2025-12-14 21:39:53 +01:00
Yang Liu 391973d4a0 [LA64_DYNAREC] Small improvements to strongmem emulation (#3272) 2025-12-14 19:47:28 +01:00
Yang Liu 136b683e81 [CI] Added nocosim label to longjumpInSignals test (#3271) 2025-12-14 17:33:15 +01:00
ptitSeb f82c3ffe74 [TESTS] Improved test21 2025-12-14 14:13:13 +01:00
ptitSeb 76e41e7b1a [TRACE][INTERP] Trace when calling/jumping to NULL 2025-12-14 11:42:04 +01:00
ptitSeb bb78e2e63b [INTERP] Fixed regression with 66 F0 prefixed opcodes, introduced with prefix refactor 2025-12-14 10:56:50 +01:00
ptitSeb 1b8da86465 [INTERP] Removed obsolete macros 2025-12-14 10:56:02 +01:00
Yang Liu b53ba64cef [WRAPPER] Reworked libxkbcommon wrapping, added a few new symbols too (#3270)
Used by wine-wayland
2025-12-14 08:38:03 +01:00
Yang Liu 3970c2d50d [WRAPPER] Added 2 more listeners to waylandclient for wine-wayland and HDR support (#3269) 2025-12-14 08:36:08 +01:00
Chi-Kuan Chiu 9b868c9511 [Box32] Check allocation end address (#3268)
The box32_malloc/calloc/realloc/memalign functions were only checking if
the returned pointer was below 4GB (ptr < 0x100000000), but not whether
the entire allocation fits within 32-bit address space.

This caused a segfault when malloc returned an address like 0xFFFEA010
for a 0x20010 byte allocation - the start address passes the check, but
ptr + size = 0x1000A020 exceeds 4GB. When 32-bit code accesses elements
near the end of the array, the address calculation wraps around due to
32-bit arithmetic truncation, resulting in NULL pointer access.

Example crash scenario:
    - malloc(0x20010) returns 0xFFFEA010
    - Old check: 0xFFFEA010 < 0x100000000 ✓ (accepted)
    - Access bitmap[0x57FA]: 0xFFFEA018 + 0x15FE8 = 0x100000000
    - 32-bit truncation: 0x100000000 → 0x00000000
    - SEGFAULT at NULL

Fix:
    - mallochook.c: Add FITS_IN_32BIT(ptr, size) macro that checks
      (ptr + size) <= 0x100000000, apply to all box32_* functions
    - custommem.c: Fix three occurrences of the same bug in
      internal_customMalloc and customMemAligned32 functions

This bug was exposed when running 32-bit x86 NBench compiled with
-m32 -mno-sse flags under box32 on RV64, where memory layout caused
large allocations to land near the top of 32-bit address space.

close #2710
2025-12-13 20:33:17 +01:00
Yang Liu acad5acbef [CPUID] Refined the CPU branding display (#3267) 2025-12-13 19:24:00 +01:00
ptitSeb e6961d845e Small improvment on cpuid handling 2025-12-13 15:19:27 +01:00
ptitSeb cb2deb5cef [ARM64_DYNAREC] Optimized 66 D3 /3 opcode 2025-12-13 15:18:32 +01:00
ptitSeb 96f786e4a9 [ARM64_DYNAREC] Optimized 66 D3 /2 opcode 2025-12-13 15:15:24 +01:00
ptitSeb 9b3e548437 [ARM64_DYNAREC] Optimized D3 /2 opcode 2025-12-13 15:07:06 +01:00
ptitSeb 5a85a5eec4 [ARM64_DYNAREC] optimised D3 /3 opcode 2025-12-13 14:47:18 +01:00
ptitSeb b481e9d4fe [ARM64_DYNAREC][TRACE] Small improvement on cpuid trace 2025-12-13 12:16:51 +01:00
ptitSeb dc138a244f [ARM64_DYNAREC] Small optim for ENTER opcode 2025-12-13 12:02:33 +01:00
Yang Liu 3810383851 [CORE] Removed BOX64_ARG0 env var after use, fixed Heroic with Proton on LoongArch (#3266) 2025-12-13 09:01:47 +01:00
Yang Liu 466e5eb84b [LA64_DYNAREC] Fixed 1 more regression intoduced by the prefix refactor (#3265) 2025-12-12 23:52:32 +01:00
Yang Liu 55b6071e63 [DYNAREC] Fixed uninitlized lock flag for 16-bit opcodes (#3264)
This is a regresion introduced by the prefix refactor, so RV64 DynaRec should be good.
2025-12-12 20:46:53 +01:00
ptitSeb ac08b010d5 [INTERP] Fixed a regression introduced with 33c9d63498 2025-12-12 18:14:53 +01:00
ptitSeb 5253a7f483 [ARM64_DYNAREC] Added some Illegal Intructions special cases 2025-12-12 16:59:29 +01:00
ptitSeb 64855cd5e9 [INTERP] Added some Illegal Intructions special cases 2025-12-12 16:59:11 +01:00
ptitSeb 0727555759 [ARM64_DYNAREC] Small improvment on handling edge case for CMPXCHG8B/16B 2025-12-12 16:54:59 +01:00
Yang Liu 92e5e5618d [LA64_DYNAREC] Refined more flags computation for LBT path (#3263) 2025-12-12 16:45:25 +01:00
ptitSeb 33c9d63498 [INTERP] Small improvment on handling edge case for CMPXCHG8B/16B 2025-12-12 16:03:13 +01:00
ptitSeb 1369ac4b0c [ARM64_DYNAREC] Better handling of some rex.w 66 0F prefixed opcodes 2025-12-12 15:42:24 +01:00
Yang Liu 529fc7fe11 [LA64_DYNAREC] Fixed 1 more UD behaviour ([RV64_DYNAREC] too) (#3262)
Ported from a1f9147868
2025-12-12 15:40:06 +01:00
Yang Liu 1dd8775ff3 [WRAPPER] Added 1 more extension to libGL (#3261)
Seems to be used by Wine 11.
2025-12-12 15:20:41 +01:00
ptitSeb a1f9147868 [ARM64_DYNAREC] More work on UD 2025-12-12 10:24:41 +01:00
ptitSeb 1df9adcd14 [INTERP] More work on UD 2025-12-12 10:24:14 +01:00
Yang Liu 52e2514279 [INTERP] Refined CLFLUSH family opcodes (#3260) 2025-12-11 17:53:17 +01:00
ptitSeb 05b561f739 [ARM64_DYNAREC] Small optim on rcl8c helper 2025-12-11 16:22:08 +01:00
ptitSeb a573268b1b [TRACE] Added some commented trace on cpuid 2025-12-11 16:21:37 +01:00
ptitSeb fe186b32e7 [INTERP][COSIM] Removed obsolete code 2025-12-11 16:20:33 +01:00
ptitSeb f79a31e535 [INTERP] Fixed 8bits and 16bits rcl when shift is 0 2025-12-11 15:41:07 +01:00
ptitSeb eb743a1307 [ARM64_DYNAREC] Refacfored the handling of deffered flags 2025-12-11 13:59:20 +01:00
Yang Liu da76e7e214 [LA64_DYNAREC] Refined CLFLUSH family opcodes ([RV64_DYNAREC] too) (#3259)
* [LA64_DYNAREC] Refined CLFLUSH family opcodes ([RV64_DYNAREC] too)

* more tweaks
2025-12-11 13:32:13 +01:00
Yang Liu 34e9bf1caf [WRAPPER] Wrapped 1 more vulkan extension (#3258) 2025-12-11 11:43:26 +01:00
Yang Liu 498019ca75 [ARM64_DYNAREC] Refined CLFLUSH family opcodes (#3257)
CLFLUSH/CLFLUSHOPT/CLWB are not used to clear icache, so we don't need to clear corresponding dynablocks, but we do need to flush dcache.
2025-12-11 09:41:37 +01:00
ptitSeb cd8890f760 [ARM64_DYNAREC] Reverted deferred dfnone as it still introduced regressions 2025-12-11 09:38:29 +01:00
Chi-Kuan Chiu aa45e2583d [DOCS] Add BOX64_DYNAREC_PURGE_AGE documentation (#3253)
Update BOX64_DYNAREC_PURGE description to explain the tick-based
cache purge mechanism and add the new BOX64_DYNAREC_PURGE_AGE
environment variable documentation.
2025-12-10 21:34:29 +01:00
ptitSeb 1c28994871 [DYNAREC] Added notion of block creation speed to avoid purge when a burst of block creation accurs (to be fine tuned) 2025-12-10 15:25:33 +01:00
ptitSeb 2a68951574 [WRAPPER] Added more cuda wrapped functions 2025-12-10 12:01:00 +01:00
Yang Liu fa03a3915b [LA64_DYNAREC] Refined prefetch opcodes (#3255) 2025-12-10 09:12:06 +01:00
Yang Liu 1cc40d8401 [LA64_DYNAREC] Added more push/pop opcodes (#3254) 2025-12-10 08:09:20 +01:00
ptitSeb 1c282c2c26 [DYNAREC] Adjusted default age for block purge to avoid too much slowdown on steamwebhelper 2025-12-09 22:28:49 +01:00
Yang Liu 2c5bdd76fb [LA64_DYNAREC] Fixed a regression in IMUL opcodes flags computation (#3252) 2025-12-09 20:15:32 +01:00
Yang Liu 789c4e4671 [INTERP] Small fix to F0 0F B1 CMPXCHG opcode (#3251) 2025-12-09 19:32:58 +01:00
phorcys df7d74f418 [LA64_DYNAREC] Opt REP STOSB for withcher3. (#3250) 2025-12-09 18:24:56 +01:00
Chi-Kuan ChiuandptitSeb 98e50e28a6 [DYNAREC_PURGE] Tick-Based Cache Purge System (#3249)
Replace the hot-counter (LFU) purge heuristic with a timestamp-based
mechanism.

The previous logic incremented a hot counter on each execution and
implicitly pinned blocks after a small number of hits, preventing
reclamation even when blocks were no longer used.

The new logic tracks the last execution time using a global tick
counter. A dynarec block becomes purgeable when its age exceeds
BOX64_DYNAREC_PURGE_AGE.

== What is "tick" ==

A global counter that increments every time AllocDynarecMap() is called.
When a block is executed, it copies the current global tick to its own tick field.
This records "when" the block was last used.

== What is "age" ==

age = my_context->tick - dynablock->tick

The difference between the current global tick and the block's tick.
It represents how many allocations have happened since the block was last executed.
A higher age means the block hasn't been used for a longer time.
This shifts eviction from frequency-based to recency-based behavior.

== Configuration ==

 - BOX64_DYNAREC_PURGE=1       Enable purging (default: 0)
 - BOX64_DYNAREC_PURGE_AGE=N   Ticks before purgeable (default: 1024)

TODO: Implement auto-adjusting threshold algorithm.
      Currently users must manually tune BOX64_DYNAREC_PURGE_AGE based on
      their workload. An adaptive algorithm that adjusts based on memory
      pressure and cache hit rate would be better.

Co-authored-by: ptitSeb <[email protected]>
2025-12-09 18:21:22 +01:00
Yang Liu 06296c77c7 [RCFILE] Refined BOX64_STEAM_VULKAN to support more cases (#3248) 2025-12-09 12:42:27 +01:00
Yang Liu db191e2e72 [LA64_DYNAREC] Refactored opcode prefix decoding (#3247) 2025-12-09 11:52:05 +01:00
Yang Liu ed21c85ade [RV64_DYNAREC] Better handling for invalid lock opcodes (#3246) 2025-12-08 18:18:08 +01:00
ptitSeb c59bc5d54a [WRAPPER] Added support for wrapped libnvidia-ml.so 2025-12-08 16:06:18 +01:00
ptitSeb ce88a2be94 [WRAPPER] Added some more Warpped OpenCL functions 2025-12-08 15:18:09 +01:00
ptitSeb 67b1569c11 [ARM64_DYNAREC] Fixed an AVX opcode name 2025-12-08 14:28:09 +01:00
Chi-Kuan Chiu dfb284aa4e Add lookup cache for customMalloc (#3244)
Allocation functions (map64_customMalloc, map128_customMalloc,
internal_customMalloc) always scanned blocks from i=0 to find free space.
Since consecutive allocations often succeed in the same block, we can
skip the linear scan by trying the last successful block first.

Add type-specific caches so each allocator remembers its last successful
block and tries it before falling back to linear scan. The shared
last_block_index is still updated for findBlock compatibility.

  Cost: 4 additional static integers. Miss path unchanged.

Test case: box64 + wine + steam.exe on rpi5

  Results:
  - map64_customMalloc:    99.9% hit rate (25,920 hits / 26 misses)
  - map128_customMalloc:   99.9% hit rate (3,484 hits / 3 misses)
  - internal_customMalloc: 73.9% hit rate (2,574 hits / 907 misses)
  - findBlock:             72.8% hit rate (14,410 hits / 5,374 misses)

At cache hit time, the allocator managed 76-812 blocks (p25-p99),
confirming that skipping linear scan provides measurable benefit.

Block count percentiles at hit time (p25/p50/p75/p99): 76 / 419 / 588 / 812
2025-12-08 11:30:58 +01:00
ptitSeb 056999e8fd Fixed exception handling on wine 10.19+ 2025-12-01 16:41:55 +01:00
ptitSeb 5540c85ae4 [BOX32][WRAPPER] Initialized the array to avoid a valgrind warning 2025-12-01 15:15:01 +01:00
ptitSeb 3e30aa0002 [ARM64_DYNAREC] Refactor opcode prefix decoding, like on interpreter, removing lots of duplicated code and making opcode more generic 2025-12-01 11:17:42 +01:00
ptitSeb 13f9a9f83e [BOX32][WRAPPER] Fixed some issue with wrapped readv 2025-12-01 11:11:31 +01:00
ptitSeb 2d2c6a2aa1 [ARM64_DYNAREC] Fixed some more regression introduced with c64a431e35 2025-11-30 17:01:44 +01:00
Yang Liu 039c6f557e [ARM_DYNAREC] Fixed a regression introduced in commit c64a431e (#3241) 2025-11-29 21:14:41 +01:00
ptitSeb c4e09fddb9 [BOX32][WRAPPER] More fixes to some inplace enlarge functions for X11 2025-11-29 18:22:14 +01:00
Yang Liu 5a0448a1d5 [BOX32] Fixed some inplace shrink/enlarge functions for libxrandr (#3239) 2025-11-29 18:17:12 +01:00
ptitSeb 185de7eaf7 [COSIM] Fixed cosim when using FSGSBASE 2025-11-29 12:33:06 +01:00
Yang Liu 90babc5c45 [WRAPPER] Silent garbage dlerrors when nogtk is used (#3236) 2025-11-29 08:33:10 +01:00
ptitSeb 555b5065a0 [INTERP] Added F0 prefix to the generic prefix handling 2025-11-28 16:16:26 +01:00
ptitSeb c4e821db36 [ARM64_DYNAREC] Fixed more regression introduce with previous previous commit 2025-11-28 15:44:30 +01:00
ptitSeb 8642d48aee [ARM64_DYNAREC] Fixed regression introduce with previous commit 2025-11-28 15:27:20 +01:00
ptitSeb c64a431e35 [ARM64_DYNAREC] Made defered dfnone effect 2025-11-28 12:34:01 +01:00
ptitSeb b0ef9838a3 Fixed a buffer size (for #3235) 2025-11-28 09:31:01 +01:00
Yang Liu ffd32899ef [BOX32] Wrapped more symbols for libc (#3234) 2025-11-28 08:06:11 +01:00
ptitSeb 3059fe2d09 [INTERP] Fake handling of RF ([DYNAREC] too) 2025-11-27 15:50:57 +01:00
ptitSeb be1c926b67 [WRAPPER] Small improvment to some ptrace calls 2025-11-27 15:47:27 +01:00
Yang Liu 76fc77d6f8 [LA64_DYNAREC] Added more opcodes (#3233)
* [LA64_DYNAREC] Added more opcodes

* some fixes
2025-11-27 15:10:46 +01:00
Yang Liu 1eb55587b6 [INTERP][DYNAREC] Added F3 0F 4X CMOVcc opcodes (#3232) 2025-11-27 14:03:15 +01:00
Max Parry 25f0bd14b8 Reimplement my32_mkstemps64 (#3231)
* Reimplement my32_mkstemps64

* Signal header to use exported function
2025-11-27 11:26:05 +01:00
Yang Liu 36b4fbae85 [LA64_DYNAREC] Enable nativeflags optimization for more patterns (#3230) 2025-11-27 10:39:24 +01:00
Yang Liu f6b6066509 [LA64_DYNAREC] Enabled native flags optimization for SETcc opcodes (#3229) 2025-11-27 08:08:31 +01:00
Yang Liu d5d4cc0951 [LA64_DYNAREC] Fixed an incomplete macro (#3226) 2025-11-26 13:53:44 +01:00
Yang Liu 57b9f6ca3c [CORE] Slightly better help message (#3225) 2025-11-26 13:16:13 +01:00
Yang Liu a1945549ad [LA64_DYNAREC] Added more opcodes (#3224) 2025-11-26 10:41:43 +01:00
Yang Liu e8e25b3f01 [LA64_DYNAREC] Added more opcodes (#3223)
* [LA64_DYNAREC] Added more opcodes

* fix
2025-11-26 10:06:02 +01:00
ptitSeb 8491e0d4db [WRAPPER] Added 1 more Vulkan extension (for #3222) 2025-11-26 10:05:11 +01:00
Yang Liu b66c932fbc [WRAPPER][LA64] Added basic simple wrapper support (#3221) 2025-11-26 08:08:59 +01:00
ptitSeb 589d042c34 [TRACE] Reworked a bit how trace are written to files/console 2025-11-25 17:42:06 +01:00
Yang Liu 0add723460 [LA64_DYNAREC] Added more opcodes (#3219) 2025-11-25 17:03:23 +01:00
ptitSeb 024bdffb02 [WRAPPER] Refactored dlsym / dlvsym, removing duplicated code 2025-11-25 12:53:04 +01:00
Yang Liu 12580e593d [LA64_DYNAREC] Added an unaligned path to 16bit XCHG opcode (#3218) 2025-11-24 19:49:55 +01:00
Yang Liu c5ce123d4d [WRAPPER] Re-wrapped libtasn1 (#3217) 2025-11-24 19:16:21 +01:00
Yang Liu c272dd95ec [RCFILE] Added discord profile (#3216) 2025-11-24 17:07:51 +01:00
Yang Liu be8a3bdfdd [SYSCALL] Added io_uring syscalls (#3215) 2025-11-24 17:03:45 +01:00
Yang Liu 8a40b11574 [LA64_DYNAREC] Added a few more 66 opcodes (#3214) 2025-11-24 15:59:50 +01:00
ptitSeb 2fd3238187 [RCFILE] Adjusted one game profile 2025-11-24 13:44:35 +01:00
ptitSeb 1371a34e0d [INTERP] Fixed some rare occurence of 66 8F opcodes 2025-11-24 13:30:10 +01:00
ptitSeb ee345ae46d [COSIM] Introduced BOX64_DYNAREC_TEST_NODUP to filter duplicate IP address in cosim output, and reenabled LOCK prefixed opcodes 2025-11-24 12:29:13 +01:00
ptitSeb cd645f7d7d [STEAM] Removed use of system ldconfig and create needed symlinks instead 2025-11-24 10:56:28 +01:00
phorcys a814aeeb37 [LA64_DYNAREC] Some small fixes. (#3212) 2025-11-24 08:26:12 +01:00
Yang Liu e8611d2f38 [RV64_DYNAREC] Fixed some scratch register conflictions, [LA64_DYNAREC] too (#3213) 2025-11-24 08:24:53 +01:00
Yang Liu c75c8eb4fa [STEAM] Enabled x86_64 python workaround only for Arm (#3211) 2025-11-23 20:00:02 +01:00
ptitSeb 3ec07fa5df [STEAM] Added another potential sources of python3 binary 2025-11-23 17:47:20 +01:00
ptitSeb 6d7b649bcd [BOX32][WRAPPER] Added 1 more 32bit wrapped function to libfreetype 2025-11-23 16:17:20 +01:00
ptitSeb d4f72f8bf5 [STEAM] Added a workaround to use x86_64 python for the proton script, needed for latest experimental version 2025-11-23 16:05:21 +01:00
ptitSeb 7befdcf0a9 [RCFILE] Introduce BOX64_PYTHON3 to have a x86_64 version of python3 running python scripts 2025-11-23 16:02:23 +01:00
ptitSeb 22197b3540 [BOX32][WRAPPER] Fixed 32bits wrapped glob/glob64 functions 2025-11-23 13:21:31 +01:00
Yang Liu 8aa23c5629 [RCFILE] Disabled libcef detection by default (#3209) 2025-11-23 12:11:21 +01:00
Yang Liu 07ef276274 [WRAPPER] Fixed a regression in myStackAlignGVariantNew (#3208)
* [WRAPPER] Fixed a regression in myStackAlignGVariantNew

* push unsaved file
2025-11-23 12:02:21 +01:00
ptitSeb 7988fca992 [BOX32][WRAPPER] Improved wrapeed glob(64) handling 2025-11-23 11:19:28 +01:00
Yang Liu 31db9ecfbc Small optimization to steam_vulkan hack (#3207)
* Small optimization to steam_vulkan hack

* try to fix old gcc build
2025-11-23 10:59:25 +01:00
ptitSeb 3ad3873d80 [BOX32][WRAPPER] Improved wrapping of XChangeProperty 2025-11-23 10:59:08 +01:00
ptitSeb 5b27657166 [BOX32][WRAPPER] Added libtcmalloc to wrapped libs 2025-11-23 10:58:20 +01:00
Yang Liu 984c9d4f2f Reverted some commits (#3206)
* Revert "[BOX32] Added some sanity check on 32bit thread cancel unwind buffers"

This reverts commit fa874dbc0b.

* Revert "[TRACE] Reverted thread local Dump CPU buffer, as it seems to break some tests"

This reverts commit e4a8d7f5c4.
2025-11-23 08:40:36 +01:00
ptitSeb e4a8d7f5c4 [TRACE] Reverted thread local Dump CPU buffer, as it seems to break some tests 2025-11-22 23:17:11 +01:00
ptitSeb 9d0d825f9f [TRACE] Made the static Dump CPU buffer thread local 2025-11-22 17:39:44 +01:00
ptitSeb fa874dbc0b [BOX32] Added some sanity check on 32bit thread cancel unwind buffers 2025-11-22 17:39:04 +01:00
ptitSeb d328d6390b [TRACE] Added thread to the Emit Signal trace 2025-11-22 17:38:16 +01:00
docgalaxyblock 0c405897d3 Fix spelling of 'Snapdragon' in CMakeLists.txt (#3205) 2025-11-22 15:55:00 +01:00
Yang Liu 187b9af1b6 [CMAKE] Fixed a typo (#3204) 2025-11-22 09:45:50 +01:00
Yang Liu cae4502731 [RCFILE] Added a new option BOX64_STEAM_VULKAN (#3203) 2025-11-22 08:50:41 +01:00
Yang Liu a91f6d82d7 Fixed my___tls_get_addr (#3202) 2025-11-21 23:05:43 +01:00
Yang Liu cc389b3ec3 [RCFILE] Updated an obsolete steam option (#3201) 2025-11-21 16:52:20 +01:00
ptitSeb 4b24f51e2d [BOX32][WRAPPER] Fixed some functions signature for wrapped libtcminimal (fix original The Stanley Parable) 2025-11-21 15:53:41 +01:00
ptitSeb e6cbf0975a [DYNAREC] Improved DIRTY=2, making HOTPAGE_ALT useless (will be remove soon) 2025-11-21 14:00:38 +01:00
ptitSeb dc9c82db25 [BOX32][WRAPPER] Added one more symbol to 32bits libc (for #3200) 2025-11-21 13:40:37 +01:00
ptitSeb 63b0debcf1 [WRAPPER] Fixed typo from previous commit ([BOX32] too) 2025-11-21 12:01:21 +01:00
ptitSeb f8cc9de4f8 [BOX32][WRAPPER] New custom implementation for 32bits pthread_once, with some workaround 2025-11-21 11:07:18 +01:00
ptitSeb cfb8879410 [WRAPPER] New custom implementation for pthread_once, with some workaround 2025-11-21 11:07:02 +01:00
ptitSeb 6f7519b36e [TRACE] Slightly better trace for code that write on protected executable pages 2025-11-21 11:06:23 +01:00
Yang Liu 85bcfadfd6 Implemented a few more libc syscalls (#3199) 2025-11-21 10:13:59 +01:00
Yang Liu c71e688663 Fixed a typo introduced in last block optimisation (#3198) 2025-11-21 08:16:31 +01:00
Yang Liu de69cb4f7b [CMAKE] Fixed git_head dependencies (#3197) 2025-11-21 08:15:20 +01:00
Yang Liu 9efde7809c [CI] Removed os from the matrix (#3196) 2025-11-21 08:14:33 +01:00
Yang Liu a170660a81 [WRAPPER] Wrapped more symbols (#3195) 2025-11-20 20:39:15 +01:00
ptitSeb ad90eaef8d Introducing EmuRun, to have proper handling of LongJump on CallBack and on Interpreter only build 2025-11-20 13:14:47 +01:00
Yang Liu 05c75d7182 [LA64_DYNAREC] Added more opcodes (#3194) 2025-11-20 12:12:19 +01:00
ptitSeb a1e8ff3faf [INTERP] Fixed 0F C7 non REX.W opcode 2025-11-20 12:11:51 +01:00
ptitSeb 3cea6dab34 [BOX32][WRAPPER] Added some more X11 symbols (for SDL3) 2025-11-20 11:28:55 +01:00
ptitSeb 27fba0e0eb [BOX32][WRAPPER] Added a couple of libc symbols 2025-11-20 09:43:43 +01:00
442d727f5e Add support for NVIDIA GB10/DGX Spark platform (#3191)
* Add support for NVIDIA GB10/DGX Spark platform

- Add NVIDIA_GB10 cmake option with -mcpu=gb10 and -mtune=gb10 flags
- Add compilation documentation for GB10 (Cortex-A725 + Cortex-X925)
- Include fallback march flags for GCC 14 and older
- Requires GCC 15.2.0+ for optimal gb10 support

* Update CMakeLists.txt

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: ptitSeb <[email protected]>
Co-authored-by: Copilot <[email protected]>
2025-11-20 08:53:53 +01:00
ptitSeb cb26e7f3fe Improved the last_bock optimisation 2025-11-19 16:26:23 +01:00
ptitSeb f74b67ed8f [TRACE] Name the rb_tree when printing it's unstable 2025-11-19 15:37:32 +01:00
phorcys 0a37916aa3 [LA64_DYNAREC] Fix 8-bit lock macros, Add F0 08 LOCK OR Eb, Gb. (#3188)
*  Fix 8-bit lock macros.
  *  Fix 0F 00 LOCK ADD Eb, Gb
  *  Add 0F 08 LOCK OR Eb, Gb
2025-11-19 11:11:58 +01:00
ptitSeb 41bdb5db66 [BOX32] Another attempt to fix build on older system 2025-11-18 16:54:10 +01:00
ptitSeb 13d0814c4d [BOX32] Try to fix build on older system 2025-11-18 16:23:16 +01:00
ptitSeb cc00818d1d [BOX32][WRAPPER] Added 1 more extension to libGL 2025-11-18 15:43:09 +01:00
ptitSeb c5aa4e7d49 [WRAPPER] Added 1 more extension to libGL 2025-11-18 15:42:31 +01:00
Yang Liu 82fbf9db7d [BOX32] Slient some warnings on padding fields (#3189) 2025-11-18 15:18:11 +01:00
ptitSeb 7b456fe1fa [BOX32][WRAPPER] Better wrapping for input event files (fixing some 32bits games and SteamInput in general) 2025-11-18 15:11:24 +01:00
phorcys b2db02a5a8 [LA64_DYNAREC] Fix avx VCVTPH2PS,VCVTDQ2PD. (#3187)
LoongArch xvffint{l,h}.d.w  xvfcvt{l,h}.s.h operate cross per 128bits channel.
2025-11-18 08:22:39 +01:00
phorcys e3b13ebd7d [LA64_DYNAREC] Fix avx VAES{IMC,INC,INCLAST,DEC,DECLAST}. (#3186)
Fix for missing 256-bits width aes.
2025-11-18 08:16:05 +01:00
phorcys 2d5b7bf979 [LA64_DYNAREC] Fix avx V{P,}GATHER{DD,DPD,QPS,QD}. (#3185)
Fix wrong xmm/ymm register width.
2025-11-18 08:06:06 +01:00
Chi-Kuan Chiu 5d7a86551e [DYNAREC_PURGE] Decrement in_used before longjmp (#3184)
Signal handlers that use siglongjmp() to escape from dynarec blocks were
abandoning blocks without decrementing their in_used reference count,
causing blocks to remain permanently marked as in-use and preventing
them from being freed even when they're no longer needed.
2025-11-17 21:48:41 +01:00
ptitSeb f69ab5733c [BOX32][WRAPPER] Improved XFixes XEvent wrapping 2025-11-17 20:03:04 +01:00
ptitSeb 3f7facd8e0 [BOX32][WRAPPER] Wrapped XINput2 XEvents 2025-11-17 19:33:00 +01:00
ptitSeb 60cea01eb5 [STEAM] Use elulated libgnutls when using a steam runtime 2025-11-17 19:32:23 +01:00
ptitSeb 809d51bd8a [DYNAREC] Speedup sequence of mmap/munmap when prot is 0 2025-11-17 16:23:44 +01:00
ptitSeb f6bec4e201 [BOX32][WRAPPER] Added 3 more wrapped functions to libfontconfig 2025-11-17 16:10:22 +01:00
ptitSeb 2bf6aa8648 [WRAPPER] Removed custom implementationof pthread_once as it did handled the 'inprogress' state 2025-11-17 14:24:10 +01:00
ptitSeb db03c644e9 [WRAPPER] Removed custom implementationof pthread_once as it did handled the 'inprogress' state 2025-11-17 14:24:03 +01:00
ptitSeb bffc81e547 [ELFLOADER] Improved a comment 2025-11-17 13:55:33 +01:00
ptitSeb c723d10dc2 [TRACE] Better trace for a dbus function 2025-11-17 13:55:11 +01:00
Leslie Zhai a453563f02 [LA64_DYNAREC] Fix incorrect stack alignment (#3183) 2025-11-17 11:31:04 +01:00
ptitSeb 6489fc199b [STEAM] Improved pressure_vessel handling 2025-11-16 17:39:47 +01:00
ptitSeb 3d378366df [DYNAREC] Better log when writing on active code page 2025-11-16 17:39:16 +01:00
Yang Liu ad60ba9fe2 [WRAPPER] Wrapped 2 more symbols (#3181) 2025-11-16 16:16:00 +01:00
ptitSeb 871259b47d [DYNACACHE] Some small improvment in dynablocks relocations at load 2025-11-16 14:42:21 +01:00
ptitSeb 22c7db557a [DYNAREC] Fixed a potential SIGFAULT when AllocDynarecMap fails 2025-11-16 14:41:47 +01:00
ptitSeb f2058e56f6 [DYNAREC] Some small fixes for when a dynablocks has a prefix 2025-11-16 14:25:14 +01:00
ptitSeb c5444fc67d [DYNAREC][ARM64_DYNAREC] Fixed some regression with getX64Address utility function 2025-11-16 14:23:08 +01:00
ptitSeb 66c09a7f7f [DYNAREC] Improved the unity3d strongmem hack 2025-11-16 11:24:41 +01:00
Yang Liu 8d3b6c5423 [LA64_DYNAREC] Refined IMUL opcodes flags computation (#3180) 2025-11-15 17:55:01 +01:00
ptitSeb 3e8c02d645 [RCFILE] Added 1 more game profile 2025-11-15 16:52:27 +01:00
ptitSeb e34da3a466 [ARM64_DYNAREC][DYNAREC_PURGE] Changed how dynablocks are checked for purge 2025-11-15 16:50:44 +01:00
Yang Liu 476592df7c [INTERP] Fixed 67 prefix handling for LEA opcode (#3179) 2025-11-15 16:40:06 +01:00
Yang Liu 9939760901 [LA64_DYNAREC] Fixed a regression introduced in 14e3d05 (#3178) 2025-11-15 16:21:56 +01:00
Yang Liu 510966a8f9 [WRAPPER] Wrapped 1 more glib2 function (#3177) 2025-11-15 16:21:27 +01:00
ptitSeb 751c229c00 [ARM64_DYNAREC][DYNAREC_PURGE] Decrement in_used when leaving block via CALLRET return too 2025-11-15 14:42:18 +01:00
Yang Liu 0a84ed5dae [DOCS] Refined usage documentation with recent changes (#3176) 2025-11-15 14:39:15 +01:00
Yang Liu f3d3f1a84e [LA64_DYNAREC] Added more opcodes (#3175) 2025-11-15 13:00:22 +01:00
Yang Liu d37b843ee9 [LA64_DYNAREC] Optimized some emit functions (#3174) 2025-11-15 12:59:27 +01:00
ptitSeb ccac55667d Fix non ARM64 Dynarec build 2025-11-15 11:06:35 +01:00
ptitSeb 81b080eb5d [ARM64_DYNAREC] Introduced DYNAREC_PURGE to allow purging old unsed dynablock and save memory 2025-11-15 10:42:56 +01:00
Yang Liu cc541b08c3 [RV64_DYNAREC] Added a few more 16bit opcodes and some fixes too (#3173) 2025-11-14 13:38:14 +01:00
ptitSeb e90676213a [ARM64_DYNAREC] Added preload of xmm/ymm regs mcanism for internal loops 2025-11-14 11:41:58 +01:00
a9ix adef248942 [WRAPPER] Wrap libicu76 (#3172) 2025-11-14 08:22:12 +01:00
Yang Liu c6e9b87ef3 [RV64_DYNAREC] Added more lock opcodes (#3171) 2025-11-13 16:10:54 +01:00
ptitSeb ca9da1855a [ARM64_DYNAREC] Avoid some visiting dynablocks when unneeded (like no x87 is used) 2025-11-13 11:01:19 +01:00
Chi-Kuan Chiu b6fb4865fb [Docs] Update outdated information in rbtree.h (#3170)
The descriptions were incorrect.
2025-11-12 22:18:10 +01:00
Yang Liu 6af34e0c43 [BOX32] Implemented getdents syscall (#3168)
* [BOX32] Implemented getdents syscall

* fix
2025-11-12 14:05:50 +01:00
Yang Liu f4ce7a0893 [BOX32] Silence a false warning (#3169) 2025-11-12 13:08:04 +01:00
Yang Liu 6f658a9b2c [TRACE][BOX32] Fixed a crash in nanosleep tracing (#3167) 2025-11-12 11:39:21 +01:00
ptitSeb c35af59da9 [WRAPPER] Removed some duplicated code in libc wrapping 2025-11-12 09:36:08 +01:00
ptitSeb 3872d8df46 [ARM64_DYNAREC] Avoid dumping uneeded xmm/ymm register when purging all fetched register on internal jump 2025-11-12 09:25:17 +01:00
Yang Liu fbbf74f601 [CORE] Added back the logging prefix (#3166) 2025-11-11 19:51:38 +01:00
Yang Liu a5ec9bfc4c [RV64_DYNAREC][LA64_DYNAREC] Fixed a wrong modreg test in nativeflags (#3165) 2025-11-11 18:30:14 +01:00
Yang Liu 0adaa219bf [LA64] Fixed a typo in last PR (#3164) 2025-11-11 23:27:31 +08:00
Yang Liu 0358034389 [LA64] Optimized CRC chksum with native instructions (#3163) 2025-11-11 15:59:39 +01:00
Yang Liu c674c13114 [LA64_DYNAREC] Added a few more opcodes (#3161) 2025-11-11 11:45:50 +01:00
Chi-Kuan Chiu a1bf126d7b Add block lookup cache to optimize findBlock() (#3160)
Cache last found block to skip RB-tree lookup on consecutive accesses.
Safe during re-entrance via direct pointer dereference (reads NULL when
blocks temporarily zeroed, causing natural cache miss).

Cache hit rates measured in real workloads:
- Small program (qsort): 64.7% (249/136)
- Large game ELF: 72.7% (35,392/13,302)
- Large game PE+Wine: 85.3% (64,432/11,097)

Wine workloads benefit most due to intensive allocation patterns.
Converts 65-85% of O(log n) lookups to O(1) cache hits.
2025-11-11 11:40:02 +01:00
phorcys 36a5020d36 [LA64_DYNAREC] Add 66 87 (LOCK) XCHG Ew, Gw. (#3157)
For steamwebhelper.
2025-11-11 09:40:57 +01:00
Yang Liu 94c7dd5796 [LA64_DYNAREC] Added more opcodes (#3158) 2025-11-10 19:31:13 +01:00
ptitSeb 8c5a5d9fb5 [ELFLOADER] Some fixes of TLS data handling 2025-11-10 17:35:29 +01:00
phorcys 2f23cf5812 [LA64_DYNAREC] Add 66 8C MOV Ew, Seg. (#3155)
For wine-10.x ntdll.
2025-11-10 17:00:28 +01:00
Yang Liu 85fd15902f [LA64_DYNAREC] Refined more flags computation (#3156) 2025-11-10 17:00:00 +01:00
phorcys 96708b31d5 [LA64_DYNAREC] Add 66 F0 0F B1 LOCK CMPXCHG Ew, Gw. (#3149)
For steamwebhelper.
2025-11-10 16:58:48 +01:00
Yang Liu b1824baf2b [INTERP] Refined BSF/BSR undefined behaviour (#3154) 2025-11-10 16:00:48 +01:00
ptitSeb 53528ddd61 [BOX32][WRAPPER] A few more functions and fixes to libc 2025-11-10 15:40:23 +01:00
ptitSeb fe19ac7c6d [BOX32][WRAPPER] A few more wrapped symbols to libc, plus some fixes 2025-11-10 15:15:09 +01:00
ptitSeb 7fec355012 [BOX32][WRAPPER] Fixed/improved dbus_message_iter_append_basic 2025-11-10 14:36:34 +01:00
Yang Liu 838060f996 [RV64_DYNAREC] Fixed some typos for nativeflags (#3153) 2025-11-10 14:12:42 +01:00
Yang Liu cebeff3d3e [LA64_DYNAREC] Refined more flags computation (#3152) 2025-11-10 11:52:42 +01:00
Yang Liu d117c77247 [RV64_DYNAREC] Fixed some minor issues for 16bit SHLD/SHRD opcodes (#3150) 2025-11-10 11:10:21 +01:00
Yang Liu 901811b8f9 [LA64_DYNAREC] Refined more flags computation (#3151) 2025-11-10 10:47:49 +01:00
ptitSeb f97a25ae0c [BOX32][WRAPPER] Imrpoved wrapping for XGetICValues 2025-11-10 08:56:24 +01:00
ptitSeb 87683a18f5 [BOX32][WRAPPER] Added support for Xkb events 2025-11-09 17:43:22 +01:00
ptitSeb dfd5ed8675 [DYNAREC] Added a workaround to avoid STRONGMEM=1 in most Unity games (thanks to @ByLaws for the hint) 2025-11-09 16:32:17 +01:00
ptitSeb 1fab6582d7 [DYNAREC] Fixed a potential Fillblock issue at border of page 2025-11-09 09:54:45 +01:00
Yang Liu 164a85c18f [RCFILE] Removed some obsolete hacks on Linux Steam (#3148) 2025-11-09 09:48:53 +01:00
Yang Liu 9d6488b35d [LA64_DYNAREC] Fixed more regressions introduced in 14e3d05 and 44822bb (#3147) 2025-11-08 22:42:41 +01:00
Yang Liu 0ef66adfa9 [LA64_DYNAREC] Refined more flags computation (#3145)
* [LA64_DYNAREC] Refined more flags computation

* more
2025-11-08 19:54:32 +01:00
ptitSeb 564a75b917 Small improvment on signal handling 2025-11-08 18:50:35 +01:00
Yang Liu 05e4b4592d [LA64_DYNAREC] Refined more flags computation (#3144) 2025-11-08 18:34:57 +01:00
Yang Liu 7faeec0864 [DYNAREC] Fixed some safeflags testing code (#3143) 2025-11-08 13:43:47 +01:00
Yang Liu 08cf5fd6c3 [LA64_DYNAREC] Refined some more flags computation (#3142) 2025-11-08 13:39:06 +01:00
Yang Liu 26aae9ba3b [LA64_DYNAREC] Refined BSF/BSR opcodes and fixed some typos (#3141) 2025-11-08 12:48:46 +01:00
ptitSeb 9b7c83f885 Added 1 more 64bits syscall 2025-11-08 12:00:39 +01:00
Yang Liu b2830d3070 [LA64_DYNAREC] Refined register names (#3140) 2025-11-08 11:57:48 +01:00
phorcys b6024590ef [LA64_DYNAREC] Update lock 32/64 macro. (#3139)
use s1-s7.
2025-11-08 10:36:57 +01:00
Yang Liu 7ee7b99a84 [CORE] Print logs to stderr by default (#3137) 2025-11-08 10:36:21 +01:00
ptitSeb 93ff6ca414 [TRACE] Show FSGSBASE trace in hex in signal 2025-11-08 10:35:39 +01:00
Yang Liu 78080748e6 [RV64_DYNAREC] Refined BSR/BSF undefined behaviour (#3136) 2025-11-07 16:50:38 +01:00
ptitSeb 522f8c3dd0 [ELFLOADER][WRAPPER] Improved handling of dlsym(RTLD_NEXT, ....) 2025-11-07 16:36:14 +01:00
Yang Liu 4825b31305 [ARM64_DYNAREC] Refined BSR/BSF undefined behaviour (#3135) 2025-11-07 16:33:56 +01:00
phorcys a96f2dcda9 [LA64_DYNAREC] Add 8bits lock op macros. (#3127)
*  Add LOCK_8_ALIGNED_4BYTE, LOCK_8_IN_4BYTE macro.
  *  F0 00 LOCK ADD Eb, Gb
2025-11-07 16:12:21 +01:00
phorcys 08f2f8255d [LA64_DYNAREC] Opt rol with LBT insts. (#3130)
Opt rol with rotr.{b,h}, rotri.{b,h}.
Those insts are list in LBT section in binutils.
https://github.com/bminor/binutils-gdb/blob/58fedddb895318d72189dbae912f4902dab96b4c/opcodes/loongarch-opc.c#L2538
2025-11-07 16:10:34 +01:00
Yang Liu 3004c7f280 [RV64_DYNAREC] Small improvments on some invalid opcodes handling (#3134) 2025-11-07 15:51:26 +01:00
ptitSeb f649132b6f Reserved highest 32bits 64K memory for Box32 or Wine to reduce potential overflow addresses computations 2025-11-07 15:35:11 +01:00
ptitSeb 503cf716ec [RCFILE][WRAPPER] Some work for GigaTribe (for #1409) 2025-11-07 14:00:42 +01:00
Yang Liu 5b8f18f6bf [RV64_DYNAREC] Refined some more flags computation (#3133) 2025-11-07 13:06:34 +01:00
ptitSeb e78169bc4e [DYNAREC] Some refactor around Hotpages and SMC code 2025-11-07 13:00:26 +01:00
ptitSeb fa7a4ce29c [LA64_DYNAREC] Fixed regression introduced by 14e3d05b87 (for #3132) 2025-11-07 10:11:28 +01:00
ptitSeb 37040f3b49 [BOX32][ELFLOADER] Added support for IFUNC in PltResolver 2025-11-06 09:50:35 +01:00
ptitSeb 4a1f92a634 [ELFLOADER] Added support for IFUNC in PltResolver 2025-11-06 09:50:24 +01:00
谢致邦 (XIE Zhibang) bffca555a3 [DOCS] fix typos (#3131)
Original-author: Johannes Schauer Marin Rodrigues <[email protected]>
Link: https://salsa.debian.org/debian/box64/-/commit/ed8749048c47b20edc4c601a86ba65871bad5b74
2025-11-06 08:06:02 +01:00
Yang Liu dcd3ba0d16 [RV64_DYNAREC] Refined more flags computation (#3129) 2025-11-05 16:48:30 +01:00
ptitSeb b2e68e8032 [BOX32] Fixed hash key creation 2025-11-05 15:08:02 +01:00
ptitSeb e0a67969ca [ARM64_DYNAREC] Fixed 32bits 67 64 prefixed opcode not being decoded by dynarec 2025-11-05 12:12:18 +01:00
ptitSeb a5ef0c2ac0 [INTERP] Fixed 32bits 67 64/65 prefixed opcodes 2025-11-05 12:02:03 +01:00
phorcys 14e3d05b87 [LA64_DYNAREC] Add more 32/64 lock opcodes. (#3126)
*  87 LOCK XCHG Ed, Gd
  *  F0 09 LOCK OR Ed, Gd
  *  F0 21 LOCK AND Ed, Gd
  *  F0 31 LOCK XOR Ed, Gd
  *  F0 81/83 /1 LOCK OR Ed, Id/Ib
  *  F0 81/83 /4 LOCK AND Ed, Id/Ib
  *  F0 81/83 /6 LOCK XOR Ed, Id/Ib
  *  F0 87 LOCK XCHG Ed, Gd
  *  F0 F7 /2 LOCK NOT Ed
  *  F0 F7 /3  fix LOCK NEG, not reading CF.
  *  Guard amo op's B_MARK3_nocond with ALIGNED_ATOMICxw
2025-11-05 11:12:43 +01:00
ptitSeb 85e48644b1 [LA64_DYNAREC] Fixed issue introduced with 2b070086 2025-11-05 09:12:51 +01:00
ptitSeb ec7a898058 [LA64_DYNAREC] Fixed issue introduced with 2b070086 (for #3125) 2025-11-05 09:10:05 +01:00
ptitSeb d0dccb8e19 [LA64_DYNAREC] Fix issue introduced with #3118 2025-11-05 08:48:53 +01:00
phorcys 85125305b9 [LA64_DYNAREC] Fix avx V{/P}GATHER{DD/DQ/DPD/DPS/QD/QPS}. (#3121)
*  index should be signed extended.
*  for VEX.128 QD/QPS , DEST[127:64] should fill with zero.
2025-11-05 07:45:56 +01:00
phorcys 0c00db9851 [LA64_DYNAREC] Add rol8 opcodes. (#3120)
small fix for rol16/32/64
Add rol8.
2025-11-05 07:45:24 +01:00
phorcys 91163afd7b [LA64_DYNAREC] Add more 32/64 bits arith lock opcodes. (#3118)
*  Fix LOCK_32_IN_8BYTE
  *  F0 0F C1 /0 LOCK XADD Ed, Gd
  *  F0 11 LOCK ADC Ed, Gd
  *  F0 19 LOCK SBB Ed, Gd
  *  F0 29 LOCK SUB Ed, Gd
  *  F0 81/83 /2 LOCK ADC Ed, Id/Ib
  *  F0 81/83 /3 LOCK SBB Ed, Id/Ib
  *  F0 81/83 /5 LOCK SUB Ed, Id/Ib
  *  F0 F7 /3 LOCK NEG Ed
  *  F0 FF /0 LOCK INC Ed
  *  F0 FF /1 LOCK DEC Ed
2025-11-05 07:44:58 +01:00
The Great Wizard Azkali db20fd7e49 [BOX32][WRAPPER] Added a missing 32bits function to libc (#3124) 2025-11-04 18:57:18 +01:00
谢致邦 (XIE Zhibang) e6843dcb9f [CMAKE] Fix typo (#3122) 2025-11-04 11:54:12 +01:00
ptitSeb 2ecde96fe2 [BOX32][WRAPPING] Better wrapping for pthread_yield (for #3119) 2025-11-04 09:04:35 +01:00
ptitSeb 1a552f2105 [ARM64_DYNAREC] Some small optimisation on various x87 opcodes 2025-11-03 16:58:46 +01:00
ptitSeb 86a207cf36 [DYNAREC] Inc DynaCache version to take FSGSBASE into account 2025-11-03 16:52:30 +01:00
Yang Liu af99dd0e76 [ARM64_DYNAREC] Refined UD behaviour of 16bit ROL/ROR opcodes (#3117) 2025-11-03 15:08:48 +01:00
Yang Liu bb7d674582 [INTERP] Refined UD behaviour of 16bit ROL/ROR opcodes (#3116) 2025-11-03 11:53:53 +01:00
ptitSeb 4f37a9a7dd [DYNAREC] Small optimisation on linux syscall 2025-11-03 11:07:19 +01:00
Yang Liu 6c291548f0 [INTERP] Refined BSF/BSR ud value (#3115) 2025-11-03 09:58:31 +01:00
ptitSeb 2b070086d1 Added FSGSBASE cpu extension 2025-11-03 07:44:04 +01:00
Yang Liu 8b72b3bf70 [RV64_DYNAREC] Refined BSF/BSR opcodes flags emulation (#3114) 2025-11-02 20:15:39 +01:00
phorcys 44822bb07b [LA64_DYNAREC] Add macros help unaligned lock opcodes. (#3107)
This patch add Macro for 32/64 bits lock opcodes.
Added lock add ed, gd/lock add ed, ib/id.
2025-11-02 17:21:23 +01:00
Yang Liu 75ea309ca1 [RV64_DYNAREC] Refined LZCNT/TZCNT flags emulation (#3113) 2025-11-02 17:20:48 +01:00
Yang Liu de020c2b4c [RV64_DYNAREC] Refined MUL/DIV flags emulation (#3112)
* [RV64_DYNAREC] Refined MUL/DIV flags emulation

* hmm
2025-11-02 17:02:34 +01:00
Yang Liu 8caf35ccd8 [RV64_DYNAREC] Refined SHLD/SHRD flags emulation (#3111) 2025-11-02 15:36:11 +01:00
phorcys 0ab3d844e7 [LA64_DYNAREC] Add rol16/rol16c opcodes. (#3110)
66 C1/D1/D3 /0  ROL Ew, Ib/1/CL
2025-11-02 15:26:05 +01:00
ptitSeb 1c34a7ce38 [RCFILE] Added some new profile, and fine tuned a few existing ones 2025-11-02 13:13:34 +01:00
ptitSeb 3f0400a89b Prepend system libs to steam one (help wit Oxygen Not Included, maybe more) 2025-11-01 10:55:32 +01:00
ptitSeb cd26f27e98 [TRACE] Small improvment in elfloader dump 2025-11-01 10:55:32 +01:00
Yang Liu 713c137e09 [RV64_DYNAREC] Refined ROL/ROR opcodes OF handling (#3109) 2025-10-31 18:02:01 +01:00
Yang Liu 64a6802b5e [RV64_DYNAREC] Refined SHL/SHR opcodes OF handling (#3106) 2025-10-31 10:27:34 +01:00
phorcys 2286636386 [LA64_DYNAREC] Add ADX opcodes. (#3103)
66 0F 38 F6 ADCX
F3 0F 38 F6 ADOX
2025-10-31 09:56:42 +01:00
Yang Liu c51edca058 [TEST] Added flags checking (#3105) 2025-10-31 09:49:45 +01:00
phorcys 69a549eb8f [LA64_DYNAREC] Add more opcodes for steam. (#3104)
06 PUSH ES
07 POP ES
36 SS
C8 ENTER
CB FAR RET
D7 XLAT
E4-E7  IN/OUT
FA CLI
FB STI
0F 0D /0 /2   PREFETCH
64 00 ADD Seg:Eb, Gb
2025-10-31 09:38:09 +01:00
ptitSeb 073a8ba703 [WRAPPER] Added __udivti3 to libc (for #1269) 2025-10-31 09:29:54 +01:00
ptitSeb 4a9fbf10c4 More work on refactoring Selector/Segments 2025-10-31 08:39:34 +01:00
Yang Liu f3fbff531c [TEST] Added cputype option (#3102)
* [TEST] Added cputype option

* tweaks
2025-10-30 19:36:28 +01:00
phorcysandphorcys 894712461f [LA64_DYNAREC] Add more 64 opcodes. (#3100)
64 0F 10 /1 MOVSD Gx, Seg:Ex
64 0F 10 /2 MOVSS Gx, Seg:Ex
64 0F 11 /0 MOVUPS Seg:Ex, Gx
64 0F 11 /1 MOVSD Seg:Ex, Gx
64 0F 11 /2 MOVSS Seg:Ex, Gx
64 0F 28 /0 MOVAPS Gx, Seg:Ex
64 0F 29 /0 MOVAPS Seg:Ex, Gx
64 0F 6F /2 MOVDQU Gx, Seg:Ex
64 0F 7F /2 MOVDQU Seg:Ex, Gx
64 0F B6 /0 MOVZX Gd, Seg:Eb
64 39 CMP Seg:Ed, Gd
64 3B CMP Gd, Seg:Ed

For wine wow64

Co-authored-by: phorcys <[email protected]>
2025-10-30 17:07:04 +01:00
ptitSeb af97642dba [COSIM] More fixes to issues introduced with last commit 2025-10-30 13:26:15 +01:00
ptitSeb 425f838ee8 [COSIM] Fixed issue introduced with last commit 2025-10-30 13:09:00 +01:00
ptitSeb 9c8b92e8df Some more refactor around Segments and TLS data 2025-10-30 11:35:06 +01:00
Yang Liu 302dfbe539 [STEAM] Added docs and some tweaks for Linux Steam, also added a new env var for it (#3101)
* [STEAM] Added docs and some tweaks for Linux Steam, also added a new env var for it

* more tweaks

* refine chinese docs
2025-10-29 16:32:23 +01:00
ptitSeb 6a717bd7c6 [ARM64_DYNAREC] Fixed UD behaviour of bsr/bsf when input is 0 2025-10-29 16:11:56 +01:00
ptitSeb b2b6d12508 [LA64] Forcing BAD_PKILL configuration on Loongarch 2025-10-29 12:01:52 +01:00
ptitSeb 86e8a24d0d Added BAD_PKILL build option, and linked LA64 to it (fixes Steam download issue on Loongarch) 2025-10-29 11:58:57 +01:00
ptitSeb a9a27a93d2 [WOWBOX64] Fixed some warning 2025-10-29 11:07:39 +01:00
ptitSeb ab8731411e [DYNAREC] Introduced DYNAREC_NOARCH to save a bit of memory when strict signal register unwind is not needed 2025-10-29 10:35:08 +01:00
phorcysandphorcys 1f7a69ef31 [LA64_DYNAREC] Add LOCK BTS/BTR. (#3093)
F0 0F AB  LOCK BTS Ed, Gd
F0 0F B3  LOCK BTR Ed, Gd
F0 0F BA /5 LOCK BTS Ed, Ib
F0 0F BA /6 LOCK BTR ED, Ib
66 F0 0F AB  LOCK BTS Ew, Gw
66 F0 0F B3  LOCK BTR Ew, Gw
66 F0 0F BA /5 LOCK BTS Ew, Ib
66 F0 0F BA /6 LOCK BTR Ew, Ib

Co-authored-by: phorcys <[email protected]>
2025-10-29 09:36:00 +01:00
Yang Liu 01e906ead8 [LA64_DYNAREC] Fixed a typo in last commit (#3099) 2025-10-29 08:56:11 +01:00
Yang Liu 5d02f2cb1b [LA64_DYNAREC] Replaced the ADDSL macro from RV64 to ALSL_D (#3098)
* [LA64_DYNAREC] Replaced the ADDSL macro from RV64 to ALSL_D

* fix
2025-10-29 08:37:58 +01:00
phorcysandphorcys b066ca201c [LA64_DYNAREC] Add more ops. (#3096)
MOV Seg:Ed, Gd
MOV Gd, Seg:Ed

Needed by dxvk-2.7.1 dxgi.dll

Co-authored-by: phorcys <[email protected]>
2025-10-29 07:49:25 +01:00
ptitSeb e735a591a0 [RCFILE][LA64][RV64] Use specific profile for DG2 on LA64 & RV64 2025-10-28 15:05:17 +01:00
Leslie Zhai e49c4d78d0 [WRAPPER] Add wrapper for rintl (#3097) 2025-10-28 13:10:33 +01:00
Leslie Zhai e6c4bbcd41 [WRAPPER] Add some wrappers for libm (#3094) 2025-10-28 08:54:58 +01:00
ptitSeb 8be949ba57 [RCFILE][BOX32] Move profile for DG2 2025-10-27 11:52:44 +01:00
ptitSeb 6d74f71d96 [RCFILE] Added a profile for DG2 2025-10-27 11:51:50 +01:00
phorcysandphorcys b4adf1e8ef [LA64_DYNAREC] Add more 00 opcodes. (#3092)
For steam linux.
60 PUSHAD
61 POPAD
62 BOUND
F1 INT1
FF /5 JMP FAR Ed

Co-authored-by: phorcys <[email protected]>
2025-10-27 10:30:58 +01:00
ptitSeb 435dce44ac [DYNAREC][TRACE] Fixed default value for BOX64_NODYNAREC_DELAY 2025-10-26 18:43:48 +01:00
ptitSeb f71fd3d2c1 [BOX32][WRAPPER] Added 1 more function to 32bits wrapped SDL2 2025-10-26 16:35:14 +01:00
ptitSeb 44e4ba2d01 [DYNAREC] Create BOX64_NODYNAREC_DELAY and use it as a workaround for a race condition in UPlay launcher 2025-10-26 16:28:28 +01:00
ptitSeb 716433658c [BOX32][WRAPPER] Improved wrapping of 32bits function nftw callback 2025-10-26 15:56:31 +01:00
ptitSeb 4e80fdfaef [ARM64_DYNAREC] Remove some assert (and replaced one with a dynarec_log) 2025-10-26 13:47:20 +01:00
ptitSeb 3280f02135 [DYNAREC] Removed some unused code 2025-10-26 10:57:26 +01:00
ptitSeb c985fe1bb7 [ARM64_DYNAREC] Added 0F 20..23 opcodes 2025-10-25 15:30:23 +02:00
ptitSeb c95c16231d [INTERP] Improved handlingof 0F 20..23 opcodes 2025-10-25 15:29:58 +02:00
Yang Liu 448ee01f44 [LA64] Fixed LBT signal handling for ABI 1.0 (#3088)
* [LA64] Fixed LBT signal handling for ABI 1.0

* fix
2025-10-23 19:12:06 +02:00
ptitSeb ea86135152 [WRAPPER] Fix build 2025-10-23 17:38:43 +02:00
ptitSeb b079d85636 [WRAPPER] Fixed a potential leak with xcb_connection 2025-10-23 17:13:12 +02:00
ptitSeb 46489c3cd6 [TRACE] Fixing wrapping name print utility function 2025-10-23 14:18:28 +02:00
ptitSeb ab72625a8f [RCFILE] Added a profile for linux Steam 2025-10-23 14:10:00 +02:00
ptitSeb f1ee1933b1 [TRACE] Added a utility function to print a wrapped function name 2025-10-23 13:38:17 +02:00
ptitSeb ec39c6393e [BOX32][WRAPPER] This fhousl fix some builds 2025-10-23 13:35:01 +02:00
ptitSeb f65b57bfac [BOX32][WRAPPER] Fixed a leak with xcb_connections (for #3089) 2025-10-23 12:08:13 +02:00
phorcysandphorcys 1cd7edf172 [LA64_DYNAREC] Add more ops. (#3091)
For steam.
1E/1F  PUSH/POP DS
AC/AD  REP LODSB/LODSD
66.A1/A3  MOV EAX,0d, MOV 0d, EAX

Co-authored-by: phorcys <[email protected]>
2025-10-22 18:21:58 +02:00
ckrinitsin 5f7a1982ac [TRACE] Fix flags output for better parsing (#3090) 2025-10-22 18:20:31 +02:00
ptitSeb d42055477c [INTERP] Removed a file leftover since last interpreter refactor 2025-10-22 15:13:31 +02:00
Yang Liu 83082b081c [RCFILE] Optimized Windows Steam download speed for LA64 and RV64 (#3087) 2025-10-22 14:42:28 +02:00
Yang Liu 66e8828345 [ENV] Introduced BOX64_PCLMULQDQ (#3086)
* [ENV] Introduced BOX64_PCLMULQDQ

* review
2025-10-22 14:41:30 +02:00
Yang Liu 0850dec01f [DYNAREC] Fixed getX64Address empty block handling (#3085) 2025-10-22 14:00:21 +02:00
Yang Liu 1a27269089 [LA64_DYNAREC] Added unaligned F0 81/83 /0,5 LOCK ADD/SUB opcodes (#3084)
* [LA64_DYNAREC] Added unaligned F0 81/83 /5 LOCK SUB opcodes

* add too
2025-10-21 23:01:50 +02:00
Yang Liu 6c1fce4a01 [DYNAREC] Fixed native_fprem/native_fprem1 (fixed the camera issue of FlatOut/FlatOut2) (#3083) 2025-10-21 21:02:06 +02:00
Yang Liu 79efa2d8e5 [RV64_DYNAREC] Added DB /2 FIST opcode (#3082) 2025-10-21 20:37:39 +02:00
Yang Liu 83a37589f2 [LA64_DYNAREC] Added a few more opcodes (#3081) 2025-10-21 20:26:50 +02:00
Yang Liu fe0e3b7a9f [LA64] Fixed LBT signal handling, also refined la64noext support (#3080) 2025-10-22 01:15:18 +08:00
ptitSeb e3cd3e8347 [RCFILE] Removed INTERP_SIGNAL for VampireSurvivors, it's not needed anymore_ 2025-10-20 12:26:20 +02:00
ptitSeb d730610c02 [DYNAREC] Reversing b40cb7b84a as it generate tons of regression and it tries to fix a non-issue 2025-10-20 12:08:29 +02:00
Yang Liu b0c11ae14f [LA64_DYNAREC] Added more opcodes (#3079) 2025-10-19 23:05:47 +02:00
Yang Liu 2db2532092 [LA64_DYNAREC] Added x87 support (#3078) 2025-10-19 19:35:39 +02:00
ptitSeb 95182c9f21 [TRACE] Move the fast _exit message to dynarec_log instead 2025-10-19 19:15:26 +02:00
ptitSeb b95f0a0ffa [DYNAREC][WOWBOX64] BOX4_DYNAREC_INTERP_SIGNAL is not availble in WowBox64 for now 2025-10-19 19:10:50 +02:00
ptitSeb 0833a07a65 [DYNAREC] Introduce BOX4_DYNAREC_INTERP_SIGNAL and 1 profile that needs it 2025-10-19 19:06:38 +02:00
ptitSeb aa4dbe72c9 [BOX32][WRAPPER] Slightly better wrapping for 2 non-standard pthread functions 2025-10-19 17:47:09 +02:00
ptitSeb b76e26dc84 [BOX32] Fixed some old issue with hash useage 2025-10-19 17:46:26 +02:00
ptitSeb ed267b1a05 [LA64] Use alternate code for unaligned CMPXCHG8B in interpreter 2025-10-19 14:42:59 +02:00
ptitSeb 609d5c27b2 [WRAPPER] Added another listener to waylandclient (for #3071) 2025-10-19 11:01:09 +02:00
ptitSeb 9960128f4e [WRAPPER] Added one more listener to waylandclient (for #3071) 2025-10-19 10:53:32 +02:00
ptitSeb 58875dee13 [WRAPPER] Fixed one of waylandclient callback signature (for #3071) 2025-10-19 10:44:17 +02:00
ptitSeb 57a6c5a8b9 [WRAPPER] Added 1 egl extension to wrapped libGL, on 64bits side, not on 32bits (for #3071) 2025-10-19 10:36:03 +02:00
ptitSeb abb6446b28 [WRAPPER] Better wrapping for a libdecor function (for #3071) 2025-10-19 10:31:26 +02:00
ptitSeb 440308f604 [WRAPPER] Added 1 egl extension to wrapped libGL (for #3071) 2025-10-19 09:56:06 +02:00
ptitSeb 25134fca48 [WRAPPER] Added 1 extension to wrapped libEGL (for #3071) 2025-10-18 13:34:49 +02:00
ptitSeb f2b168e674 [WRAPPER] Added another Wayland listener (for #3071) 2025-10-18 13:20:31 +02:00
ptitSeb bd616a3779 [WRAPPER] Added 1 more Wayland listener (for #3071) 2025-10-18 11:21:47 +02:00
ptitSeb f568ae4844 [RV64_DYNAREC] Small refactor on SIGBUS special case handling 2025-10-18 10:52:07 +02:00
Yang Liu 4edbdc005b [RCFILE] Added steamwebhelper entry for RISC-V (#3077) 2025-10-17 13:12:02 +02:00
Yang Liu 88aefd44ad [ENV] Added a new BOX64_ARCH option (#3076) 2025-10-17 13:01:37 +02:00
Leslie Zhai c8f6041ab0 [WRAPPER] Fix no more slot for glib2 GSourceFunc callback (#3075) 2025-10-17 08:05:12 +02:00
Yang Liu 640e2b8bcf [BOX32] Enlarged xcb connects size again for Linux Steam (#3074) 2025-10-16 20:45:54 +02:00
ptitSeb f4aab38964 [COSIM] Disable tests fo CD opcode 2025-10-16 13:12:45 +02:00
ptitSeb 2a06a5d1c3 [DYNAREC] Remove obsolete code now that all memory of the dynarec is static 2025-10-16 11:39:05 +02:00
ptitSeb b40cb7b84a [DYNAREC] Fixed potential issue with signel not being re-enabled after FillBlock64 got canceled in a signal handler 2025-10-16 11:00:07 +02:00
ptitSeb d0045b158b Some Segments/Selector handling refactoring , removing some pthread_getspecific use 2025-10-15 20:52:16 +02:00
Yang Liu 1d4a9e8863 [TEST] Some minor fixes to the test runner (#3072) 2025-10-15 11:27:58 +02:00
Luke Short cc68021a14 [BUNDLE] Add libgcc (#3070)
* [BUNDLE] update link

to the list of libraries that cannot be emulated. It shows how
libthread_db cannot be emulated (which is already in our exclusion
list).

* [BUNDLE] Add libgcc

This provides the 'libgcc_s.so.1' library.

Related #2389
2025-10-15 08:17:09 +02:00
ptitSeb f5a64f93b6 [ARM64_DYNAREC] Better handling for invalid opcodes 2025-10-14 09:23:15 +02:00
ptitSeb 6732546e60 [INTERP] Better handling for invalid opcode 2025-10-14 09:22:44 +02:00
Luke Short 74f4fbdcb0 Bundle OpenSSL (#3069)
* [BUNDLE] sort CSV file

* [BUNDLE] Add OpenSSL libraries

including 'libcrypto.so.1.0.0', 'libcrypto.so.1.1', and
'libssl.so'.

Related #2389
2025-10-14 09:13:36 +02:00
phorcys 524c5ad47a [LA64_DYNAREC] Fix SSE CMPPD, wrong reg operand for cUN cOR. (#3068) 2025-10-14 09:12:45 +02:00
Yang Liu 3d0423acf7 Added preliminary unit test runner (#3045)
* Added preliminary unit test runner

* Set .text section address

* Added support for added custom memory regions

* Move json.h to include

* Display banner

* Added support for custom memory data

* Added the ability to include path in nasm

* Print env variables
2025-10-14 09:11:15 +02:00
ptitSeb 3ad0ddfe88 Start of a new dev. cycle 2025-10-14 09:03:47 +02:00
437 changed files with 42401 additions and 18651 deletions

No files matched your search

+28 -21
View File
@@ -37,7 +37,6 @@ jobs:
matrix:
platform: [X64, RISCV, RK3588, ARM64, ANDROID, TERMUX, LARCH64, ANDROID_GLIBC, WOW64, ARM64-GCC-8]
type: [Release, Trace, StaticBuild, Box32]
os: [ubuntu-latest, ubuntu-22.04-arm]
exclude:
- platform: ANDROID
type: StaticBuild
@@ -49,32 +48,12 @@ jobs:
type: Box32
- platform: TERMUX
type: Box32
- platform: X64
os: ubuntu-22.04-arm
- platform: RISCV
os: ubuntu-22.04-arm
- platform: RK3588
os: ubuntu-latest
- platform: ARM64
os: ubuntu-latest
- platform: ANDROID
os: ubuntu-22.04-arm
- platform: TERMUX
os: ubuntu-22.04-arm
- platform: LARCH64
os: ubuntu-22.04-arm
- platform: ANDROID_GLIBC
os: ubuntu-latest
- platform: WOW64
os: ubuntu-latest
- platform: WOW64
type: Trace
- platform: WOW64
type: StaticBuild
- platform: WOW64
type: Box32
- platform: ARM64-GCC-8
os: ubuntu-latest
- platform: ARM64-GCC-8
type: Trace
- platform: ARM64-GCC-8
@@ -86,7 +65,35 @@ jobs:
- platform: LARCH64
type: Trace
include:
- platform: X64
os: ubuntu-latest
- platform: RISCV
os: ubuntu-latest
- platform: RK3588
os: ubuntu-22.04-arm
- platform: ARM64
os: ubuntu-22.04-arm
- platform: ANDROID
os: ubuntu-latest
- platform: TERMUX
os: ubuntu-latest
- platform: LARCH64
os: ubuntu-latest
- platform: ANDROID_GLIBC
os: ubuntu-22.04-arm
- platform: WOW64
os: ubuntu-22.04-arm
- platform: ARM64-GCC-8
os: ubuntu-22.04-arm
image: arm64v8/ubuntu:18.04
runs-on: ${{ matrix.os }}
+41 -28
View File
@@ -15,11 +15,12 @@ option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_T194})
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
option(NVIDIA_GB10 "Set to ON if targeting a DGX Spark(GB10) based device" ${NVIDIA_GB10})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(SD8G2 "Set to ON if targeting a Snapragon 8 Gen 2 based device" ${SD8G2})
option(SD845 "Set to ON if targeting a Snapdragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapdragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapdragon 888 based device" ${SD888})
option(SD8G2 "Set to ON if targeting a Snapdragon 8 Gen 2 based device" ${SD8G2})
option(SDORYON1 "Set to ON if targeting a Snapdragon Oryon 1 (X1E80100/X1E78100) based device" ${SDORYON1})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
@@ -38,6 +39,7 @@ option(SAVE_MEM "Set to ON to build dynarec with some slower memory saving optim
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(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
option(BAD_PKILL "Set to ON to activate the workaround for incoherent pthread_kill" ${BAD_PKILL})
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
option(CI "Set to ON if running in CI" ${CI})
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
@@ -66,6 +68,7 @@ if(LARCH64)
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC ON CACHE BOOL "")
set(BAD_PKILL ON CACHE BOOL "")
if(LARCH64_ABI_1)
message(STATUS "Build for Loongarch64 ABI 1.0 system")
add_definitions(-DLA64_ABI_1)
@@ -85,7 +88,7 @@ if(PPC64LE)
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR PHYTIUM OR SD845 OR SD865 OR SD888 OR SD8G2 OR SDORYON1 OR LX2160A OR M1 OR ARM64 OR ADLINK)
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR NVIDIA_GB10 OR PHYTIUM OR SD845 OR SD865 OR SD888 OR SD8G2 OR SDORYON1 OR LX2160A OR M1 OR ARM64 OR ADLINK)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -183,6 +186,9 @@ elseif(TEGRA_T194)
elseif(TEGRA_T234)
add_definitions(-DTEGRA_T234)
set(CFLAGS -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae)
elseif(NVIDIA_GB10)
add_definitions(-DNVIDIA_GB10)
set(CFLAGS -pipe -mcpu=gb10 -mtune=gb10)
elseif(PHYTIUM)
add_definitions(-DPHYTIUM)
set(CFLAGS -pipe -march=armv8.1-a+crc+simd+crypto)
@@ -224,6 +230,7 @@ elseif(M1)
set(CFLAGS -pipe -march=armv8.5-a+simd+crypto)
elseif(LARCH64)
add_definitions(-DLA64)
add_definitions(-DBAD_PKILL)
set(CFLAGS -pipe -march=loongarch64)
set(ASMFLAGS -pipe -march=loongarch64)
elseif(RV64)
@@ -260,6 +267,9 @@ endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
if(BAD_PKILL)
add_definitions(-DBAD_PKILL)
endif()
if(SAVE_MEM)
add_definitions(-DSAVE_MEM)
endif()
@@ -376,6 +386,7 @@ set(OS_LINUX_SRC
set(ELFLOADER_SRC
"${BOX64_ROOT}/src/main.c"
"${BOX64_ROOT}/src/test.c"
"${BOX64_ROOT}/src/core.c"
"${BOX64_ROOT}/src/box64context.c"
"${BOX64_ROOT}/src/build_info.c"
@@ -443,6 +454,7 @@ if(BOX32)
"${BOX64_ROOT}/src/tools/box32stack.c"
"${BOX64_ROOT}/src/emu/x86int3.c"
"${BOX64_ROOT}/src/librarian/globalsymbols32.c"
"${BOX64_ROOT}/src/libtools/box32_inputevent.c"
"${BOX64_ROOT}/src/libtools/myalign32.c"
"${BOX64_ROOT}/src/libtools/myalign64_32.c"
"${BOX64_ROOT}/src/libtools/myalignxcb32.c"
@@ -605,6 +617,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglx.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglxnvidia.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibharfbuzz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibibus.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
@@ -687,6 +700,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappednspr4.c"
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
"${BOX64_ROOT}/src/wrapped/wrappednvml.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedopencl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
@@ -755,6 +769,8 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedicui18n74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc75.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n75.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc76.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n76.c"
"${BOX64_ROOT}/src/wrapped/wrappedidn2.c"
"${BOX64_ROOT}/src/wrapped/wrappedanl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpsl5.c"
@@ -842,6 +858,7 @@ if(BOX32)
"${BOX64_ROOT}/src/wrapped32/wrappedcrashhandler.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibglxnvidia.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2image.c"
@@ -953,14 +970,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_emit_shift.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_00.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_64.c"
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_65.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_avx.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d8.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d9.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_da.c"
@@ -973,7 +983,6 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_660f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f30f.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"
@@ -1024,12 +1033,7 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_3.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_32.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
@@ -1044,7 +1048,6 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f_vector.c"
@@ -1085,14 +1088,11 @@ if(LARCH64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_emit_logic.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_00.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_0f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_64.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_6664.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_660f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f0.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f0.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f20f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c"
@@ -1107,6 +1107,14 @@ if(LARCH64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_avx_f2_0f3a.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_avx_f3_0f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_avx_f3_0f38.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_d8.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_d9.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_da.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_db.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_dc.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_dd.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_de.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_df.c"
)
endif()
@@ -1175,13 +1183,13 @@ if(DYNAREC)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS ${DYNAREC_SRC} ${DYNAREC_ASM} ${DYNAREC_PASS} ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
DEPENDS ${DYNAREC_SRC} ${DYNAREC_ASM} ${DYNAREC_PASS} ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32} ${WRAPPEDS_HEAD} ${WRAPPEDS32_HEAD}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32} ${WRAPPEDS_HEAD} ${WRAPPEDS32_HEAD}
VERBATIM)
endif()
@@ -1419,7 +1427,7 @@ if(_aarch64)
else()
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
endif()
elseif(__riscv64)
elseif(_riscv64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "riscv64")
elseif(_x86_64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
@@ -1544,7 +1552,7 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-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}
add_test(longjumpInSignals_nocosim ${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 )
@@ -1613,6 +1621,11 @@ add_test(x87pc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
set_tests_properties(x87pc PROPERTIES ENVIRONMENT "BOX64_DYNAREC_X87DOUBLE=2")
add_test(Boundary ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test33 -D TEST_OUTPUT=tmpfile33.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref33.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
else()
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
@@ -1700,7 +1713,7 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-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}
# add_test(longjumpInSignals_nocosim ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21_android -D TEST_OUTPUT=tmpfile21.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
@@ -1872,7 +1885,7 @@ if(BOX32)
set_tests_properties(sse_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(NAME longjumpInSignals_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(NAME longjumpInSignals_32bits_nocosim COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test18 -D TEST_OUTPUT=tmpfile32_18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
+3 -3
View File
@@ -4,7 +4,7 @@
[Website](https://box86.org/) | [Changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an Error](https://github.com/ptitSeb/box64/issues/new)
![Build Status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
![Build Status](https://github.com/ptitSeb/box64/actions/workflows/release.yml/badge.svg) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
---
@@ -83,9 +83,9 @@ For more information, check [Usage Documentation](docs/USAGE.md).
Box64 wraps GTK libraries, supporting both gtk2 and gtk3.
### Linux Steam
### Steam
Linux Steam requires Box86 or Box32 due to its 32-bit client app, but uses 64-bit local server binaries. Systems with less than 6GB RAM may need a swap file for optimal performance.
See [Steam Documentation](docs/STEAM.md).
### Wine
+4 -2
View File
@@ -81,9 +81,11 @@ Box64 的配置文件位于 `/etc/box64.box64rc` 和 `~/.box64rc`,均为 `.ini
Box64 包装了 GTK 库,支持 gtk2 和 gtk3。
### Linux Steam
### Steam
由于 Linux Steam 客户端应用是 32 位的,需要使用 Box86 或 Box32,但其本地服务器是 64 位的二进制文件。对于内存少于 6GB 的系统,可能需要使用交换文件以获得最佳性能。
Box64 支持 Linux Steam 和 Windows Steam,更多细节请参考[Steam 文档](docs/STEAM.md)。
> 由于 Linux Steam 客户端应用是 32 位的,需要使用 Box86 或 Box32,但其本地服务器是 64 位的二进制文件。对于内存少于 6GB 的系统,可能需要使用交换文件以获得最佳性能。
### Wine
+12 -6
View File
@@ -1,25 +1,31 @@
https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_amd64.deb,d5ae55e3a9838d12358530cd03218cc0d18127a84e9cfc73bdf79dacd40b25e4
https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_i386.deb,625e5189304d4d3bfb27cb821e257816c5ce761b1696b5da5ca4fa1035c48463
https://archive.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.2l-1~bpo8+1_amd64.deb,6e85968afe1a6643f4e82e1cc168f848c5967a131bb1c7392f11974953db0e67
https://archive.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.2l-1~bpo8+1_i386.deb,4e8b924286a064c257ca50b8ecd44fe71226443daef62b6836010590e2157329
https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/34/Everything/x86_64/os/Packages/l/libunwind-1.4.0-5.fc34.i686.rpm,eb518e9d073c36fd29862c7afd00a8a7cb186074a0e162983f18fb6c9dc71d2c
https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/34/Everything/x86_64/os/Packages/l/libunwind-1.4.0-5.fc34.x86_64.rpm,0f44e37e4eb472508e0dba8505ebbb04c2c1390c6a43970a6af80aad886037e3
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.i686.rpm,386040fc502e2f02b4b072e0cd90c034dc0a30831fbd2ddb116d17c080b6f9a4
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.x86_64.rpm,2a13461c7d5fcf72ffd682b3eb04833aea8306d61c3b8bdeb42a5081d96d5478
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/40/Everything/x86_64/Packages/s/SDL3-3.2.12-1.fc40.i686.rpm,4a3bce6e6358ddd05ed2941e7b8fcc4c8cc02df20741d3f0f9295facbc687769
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/40/Everything/x86_64/Packages/s/SDL3-3.2.12-1.fc40.x86_64.rpm,9524803ef42d80dc1b15190d5bb5925200995d5a6152eca04471383ff891af17
https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-3.0.3-21-1-x86_64.eopkg,c92f19d446b4c2450306f13b1a908f2552400da09301996fe349fee243d964d2
https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-32bit-3.0.3-21-1-x86_64.eopkg,5624990281f6520026aa2252c711f02d4916099aeac63accc83bd2135b9d3220
https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.i686.rpm,13bc8758355c3ec885f414e0e86efad29a7fe82c0999cdb3754d666949c06cc5
https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.x86_64.rpm,fb4aaa22b2e2f2fc0c451b87ac464e8746d240397d64e79f6bfd38f4e9128a5a
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/compat-openssl11-1.1.1k-4.el9_0.i686.rpm,6b9d8e1b34dcc5a5cb1196d746022b04677b7f9a105508392446508c6ae9b4cc,https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/compat-openssl11-1.1.1k-4.el9_0.x86_64.rpm,102eb4355d2dfc8093ed59dd2ebc6bf8616965524faf7e886212fd542f4c1b4b
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/compat-openssl11-1.1.1k-4.el9_0.x86_64.rpm,102eb4355d2dfc8093ed59dd2ebc6bf8616965524faf7e886212fd542f4c1b4b
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.i686.rpm,75f808f0f5f93aceb4e477aa5f302edbed07a605a0644f0ea929d4ea609e36a0
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.x86_64.rpm,b4763ca410f8479b2775efb55ba09e6722948af7526180a56309e3e090c27010
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm,d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm,d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm,ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm,d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libepoxy-1.5.5-4.el9.i686.rpm,fe35e8de9b68c8d7e7b6b525580fc36cf9c86412cdb2b022dc01f95801771981
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libepoxy-1.5.5-4.el9.x86_64.rpm,b6d1e7f1c832882ceb05187cbc2d8fe1f459bcd88c7160487ee6f734e1a5d017
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm,d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm,d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.i686.rpm,9e4ff6fa0251c5357ae8f648b3e396d0043d5b3f2fb28d23325f5bd592c67aee
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.x86_64.rpm,83b4b333e335654674032d1cda4d7deb328b5a409f95e3952c3dc482b684fd8f
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libsigc%2B%2B20-2.10.7-2.el9.i686.rpm,7c33f4c18cbd51dc0a7c9ae0190b1a27d0540ce2fd92ced4776dde66162d1a88
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libsigc%2B%2B20-2.10.7-2.el9.x86_64.rpm,8600132b9e4efadfe23d3125e90287f5a7114165fd9ecb064d9930fcca446ef2
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm,ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm,d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.i686.rpm,2155c688b516ab359d0c47be6d73e51d3c65f199ed5591f7bb7ce6d5d9799977
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.x86_64.rpm,25ab4a8ad997b450b4a34a777f5a0678eea72ca1665944a7a461ac63de4b25bf
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.i686.rpm,e38c5185fea611330ea253db020315dd564507bf95c48a81dbe7db186ce4214b
@@ -34,14 +40,14 @@ https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.i
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.x86_64.rpm,16c48c504fe62f8e19cac7c6442d3e08bba487f610c2f533116dac32357cda86
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/harfbuzz-2.7.4-10.el9.i686.rpm,5157daf2ab0a03b403d37c60b150b8f0f866754714f81e3d96368e06a16339ce
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/harfbuzz-2.7.4-10.el9.x86_64.rpm,1f81073019abe4176d4496723a89b55a349c31f507e96397a0b3efa7cea0ff61
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.i686.rpm,386040fc502e2f02b4b072e0cd90c034dc0a30831fbd2ddb116d17c080b6f9a4
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.x86_64.rpm,2a13461c7d5fcf72ffd682b3eb04833aea8306d61c3b8bdeb42a5081d96d5478
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libblkid-2.37.4-20.el9.i686.rpm,f9e62d2768c31948b53268b7de51bd1c7342cdf39a328a0d89d933b4aa0c5dd1
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libblkid-2.37.4-20.el9.x86_64.rpm,ed02d978a36488b38bad62af21d4045367c1f0b00d00c90ded01e2fc8e190536
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libbrotli-1.0.9-7.el9_5.i686.rpm,d18c20fccbb9497222059d475161a55c0c6279344f214fe551b8b0f87d3c054a
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libbrotli-1.0.9-7.el9_5.x86_64.rpm,77906ae44bcd42a9f6646d814874768e8befaabf413133d44f71a95ac6c6d68c
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libffi-3.4.2-8.el9.i686.rpm,70daa216ed2a6540e41c455efc95d2b5671db164137f854bceae07e348f58645
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libffi-3.4.2-8.el9.x86_64.rpm,1cf2d122e5c423681394c1bc599ee2281d2eafff5a3749842bc93c37db4bed5e
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgcc-11.5.0-2.el9.alma.1.i686.rpm,fed64dfadf74bd132ac2675f625ec601ca9d7ae9d05b8d7ff492a204260d0174
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgcc-11.5.0-5.el9_5.alma.1.x86_64.rpm,7bd3ec130e1712442121b61b27164386006b9bfa6f0fa188316ecb35575a768f
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.i686.rpm,686ac26afe2073a3607f26fd1592a8ccd9b78f6eec6e872528634b43c4e04dd7
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.x86_64.rpm,9a2bdc6807b22ffb6294b30dcc13e20198abe5facaeefcf1bfacec3e1013e3c2
https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgpg-error-1.42-5.el9.i686.rpm,23f828674bc30752687452dacf4a25ca8c25ef0d25e3e6953d0714b5b33cef08
1 https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_amd64.deb d5ae55e3a9838d12358530cd03218cc0d18127a84e9cfc73bdf79dacd40b25e4
2 https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_i386.deb 625e5189304d4d3bfb27cb821e257816c5ce761b1696b5da5ca4fa1035c48463
3 https://archive.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.2l-1~bpo8+1_amd64.deb 6e85968afe1a6643f4e82e1cc168f848c5967a131bb1c7392f11974953db0e67
4 https://archive.debian.org/debian/pool/main/o/openssl/libssl1.0.0_1.0.2l-1~bpo8+1_i386.deb 4e8b924286a064c257ca50b8ecd44fe71226443daef62b6836010590e2157329
5 https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/34/Everything/x86_64/os/Packages/l/libunwind-1.4.0-5.fc34.i686.rpm eb518e9d073c36fd29862c7afd00a8a7cb186074a0e162983f18fb6c9dc71d2c
6 https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/34/Everything/x86_64/os/Packages/l/libunwind-1.4.0-5.fc34.x86_64.rpm 0f44e37e4eb472508e0dba8505ebbb04c2c1390c6a43970a6af80aad886037e3
7 https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.i686.rpm 386040fc502e2f02b4b072e0cd90c034dc0a30831fbd2ddb116d17c080b6f9a4
8 https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.x86_64.rpm 2a13461c7d5fcf72ffd682b3eb04833aea8306d61c3b8bdeb42a5081d96d5478
9 https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/40/Everything/x86_64/Packages/s/SDL3-3.2.12-1.fc40.i686.rpm 4a3bce6e6358ddd05ed2941e7b8fcc4c8cc02df20741d3f0f9295facbc687769
10 https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/40/Everything/x86_64/Packages/s/SDL3-3.2.12-1.fc40.x86_64.rpm 9524803ef42d80dc1b15190d5bb5925200995d5a6152eca04471383ff891af17
11 https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-3.0.3-21-1-x86_64.eopkg c92f19d446b4c2450306f13b1a908f2552400da09301996fe349fee243d964d2
12 https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-32bit-3.0.3-21-1-x86_64.eopkg 5624990281f6520026aa2252c711f02d4916099aeac63accc83bd2135b9d3220
13 https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.i686.rpm 13bc8758355c3ec885f414e0e86efad29a7fe82c0999cdb3754d666949c06cc5
14 https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.x86_64.rpm fb4aaa22b2e2f2fc0c451b87ac464e8746d240397d64e79f6bfd38f4e9128a5a
15 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/compat-openssl11-1.1.1k-4.el9_0.i686.rpm 6b9d8e1b34dcc5a5cb1196d746022b04677b7f9a105508392446508c6ae9b4cc
16 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/compat-openssl11-1.1.1k-4.el9_0.x86_64.rpm 102eb4355d2dfc8093ed59dd2ebc6bf8616965524faf7e886212fd542f4c1b4b
17 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.i686.rpm 75f808f0f5f93aceb4e477aa5f302edbed07a605a0644f0ea929d4ea609e36a0
18 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.x86_64.rpm b4763ca410f8479b2775efb55ba09e6722948af7526180a56309e3e090c27010
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
19 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libepoxy-1.5.5-4.el9.i686.rpm fe35e8de9b68c8d7e7b6b525580fc36cf9c86412cdb2b022dc01f95801771981
20 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libepoxy-1.5.5-4.el9.x86_64.rpm b6d1e7f1c832882ceb05187cbc2d8fe1f459bcd88c7160487ee6f734e1a5d017
21 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
22 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
23 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.i686.rpm 9e4ff6fa0251c5357ae8f648b3e396d0043d5b3f2fb28d23325f5bd592c67aee
24 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.x86_64.rpm 83b4b333e335654674032d1cda4d7deb328b5a409f95e3952c3dc482b684fd8f
25 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libsigc%2B%2B20-2.10.7-2.el9.i686.rpm 7c33f4c18cbd51dc0a7c9ae0190b1a27d0540ce2fd92ced4776dde66162d1a88
26 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libsigc%2B%2B20-2.10.7-2.el9.x86_64.rpm 8600132b9e4efadfe23d3125e90287f5a7114165fd9ecb064d9930fcca446ef2
27 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
28 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
29 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.i686.rpm 2155c688b516ab359d0c47be6d73e51d3c65f199ed5591f7bb7ce6d5d9799977
30 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.x86_64.rpm 25ab4a8ad997b450b4a34a777f5a0678eea72ca1665944a7a461ac63de4b25bf
31 https://vault.almalinux.org/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.i686.rpm e38c5185fea611330ea253db020315dd564507bf95c48a81dbe7db186ce4214b
40 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.x86_64.rpm 16c48c504fe62f8e19cac7c6442d3e08bba487f610c2f533116dac32357cda86
41 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/harfbuzz-2.7.4-10.el9.i686.rpm 5157daf2ab0a03b403d37c60b150b8f0f866754714f81e3d96368e06a16339ce
42 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/harfbuzz-2.7.4-10.el9.x86_64.rpm 1f81073019abe4176d4496723a89b55a349c31f507e96397a0b3efa7cea0ff61
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.i686.rpm 386040fc502e2f02b4b072e0cd90c034dc0a30831fbd2ddb116d17c080b6f9a4
https://archives.fedoraproject.org/pub/archive/fedora/linux/updates/34/Everything/x86_64/Packages/h/hidapi-0.11.2-2.fc34.x86_64.rpm 2a13461c7d5fcf72ffd682b3eb04833aea8306d61c3b8bdeb42a5081d96d5478
43 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libblkid-2.37.4-20.el9.i686.rpm f9e62d2768c31948b53268b7de51bd1c7342cdf39a328a0d89d933b4aa0c5dd1
44 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libblkid-2.37.4-20.el9.x86_64.rpm ed02d978a36488b38bad62af21d4045367c1f0b00d00c90ded01e2fc8e190536
45 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libbrotli-1.0.9-7.el9_5.i686.rpm d18c20fccbb9497222059d475161a55c0c6279344f214fe551b8b0f87d3c054a
46 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libbrotli-1.0.9-7.el9_5.x86_64.rpm 77906ae44bcd42a9f6646d814874768e8befaabf413133d44f71a95ac6c6d68c
47 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libffi-3.4.2-8.el9.i686.rpm 70daa216ed2a6540e41c455efc95d2b5671db164137f854bceae07e348f58645
48 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libffi-3.4.2-8.el9.x86_64.rpm 1cf2d122e5c423681394c1bc599ee2281d2eafff5a3749842bc93c37db4bed5e
49 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgcc-11.5.0-2.el9.alma.1.i686.rpm fed64dfadf74bd132ac2675f625ec601ca9d7ae9d05b8d7ff492a204260d0174
50 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgcc-11.5.0-5.el9_5.alma.1.x86_64.rpm 7bd3ec130e1712442121b61b27164386006b9bfa6f0fa188316ecb35575a768f
51 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.i686.rpm 686ac26afe2073a3607f26fd1592a8ccd9b78f6eec6e872528634b43c4e04dd7
52 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.x86_64.rpm 9a2bdc6807b22ffb6294b30dcc13e20198abe5facaeefcf1bfacec3e1013e3c2
53 https://vault.almalinux.org/9.5/BaseOS/x86_64/os/Packages/libgpg-error-1.42-5.el9.i686.rpm 23f828674bc30752687452dacf4a25ca8c25ef0d25e3e6953d0714b5b33cef08
+1 -1
View File
@@ -88,7 +88,7 @@ mkdir -p usr/lib
mv box64-*-linux-gnu usr/lib
# remove libraries that cannot be emulated
# https://github.com/ptitSeb/box64/blob/v0.3.6/src/librarian/library.c#L433
# https://github.com/ptitSeb/box64/blob/v0.3.8/src/librarian/library.c#L433
set -- libc libpthread librt libGL libX11 libasound libdl libm libbsd libutil \
libresolv libXxf86vm libXinerama libXrandr libXext libXfixes libXcursor \
libXrender libXft libXi libXss libXpm libXau libXdmcp libX11-xcb libxcb \
+7 -7
View File
@@ -7,15 +7,15 @@ string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
execute_process(
COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}"
RESULT_VARIABLE rm_retval
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
ERROR_VARIABLE rm_out
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endif()
endif()
endforeach(file)
+9
View File
@@ -1,3 +1,12 @@
box64 (0.4.0) unstable; urgency=low
This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster.
=> Improved compatibility accross all architecture, allowing more DRM protected game to run
=> the prefix refactor helped removed lots of redundant source file, simplifying maintenance
=> BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later.
-- Sebastien Chevalier <[email protected]> Mon, 3 Jan 2026 10:30:33 -0100
box64 (0.3.8) unstable; urgency=low
This version introduce DynaCache, a disk cache for the generated native code. It's not enabled by default for now (but it will use cache file if present by default). It can dramaticaly speedup the load of program (try with linux factorio for example). This version also improve in the volatile metadata handling. There is a massive compatiblity improvment for box32 and on all dynarec in general too. And few more function wrapping...
+56
View File
@@ -1,3 +1,59 @@
v0.4.0
======
Highlights:
* This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster.
=> Improved compatibility accross all architecture, allowing more DRM protected game to run
=> the prefix refactor helped removed lots of redundant source file, simplifying maintenance
=> BOX32 is getting more and more stable, even if still not 100% ok. But Steam is more stable than before, runs on all architecture. And some gameoverlay UI works, on OpenGL games. gameoverlay (and fossilize) support for Vulkan is planned for later.
Version summary:
* Added new BOX64_ARCH to have settings specific to one of the supported cpu architecture (arm64, rv64, la64)
* Added BAD_PKILL build option, to workaround missing non-mandatory behaviour of pthread_kill (needed on LA64)
* Improved the handling of invalid opcodes
* Refactored handling of Selector, Segments and TLS data
* Added FSGSBASE cpu extension
* Added support for IFUNC relocation type to ElfLoader (64bits & 32bits)
* Refactored some internal behaviour to get better Interpreter only build
* Added BOX64_STEAM_VULKAN to have Vulkan renderer option injected when steamwebhelper is called
* Introduce BOX64_PYTHON3 to force using an X64 version of python (and use that on arm64 steam)
* Fixed signal handling when using Wine v10.19+
* Added some cache to customMalloc / customFree internal functions
* Some refactor on the cpuid helper function
* Wrapping: most Wayland listener for wider compatibility
* Wrapping: refactored libGL & libVulkan wrapping
* Wrapping: more wrapped functions, reworked some existing one with wrapperhelper
* Wrapping: Added a few more wrapped libs
* Wrapping: Better handling of RTLD_NEXT in dlsym function call
* Wrapping: Reworked wrapping of pthread_one (on Box32 too)
* Wrapping: a few new syscall implemented
* Wrapping: Make BOX64_EMULATED_LIBS to also affect gstreamer hacked loading of plugins
* Wrapping: BOX32: more wrapped function and some fixes to existing ones
* Wrapping: BOX32: a few new syscall implemented
* Interpreter: Added LOCK prefix to the generic opcode prefix handling
* Interpreter: A few fixes to existing opcodes
* Interpreter: Added F3 0F 40..4F opcodes
* Dynarec: Refactored HotPages Detection & Handling
* Dynarec: Introduced DYNAREC_PURGE to allow purging of old (unused?) Dynarec block and save memory
* Dynarec: Refactored prefix decoding, similar to the Interpreter
* Dynarec: ARM64: Added detection of loops and preload of xmm/ymm regs before entering
* Dynarec: ARM64: Refactored the handling of deferred flags
* Dynarec: ARM64: A few optimisation in some existing opcodes
* DYnarec: ARM64: Some fixes to existing opcodes
* Dynarec: LA64: Added x87 opcodes
* Dynarec: LA64: Added a few missing LOCK prefixed opcodes
* Dynarec: LA64: Added some more shift/roll opcodes
* Dynarec: LA64: Added support for native CRC opcodes
* Dynarec: LA64: Many fixes to some AVX opcodes
* Dynarec: LA64: Various fixes to some opcodes
* Dynarec: LA64: Addes a few 66 prefixed opcodes
* Dynarec: LA64: Added some "simple wrapper" support (allowing direct call of wrapped functions)
* Dynarec: LA64: Added some more native flags optimisations
* Dynarec: LA64: optimized REP MOVSB
* Dynarec: RV64: Fixed/Fine tunning flags on existing opcodes
* Dynarec: RV64: Various fixes to some opcodes
v0.3.8
======
+16
View File
@@ -137,6 +137,22 @@ Note: use gcc-11 or higher, older gcc doesn't know cortex-a78ae
-D TEGRA_T234=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for DGX Spark/GB10 based devices
On a 64bit OS:
Note: Requires GCC 15.2.0 or higher. Older GCC versions do not support gb10, cortex-a725, or cortex-x925.
For GCC 14 or older, you can use the following march equivalent:
```
-march=armv9.2-a+crc+sve2-aes+sve2-bitperm+sve2-sha3+sve2-sm4+memtag+profile
```
With GCC 15.2.0 or higher:
```
-D NVIDIA_GB10=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for ODROID N2/N2+
On a 64bit OS:
+19
View File
@@ -0,0 +1,19 @@
# The guide on running Steam with Box64
Steam works with Box64, both Linux version and Windows version. Systems with less than 6GB RAM may need a swap file for optimal performance.
## Install and run Linux Steam
Linux Steam requires Box86 or Box32 and it's binfmt enabled, check [Compilation Instructions](COMPILE.md) for details.
```bash
# This file can be found in the project root directory
./install_steam.sh
# And then, just run
steam
```
## Install and run Windows Steam
It's simple, just download it from Steam website and install it like other Windows applications.
+569 -479
View File
File diff suppressed because it is too large. Load diff
+157 -55
View File
@@ -57,6 +57,14 @@ Add extras to the needed libraries list, rarely needed.
* XXXX:YYYY:ZZZZ : Add library XXXX, YYYY and ZZZZ to the needed libraries list.
=item B<BOX64_AES> =I<0|1>
Expose AES capabilities. Available in WowBox64.
* 0 : Do not expose AES capabilities.
* 1 : Expose AES capabilities. [Default]
=item B<BOX64_ALLOWMISSINGLIBS> =I<0|1>
Allow missing libraries to be ignored.
@@ -65,6 +73,16 @@ Allow missing libraries to be ignored.
* 1 : Allow missing libraries.
=item B<BOX64_ARCH> =I<`arm64`|`la64`|`rv64`|`<empty>`>
Specify the architecture in rcfiles to which the current entry applies. This option only takes effect when used inside rcfiles.
* `arm64` : Only apply current entry for AArch64.
* `la64` : Only apply current entry for LoongArch64.
* `rv64` : Only apply current entry for RISC-V.
* `<empty>` : Apply current entry for all architectures, will be replaced by more specific entries. [Default]
=item B<BOX64_ARGS> =I<XXXX|XXXX YYYY ZZZZ>
Arguments to pass to the guest program, only valid if there is no existing arguments.
@@ -75,7 +93,7 @@ Arguments to pass to the guest program, only valid if there is no existing argum
=item B<BOX64_AVX> =I<0|1|2>
Expose AVX extension to CPUID and cpuinfo file. Default value is 2 on Arm64 because it's fully implemented in DynaRec, 0 otherwise. Availble in WowBox64.
Expose AVX extension to CPUID and cpuinfo file. Default value is 2 on Arm64 because it's fully implemented in DynaRec, 0 otherwise. Available in WowBox64.
* 0 : Do not expose AVX capabilities.
* 1 : Expose AVX, BMI1, F16C and VAES extensions to CPUID and cpuinfo file.
@@ -89,25 +107,9 @@ Path to the bash executable.
* XXXX : Use bash executable at path XXXX.
=item B<BOX64_CEFDISABLEGPU> =I<0|1>
Add -cef-disable-gpu argument to the guest program.
* 0 : Does nothing. [Default]
* 1 : Add -cef-disable-gpu argument to the guest program.
=item B<BOX64_CEFDISABLEGPUCOMPOSITOR> =I<0|1>
Add -cef-disable-gpu-compositor argument to the guest program.
* 0 : Does nothing. [Default]
* 1 : Add -cef-disable-gpu-compositor argument to the guest program.
=item B<BOX64_CPUTYPE> =I<0|1>
Specify the CPU type to emulate. Availble in WowBox64.
Specify the CPU type to emulate. Available in WowBox64.
* 0 : Emulate a Intel CPU Model. [Default]
* 1 : Emulate a AMD CPU Model.
@@ -117,7 +119,7 @@ Specify the CPU type to emulate. Availble in WowBox64.
Use a dummy crash handler or not.
* 0 : Use emulated crashhandler.so library if nedded.
* 0 : Use emulated crashhandler.so library if needed.
* 1 : Use an internal dummy (empty) crashhandler.so library. [Default]
@@ -131,7 +133,7 @@ Enable or disable the logging of dlsym errors.
=item B<BOX64_DUMP> =I<0|1>
Dump elfloader debug information. Availble in WowBox64.
Dump elfloader debug information. Available in WowBox64.
* 0 : Do not dump elfloader debug information. [Default]
* 1 : Dump elfloader debug information.
@@ -139,7 +141,7 @@ Dump elfloader debug information. Availble in WowBox64.
=item B<BOX64_DYNAREC> =I<0|1>
Enable/disable the Dynamic Recompiler (a.k.a DynaRec). This option defaults to 1 if it's enabled in the build options for a supported architecture. Availble in WowBox64.
Enable/disable the Dynamic Recompiler (a.k.a DynaRec). This option defaults to 1 if it's enabled in the build options for a supported architecture. Available in WowBox64.
* 0 : Disable DynaRec.
* 1 : Enable DynaRec.
@@ -147,7 +149,7 @@ Enable/disable the Dynamic Recompiler (a.k.a DynaRec). This option defaults to 1
=item B<BOX64_DYNAREC_ALIGNED_ATOMICS> =I<0|1>
Generate aligned atomics only (only available on Arm64 for now). Availble in WowBox64.
Generate aligned atomics only (only available on Arm64 for now). Available in WowBox64.
* 0 : Generate unaligned atomics handling code. [Default]
* 1 : Generate aligned atomics only, which is faster and smaller code size, but will cause SIGBUS for LOCK prefixed opcodes operating on unaligned data addresses.
@@ -155,7 +157,7 @@ Generate aligned atomics only (only available on Arm64 for now). Availble in Wow
=item B<BOX64_DYNAREC_BIGBLOCK> =I<0|1|2|3>
Enable building bigger DynaRec code blocks for better performance. Availble in WowBox64.
Enable building bigger DynaRec code blocks for better performance. Available in WowBox64.
* 0 : Do not try to build block as big as possible, suitable for programs using lots of threads and JIT, like Unity.
* 1 : Build Dynarec block as big as possible.
@@ -165,7 +167,7 @@ Enable building bigger DynaRec code blocks for better performance. Availble in W
=item B<BOX64_DYNAREC_BLEEDING_EDGE> =I<0|1>
Detect MonoBleedingEdge and apply conservative settings.
Detect MonoBleedingEdge and apply conservative settings (Linux only).
* 0 : Do not detect MonoBleedingEdge.
* 1 : Detect MonoBleedingEdge and apply BOX64_DYNAREC_BIGBLOCK=0 BOX64_DYNAREC_STRONGMEM=1 when detected. [Default]
@@ -173,7 +175,7 @@ Detect MonoBleedingEdge and apply conservative settings.
=item B<BOX64_DYNAREC_CALLRET> =I<0|1|2>
Optimize CALL/RET opcodes. Availble in WowBox64.
Optimize CALL/RET opcodes. Available in WowBox64.
* 0 : Do not optimize CALL/RET, use jump table. [Default]
* 1 : Try to optimize CALL/RET, skipping the jump table when possible.
@@ -182,7 +184,7 @@ Optimize CALL/RET opcodes. Availble in WowBox64.
=item B<BOX64_DYNAREC_DF> =I<0|1>
Enable or disable the use of deferred flags. Availble in WowBox64.
Enable or disable the use of deferred flags. Available in WowBox64.
* 0 : Disable the use of deferred flags.
* 1 : Enable the use of deferred flags. [Default]
@@ -205,9 +207,17 @@ Disable detection of hot page (where code is executed and data written at the sa
* 1 : Do not detect hot page
=item B<BOX64_DYNAREC_HOTPAGE_ALT> =I<0|1>
Use alternative way to detect HotPages (legacy way).
* 0 : Detect hot page, using new method from v0.3.9+ [Default]
* 1 : Use alternate method to detect HotPage (from v0.3.8 and earlier)
=item B<BOX64_DYNAREC_DIV0> =I<0|1>
Enable or disable the generation of division-by-zero exception. Availble in WowBox64.
Enable or disable the generation of division-by-zero exception. Available in WowBox64.
* 0 : Do not generate the division-by-zero exception. [Default]
* 1 : Generate the division-by-zero exception.
@@ -215,7 +225,7 @@ Enable or disable the generation of division-by-zero exception. Availble in WowB
=item B<BOX64_DYNAREC_DUMP> =I<0|1|2>
Enable DynaRec dump. Availble in WowBox64.
Enable DynaRec dump. Available in WowBox64.
* 0 : Do not dump DynaRec blocks. [Default]
* 1 : Dump DynaRec blocks.
@@ -224,14 +234,14 @@ Enable DynaRec dump. Availble in WowBox64.
=item B<BOX64_DYNAREC_DUMP_RANGE> =I<0xXXXXXXXX-0xYYYYYYYY>
Dump DynaRec blocks in the specified range. Availble in WowBox64.
Dump DynaRec blocks in the specified range. Available in WowBox64.
* 0xXXXXXXXX-0xYYYYYYYY : Define the range where dynablock gets dumped (inclusive-exclusive).
=item B<BOX64_DYNAREC_FASTNAN> =I<0|1>
Enable or disable fast NaN handling. Availble in WowBox64.
Enable or disable fast NaN handling. Available in WowBox64.
* 0 : Precisely emulate the -NaN generation like on x86.
* 1 : Do not do anything special with -NAN generation, faster. [Default]
@@ -239,7 +249,7 @@ Enable or disable fast NaN handling. Availble in WowBox64.
=item B<BOX64_DYNAREC_FASTROUND> =I<0|1|2>
Enable or disable fast rounding. Availble in WowBox64.
Enable or disable fast rounding. Available in WowBox64.
* 0 : Generate float/double -> int rounding and use current rounding mode for float/double computation like on x86.
* 1 : Do not do anything special with edge case rounding, faster. [Default]
@@ -248,7 +258,7 @@ Enable or disable fast rounding. Availble in WowBox64.
=item B<BOX64_DYNAREC_FORWARD> =I<0|128|XXXX>
Define max allowed forward value when building block. Availble in WowBox64.
Define max allowed forward value when building block. Available in WowBox64.
* 0 : No forward value. When current block ends, do not try to go further even if there are previous forward jumps.
* 128 : Allow up to 128 bytes of gap between end of the block and the next forward jump. [Default]
@@ -268,7 +278,7 @@ The GDBJIT debugging support, only available on build with `-DGDBJIT=ON`, enable
=item B<BOX64_DYNAREC_LOG> =I<0|1|2|3>
Disable or enable DynaRec logs. Availble in WowBox64.
Disable or enable DynaRec logs. Available in WowBox64.
* 0 : Disable DynaRec logs. [Default]
* 1 : Enable minimal DynaRec logs.
@@ -278,7 +288,7 @@ Disable or enable DynaRec logs. Availble in WowBox64.
=item B<BOX64_DYNAREC_MISSING> =I<0|1|2>
Print missing opcodes. Availble in WowBox64.
Print missing opcodes. Available in WowBox64.
* 0 : Do not print the missing opcode. [Default]
* 1 : Print missing opcodes.
@@ -287,7 +297,7 @@ Print missing opcodes. Availble in WowBox64.
=item B<BOX64_DYNAREC_NATIVEFLAGS> =I<0|1>
Enable or disable the use of native flags. Availble in WowBox64.
Enable or disable the use of native flags. Available in WowBox64.
* 0 : Do not use native flags.
* 1 : Use native flags when possible. [Default]
@@ -295,7 +305,7 @@ Enable or disable the use of native flags. Availble in WowBox64.
=item B<BOX64_DYNAREC_PAUSE> =I<0|1|2|3>
Enable x86 PAUSE emulation, may help the performance of spinlocks. Availble in WowBox64.
Enable x86 PAUSE emulation, may help the performance of spinlocks. Available in WowBox64.
* 0 : Ignore x86 PAUSE instruction. [Default]
* 1 : Use YIELD to emulate x86 PAUSE instruction.
@@ -311,9 +321,25 @@ Generate map file for Linux perf tool.
* 1 : Dynarec will generate perf map.
=item B<BOX64_DYNAREC_PURGE> =I<0|1>
Purge dynablocks that haven't been executed recently, based on tick age threshold (BOX64_DYNAREC_PURGE_AGE).
* 0 : Dynarec will not purge old unused dynablocks. [Default]
* 1 : Dynarec will purge old unused dynablocks based on tick age.
=item B<BOX64_DYNAREC_PURGE_AGE> =I<4096|XXXX>
Tick age threshold for dynablock purging (requires BOX64_DYNAREC_PURGE=1).
* 4096 : Default age threshold. [Default]
* XXXX : Custom age threshold (range: 10-65536).
=item B<BOX64_DYNAREC_SAFEFLAGS> =I<0|1|2>
Behaviour of flags emulation on CALL/RET opcodes and other edge cases. Availble in WowBox64.
Behaviour of flags emulation on CALL/RET opcodes and other edge cases. Available in WowBox64.
* 0 : Treat CALL/RET as if it never needs any flags.
* 1 : Most of RETs will need flags, most of CALLs will not. [Default]
@@ -322,7 +348,7 @@ Behaviour of flags emulation on CALL/RET opcodes and other edge cases. Availble
=item B<BOX64_DYNAREC_STRONGMEM> =I<0|1|2|3>
Enable the emulation of x86 strong memory model. Availble in WowBox64.
Enable the emulation of x86 strong memory model. Available in WowBox64.
* 0 : Do not try anything special. [Default]
* 1 : Enable some memory barriers when writing to memory to emulate the x86 strong memory model in a limited way.
@@ -340,13 +366,21 @@ Enable or disable libtbb detection.
=item B<BOX64_DYNAREC_TEST> =I<0|1|0xXXXXXXXX-0xYYYYYYYY>
Enable DynaRec execution comparison with the interpreter, very slow, only for testing. Availble in WowBox64.
Enable DynaRec execution comparison with the interpreter, very slow, only for testing. Available in WowBox64.
* 0 : No comparison. [Default]
* 1 : Each opcode runs on interpreter and on Dynarec, regs and memory are compared and printed when they differ.
* 0xXXXXXXXX-0xYYYYYYYY : Define the range where dynarec is tested (inclusive-exclusive).
=item B<BOX64_DYNAREC_TEST_NODUP> =I<0|1>
Enable deduplication of IP address where COSIM find a difference Available in WowBox64.
* 0 : Show all addresses in error [Default]
* 1 : Show address in error only 1 time, even if dump might differs
=item B<BOX64_DYNAREC_TRACE> =I<0|1>
Enable or disable DynaRec trace.
@@ -365,7 +399,7 @@ Use volatile metadata parsed from PE files, only valid for 64bit Windows games.
=item B<BOX64_DYNAREC_WAIT> =I<0|1>
Wait or not for the building of a DynaRec code block to be ready. Availble in WowBox64.
Wait or not for the building of a DynaRec code block to be ready. Available in WowBox64.
* 0 : Do not wait and use interpreter instead, might speedup a bit on massive multithread or JIT programs.
* 1 : Wait for a DynaRec code block to be ready. [Default]
@@ -373,7 +407,7 @@ Wait or not for the building of a DynaRec code block to be ready. Availble in Wo
=item B<BOX64_DYNAREC_WEAKBARRIER> =I<0|1|2>
Tweak the memory barriers to reduce the performance impact by strong memory emualtion. Availble in WowBox64.
Tweak the memory barriers to reduce the performance impact by strong memory emualtion. Available in WowBox64.
* 0 : Use regular safe barrier.
* 1 : Use weak barriers to have more performance boost. [Default]
@@ -382,13 +416,21 @@ Tweak the memory barriers to reduce the performance impact by strong memory emua
=item B<BOX64_DYNAREC_X87DOUBLE> =I<0|1|2>
Force the use of float/double for x87 emulation. Availble in WowBox64.
Force the use of float/double for x87 emulation. Available in WowBox64.
* 0 : Try to use float when possible for x87 emulation. [Default]
* 1 : Only use Double for x87 emulation.
* 2 : Check Precision Control low precision on x87 emulation.
=item B<BOX64_DYNAREC_INTERP_SIGNAL> =I<0|1>
Allow the use of Dynarec in Signal Handlers.
* 0 : Allow the use of Dynarec in signal handlers. [Default]
* 1 : Only use the Interpreter for signal handlers (as it was in v0.3.8 and earlier).
=item B<BOX64_DYNACACHE> =I<0|1|2>
Enable/disable the Dynamic Recompiler Cache (a.k.a DynaCache). This option defaults to 2 (to read cache if present but not generate any). DynaCache write file to home folder by default, and can grow without limit.
@@ -512,8 +554,8 @@ Force loading libraries with the binary.
Detect libcef and apply BOX64_MALLOC_HACK settings.
* 0 : Does nothing.
* 1 : Detect libcef, and apply BOX64_MALLOC_HACK=2 if detected. [Default]
* 0 : Does nothing. [Default]
* 1 : Detect libcef, and apply BOX64_MALLOC_HACK=2 if detected.
=item B<BOX64_LIBGL> =I<libXXXX|/path/to/libXXXX>
@@ -533,7 +575,7 @@ Set the address where the program is loaded, only active for PIE guest programs.
=item B<BOX64_LOG> =I<0|1|2|3>
Enable or disable Box64 logs, default value is 0 if stdout is not terminal, 1 otherwise. Availble in WowBox64.
Enable or disable Box64 logs, default value is 0 if stdout is not terminal, 1 otherwise. Available in WowBox64.
* 0 : Disable Box64 logs.
* 1 : Enable minimal Box64 logs.
@@ -552,7 +594,7 @@ Behaviour when hooking malloc operators.
=item B<BOX64_MAXCPU> =I<0|XXXX>
Maximum CPU cores exposed. Availble in WowBox64.
Maximum CPU cores exposed. Available in WowBox64.
* 0 : Use the actual number of CPU cores. [Default]
* XXXX : Use XXXX CPU cores.
@@ -568,7 +610,7 @@ Force 32-bit compatible memory mappings on 64-bit programs that run 32-bit code
=item B<BOX64_NOBANNER> =I<0|1>
Disable the Box64 banner. Availble in WowBox64.
Disable the Box64 banner. Available in WowBox64.
* 0 : Show the Box64 banner.
* 1 : Do not show the Box64 banner.
@@ -576,11 +618,28 @@ Disable the Box64 banner. Availble in WowBox64.
=item B<BOX64_NODYNAREC> =I<0xXXXXXXXX-0xYYYYYYYY>
Forbid dynablock creation in the address range specified, helpful for debugging behaviour difference between Dynarec and Interpreter. Availble in WowBox64.
Forbid dynablock creation in the address range specified, helpful for debugging behaviour difference between Dynarec and Interpreter. Available in WowBox64.
* 0xXXXXXXXX-0xYYYYYYYY : Define the range where dynablock creation is forbidden (inclusive-exclusive).
=item B<BOX64_NODYNAREC_DELAY> =I<0|1>
Remove NoDynarec range after a delay. Available in WowBox64.
* 0 : Do not remove NoDynarec range. [Default]
* 1 : Remove the NoDynarec range once 2 threads have been created.
=item B<BOX64_DYNAREC_NOARCH> =I<0|1|2>
Remove Architecture metatdata from Dynarec blocks (used on signal). Available in WowBox64.
* 0 : Generate all architecture metadata for each blocks, including x87/mmx/SSE/AVX regs tracking. Wil use some more memory. [Default]
* 1 : Generate only essential metadata for each blocks (flags, alignments), saving some memory, but some encrypted software might fails.
* 2 : Do not generate metadata for blocks. Saving a bit more memory but might fails on signal handling.
=item B<BOX64_NOGTK> =I<0|1>
Do not load wrapped GTK libraries.
@@ -644,6 +703,14 @@ Path to look for x86_64 binaries.
* XXXX : Add path XXXX to the binary path.
=item B<BOX64_PCLMULQDQ> =I<0|1>
Expose PCLMULQDQ capabilities. Available in WowBox64.
* 0 : Do not expose PCLMULQDQ capabilities.
* 1 : Expose PCLMULQDQ capabilities. [Default]
=item B<BOX64_PREFER_EMULATED> =I<0|1>
Prefer emulated libraries over native ones.
@@ -660,6 +727,24 @@ Prefer wrapped libs first even if the lib is specified with absolute path.
* 1 : Prefer wrapped libs first even if the lib is specified with absolute path.
=item B<BOX64_PROFILE> =I<safest|safe|default|fast|fastest>
Predefined sets of environment variables with compatibility or performance in mind. Available in WowBox64.
* safest : Profile with all the unsafe DynaRec optimizations disabled.
* safe : Well, less safer than safest.
* default : The default settings that most programs runs fine with a handy performance. [Default]
* fast : Enable many unsafe optimizations, but also enable strongmem emulation.
* fastest : Enable many unsafe optimizations to have a better performance.
=item B<BOX64_PYTHON3> =I<XXXX>
Path to a python3 executable.
* XXXX : Use python3 executable at path XXXX.
=item B<BOX64_RCFILE> =I<XXXX>
Path to the rc file to load.
@@ -702,7 +787,7 @@ Use a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2.
=item B<BOX64_SHAEXT> =I<0|1>
Expose SHAEXT (a.k.a. SHA_NI) capabilities.
Expose SHAEXT (a.k.a. SHA_NI) capabilities. Available in WowBox64.
* 0 : Do not expose SHAEXT capabilities.
* 1 : Expose SHAEXT capabilities. [Default]
@@ -726,7 +811,7 @@ Always show SIGSEGV signal detailes.
=item B<BOX64_SSE_FLUSHTO0> =I<0|1>
Behaviour of SSE Flush to 0 flags. Also tracking SSE exception flags Availble in WowBox64.
Behaviour of SSE Flush to 0 flags. Also tracking SSE exception flags Available in WowBox64.
* 0 : Just track the flag. [Default]
* 1 : Apply SSE Flush to 0 flag directly. Also reflect SSE exception flags in Dynarec (if available)
@@ -734,12 +819,20 @@ Behaviour of SSE Flush to 0 flags. Also tracking SSE exception flags Availble in
=item B<BOX64_SSE42> =I<0|1>
Expose SSE4.2 capabilities. Availble in WowBox64.
Expose SSE4.2 capabilities. Available in WowBox64.
* 0 : Do not expose SSE4.2 capabilities.
* 1 : Expose SSE4.2 capabilities. [Default]
=item B<BOX64_STEAM_VULKAN> =I<0|1>
Force Vulkan for Linux Steam UI.
* 0 : Do nothing. [Default]
* 1 : Force Vulkan for Linux Steam UI.
=item B<BOX64_SYNC_ROUNDING> =I<0|1>
Synchronize rounding mode between x86 and native.
@@ -764,13 +857,14 @@ Enable or disable EMM (i.e. MMX) trace output.
* 1 : Enable EMM trace output.
=item B<BOX64_TRACE_FILE> =I<XXXX|XXXX%pid|stderr>
=item B<BOX64_TRACE_FILE> =I<XXXX|XXXX%pid|stderr|stdout>
Send all log and trace to a file instead of `stdout`.
* XXXX : Send all log and trace to file XXXX.
* XXXX%pid : Send all log and trace to file XXXX with pid appended.
* stderr : Send all log and trace to `stderr`.
* stderr : Send all log and trace to `stderr`. [Default]
* stdout : Send all log and trace to `stdout`.
=item B<BOX64_TRACE_INIT> =I<0|1|symbolname|0xXXXXXXX-0xYYYYYYY>
@@ -815,7 +909,15 @@ Only available on box64 build with trace. Adds trace of all instructions execute
Detect UnityPlayer and apply conservative settings.
* 0 : Does nothing.
* 1 : Detect UnityPlayer, and apply BOX64_DYNAREC_STRONGMEM=1 when detected. [Default]
* 1 : Detect UnityPlayer (Windows or Linux), and apply BOX64_UNITY=1 when detected. [Default]
=item B<BOX64_UNITY> =I<0|1>
Games is a Unity one.
* 0 : Does nothing.
* 1 : Unity Game, use special detecting code for Windows, apply BOX64_DYNAREC_STRONGMEM=1 for Linux [Default]
=item B<BOX64_WRAP_EGL> =I<0|1>
@@ -852,7 +954,7 @@ Call XInitThreads when loading X11. This is mostly for old Loki games with the L
=item B<BOX64_X87_NO80BITS> =I<0|1>
Behavoiur of x87 80bits long double. Availble in WowBox64.
Behavoiur of x87 80bits long double. Available in WowBox64.
* 0 : Try to handle 80bits long double as precise as possible. [Default]
* 1 : Use 64bits double for x87.
+4 -4
View File
@@ -63,12 +63,12 @@ This configuration will apply the specified settings application-wide to any exe
for entry in data:
categories[entry["category"]].append(entry)
# Put "Performance" at the top
sorted_categories = sorted(categories.items(), key=lambda x: x[0] != "Performance")
# Put "Performance" at the top, then sort the rest alphabetically
sorted_categories = sorted(categories.items(), key=lambda x: (x[0] != "Performance", x[0]))
for category, entries in sorted_categories:
md_file.write(f"## {category}\n\n")
for entry in entries:
md_file.write(f"### {entry['name']}\n\n{entry['description']}{' Availble in WowBox64.' if entry['wine'] else ''}\n\n")
md_file.write(f"### {entry['name']}\n\n{entry['description']}{' Available in WowBox64.' if entry['wine'] else ''}\n\n")
for option in entry['options']:
md_file.write(f" * {option['key']}: {option['description']} {'[Default]' if option['default'] else ''}\n")
md_file.write("\n")
@@ -128,7 +128,7 @@ Example:
""")
for entry in data:
pod_file.write(f"\n=item B<{entry['name']}> =I<{ '|'.join(option['key'] for option in entry['options']) }>\n\n{entry['description']}{' Availble in WowBox64.' if entry['wine'] else ''}\n\n")
pod_file.write(f"\n=item B<{entry['name']}> =I<{ '|'.join(option['key'] for option in entry['options']) }>\n\n{entry['description']}{' Available in WowBox64.' if entry['wine'] else ''}\n\n")
for option in entry['options']:
pod_file.write(f" * {option['key']} : {option['description']} {'[Default]' if option['default'] else ''}\n")
pod_file.write("\n")
+288 -42
View File
@@ -17,6 +17,24 @@
}
]
},
{
"name": "BOX64_AES",
"description": "Expose AES capabilities.",
"category": "Compatibility",
"wine": true,
"options": [
{
"key": "0",
"description": "Do not expose AES capabilities.",
"default": false
},
{
"key": "1",
"description": "Expose AES capabilities.",
"default": true
}
]
},
{
"name": "BOX64_ALLOWMISSINGLIBS",
"description": "Allow missing libraries to be ignored.",
@@ -35,6 +53,34 @@
}
]
},
{
"name": "BOX64_ARCH",
"description": "Specify the architecture in rcfiles to which the current entry applies. This option only takes effect when used inside rcfiles.",
"category": "Compatibility",
"wine": false,
"options": [
{
"key": "`arm64`",
"description": "Only apply current entry for AArch64.",
"default": false
},
{
"key": "`la64`",
"description": "Only apply current entry for LoongArch64.",
"default": false
},
{
"key": "`rv64`",
"description": "Only apply current entry for RISC-V.",
"default": false
},
{
"key": "`<empty>`",
"description": "Apply current entry for all architectures, will be replaced by more specific entries.",
"default": true
}
]
},
{
"name": "BOX64_ARGS",
"description": "Arguments to pass to the guest program, only valid if there is no existing arguments.",
@@ -89,42 +135,6 @@
}
]
},
{
"name": "BOX64_CEFDISABLEGPU",
"description": "Add -cef-disable-gpu argument to the guest program.",
"category": "Arguments",
"wine": false,
"options": [
{
"key": "0",
"description": "Does nothing.",
"default": true
},
{
"key": "1",
"description": "Add -cef-disable-gpu argument to the guest program.",
"default": false
}
]
},
{
"name": "BOX64_CEFDISABLEGPUCOMPOSITOR",
"description": "Add -cef-disable-gpu-compositor argument to the guest program.",
"category": "Arguments",
"wine": false,
"options": [
{
"key": "0",
"description": "Does nothing.",
"default": true
},
{
"key": "1",
"description": "Add -cef-disable-gpu-compositor argument to the guest program.",
"default": false
}
]
},
{
"name": "BOX64_CPUTYPE",
"description": "Specify the CPU type to emulate.",
@@ -151,7 +161,7 @@
"options": [
{
"key": "0",
"description": "Use emulated crashhandler.so library if nedded.",
"description": "Use emulated crashhandler.so library if needed.",
"default": false
},
{
@@ -263,7 +273,7 @@
},
{
"name": "BOX64_DYNAREC_BLEEDING_EDGE",
"description": "Detect MonoBleedingEdge and apply conservative settings.",
"description": "Detect MonoBleedingEdge and apply conservative settings (Linux only).",
"category": "Compatibility",
"wine": false,
"options": [
@@ -361,6 +371,24 @@
}
]
},
{
"name": "BOX64_DYNAREC_HOTPAGE_ALT",
"description": "Use alternative way to detect HotPages (legacy way).",
"category": "Performance",
"wine": false,
"options": [
{
"key": "0",
"description": "Detect hot page, using new method from v0.3.9+",
"default": true
},
{
"key": "1",
"description": "Use alternate method to detect HotPage (from v0.3.8 and earlier)",
"default": false
}
]
},
{
"name": "BOX64_DYNAREC_DIV0",
"description": "Enable or disable the generation of division-by-zero exception.",
@@ -627,6 +655,42 @@
}
]
},
{
"name": "BOX64_DYNAREC_PURGE",
"description": "Purge dynablocks that haven't been executed recently, based on tick age threshold (BOX64_DYNAREC_PURGE_AGE).",
"category": "Performance",
"wine": false,
"options": [
{
"key": "0",
"description": "Dynarec will not purge old unused dynablocks.",
"default": true
},
{
"key": "1",
"description": "Dynarec will purge old unused dynablocks based on tick age.",
"default": false
}
]
},
{
"name": "BOX64_DYNAREC_PURGE_AGE",
"description": "Tick age threshold for dynablock purging (requires BOX64_DYNAREC_PURGE=1).",
"category": "Performance",
"wine": false,
"options": [
{
"key": "4096",
"description": "Default age threshold.",
"default": true
},
{
"key": "XXXX",
"description": "Custom age threshold (range: 10-65536).",
"default": false
}
]
},
{
"name": "BOX64_DYNAREC_SAFEFLAGS",
"description": "Behaviour of flags emulation on CALL/RET opcodes and other edge cases.",
@@ -719,6 +783,24 @@
}
]
},
{
"name": "BOX64_DYNAREC_TEST_NODUP",
"description": "Enable deduplication of IP address where COSIM find a difference",
"category": "Debugging",
"wine": true,
"options": [
{
"key": "0",
"description": "Show all addresses in error",
"default": true
},
{
"key": "1",
"description": "Show address in error only 1 time, even if dump might differs",
"default": false
}
]
},
{
"name": "BOX64_DYNAREC_TRACE",
"description": "Enable or disable DynaRec trace.",
@@ -819,6 +901,24 @@
}
]
},
{
"name": "BOX64_DYNAREC_INTERP_SIGNAL",
"description": "Allow the use of Dynarec in Signal Handlers.",
"category": "Compatibility",
"wine": false,
"options": [
{
"key": "0",
"description": "Allow the use of Dynarec in signal handlers.",
"default": true
},
{
"key": "1",
"description": "Only use the Interpreter for signal handlers (as it was in v0.3.8 and earlier).",
"default": false
}
]
},
{
"name": "BOX64_DYNACACHE",
"description": "Enable/disable the Dynamic Recompiler Cache (a.k.a DynaCache). This option defaults to 2 (to read cache if present but not generate any). DynaCache write file to home folder by default, and can grow without limit.",
@@ -1093,12 +1193,12 @@
{
"key": "0",
"description": "Does nothing.",
"default": false
"default": true
},
{
"key": "1",
"description": "Detect libcef, and apply BOX64_MALLOC_HACK=2 if detected.",
"default": true
"default": false
}
]
},
@@ -1251,6 +1351,47 @@
}
]
},
{
"name": "BOX64_NODYNAREC_DELAY",
"description": "Remove NoDynarec range after a delay.",
"category": "Debugging",
"wine": true,
"options": [
{
"key": "0",
"description": "Do not remove NoDynarec range.",
"default": true
},
{
"key": "1",
"description": "Remove the NoDynarec range once 2 threads have been created.",
"default": false
}
]
},
{
"name": "BOX64_DYNAREC_NOARCH",
"description": "Remove Architecture metatdata from Dynarec blocks (used on signal).",
"category": "Performance",
"wine": true,
"options": [
{
"key": "0",
"description": "Generate all architecture metadata for each blocks, including x87/mmx/SSE/AVX regs tracking. Wil use some more memory.",
"default": true
},
{
"key": "1",
"description": "Generate only essential metadata for each blocks (flags, alignments), saving some memory, but some encrypted software might fails.",
"default": false
},
{
"key": "2",
"description": "Do not generate metadata for blocks. Saving a bit more memory but might fails on signal handling.",
"default": false
}
]
},
{
"name": "BOX64_NOGTK",
"description": "Do not load wrapped GTK libraries.",
@@ -1390,6 +1531,24 @@
}
]
},
{
"name": "BOX64_PCLMULQDQ",
"description": "Expose PCLMULQDQ capabilities.",
"category": "Compatibility",
"wine": true,
"options": [
{
"key": "0",
"description": "Do not expose PCLMULQDQ capabilities.",
"default": false
},
{
"key": "1",
"description": "Expose PCLMULQDQ capabilities.",
"default": true
}
]
},
{
"name": "BOX64_PREFER_EMULATED",
"description": "Prefer emulated libraries over native ones.",
@@ -1426,6 +1585,52 @@
}
]
},
{
"name": "BOX64_PROFILE",
"description": "Predefined sets of environment variables with compatibility or performance in mind.",
"category": "Compatibility",
"wine": true,
"options": [
{
"key": "safest",
"description": "Profile with all the unsafe DynaRec optimizations disabled.",
"default": false
},
{
"key": "safe",
"description": "Well, less safer than safest.",
"default": false
},
{
"key": "default",
"description": "The default settings that most programs runs fine with a handy performance.",
"default": true
},
{
"key": "fast",
"description": "Enable many unsafe optimizations, but also enable strongmem emulation.",
"default": false
},
{
"key": "fastest",
"description": "Enable many unsafe optimizations to have a better performance.",
"default": false
}
]
},
{
"name": "BOX64_PYTHON3",
"description": "Path to a python3 executable.",
"category": "Compatibility",
"wine": false,
"options": [
{
"key": "XXXX",
"description": "Use python3 executable at path XXXX.",
"default": false
}
]
},
{
"name": "BOX64_RCFILE",
"description": "Path to the rc file to load.",
@@ -1520,7 +1725,7 @@
"name": "BOX64_SHAEXT",
"description": "Expose SHAEXT (a.k.a. SHA_NI) capabilities.",
"category": "Compatibility",
"wine": false,
"wine": true,
"options": [
{
"key": "0",
@@ -1606,6 +1811,24 @@
}
]
},
{
"name": "BOX64_STEAM_VULKAN",
"description": "Force Vulkan for Linux Steam UI.",
"category": "Compatibility",
"wine": false,
"options": [
{
"key": "0",
"description": "Do nothing.",
"default": true
},
{
"key": "1",
"description": "Force Vulkan for Linux Steam UI.",
"default": false
}
]
},
{
"name": "BOX64_SYNC_ROUNDING",
"description": "Synchronize rounding mode between x86 and native.",
@@ -1679,6 +1902,11 @@
{
"key": "stderr",
"description": "Send all log and trace to `stderr`.",
"default": true
},
{
"key": "stdout",
"description": "Send all log and trace to `stdout`.",
"default": false
}
]
@@ -1793,7 +2021,25 @@
},
{
"key": "1",
"description": "Detect UnityPlayer, and apply BOX64_DYNAREC_STRONGMEM=1 when detected.",
"description": "Detect UnityPlayer (Windows or Linux), and apply BOX64_UNITY=1 when detected.",
"default": true
}
]
},
{
"name": "BOX64_UNITY",
"description": "Games is a Unity one.",
"category": "Compatibility",
"wine": false,
"options": [
{
"key": "0",
"description": "Does nothing.",
"default": false
},
{
"key": "1",
"description": "Unity Game, use special detecting code for Windows, apply BOX64_DYNAREC_STRONGMEM=1 for Linux",
"default": true
}
]
+4 -8
View File
@@ -1,21 +1,17 @@
#!/bin/bash
# create necessary directories
mkdir -p ~/steam
mkdir -p ~/steam/tmp
mkdir -p ~/steam/tmp # makes both ~/steam and ~/steam/tmp in one cmd
cd ~/steam/tmp
# download latest deb and unpack
wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
curl -LO https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
ar x steam.deb
tar xf data.tar.xz
# remove deb archives, not needed anymore
rm ./*.tar.xz ./steam.deb
# move deb contents to steam folder
mv ./usr/* ../
cd ../ && rm -rf ./tmp/
mv ./usr/* ..
cd .. && rm -rf ./tmp
# create run script
echo '#!/bin/bash
+9 -5
View File
@@ -405,7 +405,11 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("sdl1ttf", "sdl2ttf") \
or match("libgl", "libegl") \
or match("libgl", "glesv2") \
or match("libgl", "libglxnvidia") \
or match("libglx", "libglxnvidia") \
or match("libegl", "glesv2") \
or match("libegl", "libglxnvidia") \
or match("glesv2", "libglxnvidia") \
or match("softokn3", "p11kit") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
@@ -841,17 +845,17 @@ def main(root: str, files: Iterable[Filename], ver: str):
allowed_conv = conventions[allowed_conv_ident]
# H could be allowed maybe?
allowed_simply: Dict[str, str] = {"ARM64": "v", "RV64": "v"}
allowed_regs : Dict[str, str] = {"ARM64": "cCwWiuIUlLp", "RV64": "CWIUlLp"}
allowed_fpr : Dict[str, str] = {"ARM64": "fd", "RV64": "fd"}
allowed_sextw : Dict[str, str] = {"ARM64": "", "RV64": "cwiu"}
allowed_simply: Dict[str, str] = {"ARM64": "v", "RV64": "v", "LA64": "v"}
allowed_regs : Dict[str, str] = {"ARM64": "cCwWiuIUlLp", "RV64": "CWIUlLp", "LA64": "CWIUlLp"}
allowed_fpr : Dict[str, str] = {"ARM64": "fd", "RV64": "fd", "LA64": "fd"}
allowed_sextw : Dict[str, str] = {"ARM64": "", "RV64": "cwiu", "LA64": "cwiu"}
# Detect functions which return in an x87 register
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
return_x87: str = "D"
# Sanity checks
forbidden_simple: Dict[str, str] = {"ARM64": "EDVOSNHPAxXYb", "RV64": "EDVOSNHPAxXYb"}
forbidden_simple: Dict[str, str] = {"ARM64": "EDVOSNHPAxXYb", "RV64": "EDVOSNHPAxXYb", "LA64": "EDVOSNHPAxXYb"}
assert(all(k in allowed_simply for k in forbidden_simple))
assert(all(k in allowed_regs for k in forbidden_simple))
assert(all(k in allowed_fpr for k in forbidden_simple))
+1
View File
@@ -876,6 +876,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("appindicator","appindicator3")\
or match("libgl", "libegl") \
or match("libgl", "libglx") \
or match("libgl", "libglxnvidia")\
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
+1 -1
View File
@@ -18,7 +18,7 @@ KHASH_MAP_INIT_STR(strings, ptr_t);
static kh_from_t* hash_from = NULL;
static kh_to_t* hash_to = NULL;
#define HASH_MSK 0xf000000f
#define HASH_VAL 0x00ffffff
#define HASH_VAL 0x007fffff
#define HASH_SHIFT 4
static uint32_t hash_cnt = 1;
static pthread_rwlock_t hash_lock = {0};
+22 -42
View File
@@ -72,17 +72,6 @@ int getrand(int maxval)
}
void free_tlsdatasize(void* p)
{
if(!p)
return;
tlsdatasize_t *data = (tlsdatasize_t*)p;
actual_free(data->ptr);
actual_free(p);
if(my_context)
pthread_setspecific(my_context->tlskey, NULL);
}
void x64Syscall(x64emu_t *emu);
void x86Syscall(x64emu_t *emu);
@@ -146,20 +135,25 @@ static void atfork_child_box64context(void)
init_mutexes(my_context);
}
int box64_cycle_log_initialized = 0;
void freeCycleLog(box64context_t* ctx)
{
if(BOX64ENV(rolling_log)) {
if (BOX64ENV(rolling_log) && box64_cycle_log_initialized) {
box_free(ctx->log_call);
box_free(ctx->log_ret);
ctx->log_call = NULL;
ctx->log_ret = NULL;
box64_cycle_log_initialized = 0;
}
}
void initCycleLog(box64context_t* context)
{
if(context && BOX64ENV(rolling_log)) {
context->log_call = (char*)box_calloc(BOX64ENV(rolling_log), 256*sizeof(char));
context->log_ret = (char*)box_calloc(BOX64ENV(rolling_log), 128*sizeof(char));
box64_cycle_log_initialized = 1;
}
}
@@ -178,7 +172,6 @@ box64context_t *NewBox64Context(int argc)
initCycleLog(context);
context->deferredInit = 1;
context->sel_serial = 1;
init_custommem_helper(context);
@@ -217,28 +210,25 @@ box64context_t *NewBox64Context(int argc)
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
pthread_key_create(&context->tlskey, free_tlsdatasize);
for (int i=0; i<8; ++i) context->canary[i] = 1 + getrand(255);
context->canary[getrand(4)] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary);
// init segments
for(int i=0; i<16; i++) {
context->segtls[i].limit = (uintptr_t)-1LL;
context->seggdt[i].limit = (uintptr_t)-1LL;
}
context->segtls[10].key_init = 0; // 0x53 selector
context->segtls[10].present = 1;
context->segtls[8].key_init = 0; // 0x43 selector
context->segtls[8].present = 1;
context->segtls[6].key_init = 0; // 0x33 selector
context->segtls[6].present = 1;
context->segtls[5].key_init = 0; // 0x2b selector
context->segtls[5].present = 1;
context->segtls[4].key_init = 0; // 0x23 selector
context->segtls[4].present = 1;
context->segtls[4].is32bits = 1;
// 0x53 selector
context->seggdt[10].present = 1;
// 0x43 selector
context->seggdt[8].present = 1;
// 0x33 selector
context->seggdt[6].present = 1;
// 0x2b selector
context->seggdt[5].present = 1;
// 0x23 selector
context->seggdt[4].present = 1;
context->seggdt[4].is32bits = 1;
context->globdata = NewMapSymbols();
context->uniques = NewMapSymbols();
@@ -253,6 +243,7 @@ box64context_t *NewBox64Context(int argc)
}
void freeALProcWrapper(box64context_t* context);
void freeCUDAProcWrapper(box64context_t* context);
EXPORTDYN
void FreeBox64Context(box64context_t** context)
{
@@ -316,12 +307,14 @@ void FreeBox64Context(box64context_t** context)
box_free(ctx->fullpath);
box_free(ctx->box64path);
box_free(ctx->bashpath);
box_free(ctx->pythonpath);
FreeBridge(&ctx->system);
#ifndef STATICBUILD
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
freeCUDAProcWrapper(ctx);
#ifdef BOX32
#endif
#endif
@@ -330,12 +323,6 @@ void FreeBox64Context(box64context_t** context)
box_free(ctx->stack_clone);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
}
pthread_key_delete(ctx->tlskey);
if(ctx->tlsdata)
box_free(ctx->tlsdata);
@@ -395,8 +382,6 @@ void RemoveElfHeader(box64context_t* ctx, elfheader_t* head) {
/*if(tlsbase == -ctx->tlssize) {
// not really correct, but will do for now
ctx->tlssize -= GetTLSSize(head);
if(!(++ctx->sel_serial))
++ctx->sel_serial;
}*/
}
for(int i=0; i<ctx->elfsize; ++i)
@@ -413,12 +398,7 @@ int AddTLSPartition(box64context_t* context, int 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
if(my_context) {
//ResetSegmentsCache(thread_get_emu());
if(!(++context->sel_serial))
++context->sel_serial;
}
// clean GS segment for current emu?
return -context->tlssize; // negative offset
}
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX64_VERSION_H_
#define BOX64_MAJOR 0
#define BOX64_MINOR 3
#define BOX64_REVISION 8
#define BOX64_MINOR 4
#define BOX64_REVISION 0
#endif //__BOX64_VERSION_H_
+4
View File
@@ -36,4 +36,8 @@ void PrintBox64Version(int prefix);
BOX64_STR ARCH_STR \
" v" BOX64_BUILD_INFO_STR(BOX64_MAJOR) "." BOX64_BUILD_INFO_STR(BOX64_MINOR) "." BOX64_BUILD_INFO_STR(BOX64_REVISION) " " GITREV
#define BOX64_BUILD_INFO_STRING_SHORT \
BOX64_STR \
" v" BOX64_BUILD_INFO_STR(BOX64_MAJOR) "." BOX64_BUILD_INFO_STR(BOX64_MINOR) "." BOX64_BUILD_INFO_STR(BOX64_REVISION)
#endif //__BUILD_INFO_H__
+64 -31
View File
@@ -67,6 +67,7 @@ int box64_zoom = 0;
int box64_steam = 0;
int box64_steamcmd = 0;
int box64_musl = 0;
int box64_nolibs = 0;
char* box64_custom_gstreamer = NULL;
int box64_tcmalloc_minimal = 0;
uintptr_t fmod_smc_start = 0;
@@ -74,6 +75,7 @@ uintptr_t fmod_smc_end = 0;
uint32_t default_gs = 0x53;
uint32_t default_fs = 0;
int box64_isglibc234 = 0;
int box64_unittest_mode = 0;
#ifdef DYNAREC
cpu_ext_t cpuext = {0};
@@ -135,7 +137,9 @@ static void openFTrace(void)
p = tmp;
}
if (!strcmp(p, "stderr"))
if (!strcmp(p, "stdout"))
ftrace = stdout;
else if (!strcmp(p, "stderr"))
ftrace = stderr;
else {
if (append)
@@ -143,13 +147,12 @@ static void openFTrace(void)
else
ftrace = fopen(p, "w");
if (!ftrace) {
ftrace = stdout;
printf_log(LOG_INFO, "Cannot open trace file \"%s\" for writing (error=%s), fallback to stdout\n", p, strerror(errno));
ftrace = stderr;
printf_log(LOG_INFO, "Cannot open trace file \"%s\" for writing (error=%s), fallback to stderr\n", p, strerror(errno));
} else {
ftrace_name = box_strdup(p);
if (!BOX64ENV(nobanner)) {
printf("[BOX64] Trace %s to \"%s\" (set BOX64_NOBANNER=1 to suppress this log)\n", append ? "appended" : "redirected", p);
box64_stdout_no_w = 1;
fprintf(stderr, "[BOX64] Trace %s to \"%s\" (set BOX64_NOBANNER=1 to suppress this log)\n", append ? "appended" : "redirected", p);
}
PrintBox64Version(0);
}
@@ -203,7 +206,7 @@ static void displayMiscInfo()
{
openFTrace();
if ((BOX64ENV(nobanner) || BOX64ENV(log)) && ftrace==stdout)
if ((BOX64ENV(nobanner) || BOX64ENV(log)) && ftrace == stdout)
box64_stdout_no_w = 1;
#if !defined(DYNAREC) && (defined(ARM64) || defined(RV64) || defined(LA64))
@@ -322,14 +325,19 @@ void AddNewLibs(const char* list)
}
void PrintHelp() {
PrintfFtrace(0, "This is Box64, the Linux x86_64 emulator with a twist.\n");
PrintfFtrace(0, "Usage is 'box64 [options] path/to/software [args]' to launch x86_64 software.\n");
PrintfFtrace(0, " options are:\n");
PrintfFtrace(0, " '-v'|'--version' to print box64 version and quit\n");
PrintfFtrace(0, " '-h'|'--help' to print this and quit\n");
PrintfFtrace(0, " '-k'|'--kill-all' to kill all box64 instances\n");
PrintfFtrace(0, " '--dynacache-list' to list of DynaCache file and their validity\n");
PrintfFtrace(0, " '--dynacache-clean' to remove invalide DynaCache files\n");
PrintfFtrace(0, "%s\n", BOX64_BUILD_INFO_STRING);
PrintfFtrace(0, "Linux userspace x86-64 emulator with a twist.\n");
PrintfFtrace(0, "There are many environment variables to control Box64's behaviour, checkout the documentation here: https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md\n\n");
PrintfFtrace(0, "USAGE:\n");
PrintfFtrace(0, "\tbox64 [options] path/to/x86_64/executable [args]\n");
PrintfFtrace(0, "\tbox64-bash\n");
PrintfFtrace(0, "OPTIONS:\n");
PrintfFtrace(0, "\t-v, --version print box64 version and quit\n");
PrintfFtrace(0, "\t-h, --help print this and quit\n");
PrintfFtrace(0, "\t-k, --kill-all kill all box64 instances\n");
PrintfFtrace(0, "\t-t, --test run a unit test\n");
PrintfFtrace(0, "\t--dynacache-list list of DynaCache file and their validity\n");
PrintfFtrace(0, "\t--dynacache-clean remove invalid DynaCache files\n");
}
void KillAllInstances()
@@ -410,7 +418,8 @@ static void addLibPaths(box64context_t* context)
AddPath("libunwind.so.8", &context->box64_emulated_libs, 0);
AddPath("libpng12.so.0", &context->box64_emulated_libs, 0);
AddPath("libcurl.so.4", &context->box64_emulated_libs, 0);
//AddPath("libgnutls.so.30", &context->box64_emulated_libs, 0);
if(getenv("BOX64_PRESSURE_VESSEL_FILES")) // use emulated gnutls in this case, it's safer
AddPath("libgnutls.so.30", &context->box64_emulated_libs, 0);
AddPath("libtbbmalloc.so.2", &context->box64_emulated_libs, 0);
AddPath("libtbbmalloc_proxy.so.2", &context->box64_emulated_libs, 0);
@@ -428,7 +437,7 @@ static void addLibPaths(box64context_t* context)
AppendList(&context->box64_path, getenv("PATH"), 1); // in case some of the path are for x86 world
}
void setupZydis(box64context_t* context)
static void setupZydis(box64context_t* context)
{
#ifdef HAVE_TRACE
if ((BOX64ENV(trace_init) && strcmp(BOX64ENV(trace_init), "0")) || (BOX64ENV(trace) && strcmp(BOX64ENV(trace), "0"))) {
@@ -728,13 +737,17 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
if(argc>1 && !strcmp(argv[1], "/usr/bin/gdb") && BOX64ENV(trace_file))
exit(0);
// uname -m is redirected to box64 -m
if(argc==2 && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "-p") || !strcmp(argv[1], "-i")))
{
if (argc == 2 && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "-p") || !strcmp(argv[1], "-i"))) {
printf("x86_64\n");
exit(0);
}
ftrace = stdout;
if (argc >= 3 && (!strcmp(argv[1], "--test") || !strcmp(argv[1], "-t"))) {
box64_unittest_mode = 1;
exit(unittest(argc, argv));
}
ftrace = stderr;
// grab pagesize
box64_pagesize = sysconf(_SC_PAGESIZE);
@@ -799,6 +812,18 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
}
}
}
char* pythonpath = NULL;
{
char* p = BOX64ENV(python3);
if(p) {
if(FileIsX64ELF(p)) {
pythonpath = p;
printf_log(LOG_INFO, "Using python3 \"%s\"\n", pythonpath);
} else {
printf_log(LOG_INFO, "The x86_64 python3 \"%s\" is not an x86_64 binary.\n", p);
}
}
}
// precheck, for win-preload
const char* prog_ = strrchr(prog, '/');
@@ -823,6 +848,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
// pre-check for pressure-vessel-wrap
if(!strcmp(prog_, "pressure-vessel-wrap")) {
printf_log(LOG_INFO, "pressure-vessel-wrap detected\n");
unsetenv("BOX64_ARG0");
pressure_vessel(argc, argv, nextarg+1, prog);
}
#endif
@@ -1020,6 +1046,8 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
bashpath = ResolveFile("box64-bash", &my_context->box64_path);
if(bashpath)
my_context->bashpath = box_strdup(bashpath);
if(pythonpath)
my_context->pythonpath = box_strdup(pythonpath);
ApplyEnvFileEntry(box64_guest_name);
if (box64_wine && box64_wine_guest_name) {
@@ -1027,7 +1055,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
box64_wine_guest_name = NULL;
}
// Try to open ftrace again after applying rcfile.
openFTrace();
displayMiscInfo();
setupZydis(my_context);
PrintEnvVariables(&box64env, LOG_INFO);
@@ -1050,14 +1078,6 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
{
add_argv("--in-process-gpu");
}
if(BOX64ENV(cefdisablegpu))
{
add_argv("-cef-disable-gpu");
}
if(BOX64ENV(cefdisablegpucompositor))
{
add_argv("-cef-disable-gpu-compositor");
}
// add new args only if there is no args already
if(BOX64ENV(args)) {
char tmp[256];
@@ -1125,8 +1145,10 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
}
if(!(my_context->fullpath = box_realpath(my_context->argv[0], NULL)))
my_context->fullpath = box_strdup(my_context->argv[0]);
if(getenv("BOX64_ARG0"))
if (getenv("BOX64_ARG0")) {
my_context->argv[0] = box_strdup(getenv("BOX64_ARG0"));
unsetenv("BOX64_ARG0");
}
FILE *f = fopen(my_context->fullpath, "rb");
if(!f) {
printf_log(LOG_NONE, "Error: Cannot open %s\n", my_context->fullpath);
@@ -1138,7 +1160,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
#ifdef BOX32
box64_is32bits = FileIsX86ELF(my_context->fullpath);
// try to switch personality, but only if not already tried
if(box64_is32bits) {
if(box64_is32bits && !box64env.nopersona32bits) {
int tried = getenv("BOX32_PERSONA32BITS")?1:0;
if(tried) {
unsetenv("BOX32_PERSONA32BITS");
@@ -1175,6 +1197,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
if(!elf_header) {
int x86 = my_context->box86path?FileIsX86ELF(my_context->fullpath):0;
int script = my_context->bashpath?FileIsShell(my_context->fullpath):0;
int python3 = my_context->pythonpath?FileIsPython(my_context->fullpath):0;
printf_log(LOG_NONE, "Error: Reading elf header of %s, Try to launch %s instead\n", my_context->fullpath, x86?"using box86":(script?"using bash":"natively"));
fclose(f);
FreeCollection(&ld_preload);
@@ -1194,6 +1217,14 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
for(int i=0; i<my_context->argc; ++i)
newargv[i+2] = my_context->argv[i];
ret = execvp(newargv[0], (char * const*)newargv);
} else if (python3) {
// duplicate the array and insert 1st arg as box64, 2nd is python3
const char** newargv = (const char**)box_calloc(my_context->argc+3, sizeof(char*));
newargv[0] = my_context->box64path;
newargv[1] = my_context->pythonpath;
for(int i=0; i<my_context->argc; ++i)
newargv[i+2] = my_context->argv[i];
ret = execvp(newargv[0], (char * const*)newargv);
} else {
const char** newargv = (const char**)box_calloc(my_context->argc+1, sizeof(char*));
for(int i=0; i<my_context->argc; ++i)
@@ -1316,6 +1347,8 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
my_context->orig_argc = argc;
my_context->orig_argv = (char**)argv;
}
box64_nolibs = (NeededLibs(elf_header)==0);
if(box64_nolibs) printf_log(LOG_INFO, "Warning, box64 is not really compatible with staticaly linked binaries. Expect crash!\n");
box64_isglibc234 = GetNeededVersionForLib(elf_header, "libc.so.6", "GLIBC_2.34");
if(box64_isglibc234)
printf_log(LOG_DEBUG, "Program linked with GLIBC 2.34+\n");
@@ -1399,7 +1432,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
setupTraceInit();
RunDeferredElfInit(emu);
// update TLS of main elf
RefreshElfTLS(elf_header);
RefreshElfTLS(elf_header, emu);
// do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
ResetSpecialCaseMainElf(elf_header);
// init...
+355 -76
View File
@@ -26,6 +26,7 @@
#include "dynarec/dynablock_private.h"
#include "dynarec/native_lock.h"
#include "dynarec/dynarec_next.h"
#include "freq.h"
// init inside dynablocks.c
static mmaplist_t *mmaplist = NULL;
@@ -93,8 +94,8 @@ typedef struct blocklist_s {
size_t size;
void* first;
uint32_t lowest;
uint8_t type; // could use 7bits for type and 1bit fot is32bits,
uint8_t is32bits; // but that wont really change the size of structure anyway
uint8_t type;
uint8_t is32bits;
} blocklist_t;
#define MMAPSIZE (512*1024) // allocate 512kb sized blocks
@@ -108,6 +109,13 @@ static int c_blocks = 0; // capacity of blocks for custom
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
static int setting_prot = 0;
// Block lookup cache (shared for findBlock/free)
static int last_block_index = -1;
// Per-type allocation caches for better hit rates
static int last_block_index_map64 = -1;
static int last_block_index_map128 = -1;
static int last_block_index_list = -1;
typedef union mark_s {
struct {
unsigned int offs:31;
@@ -118,13 +126,14 @@ typedef union mark_s {
typedef struct blockmark_s {
mark_t prev;
mark_t next;
uint8_t mark[];
// make sure the data always aligned to 16 bytes, this is needed by KHASH_MAP(khint128_t) for example.
uint8_t __attribute__((aligned(16))) mark[];
} blockmark_t;
#define NEXT_BLOCK(b) (blockmark_t*)((uintptr_t)(b) + (b)->next.offs)
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.offs))
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
#define SIZE_BLOCK(b) (((ssize_t)b.offs)-sizeof(blockmark_t))
#define SIZE_BLOCK(b) ((size_t)(b).offs-sizeof(blockmark_t))
void printBlock(blockmark_t* b, void* start, size_t sz)
{
@@ -186,7 +195,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
// get start of block
if(start) {
blockmark_t *m = (blockmark_t*)start;
ssize_t maxsize = 0;
size_t maxsize = 0;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && SIZE_BLOCK(m->next)>maxsize) {
maxsize = SIZE_BLOCK(m->next);
@@ -196,7 +205,7 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
return maxsize;
} else {
blockmark_t *m = LAST_BLOCK(block, block_size); // start with the end
ssize_t maxsize = 0;
size_t maxsize = 0;
while(m->prev.x32 && (((uintptr_t)block+maxsize)<(uintptr_t)m)) { // while there is a subblock
if(!m->prev.fill && SIZE_BLOCK(m->prev)>maxsize) {
maxsize = SIZE_BLOCK(m->prev);
@@ -379,7 +388,7 @@ int printBlockCoherent(int i)
while(m->next.x32) {
blockmark_t* n = NEXT_BLOCK(m);
if(!m->next.fill && !n->next.fill && n!=last) {
printf_log(LOG_NONE, "Chain contains 2 subsequent free blocks %p (%d) and %p (%d) for block %d\n", m, SIZE_BLOCK(m->next), n, SIZE_BLOCK(n->next), i);
printf_log(LOG_NONE, "Chain contains 2 subsequent free blocks %p (%zu) and %p (%zu) for block %d\n", m, SIZE_BLOCK(m->next), n, SIZE_BLOCK(n->next), i);
ret = 0;
}
m = n;
@@ -400,7 +409,7 @@ static char* niceSize(size_t sz)
const char* units[] = {"b", "kb", "Mb", "Gb"};
const size_t vals[] = {1, 1024, 1024*1024, 1024*1024*1024};
int k = 0;
for(int j=0; j<sizeof(vals)/sizeof(vals[0]); ++j)
for(size_t j=0; j<sizeof(vals)/sizeof(vals[0]); ++j)
if(vals[j]<sz)
k = j;
sprintf(rets[i], "%zd %s", sz/vals[k], units[k]);
@@ -472,15 +481,24 @@ int blockstree_index = 0;
blocklist_t* findBlock(uintptr_t addr)
{
blocklist_t* last_found_block = (last_block_index>=0 && last_block_index<n_blocks)?(&p_blocks[last_block_index]):NULL;
if (last_found_block && addr >= (uintptr_t)last_found_block->block && addr < (uintptr_t)last_found_block->block + last_found_block->size)
return last_found_block;
if(blockstree) {
uint32_t i;
uintptr_t end;
if(rb_get_end(blockstree, addr, &i, &end))
if(rb_get_end(blockstree, addr, &i, &end)){
// Upate cache
last_block_index = i;
return &p_blocks[i];
}
} else {
for(int i=0; i<n_blocks; ++i)
if((addr>=(uintptr_t)p_blocks[i].block) && (addr<=(uintptr_t)p_blocks[i].block+p_blocks[i].size))
if((addr>=(uintptr_t)p_blocks[i].block) && (addr<=(uintptr_t)p_blocks[i].block+p_blocks[i].size)){
// Upate cache
last_block_index = i;
return &p_blocks[i];
}
}
return NULL;
}
@@ -571,6 +589,25 @@ void* map128_customMalloc(size_t size, int is32bits)
{
size = 128;
mutex_lock(&mutex_blocks);
// Try cached hint first
if(last_block_index_map128 >= 0 && last_block_index_map128 < n_blocks) {
blocklist_t* hint = &p_blocks[last_block_index_map128];
if(hint && hint->block && (hint->type == BTYPE_MAP) && hint->maxfree && (hint->is32bits==is32bits)) {
uint8_t* map = hint->first;
for(uint32_t idx=hint->lowest; idx<(hint->size>>7); ++idx) {
if(!(idx&7) && map[idx>>3]==0xff)
idx+=7;
else if(!(map[idx>>3]&(1<<(idx&7)))) {
map[idx>>3] |= 1<<(idx&7);
hint->maxfree -= 128;
hint->lowest = idx+1;
last_block_index = last_block_index_map128;
mutex_unlock(&mutex_blocks);
return hint->block+(idx<<7);
}
}
}
}
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].block && (p_blocks[i].type == BTYPE_MAP) && p_blocks[i].maxfree && (p_blocks[i].is32bits==is32bits)) {
// look for a free block
@@ -582,6 +619,8 @@ void* map128_customMalloc(size_t size, int is32bits)
map[idx>>3] |= 1<<(idx&7);
p_blocks[i].maxfree -= 128;
p_blocks[i].lowest = idx+1;
last_block_index = i;
last_block_index_map128 = i;
mutex_unlock(&mutex_blocks);
return p_blocks[i].block+(idx<<7);
}
@@ -596,6 +635,7 @@ void* map128_customMalloc(size_t size, int is32bits)
if(n_blocks>c_blocks) {
c_blocks += box64_is32bits?256:8;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks*sizeof(blocklist_t));
__sync_synchronize();
}
size_t allocsize = MMAPSIZE128;
p_blocks[i].block = NULL; // incase there is a re-entrance
@@ -618,11 +658,11 @@ void* map128_customMalloc(size_t size, int is32bits)
p_blocks[i].size = allocsize;
// setup marks
uint8_t* map = p_blocks[i].first;
for(int idx=(allocsize-mapsize)>>7; idx<(allocsize>>7); ++idx)
for(size_t idx=(allocsize-mapsize)>>7; idx<(allocsize>>7); ++idx)
map[idx>>3] |= (1<<(idx&7));
// 32bits check
if(is32bits && p>(void*)0xffffffffLL) {
printf_log(LOG_INFO, "Warning: failed to allocate 0x%x (0x%x) bytes in 32bits address space (block %d)\n", size, allocsize, i);
// 32bits check - ensure entire allocation fits in 32-bit space
if(is32bits && ((uintptr_t)p + allocsize > 0x100000000ULL)) {
printf_log(LOG_INFO, "Warning: failed to allocate 0x%x (0x%x) bytes in 32bits address space (block %d, addr %p)\n", size, allocsize, i, p);
// failed to allocate memory
if(BOX64ENV(showbt) || BOX64ENV(showsegv)) {
// mask size from this block
@@ -661,6 +701,8 @@ void* map128_customMalloc(size_t size, int is32bits)
p_blocks[i].maxfree = allocsize - (mapsize+128);
mutex_unlock(&mutex_blocks);
add_blockstree((uintptr_t)p, (uintptr_t)p+allocsize, i);
last_block_index = i;
last_block_index_map128 = i;
if(mapallmem) {
if(setting_prot) {
// defer the setProtection...
@@ -677,8 +719,28 @@ void* map128_customMalloc(size_t size, int is32bits)
// the bitmap itself is also allocated in that mapping, as a slice of 256bytes, at the end of the mapping (and so marked as allocated)
void* map64_customMalloc(size_t size, int is32bits)
{
size = 64;
size = 64; (void)size;
mutex_lock(&mutex_blocks);
// Try cached hint first
if(last_block_index_map64 >= 0 && last_block_index_map64 < n_blocks) {
blocklist_t* hint = &p_blocks[last_block_index_map64];
if (hint && hint->block && hint->type == BTYPE_MAP64 && hint->maxfree && (hint->is32bits==is32bits)) {
uint16_t* map = hint->first;
uint32_t slices = hint->size >> 6;
for (uint32_t idx = hint->lowest; idx < slices; ++idx) {
if (!(idx & 15) && map[idx >> 4] == 0xFFFF)
idx += 15;
else if (!(map[idx >> 4] & (1u << (idx & 15)))) {
map[idx >> 4] |= 1u << (idx & 15);
hint->maxfree -= 64;
hint->lowest = idx + 1;
last_block_index = last_block_index_map64;
mutex_unlock(&mutex_blocks);
return hint->block + (idx << 6);
}
}
}
}
for(int i = 0; i < n_blocks; ++i) {
if (p_blocks[i].block
&& p_blocks[i].type == BTYPE_MAP64
@@ -686,7 +748,7 @@ void* map64_customMalloc(size_t size, int is32bits)
&& (p_blocks[i].is32bits==is32bits)
) {
uint16_t* map = p_blocks[i].first;
uint32_t slices = p_blocks[i].size >> 6;
uint32_t slices = p_blocks[i].size >> 6;
for (uint32_t idx = p_blocks[i].lowest; idx < slices; ++idx) {
if (!(idx & 15) && map[idx >> 4] == 0xFFFF)
idx += 15;
@@ -694,6 +756,8 @@ void* map64_customMalloc(size_t size, int is32bits)
map[idx >> 4] |= 1u << (idx & 15);
p_blocks[i].maxfree -= 64;
p_blocks[i].lowest = idx + 1;
last_block_index = i;
last_block_index_map64 = i;
mutex_unlock(&mutex_blocks);
return p_blocks[i].block + (idx << 6);
}
@@ -709,6 +773,7 @@ void* map64_customMalloc(size_t size, int is32bits)
if (n_blocks > c_blocks) {
c_blocks += box64_is32bits ? 256 : 8;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks * sizeof(blocklist_t));
__sync_synchronize();
}
size_t allocsize = MMAPSIZE64;
@@ -762,6 +827,8 @@ void* map64_customMalloc(size_t size, int is32bits)
mutex_unlock(&mutex_blocks);
add_blockstree((uintptr_t)p, (uintptr_t)p + allocsize, i);
last_block_index = i;
last_block_index_map64 = i;
if (mapallmem) {
if (setting_prot) {
@@ -790,6 +857,26 @@ void* internal_customMalloc(size_t size, int is32bits)
blockmark_t* sub = NULL;
size_t fullsize = size+2*sizeof(blockmark_t);
mutex_lock(&mutex_blocks);
// Try cached hint first
if(last_block_index_list >= 0 && last_block_index_list < n_blocks) {
blocklist_t* hint = &p_blocks[last_block_index_list];
if(hint && hint->block && (hint->type == BTYPE_LIST) && hint->maxfree>=init_size && (hint->is32bits==is32bits)) {
size_t rsize = 0;
sub = getFirstBlock(hint->block, init_size, &rsize, hint->first);
if(sub) {
if(size>rsize)
size = init_size;
if(rsize-size<THRESHOLD)
size = rsize;
void* ret = allocBlock(hint->block, sub, size, &hint->first);
if(rsize==hint->maxfree)
hint->maxfree = getMaxFreeBlock(hint->block, hint->size, hint->first);
last_block_index = last_block_index_list;
mutex_unlock(&mutex_blocks);
return ret;
}
}
}
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].block && (p_blocks[i].type == BTYPE_LIST) && p_blocks[i].maxfree>=init_size && (p_blocks[i].is32bits==is32bits)) {
size_t rsize = 0;
@@ -802,6 +889,8 @@ void* internal_customMalloc(size_t size, int is32bits)
void* ret = allocBlock(p_blocks[i].block, sub, size, &p_blocks[i].first);
if(rsize==p_blocks[i].maxfree)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
last_block_index = i;
last_block_index_list = i;
mutex_unlock(&mutex_blocks);
return ret;
}
@@ -812,6 +901,7 @@ void* internal_customMalloc(size_t size, int is32bits)
if(n_blocks>c_blocks) {
c_blocks += box64_is32bits?256:8;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks*sizeof(blocklist_t));
__sync_synchronize();
}
size_t allocsize = (fullsize>MMAPSIZE)?fullsize:MMAPSIZE;
allocsize = (allocsize+box64_pagesize-1)&~(box64_pagesize-1);
@@ -842,8 +932,9 @@ void* internal_customMalloc(size_t size, int is32bits)
blockmark_t* n = NEXT_BLOCK(m);
n->next.x32 = 0;
n->prev.x32 = m->next.x32;
if(is32bits && p>(void*)0xffffffffLL) {
printf_log(LOG_INFO, "Warning: failed to allocate 0x%x (0x%x) bytes in 32bits address space (block %d)\n", size, allocsize, i);
// 32bits check - ensure entire allocation fits in 32-bit space
if(is32bits && ((uintptr_t)p + allocsize > 0x100000000ULL)) {
printf_log(LOG_INFO, "Warning: failed to allocate 0x%x (0x%x) bytes in 32bits address space (block %d, addr %p)\n", size, allocsize, i, p);
// failed to allocate memory
if(BOX64ENV(showbt) || BOX64ENV(showsegv)) {
// mask size from this block
@@ -880,6 +971,8 @@ void* internal_customMalloc(size_t size, int is32bits)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
mutex_unlock(&mutex_blocks);
add_blockstree((uintptr_t)p, (uintptr_t)p+allocsize, i);
last_block_index = i;
last_block_index_list = i;
if(mapallmem) {
if(setting_prot) {
// defer the setProtection...
@@ -1108,6 +1201,7 @@ void* internal_customMemAligned(size_t align, size_t size, int is32bits)
if(n_blocks>c_blocks) {
c_blocks += 4;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks*sizeof(blocklist_t));
__sync_synchronize();
}
p_blocks[i].block = NULL; // incase there is a re-entrance
p_blocks[i].first = NULL;
@@ -1130,8 +1224,9 @@ void* internal_customMemAligned(size_t align, size_t size, int is32bits)
p_blocks[i].block = p;
p_blocks[i].first = p;
p_blocks[i].size = allocsize;
if(is32bits && p>(void*)0xffffffffLL) {
printf_log(LOG_INFO, "Warning: failed to allocate aligned 0x%x (0x%x) bytes in 32bits address space (block %d)\n", size, allocsize, i);
// 32bits check - ensure entire allocation fits in 32-bit space
if(is32bits && ((uintptr_t)p + allocsize > 0x100000000ULL)) {
printf_log(LOG_INFO, "Warning: failed to allocate aligned 0x%x (0x%x) bytes in 32bits address space (block %d, addr %p)\n", size, allocsize, i, p);
// failed to allocate memory
if(BOX64ENV(showbt) || BOX64ENV(showsegv)) {
// mask size from this block
@@ -1187,9 +1282,11 @@ void* internal_customMemAligned(size_t align, size_t size, int is32bits)
void* ret = allocBlock(p_blocks[i].block, new_sub, size, &p_blocks[i].first);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
mutex_unlock(&mutex_blocks);
add_blockstree((uintptr_t)p, (uintptr_t)p+allocsize, i);
if(mapallmem)
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
add_blockstree((uintptr_t)p, (uintptr_t)p+allocsize, i);
last_block_index = i;
last_block_index_list = i;
return ret;
}
void* customMemAligned(size_t align, size_t size)
@@ -1379,24 +1476,30 @@ int MmaplistAddBlock(mmaplist_t* list, int fd, off_t offset, void* orig, size_t
#define GO(A) if(bl->A) bl->A = ((void*)bl->A)+delta
GO(block);
GO(actual_block);
GO(previous);
GO(instsize);
GO(arch);
GO(callrets);
GO(jmpnext);
GO(table64);
GO(relocs);
#ifdef GBDJIT
GO(gdbjit_block);
#endif
#undef GO
bl->previous = NULL; // that seems safer that way
// shift the self referece to dynablock
if(bl->block!=bl->jmpnext) {
void** db_ref = (bl->jmpnext-sizeof(void*));
*db_ref = (*db_ref)+delta;
db_ref = (bl->jmpnext-sizeof(void*)+3*sizeof(void*));
*db_ref = native_next;
}
// adjust x64_addr with delta_map
bl->x64_addr += delta_map;
*(uintptr_t*)(bl->jmpnext+2*sizeof(void*)) = RelocGetNext();
if(bl->relocs && bl->relocsize)
ApplyRelocs(bl, delta, delta_map, mapping_start);
ClearCache(bl->jmpnext, 4*sizeof(void*));
ClearCache(bl->actual_block+sizeof(void*), bl->native_size);
//add block, as dirty for now
if(!addJumpTableIfDefault64(bl->x64_addr, bl->jmpnext)) {
@@ -1482,6 +1585,68 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
return NULL;
}
// To measure speed at wich blocks are created, to avoid purge when lots of blocks are created in burst
static uint64_t start_time = 0;
static uint32_t start_tick = 0;
static uint64_t tick_freq = 0;
static uint64_t cur_speed = 0;
void UpdateBlockCreationSpeed()
{
if(!tick_freq) {
tick_freq = ReadTSCFrequency(NULL);
start_tick = my_context->tick;
start_time = ReadTSC(NULL);
}
uint64_t cur_time = ReadTSC(NULL);
// compute elapsed time is micro seconds
uint64_t elapsed_time = (cur_time-start_time)*1000000LL/tick_freq;
if(my_context->tick-start_tick>100 || elapsed_time>1000) {
// update speed each 100 blocks created or 1ms elapsed
cur_speed = (my_context->tick-start_tick)*1000000LL/elapsed_time;
start_tick = my_context->tick;
start_time = cur_time;
}
}
int PurgeDynarecMap(mmaplist_t* list, size_t size)
{
if(cur_speed>100) return 0; // 100 blocks / sec is a burst!
// check all blocks where tick is old enough and in_used==0, then delete them
// return 1 as soon as one block has been deleted, 0 else
// beware that tick=0 blocks means they were never executed and should not be touched
int ret = 0;
for(int i=0; i<list->size && !ret; ++i) {
blocklist_t* bl = list->chunks[i];
blockmark_t* p = bl->block;
blockmark_t* end = bl->block + bl->size - sizeof(blockmark_t);
while(p<end) {
blockmark_t *n = NEXT_BLOCK(p);
if(p->next.fill) {
dynablock_t* dynablock = *(dynablock_t**)p->mark;
int tick = native_lock_get_d(&dynablock->tick);
if(tick && dynablock->done && (my_context->tick > tick) && ((my_context->tick-tick)>=BOX64ENV(dynarec_purge_age))) {
int in_used = native_lock_get_d(&dynablock->in_used);
if(!in_used) {
// free the block, but unreference it first
//if(setJumpTableDefaultIfRef64(dynablock->x64_addr, dynablock->block))
{
dynarec_log(LOG_INFO/*LOG_DEBUG*/, " PurgeDynablock %p\n", dynablock);
if((n<end) && !n->next.fill )
n = NEXT_BLOCK(n); //because the block will be agglomerated
FreeDynablock(dynablock, 0, 1);
if((bl->maxfree>=size))
ret = 1;
} // fail to set default jump, so skipping
}
}
}
p = n;
}
}
return ret;
}
#ifdef TRACE_MEMSTAT
static uint64_t dynarec_allocated = 0;
#endif
@@ -1492,6 +1657,11 @@ uintptr_t AllocDynarecMap(uintptr_t x64_addr, size_t size, int is_new)
size = roundSize(size);
if(BOX64ENV(dynarec_purge)) {
__atomic_fetch_add(&my_context->tick, 1, __ATOMIC_RELAXED);
UpdateBlockCreationSpeed();
}
mmaplist_t* list = GetMmaplistByAddr(x64_addr);
if(!list)
list = mmaplist;
@@ -1501,19 +1671,26 @@ uintptr_t AllocDynarecMap(uintptr_t x64_addr, size_t size, int is_new)
list->dirty = 1;
// check if there is space in current open ones
uintptr_t sz = size + 2*sizeof(blockmark_t);
for(int i=0; i<list->size; ++i)
if(list->chunks[i]->maxfree>=size) {
// looks free, try to alloc!
size_t rsize = 0;
void* sub = getFirstBlock(list->chunks[i]->block, size, &rsize, list->chunks[i]->first);
if(sub) {
void* ret = allocBlock(list->chunks[i]->block, sub, size, &list->chunks[i]->first);
if(rsize==list->chunks[i]->maxfree)
list->chunks[i]->maxfree = getMaxFreeBlock(list->chunks[i]->block, list->chunks[i]->size, list->chunks[i]->first);
//rb_set_64(list->chunks[i].tree, (uintptr_t)ret, (uintptr_t)ret+size, (uintptr_t)ret);
return (uintptr_t)ret;
int recheck = 0;
do {
for(int i=0; i<list->size; ++i) {
if(list->chunks[i]->maxfree>=size) {
// looks free, try to alloc!
size_t rsize = 0;
void* sub = getFirstBlock(list->chunks[i]->block, size, &rsize, list->chunks[i]->first);
if(sub) {
void* ret = allocBlock(list->chunks[i]->block, sub, size, &list->chunks[i]->first);
if(rsize==list->chunks[i]->maxfree)
list->chunks[i]->maxfree = getMaxFreeBlock(list->chunks[i]->block, list->chunks[i]->size, list->chunks[i]->first);
//rb_set_64(list->chunks[i].tree, (uintptr_t)ret, (uintptr_t)ret+size, (uintptr_t)ret);
return (uintptr_t)ret;
}
}
}
// check if we can remove blocks before allocating a new one
if(BOX64ENV(dynarec_purge))
recheck = recheck?0:PurgeDynarecMap(list, size); // don't do purge all the time, it's too time consuming
} while(recheck);
// need to add a new
if(list->size == list->cap) {
list->cap+=4;
@@ -1825,6 +2002,32 @@ void setJumpTableDefault64(void* addr)
idx0 = (((uintptr_t)addr) )&JMPTABLE_MASK0;
native_lock_store_dd(&box64_jmptbl3[idx3][idx2][idx1][idx0], (uintptr_t)native_next);
}
int setJumpTableDefaultIfRef64(void* addr, void* jmp)
{
uintptr_t idx3, idx2, idx1, idx0;
#ifdef JMPTABL_SHIFT4
uintptr_t idx4;
idx4 = (((uintptr_t)addr)>>JMPTABL_START4)&JMPTABLE_MASK4;
if(box64_jmptbl4[idx4] == box64_jmptbldefault3)
return 0;
uintptr_t ****box64_jmptbl3 = box64_jmptbl4[idx4];
#endif
idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
return 0;
idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
return 0;
idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
return 0;
idx0 = (((uintptr_t)addr) )&JMPTABLE_MASK0;
#ifdef JMPTABL_SHIFT4
return (native_lock_storeifref(create_jmptbl(0, idx0, idx1, idx2, idx3, idx4), native_next, jmp)==native_next)?1:0;
#else
return (native_lock_storeifref(create_jmptbl(0, idx0, idx1, idx2, idx3), native_next, jmp)==native_next)?1:0;
#endif
}
void setJumpTableDefaultRef64(void* addr, void* jmp)
{
uintptr_t idx3, idx2, idx1, idx0;
@@ -2195,15 +2398,17 @@ typedef union hotpage_s {
uint64_t x;
} hotpage_t;
#define HOTPAGE_MAX ((1<<28)-1)
#define N_HOTPAGE 8
#define N_HOTPAGE 32
#define N_HOTPAGE_ALT 8
#define HOTPAGE_MARK 64
#define HOTPAGE_DIRTY 1024
#define HOTPAGE_DIRTY 128
#define HOTPAGE_DIRTY_ALT 1024
static hotpage_t hotpage[N_HOTPAGE] = {0};
void SetHotPage(int idx, uintptr_t page)
{
hotpage_t tmp = hotpage[idx];
tmp.addr = page;
tmp.cnt = BOX64ENV(dynarec_dirty)?HOTPAGE_DIRTY:HOTPAGE_MARK;
tmp.cnt = BOX64ENV(dynarec_dirty)?(BOX64ENV(dynarec_hotpage_alt)?HOTPAGE_DIRTY_ALT:HOTPAGE_DIRTY):HOTPAGE_MARK;
//TODO: use Atomics to update hotpage?
native_lock_store_dd(hotpage+idx, tmp.x);
}
@@ -2222,28 +2427,38 @@ int IdxOldestHotPage(uintptr_t page)
{
int best_idx = -1;
uint32_t best_cnt = HOTPAGE_MAX+1;
// to reset hotpage with new value...
hotpage_t tmp;
tmp.addr = page;
tmp.cnt = HOTPAGE_MAX;
for(int i=0; i<N_HOTPAGE; ++i) {
if(!hotpage[i].cnt) {
native_lock_store_dd(hotpage+i, tmp.x);
return i;
}
if(BOX64ENV(dynarec_hotpage_alt)) {
hotpage_t tmp;
tmp.addr = page;
tmp.cnt = HOTPAGE_MAX;
for(int i=0; i<N_HOTPAGE_ALT; ++i) {
if(!hotpage[i].cnt) {
native_lock_store_dd(hotpage+i, tmp.x);
return i;
}
uint32_t cnt = hotpage[i].cnt;
if(cnt==HOTPAGE_MAX) cnt = 0;
if(cnt < best_cnt) {
best_idx = i;
best_cnt = cnt;
if(cnt < best_cnt) {
best_idx = i;
best_cnt = cnt;
}
}
hotpage_t old = hotpage[best_idx];
native_lock_store_dd(hotpage+best_idx, tmp.x);
if(old.cnt && old.cnt!=HOTPAGE_MAX && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(old.addr);
} else {
for(int i=0; i<N_HOTPAGE && best_cnt; ++i) {
uint32_t cnt = hotpage[i].cnt;
if(cnt < best_cnt) {
best_idx = i;
best_cnt = cnt;
}
}
}
hotpage_t old = hotpage[best_idx];
native_lock_store_dd(hotpage+best_idx, tmp.x);
if(old.cnt && old.cnt!=HOTPAGE_MAX && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(old.addr);
return best_idx;
}
// this function will create a new HotPage, or re-arm it if it's already registered
void CheckHotPage(uintptr_t addr, uint32_t prot)
{
if(addr>=0x1000000000000LL) // more than 48bits
@@ -2253,20 +2468,41 @@ void CheckHotPage(uintptr_t addr, uint32_t prot)
if(BOX64ENV(dynarec_nohotpage))
return;
uintptr_t page = addr>>12;
if(!BOX64ENV(dynarec_hotpage_alt)) {
if(!(prot&PROT_EXEC))
return; // needs to be an executable page
/*if(BOX64ENV(dynarec_dirty)>1) {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p, marking page as NEVERCLEAN\n", (void*)(page<<12));
neverprotectDB(page<<12, box64_pagesize, 1);
return;
}*/
}
// look for idx
int idx = IdxHotPage(page);
if(idx==-1) { IdxOldestHotPage(page); return; }
hotpage_t hp = hotpage[idx];
/*if(hp.cnt==HOTPAGE_MAX)*/ {
if(BOX64ENV(dynarec_dirty)>1) {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d), marking page as NEVERCLEAN\n", (void*)(page<<12), idx);
neverprotectDB(page<<12, box64_pagesize, 1);
hp.cnt = 0;
native_lock_store_dd(hotpage+idx, hp.x); // free slot
} else {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
SetHotPage(idx, page);
if(BOX64ENV(dynarec_hotpage_alt)) {
if(idx==-1) { IdxOldestHotPage(page); return; }
hotpage_t hp = hotpage[idx];
/*if(hp.cnt==HOTPAGE_MAX)*/ {
if(BOX64ENV(dynarec_dirty)>1) {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d), marking page as NEVERCLEAN\n", (void*)(page<<12), idx);
neverprotectDB(page<<12, box64_pagesize, 1);
hp.cnt = 0;
native_lock_store_dd(hotpage+idx, hp.x); // free slot
} else {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
SetHotPage(idx, page);
}
}
} else {
if(idx!=-1 && BOX64ENV(dynarec_dirty)>1 && !hotpage[idx].cnt) {
// Re-arming, so put the page as NEVERCLEAN and stop bothering
neverprotectDB(page<<12, box64_pagesize, 1);
return;
}
if(idx==-1) idx = IdxOldestHotPage(page);
if(idx==-1) return;
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
SetHotPage(idx, page);
}
}
int isInHotPage(uintptr_t addr)
@@ -2274,22 +2510,45 @@ int isInHotPage(uintptr_t addr)
if(addr>0x1000000000000LL) return 0;
uintptr_t page = addr>>12;
int idx = IdxHotPage(page);
if(idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))
return 0;
//TODO: do Atomic stuffs instead
hotpage_t hp = hotpage[idx];
--hp.cnt;
native_lock_store_dd(hotpage+idx, hp.x);
if(!hp.cnt && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(hp.addr);
return 1;
if(BOX64ENV(dynarec_hotpage_alt)) {
if(idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))
return 0;
//TODO: do Atomic stuffs instead
hotpage_t hp = hotpage[idx];
--hp.cnt;
native_lock_store_dd(hotpage+idx, hp.x);
if(!hp.cnt && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(hp.addr);
return 1;
} else {
int ret = ((idx==-1) || !hotpage[idx].cnt)?0:1;
// decrement all hotpage, it's a hotpage "tick"
for(int i=0; i<N_HOTPAGE; ++i) {
int ok = 0;
do {
hotpage_t hp = hotpage[i];
hotpage_t old = hp;
if(!hp.cnt || (hp.cnt==HOTPAGE_MAX)) {
ok = 1;
} else {
--hp.cnt;
ok = native_lock_storeifref2(hotpage+i, (void*)hp.x, (void*)old.x)==(void*)old.x;
}
} while(!ok);
}
return ret;
}
}
int checkInHotPage(uintptr_t addr)
{
if(addr>0x1000000000000LL) return 0;
uintptr_t page = addr>>12;
int idx = IdxHotPage(page);
return (idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))?0:1;
if(BOX64ENV(dynarec_hotpage_alt)) {
return (idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))?0:1;
} else {
return ((idx==-1) || !hotpage[idx].cnt)?0:1;
}
}
@@ -2467,7 +2726,8 @@ void loadProtectionFromMap()
printf_log(LOG_INFO, "Didn't detect 48bits of address space, considering it's 39bits\n");
}
if(!pbrk) {
printf_log(LOG_INFO, "Warning, program break not found\n");
if (!box64_unittest_mode)
printf_log(LOG_INFO, "Warning, program break not found\n");
if(cur_brk) pbrk = *cur_brk; // approximate is better than nothing
}
fclose(f);
@@ -2669,6 +2929,21 @@ static void atfork_child_custommem(void)
// (re)init mutex if it was lock before the fork
init_mutexes();
}
void preserve_highest32()
{
// reserve area close to 0xffffffff too, to avoid roll over on some opcodes...
void* cur = InternalMmap((void*)(0x100000000LL-65536), 65536, 0, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
if(cur!=MAP_FAILED && (cur==(void*)(0x100000000LL-65536))) {
rb_set(mapallmem, (uintptr_t)cur, (uintptr_t)cur+65536, MEM_RESERVED);
} else {
printf_log(LOG_INFO, " Tried to reserve high %p+>%p (%zx)\n", (void*)(0x100000000LL-65536), cur, 65536);
if(cur!=(void*)(0x100000000LL-65536))
InternalMunmap(cur, 65536);
else
munmap(cur, 65536);
}
}
#ifdef BOX32
void reverveHigMem32(void)
{
@@ -2692,11 +2967,11 @@ void reverveHigMem32(void)
printf_log(LOG_INFO, "Memory higher than 32bits reserved\n");
if (BOX64ENV(log)>=LOG_DEBUG) {
uintptr_t start=0x100000000LL;
int prot;
uint32_t prot;
uintptr_t bend = start;
while (bend!=0xffffffffffffffffLL) {
if(rb_get_end(mapallmem, start, &prot, &bend)) {
printf_log(LOG_NONE, " Reserved: %p - %p (%d)\n", (void*)start, (void*)bend, prot);
printf_log(LOG_NONE, " Reserved: %p - %p (%u)\n", (void*)start, (void*)bend, prot);
}
start = bend;
}
@@ -2891,6 +3166,10 @@ void fini_custommem_helper(box64context_t *ctx)
for(int i=0; i<n_blocks; ++i)
InternalMunmap(p_blocks[i].block, p_blocks[i].size);
box_free(p_blocks);
last_block_index = -1;
last_block_index_map64 = -1;
last_block_index_map128 = -1;
last_block_index_list = -1;
#if !defined(USE_CUSTOM_MUTEX)
pthread_mutex_destroy(&mutex_prot);
pthread_mutex_destroy(&mutex_blocks);
+19 -15
View File
@@ -40,6 +40,7 @@ int convert_bitmask(uint64_t bitmask);
#define MOV64xw(Rd, imm64) if(rex.w) {MOV64x(Rd, imm64);} else {MOV32w(Rd, imm64);}
#define MOV64z(Rd, imm64) if(rex.is32bits) {MOV32w(Rd, imm64);} else {MOV64x(Rd, imm64);}
#define MOV64y(Rd, imm64) if(rex.is32bits || rex.is67) {MOV32w(Rd, imm64);} else {MOV64x(Rd, imm64);}
// ADD / SUB
@@ -48,14 +49,16 @@ int convert_bitmask(uint64_t bitmask);
#define ADDSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b01, Rm, lsr, Rn, Rd))
#define ADDz_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDz_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen((rex.is32bits)?0:1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDy_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen((rex.is32bits || rex.is67)?0:1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b01, Rm, lsr, Rn, Rd))
#define ADDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, lsl, Rn, Rd))
#define ADDxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen((rex.is32bits)?0:1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDy_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen((rex.is32bits || rex.is67)?0:1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
@@ -66,7 +69,8 @@ int convert_bitmask(uint64_t bitmask);
#define ADDSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen((rex.is32bits)?0:1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDy_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen((rex.is32bits || rex.is67)?0:1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
@@ -81,6 +85,7 @@ int convert_bitmask(uint64_t bitmask);
#define SUBSw_REG_ASR(Rd, Rn, Rm, asr) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b10, Rm, asr, Rn, Rd))
#define SUBxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBy_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen((rex.is32bits || rex.is67)?0:1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG_ASR(Rd, Rn, Rm, asr) FEMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b10, Rm, asr, Rn, Rd))
#define CMPSx_REG(Rn, Rm) SUBSx_REG(xZR, Rn, Rm)
@@ -103,6 +108,7 @@ int convert_bitmask(uint64_t bitmask);
#define SUBSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBy_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen((rex.is32bits || rex.is67)?0:1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define CMPSx_U12(Rn, imm12) SUBSx_U12(xZR, Rn, imm12)
#define CMPSw_U12(Rn, imm12) SUBSw_U12(wZR, Rn, imm12)
@@ -127,6 +133,8 @@ int convert_bitmask(uint64_t bitmask);
#define SUBw_UXTB(Rd, Rn, Rm) EMIT(ADDSUB_ext(0, 1, 0, Rm, 0b000, 0, Rn, Rd))
#define ADDw_UXTH(Rd, Rn, Rm) EMIT(ADDSUB_ext(0, 0, 0, Rm, 0b001, 0, Rn, Rd))
#define ADDx_UXTW(Rd, Rn, Rm) EMIT(ADDSUB_ext(1, 0, 0, Rm, 0b010, 0, Rn, Rd))
#define ADDx_SXTW(Rd, Rn, Rm) EMIT(ADDSUB_ext(1, 0, 0, Rm, 0b110, 0, Rn, Rd))
#define ADDx_REGy(Rd, Rn, Rm) do {if(rex.is32bits || rex.is67) ADDx_SXTW(Rd, Rn, Rm); else ADDx_REG(Rd, Rn, Rm); } while(0)
// CCMP compare if cond is true, set nzcv if false
#define CCMP_reg(sf, Rm, cond, Rn, nzcv) ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
@@ -149,6 +157,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDRH_S9_postindex(Rt, Rn, imm9) EMIT(LDR_gen(0b01, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define LDRH_S9_preindex(Rt, Rn, imm9) EMIT(LDR_gen(0b01, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
#define LDRxw_S9_postindex(Rt, Rn, imm9) EMIT(LDR_gen(rex.w?0b11:0b10, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define LDRz_S9_preindex(Rt, Rn, imm9) EMIT(LDR_gen(rex.is32bits?0b10:0b11, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
#define LDRS_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_S9_postindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
@@ -172,24 +181,16 @@ int convert_bitmask(uint64_t bitmask);
#define LDRx_REG_LSL3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
#define LDRx_REG_UXTW3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b010, 1, Rn, Rt))
#define LDRx_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRx_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRw_REG_LSL2(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt))
#define LDRw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDRw_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRxw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b011, 0, Rn, Rt))
#define LDRz_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
#define LDRxw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b110, 0, Rn, Rt))
#define LDRxw_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRz_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRz_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define LDRB_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b010, 0, Rn, Rt))
#define LDRB_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b110, 0, Rn, Rt))
#define LDRB_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define LDRH_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b110, 0, Rn, Rt))
#define LDRH_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
@@ -202,8 +203,6 @@ int convert_bitmask(uint64_t bitmask);
#define LDRS_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_REG(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRSW_REG_SXTW(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDRSW_REGz(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRSH_REGz(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b01, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
#define LDRx_literal(Rt, imm21) EMIT(LDR_PC_gen(0b01, (((int64_t)(imm21))>>2)&0x7FFFF, Rt))
@@ -403,6 +402,9 @@ int convert_bitmask(uint64_t bitmask);
#define DSB_ST() EMIT(DSB_gen(0b1110))
#define DSB_SY() EMIT(DSB_gen(0b1111))
#define DC_gen(op1, CRm, op2, Xt) (0b1101010100001<<19 | (op1)<<16 | 0b0111<<12 | (CRm)<<8 | (op2)<<5 | Xt)
#define DC_CIVAC(Xt) EMIT(DC_gen(0b011, 0b1110, 0b001, Xt))
// Break
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
#define BRK(imm16) EMIT(BRK_gen(imm16))
@@ -417,11 +419,11 @@ int convert_bitmask(uint64_t bitmask);
#define CBNZx(Rt, imm19) EMIT(CB_gen(1, 1, ((imm19)>>2)&0x7FFFF, Rt))
#define CBNZw(Rt, imm19) EMIT(CB_gen(0, 1, ((imm19)>>2)&0x7FFFF, Rt))
#define CBNZxw(Rt, imm19) EMIT(CB_gen(rex.w, 1, ((imm19)>>2)&0x7FFFF, Rt))
#define CBNZz(Rt, imm19) EMIT(CB_gen(rex.is32bits?0:1, 1, ((imm19)>>2)&0x7FFFF, Rt))
#define CBNZy(Rt, imm19) EMIT(CB_gen((rex.is32bits || rex.is67)?0:1, 1, ((imm19)>>2)&0x7FFFF, Rt))
#define CBZx(Rt, imm19) EMIT(CB_gen(1, 0, ((imm19)>>2)&0x7FFFF, Rt))
#define CBZw(Rt, imm19) EMIT(CB_gen(0, 0, ((imm19)>>2)&0x7FFFF, Rt))
#define CBZxw(Rt, imm19) EMIT(CB_gen(rex.w, 0, ((imm19)>>2)&0x7FFFF, Rt))
#define CBZz(Rt, imm19) EMIT(CB_gen(rex.is32bits?0:1, 0, ((imm19)>>2)&0x7FFFF, Rt))
#define CBZy(Rt, imm19) EMIT(CB_gen((rex.is32bits || rex.is67)?0:1, 0, ((imm19)>>2)&0x7FFFF, Rt))
#define TB_gen(b5, op, b40, imm14, Rt) ((b5)<<31 | 0b011011<<25 | (op)<<24 | (b40)<<19 | (imm14)<<5 | (Rt))
#define TBZ(Rt, bit, imm16) EMIT(TB_gen(((bit)>>5)&1, 0, (bit)&0x1f, ((imm16)>>2)&0x3FFF, Rt))
@@ -614,6 +616,7 @@ int convert_bitmask(uint64_t bitmask);
#define LSLx(Rd, Rn, lsl) UBFMx(Rd, Rn, ((-(lsl))%64)&63, 63-(lsl))
#define LSLw(Rd, Rn, lsl) UBFMw(Rd, Rn, ((-(lsl))%32)&31, 31-(lsl))
#define LSLxw(Rd, Rn, lsl) UBFMxw(Rd, Rn, rex.w?(((-(lsl))%64)&63):(((-(lsl))%32)&31), (rex.w?63:31)-(lsl))
#define LSLy(Rd, Rn, lsl) do {if(rex.is32bits || rex.is67) LSLw(Rd, Rn, lsl); else LSLx(Rd, Rn, lsl);} while(0)
// Take width first bits from Rn, LSL lsb and create Rd
#define UBFIZx(Rd, Rn, lsb, width) UBFMx(Rd, Rn, ((-(lsb))%64)&63, width-1)
// Take width first bits from Rn, LSL lsb and create Rd
@@ -2074,6 +2077,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDADDAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b000, Rn, Rt))
#define LDADDALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b000, Rn, Rt))
#define LDADDLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, Rt))
#define STADDLw(Rs, Rn) EMIT(ATOMIC_gen(0b10, 0, 1, Rs, 0b000, Rn, 0b11111))
#define STADDxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b000, Rn, 0b11111))
#define STADDLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, 0b11111))
#define LDADDB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b000, Rn, Rt))
+1 -1
View File
@@ -20,7 +20,7 @@ arm64_epilog:
stp x26, x27, [x0, (8 * 16)] // put back reg value in emu, including EIP (so x27 must be EIP now)
//restore all used register
#ifdef _WIN32
ldr x18, [x0, 3120]
ldr x18, [x0, 3104]
#endif
add sp, x28, 0
//vpop {d8-d15}
+1
View File
@@ -60,6 +60,7 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur
// convert a x86 register to native according to the register mapping
#define TO_NAT(A) (xRAX + (A))
#define IS_GPR(A) ((A)>=xRAX && (A)<=xRIP)
// 32bits version
#define wEAX xRAX
+1 -1
View File
@@ -23,7 +23,7 @@ arm64_next:
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
#ifdef _WIN32
ldr x18, [x0, 3120]
ldr x18, [x0, 3104]
#endif
mov x1, x27 // xRIP, should not be needed most of the time
mov x2, x30 // "from" is in lr, so put in x2
+10
View File
@@ -565,6 +565,16 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "SUB %s, %s, %s %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[sf][shift], imm);
return buff;
}
if(isMask(opcode, "f0001011001mmmmmoooiiinnnnnddddd", &a)) {
const char* shifts[2][8] = {{ "UXTB", "UXTH", "LSL", "UXTX", "SXTB", "SXTH", "SXTW", "SXTX"}, {"UXTB", "UXTH", "UXTW", "LSL", "SXTB", "SXTH", "SXTW", "SXTX" }};
if(((sf==0 && shift==2) || (sf==1 && shift==3)) && imm==0)
snprintf(buff, sizeof(buff), "ADD %s, %s, %s", sf?XtSp[Rd]:WtSp[Rd], sf?XtSp[Rn]:WtSp[Rn], sf?XtSp[Rm]:WtSp[Rm]);
else if(shift==0)
snprintf(buff, sizeof(buff), "ADD %s, %s, %s %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[sf][shift]);
else
snprintf(buff, sizeof(buff), "ADD %s, %s, %s %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[sf][shift], imm);
return buff;
}
// ---- LOGIC
if(isMask(opcode, "f11100100Nrrrrrrssssssnnnnnddddd", &a)) {
uint64_t i = DecodeBitMasks(a.N, imms, immr);
File diff suppressed because it is too large. Load diff
+122 -71
View File
@@ -20,10 +20,13 @@
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
#ifndef __WIN32
#include "elfloader.h"
#endif
uintptr_t dynarec64_0F(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_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
@@ -165,7 +168,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMEND();
GETIP(addr);
STORE_XEMU_CALL(xRIP);
CALL_S(const_x64syscall, -1);
#ifndef __WIN32
if(!box64_wine || FindElfAddress(my_context, ip)) {
CALL_S(const_x64syscall_linux, -1);
} else
#endif
{
CALL_S(const_x64syscall, -1);
}
LOAD_XEMU_CALL(xRIP);
TABLE64(x3, addr); // expected return address
SUBx_REG(x3, x3, xRIP);
@@ -184,9 +194,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
BARRIER(BARRIER_FLOAT);
GETIP(ip);
UDF(0);
STORE_XEMU_CALL(xRIP);
CALL_S(const_native_priv, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
@@ -367,22 +378,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("PREFETCHh Ed");
INST_NAME("PREFETCHNTA Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PLD_L1_STREAM_U12(ed, fixedaddress);
break;
case 1:
INST_NAME("PREFETCHh Ed");
INST_NAME("PREFETCHT0 Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PLD_L1_KEEP_U12(ed, fixedaddress);
break;
case 2:
INST_NAME("PREFETCHh Ed");
INST_NAME("PREFETCHT1 Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PLD_L2_KEEP_U12(ed, fixedaddress);
break;
case 3:
INST_NAME("PREFETCHh Ed");
INST_NAME("PREFETCHT2 Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PLD_L3_KEEP_U12(ed, fixedaddress);
break;
@@ -403,6 +414,31 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
FAKEED;
break;
case 0x20: /* MOV REG, crX */
case 0x21: /* MOV REG, drX */
case 0x22: /* MOV cxR, REG */
case 0x23: /* MOV drX, REG */
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
nextop = F8;
GETIP(ip);
u8 = (rex.r*8)+(nextop>>3&7);
if((((opcode==0x20) || (opcode==0x22)) && ((u8==1) || (u8==5) || (u8==6) || (u8==7) || (u8>8))) || (((opcode==0x21) || (opcode==0x23) && rex.r))) {
INST_NAME("Illegal 0F 20..23");
UDF(0);
} else {
INST_NAME(opcode==0x20?"MOV REG, crX":(opcode==0x21?"MOV REG, drX":(opcode==0x22?"MOV cxR, REG":"MOV dxR, REG")));
STORE_XEMU_CALL(xRIP);
CALL_S(const_native_priv, -1);
LOAD_XEMU_CALL(xRIP);
}
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0x28:
INST_NAME("MOVAPS Gx,Ex");
@@ -535,7 +571,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET_NODF);
SETFLAGS(X_ALL, SF_SET_DF);
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
@@ -1699,7 +1735,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3, 0); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd); \
@@ -1749,17 +1785,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POP FS");
POP1z(x2);
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_FS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_FS]));
CBZw_NEXT(x2);
MOV32w(x1, _FS);
CALL(const_getsegmentbase, -1);
break;
case 0xA2:
INST_NAME("CPUID");
NOTEST(x1);
GETIP(ip); // sync RIP for easier debugging
STRx_U12(xRIP, xEmu, offsetof(x64emu_t, ip));
MOVx_REG(x1, xRAX);
CALL_(const_cpuid, -1, 0);
break;
case 0xA3:
INST_NAME("BT Ed, Gd");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -1773,7 +1813,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
ADDy_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
}
@@ -1833,12 +1873,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POP GS");
POP1z(x2);
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_GS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_GS]));
CBZw_NEXT(x2);
MOV32w(x1, _GS);
CALL(const_getsegmentbase, -1);
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -1853,7 +1895,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
ADDy_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -2021,12 +2063,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization (CLFLUSH)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(const_native_clflush, -1, 0);
DC_CIVAC(ed);
SMDMB();
break;
default:
DEFAULT;
@@ -2034,7 +2073,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2127,7 +2166,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xB3:
INST_NAME("BTR Ed, Gd");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2143,7 +2182,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
ADDy_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -2205,7 +2244,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ed, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2227,7 +2266,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5:
INST_NAME("BTS Ed, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2255,7 +2294,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("BTR Ed, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2282,7 +2321,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("BTC Ed, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2314,7 +2353,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBB:
INST_NAME("BTC Ed, Gd");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2329,7 +2368,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
ASRxw(x1, gd, 5+rex.w); // r1 = (gd>>5)
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
ADDy_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -2353,7 +2392,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBC:
INST_NAME("BSF Gd, Ed");
if(!BOX64ENV(dynarec_safeflags) || BOX64ENV(cputype)) {
if (!BOX64DRENV(dynarec_safeflags) || BOX64ENV(cputype)) {
SETFLAGS(X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2362,12 +2401,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETED(0);
GETGD;
IFX(X_ZF) {
TSTxw_REG(ed, ed);
B_MARK(cEQ);
} else {
CBZxw_MARK(ed);
}
TSTxw_REG(ed, ed);
B_MARK(cEQ);
RBITxw(x1, ed); // reverse
CLZxw(gd, x1); // x2 gets leading 0 == BSF
MARK;
@@ -2377,7 +2412,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIw(xFlags, x2, F_ZF, 1);
}
}
if(BOX64ENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_CF) BFCw(xFlags, F_CF, 1);
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -2387,7 +2422,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
if(!BOX64ENV(dynarec_safeflags) || BOX64ENV(cputype)) {
if (!BOX64DRENV(dynarec_safeflags) || BOX64ENV(cputype)) {
SETFLAGS(X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2396,12 +2431,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETED(0);
GETGD;
IFX(X_ZF) {
TSTxw_REG(ed, ed);
B_MARK(cEQ);
} else {
CBZxw_MARK(ed);
}
TSTxw_REG(ed, ed);
B_MARK(cEQ);
CLZxw(gd, ed); // x2 gets leading 0
SUBxw_U12(gd, gd, rex.w?63:31);
NEGxw_REG(gd, gd); // complement
@@ -2412,7 +2443,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIw(xFlags, x2, F_ZF, 1);
}
}
if(BOX64ENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_CF) BFCw(xFlags, F_CF, 1);
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -2625,32 +2656,52 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
} else switch((nextop>>3)&7) {
case 1:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDPxw_S7_offset(x2, x3, wback, 0);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
STPxw_S7_offset(xRBX, xRCX, wback, 0);
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 1);}
}
B_MARK3_nocond;
MARK;
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 0);}
}
MARK3;
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {
BFIw(xFlags, x1, F_ZF, 1);
if(MODREG) {
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if (rex.w) {
INST_NAME("CMPXCHG16B Gq, Eq");
} else {
INST_NAME("CMPXCHG8B Gq, Eq");
}
SETFLAGS(X_ZF, SF_SUBSET);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.w && BOX64DRENV(dynarec_safeflags)>1) {
// unaligned memory cause a GPF
TSTx_mask(wback, 1, 0, 3);
B_MARK2(cEQ); // alligned, continue...
STORE_XEMU_CALL(xRIP);
CALL_S(const_native_gpf, -1);
LOAD_XEMU_CALL(xRIP);
MARK2;
}
LDPxw_S7_offset(x2, x3, wback, 0);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
STPxw_S7_offset(xRBX, xRCX, wback, 0);
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 1);}
}
B_MARK3_nocond;
MARK;
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {MOV32w(x1, 0);}
}
MARK3;
UFLAG_IF {
IFNATIVE(NF_EQ) {} else {
BFIw(xFlags, x1, F_ZF, 1);
}
}
SMWRITE();
}
SMWRITE();
break;
case 4:
INST_NAME("Unsupported XSAVEC Ed");
File diff suppressed because it is too large. Load diff
+221 -225
View File
@@ -22,7 +22,7 @@
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_66(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_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
@@ -42,17 +42,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(j64);
MAYUSE(lock);
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x26) || (opcode==0x66)) // ignoring CS:, SS:, ES: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
GETREX();
if(rex.w && !(opcode==0x0f || opcode==0xf0 || opcode==0x64 || opcode==0x65)) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
if(rex.w && !(opcode==0x0f)) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog); // addr-1, to "put back" opcode
switch(opcode) {
case 0x01:
@@ -91,7 +82,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POP ES");
POP1_16(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_ES]));
break;
case 0x09:
@@ -122,12 +112,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x0F:
switch(rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
switch(rex.rep) {
case 1:
addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
case 2:
addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
default:
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
}
break;
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
@@ -198,7 +194,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POP DS");
POP1_16(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
break;
case 0x21:
@@ -384,9 +379,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
PUSH1_16(xRBP);
PUSH1_16(xRSI);
PUSH1_16(xRDI);
} else {
DEFAULT;
}
} else
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
break;
case 0x61:
if(rex.is32bits) {
@@ -406,19 +400,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIz(xRCX, x1, 0, 16);
POP1_16(x1);
BFIz(xRAX, x1, 0, 16);
} else {
DEFAULT;
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
} else
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
break;
case 0x68:
@@ -434,7 +417,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) > 1 && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -473,8 +456,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
PUSH1_16(x2);
break;
case 0x6C:
case 0x6E:
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0x6D:
INST_NAME(opcode == 0x6C ? "INSB" : "INSW");
INST_NAME("INSW");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
@@ -488,9 +473,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
*need_epilog = 0;
*ok = 0;
break;
case 0x6E:
case 0x6F:
INST_NAME(opcode == 0x6C ? "OUTSB" : "OUTSW");
INST_NAME("OUTSW");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
@@ -522,7 +506,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x7e:
case 0x7f:
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0x81:
case 0x83:
@@ -706,39 +690,55 @@ uintptr_t dynarec64_66(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
rex.seg = 0;
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if (rex.w)
MOVx_REG(gd, ed);
else
BFIx(gd, ed, 0, 16);
BFIx(gd, ed, 0, 16);
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
u8 = (nextop&0x38)>>3;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if((u8>5) || (u8==1)) {
INST_NAME("Invalid MOV Seg,Ew");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDH(x1, wback, fixedaddress);
ed = x1;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDH(x1, wback, fixedaddress);
ed = x1;
}
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
if((u8==_FS) || (u8==_GS)) {
// refresh offset if needed
CBZw_NEXT(ed);
MOV32w(x1, u8);
CALL(const_getsegmentbase, -1);
}
}
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0x8F:
INST_NAME("POP Ew");
nextop = F8;
POP1_16(x1);
if (MODREG) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BFIz(wback, x1, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x1, wback, fixedaddress);
switch((nextop>>3)&7) {
case 0:
INST_NAME("POP Ew");
POP1_16(x1);
if (MODREG) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BFIz(wback, x1, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x1, wback, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x90:
@@ -794,96 +794,80 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA1:
INST_NAME("MOV AX,Od");
if(rex.is32bits)
u64 = F32;
if(rex.is32bits && rex.is67)
u64 = F16S;
else if(rex.is32bits || rex.is67)
u64 = F32S;
else
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
unscaled = 0; fixedaddress = 0;
if(rex.seg && (u64<0x1000 || (int64_t)u64>-0x1000 || (u64<(0x1000<<1) && !(u64&1)))) {
grab_segdata(dyn, addr, ninst, x1, rex.seg, 0);
if(u64) {
if(u64<0x100)
{fixedaddress = u64; unscaled = 1;}
else if(u64<(0x1000<<1) && !(u64&1))
fixedaddress = u64;
else if(u64<0x1000)
ADDx_U12(x1, x1, u64);
else if((int64_t)u64 > -0x100)
{fixedaddress = (int64_t)u64; unscaled = 1;}
else
SUBx_U12(x1, x1, -(int64_t)u64);
}
} else {
MOV64y(x1, u64);
if(rex.seg) {
grab_segdata(dyn, addr, ninst, x3, rex.seg, 0);
ADDx_REGy(x1, x3, x1);
}
}
lock=(rex.seg)?0:isLockAddress(u64);
SMREADLOCK(lock);
LDRH_U12(x2, x1, 0);
LDH(x2, x1, fixedaddress);
BFIz(xRAX, x2, 0, 16);
break;
case 0xA3:
INST_NAME("MOV Od,AX");
if(rex.is32bits)
u64 = F32;
if(rex.is32bits && rex.is67)
u64 = F16S;
else if(rex.is32bits || rex.is67)
u64 = F32S;
else
u64 = F64;
MOV64z(x1, u64);
lock = isLockAddress(u64);
STRH_U12(xRAX, x1, 0);
unscaled = 0; fixedaddress = 0;
if(rex.seg && (u64<0x1000 || (int64_t)u64>-0x1000 || (u64<(0x1000<<1) && !(u64&1)))) {
grab_segdata(dyn, addr, ninst, x1, rex.seg, 0);
if(u64) {
if(u64<0x100)
{fixedaddress = u64; unscaled = 1;}
else if(u64<(0x1000<<1) && !(u64&1))
fixedaddress = u64;
else if(u64<0x1000)
ADDx_U12(x1, x1, u64);
else if((int64_t)u64 > -0x100)
{fixedaddress = (int64_t)u64; unscaled = 1;}
else
SUBx_U12(x1, x1, -(int64_t)u64);
}
} else {
MOV64y(x1, u64);
if(rex.seg) {
grab_segdata(dyn, addr, ninst, x3, rex.seg, 0);
ADDx_REGy(x1, x3, x1);
}
}
lock=(rex.seg)?0:isLockAddress(u64);
SMREADLOCK(lock);
STH(xRAX, x1, fixedaddress);
SMWRITELOCK(lock);
break;
case 0xA4:
SMREAD();
if(rep) {
INST_NAME("REP MOVSB");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
IF_UNALIGNED(ip) {
MESSAGE(LOG_DEBUG, "\tUnaligned path");
// special optim for large RCX value on forward case only
// but because it's unaligned path, check if a byte per byt is needed, and do 4-bytes per 4-bytes only instead
if(BOX64DRENV(dynarec_safeflags)) {
SUBx_REG(x2, xRDI, xRSI);
CMPSx_U12(x2, 4);
B_MARK(cCC);
}
ORRw_REG(x1, xRSI, xRDI);
ANDw_mask(x1, x1, 0, 1); //mask = 3
CBNZw_MARK(x1);
MARK3;
CMPSx_U12(xRCX, 4);
B_MARK(cCC);
LDRw_S9_postindex(x1, xRSI, 4);
STRw_S9_postindex(x1, xRDI, 4);
SUBx_U12(xRCX, xRCX, 4);
CBNZx_MARK3(xRCX);
CBZx_MARKLOCK(xRCX);
} else {
if(BOX64DRENV(dynarec_safeflags)) {
SUBx_REG(x2, xRDI, xRSI);
CMPSx_U12(x2, 8);
B_MARK(cCC);
}
// special optim for large RCX value on forward case only
MARK3;
CMPSx_U12(xRCX, 8);
B_MARK(cCC);
LDRx_S9_postindex(x1, xRSI, 8);
STRx_S9_postindex(x1, xRDI, 8);
SUBx_U12(xRCX, xRCX, 8);
CBNZx_MARK3(xRCX);
CBZx_MARKLOCK(xRCX);
}
MARK; // Part with DF==0
LDRB_S9_postindex(x1, xRSI, 1);
STRB_S9_postindex(x1, xRDI, 1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_MARKLOCK_nocond;
MARK2; // Part with DF==1
LDRB_S9_postindex(x1, xRSI, -1);
STRB_S9_postindex(x1, xRDI, -1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
MARKLOCK;
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, 1);
LDRB_U12(x1, xRSI, 0);
STRB_U12(x1, xRDI, 0);
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
}
SMWRITE();
break;
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xA5:
SMREAD();
if(rep) {
if(rex.rep) {
INST_NAME("REP MOVSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
@@ -912,10 +896,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA7:
SMREAD();
switch(rep) {
switch(rex.rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
if(rex.rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
@@ -928,7 +912,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRH_S9_postindex(x2, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
B_MARK3((rex.rep==1)?cEQ:cNE);
CBNZx_MARK(xRCX);
B_MARK3_nocond;
MARK2; // Part with DF==1
@@ -936,7 +920,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRH_S9_postindex(x2, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
B_MARK3((rex.rep==1)?cEQ:cNE);
CBNZx_MARK2(xRCX);
MARK3; // end
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
@@ -963,7 +947,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAB:
if(rep) {
if(rex.rep) {
INST_NAME("REP STOSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
@@ -988,7 +972,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAD:
if(rep) {
if(rex.rep) {
INST_NAME("REP LODSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
@@ -1014,10 +998,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAF:
switch(rep) {
switch(rex.rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
if(rex.rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
@@ -1030,14 +1014,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRH_S9_postindex(x2, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
B_MARK3((rex.rep==1)?cEQ:cNE);
CBNZx_MARK(xRCX);
B_MARK3_nocond;
MARK2; // Part with DF==1
LDRH_S9_postindex(x2, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
B_MARK3((rex.rep==1)?cEQ:cNE);
CBNZx_MARK2(xRCX);
MARK3; // end
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
@@ -1174,26 +1158,32 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u16 = F16;
if(u16) {
MOV32w(x1, u16);
BFIz(ed, x1, 0, 16);
} else
BFCz(ed, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
if(u16) {
MOV32w(x1, u16);
STH(x1, ed, fixedaddress);
} else {
STH(xZR, ed, fixedaddress);
}
SMWRITELOCK(lock);
switch((nextop>>3)&7) {
case 0:
INST_NAME("MOV Ew, Iw");
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u16 = F16;
if(u16) {
MOV32w(x1, u16);
BFIz(ed, x1, 0, 16);
} else
BFCz(ed, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
if(u16) {
MOV32w(x1, u16);
STH(x1, ed, fixedaddress);
} else {
STH(xZR, ed, fixedaddress);
}
SMWRITELOCK(lock);
}
break;
default:
DEFAULT;
}
break;
@@ -1318,33 +1308,84 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization (RCL Ex, CL)\n");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
SETFLAGS(X_OF|X_CF, SF_SUBSET);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
// get CL % 17
MOV32w(x3, 0xf10); // 0x10000 / 17 + 1 (this is precise enough in the 0..31 range)
MULw(x3, x3, x2);
LSRw(x3, x3, 16); // x3 = CL / 17
MOV32w(x4, 17);
MSUBw(x2, x3, x4, x2); // CL mod 17
GETEW(x1, 0);
CALL_(const_rcl16, x1, x3);
CBZw_MARK(x2);
IFX2(X_OF, && !BOX64ENV(cputype)) {
LSRw(x5, ed, 14);
EORw_REG_LSR(x5, x5, x5, 1);
BFIw(xFlags, x5, F_OF, 1);
}
BFIw(ed, xFlags, 16, 1); // insert CF
ORRx_REG_LSL(ed, ed, ed, 17); // insert rest of ed
SUBw_REG(x2, x4, x2);
IFX(X_OF|X_CF) {
SUBw_U12(x5, x2, 1);
LSRx_REG(x5, ed, x5); // keep the new CF in x5
}
LSRx_REG(ed, ed, x2);
EWBACK;
u8 = X_CF;
if(BOX64ENV(cputype)) u8 |= X_OF;
IFX(u8) {
BFXILw(xFlags, x5, 0, 1);
}
MARK;
IFX2(X_OF, && BOX64ENV(cputype)) {
EORw_REG_LSR(x2, xFlags, ed, 7);
BFIw(xFlags, x2, F_OF, 1);
}
break;
case 3:
INST_NAME("RCR Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization (RCR Ew, CL)\n");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
SETFLAGS(X_OF|X_CF, SF_SUBSET);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
// get CL % 17
MOV32w(x3, 0xf10); // 0x10000 / 17 + 1
MULw(x3, x3, x2);
LSRw(x3, x3, 16); // x3 = CL / 17
MOV32w(x4, 17);
MSUBw(x2, x3, x4, x2); // CL mod 17
GETEW(x1, 0);
CALL_(const_rcr16, x1, x3);
CBZw_MARK(x2);
BFIw(ed, xFlags, 16, 1); // insert CF
ORRx_REG_LSL(ed, ed, ed, 17); // insert rest of ed
IFX2(X_OF, && !BOX64ENV(cputype)) {
EORw_REG_LSR(x5, xFlags, ed, 15);
BFIw(xFlags, x5, F_OF, 1);
}
IFX(X_CF) {
SUBw_U12(x4, x2, 1);
LSRw_REG(x5, ed, x4);
BFIw(xFlags, x5, F_CF, 1);
}
LSRx_REG(ed, ed, x2);
EWBACK;
MARK;
IFX2(X_OF, && BOX64ENV(cputype)) {
LSRw(x4, ed, 14);
EORw_REG_LSR(x4, x4, x4, 1);
BFIw(xFlags, x4, F_OF, 1);
}
break;
case 4:
case 6:
@@ -1447,49 +1488,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xE5: /* IN AX, Ib */
case 0xE6: /* OUT Ib, AL */
case 0xE7: /* OUT Ib, AX */
INST_NAME(opcode==0xE4?"IN AL, Ib":(opcode==0xE5?"IN AX, Ib":(opcode==0xE6?"OUT Ib, AL":"OUT Ib, AX")));
if (rex.is32bits && BOX64ENV(ignoreint3)) {
F8;
} else {
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
u8 = F8;
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL_S(const_native_priv, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
}
break;
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xEC: /* IN AL, DX */
case 0xED: /* IN AX, DX */
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, AX */
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN AX, DX":(opcode==0xEE?"OUT DX, AL":"OUT DX, AX")));
if(rex.is32bits && BOX64ENV(ignoreint3))
{} else {
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL_S(const_native_priv, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xF7:
nextop = F8;
@@ -1523,7 +1528,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4:
INST_NAME("MUL AX, Ew");
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -1554,7 +1559,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5:
INST_NAME("IMUL AX, Ew");
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -1618,9 +1623,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("IDIV Ew");
SKIPTEST(x1);
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET);
} else if(BOX64ENV(cputype)) {
} else if (BOX64ENV(cputype)) {
SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET);
}
GETSEW(x1, 0);
@@ -1640,7 +1645,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SET_DFNONE();
}
IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10
@@ -1651,17 +1656,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xF8:
INST_NAME("CLC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE();
BFCx(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE();
ORRx_mask(xFlags, xFlags, 1, 0, 0); // xFlags | 1
break;
return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xFF:
nextop = F8;
+35 -31
View File
@@ -1616,6 +1616,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
#define GO(GETFLAGS, NO, YES, F) \
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog); \
READFLAGS(F); \
GETFLAGS; \
nextop = F8; \
@@ -2377,7 +2378,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xA3:
INST_NAME("BT Ew, Gw");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2401,6 +2402,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xA4:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("SHLD Ew, Gw, Ib");
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f;
@@ -2417,6 +2419,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xA5:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHLD Ew, Gw, CL");
if(BOX64DRENV(dynarec_safeflags)>1) {
@@ -2436,7 +2439,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xAB:
INST_NAME("BTS Ew, Gw");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2468,6 +2471,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xAC:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHRD Ew, Gw, Ib");
u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f;
@@ -2484,6 +2488,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xAD:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
INST_NAME("SHRD Ew, Gw, CL");
if(BOX64DRENV(dynarec_safeflags)>1) {
@@ -2512,21 +2517,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch((nextop>>3)&7) {
case 6:
INST_NAME("CLWB Ed");
MESSAGE(LOG_DUMP, "Need Optimization (CLWB)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(const_native_clflush, -1, 0);
DC_CIVAC(ed);
break;
case 7:
INST_NAME("CLFLUSHOPT Ed");
MESSAGE(LOG_DUMP, "Need Optimization (CLFLUSHOPT)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(const_native_clflush, -1, 0);
DC_CIVAC(ed);
break;
default:
DEFAULT;
@@ -2534,7 +2531,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0xAF:
INST_NAME("IMUL Gw,Ew");
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2567,7 +2564,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xB3:
INST_NAME("BTR Ew, Gw");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2599,6 +2596,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0xB6:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVZX Gw, Eb");
nextop = F8;
if(MODREG) {
@@ -2620,6 +2618,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16); // insert in Gw
break;
case 0xB7:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVZX Gw, Ew");
nextop = F8;
if(MODREG) {
@@ -2636,11 +2635,12 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xBA:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
nextop = F8;
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ew, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2655,7 +2655,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 5:
INST_NAME("BTS Ew, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2672,7 +2672,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 6:
INST_NAME("BTR Ew, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2688,7 +2688,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 7:
INST_NAME("BTC Ew, Ib");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2708,8 +2708,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xBB:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BTC Ew, Gw");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
@@ -2742,8 +2743,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xBC:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BSF Gw,Ew");
if(!BOX64ENV(dynarec_safeflags) || BOX64ENV(cputype)) {
if (!BOX64DRENV(dynarec_safeflags) || BOX64ENV(cputype)) {
SETFLAGS(X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2759,17 +2761,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CBZw_MARK(x1);
}
RBITw(x1, x1); // reverse
CLZw(x1, x1); // x2 gets leading 0 == BSF
if(!MODREG) MARK; // value gets written on 0 input only if input is a memory it seems
CLZw(x1, x1); // x1 gets leading 0
BFIx(gd, x1, 0, 16);
if(MODREG) MARK;
MARK;
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(x2, cEQ); //ZF not set
BFIw(xFlags, x2, F_ZF, 1);
}
}
if(BOX64ENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_CF) BFCw(xFlags, F_CF, 1);
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -2778,8 +2779,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xBD:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("BSR Gw,Ew");
if(!BOX64ENV(dynarec_safeflags) || BOX64ENV(cputype)) {
if (!BOX64DRENV(dynarec_safeflags) || BOX64ENV(cputype)) {
SETFLAGS(X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_ALL, SF_SET);
@@ -2797,17 +2799,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
LSLw(x1, x1, 16); // put bits on top
CLZw(x2, x1); // x2 gets leading 0
SUBw_U12(x2, x2, 15);
NEGw_REG(x1, x2); // complement
if(!MODREG) MARK;
NEGw_REG(x1, x2); // complement
BFIx(gd, x1, 0, 16);
if(MODREG) MARK;
MARK;
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(x2, cEQ); //ZF not set
BFIw(xFlags, x2, F_ZF, 1);
}
}
if(BOX64ENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_CF) BFCw(xFlags, F_CF, 1);
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -2816,6 +2817,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xBE:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVSX Gw, Eb");
nextop = F8;
GETGD;
@@ -2838,6 +2840,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16);
break;
case 0xBF:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("MOVSX Gw, Ew");
nextop = F8;
GETGD;
@@ -2853,6 +2856,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0xC1:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
@@ -2954,8 +2958,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(rex.w) {
REV64x(gd, gd);
} else {
REV16w(x1, gd);
BFIx(gd, x1, 0, 16);
// this is undefined behaviour
BFCx(gd, 0, 16);
}
break;
-275
View File
@@ -1,275 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wb1, wback;
int64_t j64;
int16_t i16;
int v0, v1;
int64_t fixedaddress;
int unscaled;
MAYUSE(j64);
GETREX();
/*if(rex.w && opcode!=0x0f) { // rex.w cancels "66", but not for 66 0f type of prefix
MESSAGE(LOG_DUMP, "Here!\n");
return dynarec64_64(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
}*/
switch(opcode) {
case 0x0F:
opcode = F8;
switch(opcode) {
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;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
v1 = fpu_get_scratch(dyn, ninst);
VLD64(v1, ed, fixedaddress);
}
IFX(X_CF|X_PF|X_ZF) {
FCMPD(v0, v1);
}
FCOMI(x1, x2);
break;
case 0x6F:
INST_NAME("MOVDQA Gx,Ex");
nextop = F8;
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);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
SMREAD();
ADDz_REG(x4, x4, ed);
VLD128(v0, x4, fixedaddress);
}
break;
case 0x7F:
INST_NAME("MOVDQA Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVQ(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
VST128(v0, x4, fixedaddress);
SMWRITE2();
}
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
VST64(v0, x4, fixedaddress);
SMWRITE();
}
break;
default:
DEFAULT;
}
break;
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV FS:Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(ed, gd);
} else {
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
}
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(rex.w?3:1), rex.w?7:1, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
if(rex.w) {
STx(gd, ed, fixedaddress);
} else {
STH(gd, ed, fixedaddress);
}
SMWRITE();
}
break;
case 0x8B:
INST_NAME("MOV Gw, FS:Ew");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(gd, ed);
} else {
if(ed!=gd) {
BFIx(gd, ed, 0, 16);
}
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(rex.w?3:1), rex.w?7:1, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
if(rex.w) {
LDx(gd, ed, fixedaddress);
} else {
LDH(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+115 -143
View File
@@ -21,9 +21,9 @@
#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)
uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
@@ -39,26 +39,19 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MAYUSE(wb2);
MAYUSE(j64);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
GETREX();
switch(opcode) {
case 0x01:
INST_NAME("LOCK ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
UFLAG_IF {
@@ -78,16 +71,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0x09:
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
UFLAG_IF {
@@ -111,19 +104,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch(opcode) {
case 0xB1:
INST_NAME("LOCK CMPXCHG Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
UXTHw(x6, xRAX);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
UXTHw(x1, ed);
CMPSxw_REG(x6, x1);
B_MARK(cNE);
BFIx(ed, gd, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK CMPXCHG Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGD;
UXTHw(x6, xRAX);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICH) {
if(cpuext.uscat) {
@@ -164,25 +155,25 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CBNZx_MARK3(x4);
STRH_U12(gd, wback, 0);
}
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
BFIx(xRAX, x1, 0, 16);
}
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
BFIx(xRAX, x1, 0, 16);
break;
case 0xC1:
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
UXTHx(x5, gd);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BFIx(gd, ed, 0, 16);
emit_add16(dyn, ninst, x5, gd, x3, x4);
BFIx(ed, x5, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
UXTHx(x5, gd);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
LDADDALH(x5, x1, wback);
@@ -207,17 +198,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0x11:
INST_NAME("LOCK ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
@@ -228,16 +219,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0x21:
INST_NAME("LOCK AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, gd, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
MVNw_REG(x3, gd);
@@ -262,20 +253,18 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
@@ -321,15 +310,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(!i64) {MOV32w(x5, i16);}
@@ -356,17 +344,15 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
@@ -378,17 +364,15 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
@@ -400,15 +384,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
@@ -440,16 +423,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
@@ -496,15 +477,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_xor16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
@@ -529,18 +509,10 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
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) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x5, i16);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
}
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
break;
}
break;
@@ -550,14 +522,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch((nextop>>3)&7)
{
case 0: // INC Ew
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_inc16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
MOV32w(x3, 1);
@@ -577,14 +549,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 1: //DEC Ew
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_dec16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
INST_NAME("Invalid LOCK");
UDF(0);
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(cpuext.atomics) {
MOV32w(x3, -1);
+4 -4
View File
@@ -79,7 +79,7 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xBC:
INST_NAME("TZCNT Gw, Ew");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
} else {
if(BOX64ENV(cputype)) {
@@ -106,7 +106,7 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
if(BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -117,7 +117,7 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xBD:
INST_NAME("LZCNT Gw, Ew");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
} else {
if(BOX64ENV(cputype)) {
@@ -142,7 +142,7 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
if(BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
File diff suppressed because it is too large. Load diff
-94
View File
@@ -1,94 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop & 0x38) >> 3)
uintptr_t dynarec64_6764(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
rep = 0;
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
rex.rex = 0;
while (opcode >= 0x40 && opcode <= 0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch (opcode) {
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
STRxw_REG(gd, x4, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg => reg
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem => reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRxw_REG(gd, x4, ed);
}
break;
default:
DEFAULT;
}
return addr;
}
-159
View File
@@ -1,159 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(!rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
STz(gd, x4, fixedaddress);
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
nextop=F8;
GETGD;
if(MODREG) { // reg => reg
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem => reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
LDz(gd, x4, fixedaddress);
}
break;
case 0x8F:
INST_NAME("POP Seg:Ed");
nextop=F8;
if(MODREG) { // reg <= reg
POP1_32(x1);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), x1);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
POP1_32(x1);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
STz(x1, x4, fixedaddress);
}
break;
case 0xA1:
INST_NAME("MOV EAX, Seg:[Od]");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if(i32<4096 && !(i32&3)) {
LDRw_U12(xRAX, x4, i32);
} else if(i32<256) {
LDURw_I9(xRAX, x4, i32);
} else {
MOV32w(x1, i32);
LDRw_REG(xRAX, x4, x1);
}
break;
case 0xA3:
INST_NAME("MOV Seg:[Od], EAX");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if(i32<4096 && !(i32&3)) {
STRw_U12(xRAX, x4, i32);
} else if(i32<256) {
STURw_I9(xRAX, x4, i32);
} else {
MOV32w(x1, i32);
STRw_REG(xRAX, x4, x1);
}
break;
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if (MODREG) {
DEFAULT;
} else {
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
LDW(x3, x4, fixedaddress);
PUSH1_32(x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
-160
View File
@@ -1,160 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(!rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x0F:
opcode=F8;
switch(opcode) {
case 0x29:
INST_NAME("MOVAPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, 0);
VST128(v0, ed, fixedaddress);
SMWRITE2();
}
break;
default:
DEFAULT;
}
break;
case 64:
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
#define GO(NO, YES) \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
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&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
SMEND();
UXTHw(x1, xRCX);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
case 0xE1:
INST_NAME("LOOPZ (16bits)");
READFLAGS(X_ZF);
SMEND();
i8 = F8S;
UXTHw(x1, xRCX);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
case 0xE2:
INST_NAME("LOOP (16bits)");
i8 = F8S;
SMEND();
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
GO(cEQ, cNE);
break;
case 0xE3:
INST_NAME("JCXZ");
i8 = F8S;
SMEND();
TSTw_mask(xRCX, 0, 15); //mask=0xffff
GO(cNE, cEQ);
break;
#undef GO
default:
DEFAULT;
}
return addr;
}
-154
View File
@@ -1,154 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.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_functions.h"
#include "../dynarec_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
switch(p) {
case VEX_P_NONE: return "0";
case VEX_P_66: return "66";
case VEX_P_F2: return "F2";
case VEX_P_F3: return "F3";
default: return "??";
}
}
static const char* avx_map_string(uint16_t m)
{
switch(m) {
case VEX_M_NONE: return "0";
case VEX_M_0F: return "0F";
case VEX_M_0F38: return "0F38";
case VEX_M_0F3A: return "0F3A";
default: return "??";
}
}
uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) {
switch(opcode) {
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED32(0);
GETVD;
if(rex.w) {
// 64bits mul
if((gd==xRDX) || (gd==ed) || (gd==vd))
gb1 = x3;
else
gb1 = gd;
UMULH(gb1, xRDX, ed);
if(gd!=vd) {MULx(vd, xRDX, ed);}
if(gb1==x3) {
MOVx_REG(gd, gb1);
}
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
if(gd!=vd) {MOVw_REG(vd, x3);}
LSRx(gd, x3, 32);
}
break;
default:
DEFAULT;
}
}
else if((vex.m==VEX_M_0F) && (vex.p==VEX_P_66)) {
switch(opcode) {
case 0xD6:
INST_NAME("VMOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOV(v1, v0);
YMM0(ed);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
}
break;
case 0x6E:
INST_NAME("VMOVD Gx, Ed");
nextop = F8;
GETGX_empty(v0);
GETED(0);
VEORQ(v0, v0, v0); // RAZ vector
if(rex.w) {
FMOVDx(v0, ed);
} else {
FMOVSw(v0, ed);
}
YMM0(gd);
break;
default:
DEFAULT;
}
}
else {DEFAULT;}
if((*ok==-1) && (BOX64ENV(dynarec_log)>=LOG_INFO || dyn->need_dump || BOX64ENV(dynarec_missing)==1))
if(!dyn->size || BOX64ENV(dynarec_log)>LOG_INFO || dyn->need_dump) {
dynarec_log(LOG_NONE, " Dynarec unimplemented VEX opcode size %d prefix %s map %s opcode %02X\n", 128 << vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
}
return addr;
}
+65 -61
View File
@@ -82,13 +82,13 @@ typedef struct arch_build_s
static arch_build_t static_build[MAX_INSTS+2] = {0};
static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch)
static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noarch)
{
memset(arch, 0, sizeof(arch_build_t));
// flags
if((dyn->insts[ninst].f_entry.dfnone==0) || dyn->insts[ninst].need_nat_flags || dyn->insts[ninst].before_nat_flags) {
if(((dyn->insts[ninst].f_entry!=status_none && dyn->insts[ninst].f_entry!=status_none_pending)) || dyn->insts[ninst].need_nat_flags || dyn->insts[ninst].before_nat_flags) {
arch->flags = 1;
arch->flags_.defered = dyn->insts[ninst].f_entry.dfnone==0;
arch->flags_.defered = (dyn->insts[ninst].f_entry!=status_none && dyn->insts[ninst].f_entry!=status_none_pending);
uint8_t flags = dyn->insts[ninst].need_nat_flags | dyn->insts[ninst].before_nat_flags;
arch->flags_.vf = flags&NF_VF;
arch->flags_.nf = flags&NF_SF;
@@ -97,65 +97,67 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch)
if(arch->flags_.cf)
arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry;
}
// got through all naoncache to gather regs assignments
int idx;
for(int i=0; i<32; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
switch(dyn->insts[ninst].n.neoncache[i].t) {
case NEON_CACHE_XMMW:
arch->sse = 1;
arch->sse_.sse |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_MM:
arch->mmx = 1;
arch->mmx_.mmx |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_YMMW:
arch->ymm = 1;
arch->ymm_.ymm |= 1<<dyn->insts[ninst].n.neoncache[i].n;
idx = i;
if(idx>=EMM0 && idx<=EMM0+8)
idx-=EMM0;
else
idx-=SCRATCH0-8;
arch->ymm_.ymm_pos |= idx<<(dyn->insts[ninst].n.neoncache[i].n*4);
break;
case NEON_CACHE_ST_D:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_D)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_F:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_F)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_I64:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_I64)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_XMMR:
case NEON_CACHE_YMMR:
default:
// doing nothing, it's just a value read in memory
break;
}
// ymm0
if(dyn->insts[ninst].ymm0_out) {
arch->ymm = 1;
arch->ymm_.ymm0 = dyn->insts[ninst].ymm0_out;
}
// x87 top
if(dyn->insts[ninst].n.x87stack) {
arch->x87 = 1;
arch->x87_.delta = dyn->insts[ninst].n.x87stack;
}
// opcode can handle unaligned
arch->unaligned = dyn->insts[ninst].unaligned;
if(!noarch) {
// got through all naoncache to gather regs assignments
int idx;
for(int i=0; i<32; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
switch(dyn->insts[ninst].n.neoncache[i].t) {
case NEON_CACHE_XMMW:
arch->sse = 1;
arch->sse_.sse |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_MM:
arch->mmx = 1;
arch->mmx_.mmx |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_YMMW:
arch->ymm = 1;
arch->ymm_.ymm |= 1<<dyn->insts[ninst].n.neoncache[i].n;
idx = i;
if(idx>=EMM0 && idx<=EMM0+8)
idx-=EMM0;
else
idx-=SCRATCH0-8;
arch->ymm_.ymm_pos |= idx<<(dyn->insts[ninst].n.neoncache[i].n*4);
break;
case NEON_CACHE_ST_D:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_D)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_F:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_F)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_I64:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_I64)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_XMMR:
case NEON_CACHE_YMMR:
default:
// doing nothing, it's just a value read in memory
break;
}
// ymm0
if(dyn->insts[ninst].ymm0_out) {
arch->ymm = 1;
arch->ymm_.ymm0 = dyn->insts[ninst].ymm0_out;
}
// x87 top
if(dyn->insts[ninst].n.x87stack) {
arch->x87 = 1;
arch->x87_.delta = dyn->insts[ninst].n.x87stack;
}
}
return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned;
}
@@ -179,6 +181,8 @@ static int sizeof_arch_build(arch_build_t* build)
size_t get_size_arch(dynarec_arm_t* dyn)
{
int noarch = BOX64ENV(dynarec_noarch);
if(noarch>1) return 0;
arch_build_t* previous = NULL;
size_t sz = 0;
int seq = 0;
@@ -187,7 +191,7 @@ size_t get_size_arch(dynarec_arm_t* dyn)
if(!dyn->size) return 0;
for(int i=0; i<dyn->size; ++i) {
arch_build_t* build = static_build+i;
last = arch_build(dyn, i, build);
last = arch_build(dyn, i, build, noarch);
if(i && (!memcmp(build, previous, sizeof(arch_build_t))) && (seq<((1<<10)-1))) {
// same sequence, increment
++seq;
+1 -1
View File
@@ -290,7 +290,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("VCOMISS Gx, Ex");} else {INST_NAME("VUCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET_NODF);
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
+4 -4
View File
@@ -132,7 +132,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
IFX(X_OF) {
IFNATIVE(NF_VF) {} else { BFCw(xFlags, F_OF, 1); }
}
if (BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
// those are UD flags
IFX(X_AF) BFCw(xFlags, F_AF, 1);
if(BOX64ENV(cputype)) {
@@ -176,7 +176,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
IFX(X_OF) {
IFNATIVE(NF_VF) {} else { BFCw(xFlags, F_OF, 1); }
}
if (BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
// those are UD flags
IFX(X_AF) BFCw(xFlags, F_AF, 1);
if(BOX64ENV(cputype)) {
@@ -221,7 +221,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
IFX(X_OF) {
IFNATIVE(NF_VF) {} else { BFCw(xFlags, F_OF, 1); }
}
if (BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
// those are UD flags
IFX(X_AF) BFCw(xFlags, F_AF, 1);
if(BOX64ENV(cputype)) {
@@ -277,7 +277,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
IFX(X_OF) {
IFNATIVE(NF_VF) {} else { BFCw(xFlags, F_OF, 1); }
}
if (BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
// those are UD flags
IFX(X_AF) BFCw(xFlags, F_AF, 1);
if(BOX64ENV(cputype)) {
@@ -105,7 +105,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!vex.l) YMM0(gd);
break;
case 0x04:
INST_NAME("PMADDUBSW Gx, Vx, Ex");
INST_NAME("VPMADDUBSW Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
+9 -9
View File
@@ -53,7 +53,6 @@ uintptr_t getConst(arm64_consts_t which)
case const_native_int3: return (uintptr_t)native_int3;
case const_native_int: return (uintptr_t)native_int;
case const_native_div0: return (uintptr_t)native_div0;
case const_native_clflush: return (uintptr_t)native_clflush;
case const_native_frstor16: return (uintptr_t)native_frstor16;
case const_native_fsave16: return (uintptr_t)native_fsave16;
case const_native_fsave: return (uintptr_t)native_fsave;
@@ -70,16 +69,16 @@ uintptr_t getConst(arm64_consts_t which)
case const_native_pclmul: return (uintptr_t)native_pclmul;
case const_native_pclmul_x: return (uintptr_t)native_pclmul_x;
case const_native_pclmul_y: return (uintptr_t)native_pclmul_y;
case const_native_f2xm1: return (uintptr_t)native_f2xm1;
case const_native_fyl2x: return (uintptr_t)native_fyl2x;
case const_native_fyl2xp1: return (uintptr_t)native_fyl2xp1;
case const_direct_f2xm1: return (uintptr_t)direct_f2xm1;
case const_direct_fyl2x: return (uintptr_t)direct_fyl2x;
case const_direct_fyl2xp1: return (uintptr_t)direct_fyl2xp1;
case const_native_fxtract: return (uintptr_t)native_fxtract;
case const_native_ftan: return (uintptr_t)native_ftan;
case const_native_fpatan: return (uintptr_t)native_fpatan;
case const_native_fcos: return (uintptr_t)native_fcos;
case const_native_fsin: return (uintptr_t)native_fsin;
case const_direct_ftan: return (uintptr_t)direct_ftan;
case const_direct_fpatan: return (uintptr_t)direct_fpatan;
case const_direct_fcos: return (uintptr_t)direct_fcos;
case const_direct_fsin: return (uintptr_t)direct_fsin;
case const_native_fsincos: return (uintptr_t)native_fsincos;
case const_native_fscale: return (uintptr_t)native_fscale;
case const_direct_fscale: return (uintptr_t)direct_fscale;
case const_native_fld: return (uintptr_t)native_fld;
case const_native_fstp: return (uintptr_t)native_fstp;
case const_native_frstor: return (uintptr_t)native_frstor;
@@ -87,6 +86,7 @@ uintptr_t getConst(arm64_consts_t which)
case const_int3: return (uintptr_t)EmuInt3;
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
case const_x64syscall_linux: return (uintptr_t)EmuX64Syscall_linux;
case const_rcl16: return (uintptr_t)rcl16;
case const_rcl32: return (uintptr_t)rcl32;
case const_rcl64: return (uintptr_t)rcl64;
+9 -9
View File
@@ -17,7 +17,6 @@ typedef enum arm64_consts_s {
const_native_int3,
const_native_int,
const_native_div0,
const_native_clflush,
const_native_frstor16,
const_native_fsave16,
const_native_fsave,
@@ -34,16 +33,16 @@ typedef enum arm64_consts_s {
const_native_pclmul,
const_native_pclmul_x,
const_native_pclmul_y,
const_native_f2xm1,
const_native_fyl2x,
const_native_fyl2xp1,
const_direct_f2xm1,
const_direct_fyl2x,
const_direct_fyl2xp1,
const_native_fxtract,
const_native_ftan,
const_native_fpatan,
const_native_fcos,
const_native_fsin,
const_direct_ftan,
const_direct_fpatan,
const_direct_fcos,
const_direct_fsin,
const_native_fsincos,
const_native_fscale,
const_direct_fscale,
const_native_fld,
const_native_fstp,
const_native_frstor,
@@ -51,6 +50,7 @@ typedef enum arm64_consts_s {
const_int3,
const_x86syscall,
const_x64syscall,
const_x64syscall_linux,
const_rcl16,
const_rcl32,
const_rcl64,
+2 -2
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_D8(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_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
+35 -46
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
@@ -269,57 +269,54 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xF0:
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization (F2XM1)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(const_native_f2xm1, -1);
x87_unstackcount(dyn, ninst, x1, i1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
CALL_D(const_direct_f2xm1, v1, v1, -1, -1, -1);
break;
case 0xF1:
INST_NAME("FYL2X");
MESSAGE(LOG_DUMP, "Need Optimization (FYL2X)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(const_native_fyl2x, -1);
x87_unstackcount(dyn, ninst, x1, i1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
CALL_D(const_direct_fyl2x, v2, v1, v2, -1, -1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization (FPTAN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(const_native_ftan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
x87_unstackcount(dyn, ninst, x1, i1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emitting 1\n");
u8 = F8;
u8 = F8;
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
} else {
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
FMOVS_8(v2, 0b01110000);
} else {
FMOVD_8(v1, 0b01110000);
FMOVD_8(v2, 0b01110000);
}
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
}
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
else
u8 = 0;
CALL_D(const_direct_ftan, v1, v1, -1, u8, -1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xF3:
INST_NAME("FPATAN");
MESSAGE(LOG_DUMP, "Need Optimization (FPATAN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(const_native_fpatan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
else
u8 = 0;
CALL_D(const_direct_fpatan, v2, v1, v2, u8, -1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF4:
@@ -396,11 +393,9 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xF9:
INST_NAME("FYL2XP1");
MESSAGE(LOG_DUMP, "Need Optimization (FYL2XP1)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(const_native_fyl2xp1, -1);
x87_unstackcount(dyn, ninst, x1, i1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
CALL_D(const_direct_fyl2xp1, v2, v1, v2, -1, -1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xFA:
@@ -444,39 +439,33 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xFD:
INST_NAME("FSCALE");
MESSAGE(LOG_DUMP, "Need Optimization (FSCALE)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(const_native_fscale, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
CALL_D(const_direct_fscale, v1, v1, v2, -1, -1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization (FSIN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
MESSAGE(LOG_DUMP, "Need Optimization (FCOS)\n");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(const_native_fsin, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
CALL_D(const_direct_fsin, v1, v1, -1, -1, -1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization (FCOS)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(const_native_fcos, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
CALL_D(const_direct_fcos, v1, v1, -1, -1, -1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
default:
DEFAULT;
+1 -1
View File
@@ -21,7 +21,7 @@
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int64_t j64;
+2 -2
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
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_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
+2 -2
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
+2 -2
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
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_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
+2 -2
View File
@@ -21,9 +21,9 @@
#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)
uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
+2 -2
View File
@@ -21,9 +21,9 @@
#include "dynarec_arm64_functions.h"
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_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed, wback, u8;
+100 -13
View File
@@ -1030,7 +1030,7 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
if (!c) return;
if(!BOX64ENV(cputype))
IFX(X_OF) {
IFX2(X_OF, && c == 1) {
LSRw(s3, s1, 14);
EORw_REG_LSR(s3, s3, s3, 1);
BFIw(xFlags, s3, F_OF, 1);
@@ -1058,7 +1058,7 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
if (!c) return;
if(!BOX64ENV(cputype))
IFX(X_OF) {
IFX2(X_OF, && c == 1) {
EORw_REG_LSR(s3, s1, s1, 15);
BFIw(xFlags, s3, F_OF, 1);
}
@@ -1086,20 +1086,11 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
if (!c && !BOX64ENV(cputype)) return;
if(c) {
BFIw(s1, xFlags, 8, 1); // insert cf
if(BOX64ENV(cputype)) {
IFX(X_OF|X_CF) {
BFXILw(xFlags, s1, 8-c, 1);
}
} else {
IFX(X_CF) {
BFXILw(xFlags, s1, 8-c, 1);
}
}
}
if(!BOX64ENV(cputype)) {
IFX(X_OF|X_CF) {
BFXILw(xFlags, s1, 8-c, 1);
}
}
if(!BOX64ENV(cputype)) {
IFX(X_OF) {
LSRw(s3, s1, 6);
EORw_REG_LSR(s3, s3, s3, 1);
@@ -1281,6 +1272,102 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
}
}
// emit RCL32/RCL64 instruction, from s1 , shift s2 (destroyed), store result in s1 using s3 and s4 as scratch
void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if(BOX64ENV(cputype)) {
IFX(X_OF|X_CF) {
MOVZw(s4, rex.w?64:32);
SUBx_REG(s4, s4, s2);
LSRxw_REG(s3, s1, s4);
}
} else {
IFX(X_CF) {
MOVZw(s4, rex.w?64:32);
SUBx_REG(s4, s4, s2);
LSRxw_REG(s3, s1, s4);
}
}
if(!BOX64ENV(cputype))
IFX(X_OF) {
LSRxw(s4, s1, rex.w?62:30);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1);
}
SUBw_U12(s4, s2, 1);
CBNZw(s4, 4+4*3);
/*if(c==1)*/
{
LSLxw(s1, s1, 1);
BFIxw(s1, xFlags, 0, 1);
B(4+4*9);
}
/*else*/
{
LSLxw_REG(s4, s1, s2);
UBFXw(s5, xFlags, 0, 1);
SUBw_U12(s2, s2, 1); //s2 = c-1 now
LSLxw_REG(s5, s5, s2);
ORRxw_REG(s4, s4, s5);
MOVZw(s5, rex.w?64:32); // -1 to compensate from the c-1 is s2
SUBw_REG(s5, s5, s2);
LSRxw_REG(s1, s1, s5);
ORRxw_REG(s1, s1, s4);
}
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
IFX2(X_OF, && BOX64ENV(cputype)) {
EORxw_REG_LSR(s3, s3, s1, rex.w?63:31);
BFIw(xFlags, s3, F_OF, 1);
}
}
// emit RCR32/RCR64 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch
void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
IFX2(X_OF, && !BOX64ENV(cputype)) {
EORxw_REG_LSR(s3, xFlags, s1, rex.w?63:31);
BFIw(xFlags, s3, F_OF, 1);
}
SUBw_U12(s4, s2, 1);
IFX(X_CF) {
LSRxw_REG(s3, s1, s4);
BFIw(xFlags, s3, F_res2, 1); // saving the value without reserving s3
}
CBNZw(s4, 4+4*3);
/*if(c==1)*/
{
LSRxw(s1, s1, 1);
BFIxw(s1, xFlags, rex.w?63:31, 1);
B(4+4*9);
}
/*else*/
{
LSRxw_REG(s5, s1, s2);
UBFXw(s4, xFlags, 0, 1);
MOVZw(s3, (rex.w?64:32));
SUBx_REG(s3, s3, s2);
LSLxw_REG(s4, s4, s3);
ORRxw_REG(s5, s5, s4);
ADDx_U12(s3, s3, 1);
LSLxw_REG(s1, s1, s3);
ORRxw_REG(s1, s1, s5);
}
IFX(X_CF) {
BFXILw(xFlags, xFlags, F_res2, 1);
BFCw(xFlags, F_res2, 1);
}
IFX2(X_OF, && BOX64ENV(cputype)) {
LSRxw(s4, s1, rex.w?62:30);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1);
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -465,7 +465,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3, 0); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd); \
+46 -11
View File
@@ -212,6 +212,24 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
CSELxw(gd, ed, gd, YES); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, NULL, 0, 0); \
Bcond(NO, +8); \
LDxw(gd, ed, fixedaddress); \
if (!rex.w) { MOVw_REG(gd, gd); } \
}
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
@@ -503,15 +521,32 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
if(rex.is32bits || !MODREG) {
INST_NAME("Illegal AE");
FAKEED;
UDF(0);
} else {
if(((nextop>>3)&7)==1) {INST_NAME("RDGSBASE");} else {INST_NAME("RDFSBASE");}
ed = TO_NAT((nextop & 7) + (rex.b << 3));
int seg = _FS + ((nextop>>3)&7);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
MOVxw_REG(ed, x4);
}
break;
case 2:
INST_NAME("(unsupported) WRFSBASE Ed");
FAKEED;
UDF(0);
break;
case 3:
INST_NAME("(unsupported) WRGSBASE Ed");
FAKEED;
UDF(0);
if(rex.is32bits || !MODREG) {
INST_NAME("Illegal AE");
FAKEED;
UDF(0);
} else {
if(((nextop>>3)&7)==3) {INST_NAME("WRGSBASE");} else {INST_NAME("WRFSBASE");}
ed = TO_NAT((nextop & 7) + (rex.b << 3));
int seg = _FS + ((nextop>>3)&7)-2;
STRx_U12(ed, xEmu, offsetof(x64emu_t, segs_offs[seg]));
}
break;
case 5:
INST_NAME("(unsupported) INCSSPD/INCSSPQ Ed");
@@ -574,7 +609,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
} else {
if(BOX64ENV(cputype)) {
@@ -599,7 +634,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
if(BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
@@ -608,7 +643,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
if(!BOX64ENV(dynarec_safeflags)) {
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
} else {
if(BOX64ENV(cputype)) {
@@ -632,7 +667,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
if(BOX64ENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
+147 -7
View File
@@ -91,6 +91,7 @@ int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n)
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i].t = t;
dyn->n.news |= (1<<i);
dyn->use_x87 = 1;
return i; // return a Dx
}
// Free a FPU double reg
@@ -130,6 +131,7 @@ int fpu_get_reg_emm(dynarec_arm_t* dyn, int ninst, int emm)
dyn->n.neoncache[ret].t = NEON_CACHE_MM;
dyn->n.neoncache[ret].n = emm;
dyn->n.news |= (1<<(ret));
dyn->use_mmx = 1;
return ret;
}
// Get an XMM quad reg
@@ -145,10 +147,12 @@ int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
dyn->n.neoncache[i].t = t;
dyn->n.neoncache[i].n = xmm;
dyn->n.news |= (1<<i);
dyn->use_xmm = 1;
return i;
}
int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg)
{
dyn->use_ymm = 1;
if((dyn->n.neoncache[reg].t==NEON_CACHE_YMMR) || (dyn->n.neoncache[reg].t==NEON_CACHE_YMMW)) {
if(dyn->n.neoncache[reg].n == ymm) {
// already there!
@@ -767,6 +771,8 @@ static register_mapping_t register_mappings[] = {
{ "rip", "x27" },
};
static const char* df_status[] = {"unknown", "set", "none_pending", "none"};
void printf_x64_instruction(dynarec_native_t* dyn, zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
{
@@ -780,15 +786,13 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
}
static char buf[4096];
int length = sprintf(buf, "barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%d, %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].f_entry.pending,
dyn->insts[ninst].f_entry.dfnone,
dyn->insts[ninst].f_exit.pending,
dyn->insts[ninst].f_exit.dfnone,
df_status[dyn->f],
df_status[dyn->insts[ninst].f_entry],
df_status[dyn->insts[ninst].f_exit],
dyn->insts[ninst].df_notneeded,
dyn->insts[ninst].x64.may_set ? "may" : "set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
@@ -868,6 +872,9 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
if (dyn->insts[ninst].purge_ymm) {
length += sprintf(buf + length, " purgeYmm=%04x", dyn->insts[ninst].purge_ymm);
}
if (dyn->insts[ninst].preload_xmmymm) {
length += sprintf(buf + length, " preload=%x/%d", dyn->insts[ninst].preload_xmmymm, dyn->insts[ninst].preload_from);
}
if (dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) {
length += sprintf(buf + length, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
}
@@ -1197,6 +1204,25 @@ void fpu_unwind_restore(dynarec_arm_t* dyn, int ninst, neoncache_t* cache)
memcpy(&dyn->insts[ninst].n, cache, sizeof(neoncache_t));
}
static uint32_t getXYMMMask(dynarec_arm_t* dyn, int ninst)
{
if(ninst<0) return 0;
uint32_t ret = 0;
for (int i=0; i<32; ++i) {
switch(dyn->insts[ninst].n.neoncache[i].t) {
case NEON_CACHE_XMMR:
case NEON_CACHE_XMMW:
ret |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_YMMR:
case NEON_CACHE_YMMW:
ret |= 1<<(16+dyn->insts[ninst].n.neoncache[i].n);
break;
}
}
return ret;
}
static void propagateXYMMUneeded(dynarec_arm_t* dyn, int ninst, uint16_t mask_x, uint16_t mask_y)
{
if(!ninst) return;
@@ -1218,10 +1244,37 @@ static void propagateXYMMUneeded(dynarec_arm_t* dyn, int ninst, uint16_t mask_x,
void updateUneeded(dynarec_arm_t* dyn)
{
if(!dyn->use_xmm && !dyn->use_ymm)
return;
for(int ninst=0; ninst<dyn->size; ++ninst) {
if(dyn->insts[ninst].n.xmm_unneeded || dyn->insts[ninst].n.ymm_unneeded)
propagateXYMMUneeded(dyn, ninst, dyn->insts[ninst].n.xmm_unneeded, dyn->insts[ninst].n.ymm_unneeded);
if(dyn->insts[ninst].df_notneeded)
propagate_nodf(dyn, ninst);
}
// try to add some preload of XYMM on jump were it would make sense
for(int ninst=0; ninst<dyn->size; ++ninst)
if((ninst && dyn->insts[ninst].pred_sz>1) || (!ninst && dyn->insts[ninst].pred_sz)) {
int i2 = dyn->size+1;
for(int j=0; j<dyn->insts[ninst].pred_sz; ++j)
if(dyn->insts[ninst].pred[j]!=ninst-1 && dyn->insts[ninst].pred[j]<i2)
i2 = dyn->insts[ninst].pred[j];
if(i2!=dyn->size+1 && i2>ninst) {
uint32_t used = getXYMMMask(dyn, i2);
if(used) {
int prev = getNominalPred(dyn, ninst);
if((prev==ninst-1) || !ninst) {
uint32_t dest = getXYMMMask(dyn, prev);
// removed unneeded
uint32_t unnedded = dyn->insts[ninst].n.xmm_unneeded | (dyn->insts[ninst].n.ymm_unneeded<<16);
// create the preload mask
uint32_t preload = (used & ~dest) & ~unnedded;
if(preload)
addSSEPreload(dyn, i2, ninst, preload);
}
}
}
}
}
void tryEarlyFpuBarrier(dynarec_arm_t* dyn, int last_fpu_used, int ninst)
@@ -1274,6 +1327,8 @@ void tryEarlyFpuBarrier(dynarec_arm_t* dyn, int last_fpu_used, int ninst)
void propagateFpuBarrier(dynarec_arm_t* dyn)
{
if(!dyn->use_x87)
return;
int last_fpu_used = -1;
for(int ninst=0; ninst<dyn->size; ++ninst) {
int fpu_used = dyn->insts[ninst].n.xmm_used || dyn->insts[ninst].n.ymm_used || dyn->insts[ninst].mmx_used || dyn->insts[ninst].x87_used;
@@ -1289,6 +1344,8 @@ void propagateFpuBarrier(dynarec_arm_t* dyn)
void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached)
{
if(!dyn->use_ymm)
return;
int can_incr = ninst == max_ninst_reached; // Are we the top-level call?
int ok = 1;
while ((can_incr || ok) && ninst < dyn->size) {
@@ -1394,3 +1451,86 @@ void avx_mark_zero_reset(dynarec_arm_t* dyn, int ninst)
{
dyn->ymm_zero = 0;
}
static int xmm_preload_reg(dynarec_arm_t* dyn, int ninst, int last, int xmm)
{
return (xmm>7)?(XMM8 + xmm - 8):(XMM0 + xmm);
}
static int ymm_preload_reg(dynarec_arm_t* dyn, int ninst, int last, int ymm)
{
int i = -1;
// search for when it will be loaded the first time
int start = ninst;
for(int ii=0; ii<32 && i==-1; ++ii)
if(dyn->insts[last].n.neoncache[ii].n==ymm && (dyn->insts[last].n.neoncache[ii].t==NEON_CACHE_YMMR || dyn->insts[last].n.neoncache[ii].t==NEON_CACHE_YMMW))
i = ii;
while((ninst<last) && (i!=-1)) {
// check if the reg is always free
if(!(!dyn->insts[ninst].n.neoncache[i].v ||
(dyn->insts[ninst].n.neoncache[i].n==ymm
&& (dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_YMMR || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_YMMW))))
i = -1; // nope
else
++ninst;
}
return i;
}
void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload)
{
if((i2<0) || (i2>ninst) || !preload || dyn->insts[i2].preload_from)
return;
if(i2 && !dyn->insts[i2-1].x64.has_next) // need a previous opcode to set the preload, unless it's the #0
return;
// check if there is jump out or outside this loop
for(int i=i2; i<ninst; ++i) {
if(!dyn->insts[i].x64.has_next || (dyn->insts[i].x64.barrier&BARRIER_FLOAT))
return;
// for now, unneeded stop at first jump, so this should also stop there
if(dyn->insts[i].x64.jmp/* && ((dyn->insts[i].x64.jmp_insts>ninst) || (dyn->insts[i].x64.jmp_insts<i2))*/)
return;
}
uint16_t ymm_mask = 0;
for(int i=0; i<16; ++i) {
if(preload&(1<<i)) {
int v = xmm_preload_reg(dyn, i2?(i2-1):0, ninst, i);
// propagate until not needed
int i3 = i2;
while(i3<ninst) {
if(dyn->insts[i3].n.xmm_used&(1<<i))
i3 = ninst;
else {
dyn->insts[i3].n.ssecache[i].write = 0;
dyn->insts[i3].n.ssecache[i].reg = v;
dyn->insts[i3].n.neoncache[v].t = NEON_CACHE_XMMR;
dyn->insts[i3].n.neoncache[v].n = i;
++i3;
}
}
}
if(preload&(1<<(16+i))) {
int v = ymm_preload_reg(dyn, i2?(i2-1):0, ninst, i);
if(v!=-1) {
ymm_mask |= 1<<i;
// propagate until not needed
int i3 = i2;
while(i3<ninst) {
if(dyn->insts[i3].n.ymm_used&(1<<i))
i3 = ninst;
else {
dyn->insts[i3].n.neoncache[v].t = NEON_CACHE_YMMR;
dyn->insts[i3].n.neoncache[v].n = i;
++i3;
}
}
}
}
}
preload = (preload&0xffff) | (ymm_mask<<16); // update ymm_mask
//TODO: should check native calls too?
dyn->insts[i2].preload_xmmymm = preload;
dyn->insts[i2].preload_from = ninst;
dyn->insts[i2].n.xmm_unneeded |= preload&0xffff;
dyn->insts[i2].n.ymm_unneeded |= ymm_mask;
}
@@ -93,6 +93,9 @@ void updateUneeded(dynarec_arm_t* dyn);
void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached);
// add a preload of SSE/AVX register preload before i2, for a jump in ninst. Might not do it if there is jump in between that goes outside this ninst-i2 interval
void addSSEPreload(dynarec_arm_t* dyn, int ninst, int i2, uint32_t preload);
// AVX helpers
void avx_mark_zero(dynarec_arm_t* dyn, int ninst, int reg);
int is_avx_zero(dynarec_arm_t* dyn, int ninst, int reg);
+274 -388
View File
@@ -23,8 +23,6 @@
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, int* l, int s);
/* 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* unscaled, int absmax, uint32_t mask, rex_t rex, int *l, int s, int delta)
{
@@ -33,15 +31,14 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if (l == LOCK_LOCK) {
dyn->insts[ninst].lock = 1;
}
if(rex.is32bits)
return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
int lock = l?((l==LOCK_LOCK)?1:2):0;
if(lock==2) *l = 0;
if(rex.is32bits && rex.is67)
return geted16(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, rex, s);
if(unscaled)
*unscaled = 0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
@@ -49,6 +46,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if(hint>0 && hint<xRAX) scratch = hint;
int absmin = 0;
if(s) absmin=-absmax;
int seg_done = 0;
MAYUSE(scratch);
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
@@ -58,11 +56,11 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV64x(scratch, tmp);
ADDx_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
MOV64y(scratch, tmp);
ADDy_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
} else {
if(sib>>6) {
LSLx(ret, TO_NAT(sib_reg), (sib>>6));
LSLy(ret, TO_NAT(sib_reg), (sib>>6));
} else
ret = TO_NAT(sib_reg);
if(unscaled && (tmp>-256) && (tmp<256))
@@ -70,46 +68,79 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
*fixaddress = tmp;
}
} else {
if(rex.seg && !(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256))))) {
grab_segdata(dyn, addr, ninst, ret, rex.seg, 0);
seg_done = 1;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
*fixaddress = tmp;
} else if(rex.seg && tmp>-0x1000 && tmp<0x1000) {
grab_segdata(dyn, addr, ninst, ret, rex.seg, 0);
if(tmp) {
if(tmp>0) ADDx_U12(ret, ret, tmp);
else SUBx_U12(ret, ret, -tmp);
}
seg_done = 1;
} else
MOV64y(ret, tmp);
switch(lock) {
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV64x(ret, tmp);
}
} else {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, TO_NAT((sib&0x7)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
ADDy_REG_LSL(ret, TO_NAT((sib&0x7)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
ret = TO_NAT((sib&0x7)+(rex.b<<3));
}
}
} else if((nextop&7)==5) {
int64_t tmp = F32S64;
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
} else if(unscaled && (tmp>-256) && (tmp<256)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
*unscaled = 1;
} else if(tmp>0 && tmp<0x1000) {
GETIP(addr+delta);
ADDx_U12(ret, xRIP, tmp);
} else if(tmp<0 && tmp>-0x1000) {
GETIP(addr+delta);
SUBx_U12(ret, xRIP, -tmp);
} else if((tmp+addr+delta<0x1000000000000LL) && !dyn->need_reloc) { // 3 opcodes to load immediate is cheap enough
MOV64x(ret, tmp+addr+delta);
if(rex.is32bits) {
int tmp = F32S;
if(rex.seg && tmp>-0x1000 && tmp<0x1000) {
grab_segdata(dyn, addr, ninst, ret, rex.seg, 0);
if(tmp) {
if(tmp>0) ADDx_U12(ret, ret, tmp);
else SUBx_U12(ret, ret, -tmp);
}
seg_done = 1;
} else
MOV32w(ret, tmp);
if(!rex.seg)
switch(lock) {
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
} else {
MOV64x(ret, tmp);
GETIP(addr+delta);
ADDx_REG(ret, ret, xRIP);
}
switch(lock) {
case 1: addLockAddress(addr+delta+tmp); if(fixaddress) *fixaddress=addr+delta+tmp; break;
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
int64_t tmp = F32S64;
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
} else if(unscaled && (tmp>-256) && (tmp<256)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
*unscaled = 1;
} else if(tmp>0 && tmp<0x1000) {
GETIP(addr+delta);
ADDy_U12(ret, xRIP, tmp);
} else if(tmp<0 && tmp>-0x1000) {
GETIP(addr+delta);
SUBy_U12(ret, xRIP, -tmp);
} else if((tmp+addr+delta<0x1000000000000LL) && !dyn->need_reloc) { // 3 opcodes to load immediate is cheap enough
MOV64y(ret, tmp+addr+delta);
} else {
MOV64y(ret, tmp);
GETIP(addr+delta);
ADDy_REG(ret, ret, xRIP);
}
if(!rex.seg)
switch(lock) {
case 1: addLockAddress(addr+delta+tmp); if(fixaddress) *fixaddress=addr+delta+tmp; break;
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
}
} else {
ret = TO_NAT((nextop & 7) + (rex.b << 3));
@@ -132,7 +163,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
ADDy_REG_LSL(ret, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
ret = TO_NAT((sib&0x07)+(rex.b<<3));
}
@@ -144,325 +175,64 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
ADDy_REG_LSL(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
scratch = TO_NAT((sib&0x07)+(rex.b<<3));
}
} else
scratch = TO_NAT((nextop & 0x07) + (rex.b << 3));
if(sub) {
SUBx_U12(ret, scratch, i64);
SUBy_U12(ret, scratch, i64);
} else {
ADDx_U12(ret, scratch, i64);
ADDy_U12(ret, scratch, i64);
}
} else {
MOV64x(scratch, i64);
MOV64y(scratch, i64);
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBx_REG(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), scratch);
SUBy_REG(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), scratch);
} else {
ADDx_REG(scratch, scratch, TO_NAT((sib&0x07)+(rex.b<<3)));
ADDy_REG(scratch, scratch, TO_NAT((sib&0x07)+(rex.b<<3)));
}
ADDx_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
ADDy_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
} else {
PASS3(int tmp = TO_NAT(sib & 0x07) + (rex.b << 3));
if(sub) {
SUBx_REG(ret, tmp, scratch);
SUBy_REG(ret, tmp, scratch);
} else {
ADDx_REG(ret, tmp, scratch);
ADDy_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3)));
if(sub) {
SUBx_REG(ret, tmp, scratch);
SUBy_REG(ret, tmp, scratch);
} else {
ADDx_REG(ret, tmp, scratch);
ADDy_REG(ret, tmp, scratch);
}
}
}
}
}
*ed = ret;
return addr;
}
static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, int* l, int s)
{
MAYUSE(dyn); MAYUSE(ninst);
int lock = l?((l==LOCK_LOCK)?1:2):0;
if(unscaled)
*unscaled = 0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
if(hint>0) ret = hint;
if(hint>0 && hint<xRAX) scratch = hint;
int absmin = 0;
if(s) absmin=-absmax;
MAYUSE(scratch);
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = (sib>>3)&7;
if((sib&0x7)==5) {
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV32w(scratch, tmp);
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
LSLw(ret, TO_NAT(sib_reg), (sib >> 6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
}
} else {
switch(lock) {
case 1: addLockAddress((int32_t)tmp); if(fixaddress) *fixaddress=(int32_t)tmp; break;
case 2: if(isLockAddress((int32_t)tmp)) *l=1; break;
}
MOV32w(ret, tmp);
}
} else {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, TO_NAT(sib & 0x7), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = TO_NAT(sib & 0x7);
}
}
} else if((nextop&7)==5) {
uint64_t tmp = F32;
MOV32w(ret, tmp);
switch(lock) {
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
} else {
ret = TO_NAT(nextop & 7);
if(ret==hint) {
MOVw_REG(hint, ret); //to clear upper part
}
}
} else {
int64_t i32;
uint8_t sib = 0;
int sib_reg = 0;
if((nextop&7)==4) {
sib = F8;
sib_reg = (sib>>3)&7;
}
if(nextop&0x80)
i32 = F32S;
else
i32 = F8S;
if(i32==0 || ((i32>=absmin) && (i32<=absmax) && !(i32&mask)) || (unscaled && (i32>-256) && (i32<256))) {
*fixaddress = i32;
if(unscaled && i32 && (i32>-256) && (i32<256))
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, TO_NAT(sib & 0x07), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = TO_NAT(sib & 0x07);
}
} else {
ret = TO_NAT(nextop & 0x07);
}
} else {
int64_t sub = (i32<0)?1:0;
if(sub) i32 = -i32;
if(i32<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(scratch, TO_NAT(sib & 0x07), TO_NAT(sib_reg), (sib >> 6));
} else {
scratch = TO_NAT(sib & 0x07);
}
} else
scratch = TO_NAT(nextop & 0x07);
if(sub) {
SUBw_U12(ret, scratch, i32);
} else {
ADDw_U12(ret, scratch, i32);
}
} else {
MOV32w(scratch, i32);
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBw_REG(scratch, TO_NAT(sib & 0x07), scratch);
} else {
ADDw_REG(scratch, scratch, TO_NAT(sib & 0x07));
}
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
PASS3(int tmp = TO_NAT(sib & 0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = TO_NAT(nextop & 0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
}
}
if(rex.is67 && IS_GPR(ret) && !rex.seg) {
MOVw_REG(hint, ret); // truncate for is67 case only (is32bits case regs are already 32bits only)
ret = hint;
}
*ed = ret;
return addr;
}
/* 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* unscaled, 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(unscaled)
*unscaled = 0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
if(hint>0) ret = hint;
if(hint>0 && hint<xRAX) scratch = hint;
int absmin = 0;
if(s) absmin=-absmax;
MAYUSE(scratch);
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
if((sib&0x7)==5) {
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV64x(scratch, tmp);
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
LSLw(ret, TO_NAT(sib_reg), (sib >> 6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
}
} else {
switch(lock) {
case 1: addLockAddress(tmp); break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV64x(ret, tmp);
}
} else {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, TO_NAT((sib & 0x7) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = TO_NAT((sib & 0x7)) + (rex.b << 3);
}
}
} else if((nextop&7)==5) {
uint32_t tmp = F32;
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 = TO_NAT((nextop & 7) + (rex.b << 3));
if(ret==hint) {
MOVw_REG(hint, ret); //to clear upper part
}
}
} else {
int64_t i64;
uint8_t sib = 0;
int sib_reg = 0;
if((nextop&7)==4) {
sib = F8;
sib_reg = ((sib>>3)&7)+(rex.x<<3);
}
if(nextop&0x80)
i64 = F32S;
else
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask)) || (unscaled && (i64>-256) && (i64<256))) {
*fixaddress = i64;
if(unscaled && (i64>-256) && (i64<256))
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, TO_NAT((sib & 0x07) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = TO_NAT((sib & 0x07) + (rex.b << 3));
}
} else {
ret = TO_NAT((nextop & 0x07) + (rex.b << 3));
}
} else {
int64_t sub = (i64<0)?1:0;
if(sub) i64 = -i64;
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(scratch, TO_NAT((sib & 0x07) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
scratch = TO_NAT((sib & 0x07) + (rex.b << 3));
}
} else
scratch = TO_NAT((nextop & 0x07) + (rex.b << 3));
if(sub) {
SUBw_U12(ret, scratch, i64);
} else {
ADDw_U12(ret, scratch, i64);
}
} else {
MOV32w(scratch, i64);
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBw_REG(scratch, TO_NAT((sib & 0x07) + (rex.b << 3)), scratch);
} else {
ADDw_REG(scratch, scratch, TO_NAT((sib & 0x07) + (rex.b << 3)));
}
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
PASS3(int tmp = TO_NAT((sib & 0x07) + (rex.b << 3)));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3)));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
}
}
if(rex.seg && !seg_done) {
if(scratch==ret)
scratch=ret+1;
grab_segdata(dyn, addr, ninst, scratch, rex.seg, 0);
//seg offset is 64bits, so no truncation here
ADDx_REGy(hint, scratch, ret);
ret = hint;
}
*ed = ret;
return addr;
}
/* setup r2 to address pointed by ED, r3 as scratch 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 geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, int s)
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* unscaled, int absmax, uint32_t mask, rex_t rex, int s)
{
MAYUSE(dyn); MAYUSE(ninst);
@@ -542,6 +312,17 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
}
if(rex.seg) {
if(scratch==ret)
scratch=ret+1;
grab_segdata(dyn, addr, ninst, scratch, rex.seg, 0);
//seg offset is 64bits, so no truncation here
if(IS_GPR(ret)) {
ADDx_REG(hint, ret, scratch);
ret = hint;
} else
ADDx_REG(ret, ret, scratch);
}
*ed = ret;
return addr;
}
@@ -561,6 +342,9 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
NOTEST(x2);
TABLE64C(x2, const_epilog);
SMEND();
CHECK_DFNONE(0);
if(dyn->have_purge)
doLeaveBlock(dyn, ninst, x4, x5, x6);
BR(x2);
}
@@ -568,7 +352,6 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
static int indirect_lookup(dynarec_arm_t* dyn, int ninst, int is32bits, int s1, int s2)
{
MAYUSE(dyn);
if (!is32bits) {
// check higher 48bits
LSRx_IMM(s1, xRIP, 48);
@@ -615,7 +398,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
ip &= 0xffffffffLL;
SMEND();
CHECK_DFNONE(0);
int dest;
if (reg) {
if (reg != xRIP) {
@@ -636,6 +419,8 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
if(reg!=x1) {
MOVx_REG(x1, xRIP);
}
if(dyn->have_purge && !dyn->insts[ninst].x64.has_callret)
doLeaveBlock(dyn, ninst, x4, x5, x6);
#ifdef HAVE_TRACE
//MOVx(x3, 15); no access to PC reg
BLR(dest); // save LR...
@@ -652,6 +437,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex)
{
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Ret to epilog\n");
CHECK_DFNONE(0);
POP1z(xRIP);
MOVz_REG(x1, xRIP);
SMEND();
@@ -659,6 +445,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex)
// pop the actual return address for ARM stack
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
if(dyn->have_purge)
doLeaveBlock(dyn, ninst, x4, x5, x3);
CBNZx(x6, 2*4);
RET(xLR);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
@@ -666,6 +454,8 @@ void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex)
}
NOTEST(x2);
int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3);
if(dyn->have_purge && !BOX64DRENV(dynarec_callret))
doLeaveBlock(dyn, ninst, x4, x5, x6);
#ifdef HAVE_TRACE
BLR(dest);
#else
@@ -678,6 +468,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int
{
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Retn to epilog\n");
CHECK_DFNONE(0);
POP1z(xRIP);
if(n>0xfff) {
MOV32w(w1, n);
@@ -691,6 +482,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int
// pop the actual return address for ARM stack
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
if(dyn->have_purge)
doLeaveBlock(dyn, ninst, x4, x5, x3);
CBNZx(x6, 2*4);
RET(xLR);
// not the correct return address, regular jump
@@ -698,6 +491,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int
}
NOTEST(x2);
int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3);
if(dyn->have_purge && !BOX64DRENV(dynarec_callret))
doLeaveBlock(dyn, ninst, x4, x5, x6);
#ifdef HAVE_TRACE
BLR(dest);
#else
@@ -729,10 +524,10 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
// check CS is NULL, sgfault if it is
CBZw_MARK3(x1);
// clean EFLAGS
MOV32w(x4, 0x3F7FD7);
MOV32w(x4, 0x3E7FD7); // also mask RF, because it's not really handled
ANDx_REG(x3, x3, x4);
ORRx_mask(x3, x3, 1, 0b111111, 0); // xFlags | 0b10
SET_DFNONE();
FORCE_DFNONE();
if(is32bits) {
ANDw_mask(x4, x2, 0, 7); // mask 0xff
// check if return segment is 64bits, then restore rsp too
@@ -751,13 +546,11 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
CBZw_MARK(x5);
// POP SS
STRH_U12(x5, xEmu, offsetof(x64emu_t, segs[_SS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
// set new RSP
MOVx_REG(xRSP, x4);
MARKSEG;
// x2 is CS, x1 is IP, x3 is eFlags
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
MOVx_REG(xRIP, x1);
MOVw_REG(xFlags, x3);
// Ret....
@@ -766,6 +559,8 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
TABLE64C(x2, const_epilog);
else
MOV64x(x2, getConst(const_epilog));
if(dyn->have_purge)
doLeaveBlock(dyn, ninst, x4, x5, x6);
BR(x2);
CLEARIP();
MARK;
@@ -784,6 +579,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int savereg)
{
MAYUSE(fnc);
CHECK_DFNONE(1);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
@@ -835,16 +631,17 @@ void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret,
//SET_NODF();
}
void call_i(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc)
void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1, int arg2, int sav1, int sav2)
{
MAYUSE(fnc);
CHECK_DFNONE(1);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
STPx_S7_preindex(x6, x87pc, xSP, -16);
STPx_S7_preindex(x4, x5, xSP, -16);
STPx_S7_preindex(x2, x3, xSP, -16);
STPx_S7_preindex(xEmu, x1, xSP, -16); // ARM64 stack needs to be 16byte aligned
STPx_S7_preindex(xEmu, x87pc, xSP, -16);
if((sav1>0) || (sav2>0)) {
STPx_S7_preindex((sav1>0)?sav1:xZR, (sav2>0)?sav2:xZR, xSP, -16);
}
STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller
STPx_S7_offset(xRDX, xRBX, xEmu, offsetof(x64emu_t, regs[_DX]));
STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
@@ -856,11 +653,18 @@ void call_i(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc)
#ifdef _WIN32
LDRx_U12(xR8, xEmu, offsetof(x64emu_t, win64_teb));
#endif
if(arg1!=-1)
FMOVD(0, arg1);
if(arg2!=-1)
FMOVD(1, arg2);
TABLE64C(x87pc, fnc);
BLR(x87pc);
LDPx_S7_postindex(xEmu, x1, xSP, 16);
LDPx_S7_postindex(x2, x3, xSP, 16);
LDPx_S7_postindex(x4, x5, xSP, 16);
if(ret!=-1)
FMOVD(ret, 0); // will not work if ret is 0..7 and XMM are used
if((sav1>0) || (sav2>0)) {
LDPx_S7_postindex((sav1>0)?sav1:xZR, (sav2>0)?sav2:xZR, xSP, 16);
}
LDPx_S7_postindex(xEmu, x87pc, xSP, 16);
#define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
GO(RAX, RCX);
GO(RDX, RBX);
@@ -869,14 +673,14 @@ void call_i(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc)
GO(R8, R9);
#undef GO
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
fpu_popcache(dyn, ninst, x87pc, 0); // savereg will not be used
LDPx_S7_postindex(x6, x87pc, xSP, 16);
fpu_popcache(dyn, ninst, x1, 0); // savereg will not be used
//SET_NODF();
}
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
{
MAYUSE(fnc);
CHECK_DFNONE(1);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
@@ -937,26 +741,7 @@ void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int se
MAYUSE(j64);
if (modreg) return;
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
int t2 = x4;
if(reg==t2) ++t2;
#ifdef _WIN32
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
#else
LDRw_U12(t2, xEmu, offsetof(x64emu_t, segs_serial[segment]));
/*if(segment==_GS) {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
CBNZw_MARKSEG(t2); // fast check
} else*/ {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, context));
LDRw_U12(reg, reg, offsetof(box64context_t, sel_serial));
SUBw_REG(t2, reg, t2);
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
CBZw_MARKSEG(t2);
}
MOVZw(x1, segment);
call_c(dyn, ninst, const_getsegmentbase, t2, reg, 1, 0);
MARKSEG;
#endif
MESSAGE(LOG_DUMP, "----%s Offset\n", (segment==_FS)?"FS":"GS");
}
@@ -1402,7 +1187,6 @@ int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
#endif
return i;
}
assert(dyn->n.x87cache[i]<8);
}
return -1;
}
@@ -1450,7 +1234,7 @@ int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
|| dyn->n.neoncache[ii].t == NEON_CACHE_ST_I64)
&& dyn->n.neoncache[ii].n==st)
return ii;
assert(0);
dynarec_log(LOG_NONE, "Warning: x87_get_neoncache didn't find cache for ninst=%d\n", ninst);
return -1;
}
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t)
@@ -1840,11 +1624,11 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
}
// purge the SSE cache only
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, uint32_t unneeded)
{
int old = -1;
for (int i=0; i<16; ++i)
if(dyn->n.ssecache[i].v!=-1) {
if(dyn->n.ssecache[i].v!=-1 && !(unneeded&(1<<i))) {
if(next) dyn->n.xmm_used |= (1<<i);
if(dyn->n.ssecache[i].write) {
if (old==-1) {
@@ -1877,7 +1661,7 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
avx_mark_zero_reset(dyn, ninst);
}
for(int i=0; i<32; ++i) {
if(dyn->n.neoncache[i].t==NEON_CACHE_YMMW) {
if(dyn->n.neoncache[i].t==NEON_CACHE_YMMW && !(unneeded&(1<<(dyn->n.neoncache[i].n+16)))) {
if (old==-1) {
MESSAGE(LOG_DUMP, "\tPurge %sSSE Cache ------\n", next?"locally ":"");
++old;
@@ -2081,11 +1865,11 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
}
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3, uint32_t unneeded)
{
x87_purgecache(dyn, ninst, next, s1, s2, s3);
mmx_purgecache(dyn, ninst, next, s1);
sse_purgecache(dyn, ninst, next, s1);
sse_purgecache(dyn, ninst, next, s1, unneeded);
if(!next) {
fpu_reset_reg(dyn);
dyn->insts[ninst].fpupurge = 1;
@@ -2334,18 +2118,17 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
if(i2<0)
return;
MESSAGE(LOG_DUMP, "\tCache Transform ---- ninst=%d -> %d\n", ninst, i2);
uint32_t unneeded = dyn->insts[i2].n.xmm_unneeded | (dyn->insts[i2].n.ymm_unneeded<<16);
if((!i2) || (dyn->insts[i2].x64.barrier&BARRIER_FLOAT)) {
if(dyn->n.stack_next) {
fpu_purgecache(dyn, ninst, 1, s1, s2, s3);
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
return;
int need_purge = 0;
if(dyn->n.stack_next)
need_purge = 1;
for(int i=0; i<24 && !need_purge; ++i)
if(dyn->n.neoncache[i].v)
need_purge = 1;
if(need_purge) { // there is something at ninst for i
fpu_purgecache(dyn, ninst, 1, s1, s2, s3, unneeded);
}
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v) { // there is something at ninst for i
fpu_purgecache(dyn, ninst, 1, s1, s2, s3);
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
return;
}
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
return;
}
@@ -2369,7 +2152,7 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
if(cache_i2.neoncache[i].v)
purge = 0;
if(purge) {
fpu_purgecache(dyn, ninst, 1, s1, s2, s3);
fpu_purgecache(dyn, ninst, 1, s1, s2, s3, unneeded);
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
return;
}
@@ -2514,24 +2297,38 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst)
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return;
if(dyn->f.dfnone || ((dyn->insts[jmp].f_exit.dfnone && !dyn->insts[jmp].f_entry.dfnone) && !dyn->insts[jmp].x64.use_flags)) // flags are fully known, nothing we can do more
if(dyn->insts[jmp].f_exit==dyn->insts[jmp].f_entry) // flags will be fully known, nothing we can do more
return;
if(dyn->insts[jmp].df_notneeded)
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone && !dyn->insts[jmp].df_notneeded)?1:0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN:
go = 0;
break;
default:
if(go && !(dyn->insts[jmp].x64.need_before&X_PEND) && (dyn->f.pending!=SF_UNKNOWN)) {
// just clear df flags
go = 0;
STRw_U12(xZR, xEmu, offsetof(x64emu_t, df));
int go_fetch = 0;
switch(dyn->insts[jmp].f_entry) {
case status_unk:
if(dyn->insts[ninst].f_exit==status_none_pending) {
FORCE_DFNONE();
}
break;
case status_set:
if(dyn->insts[ninst].f_exit==status_none_pending) {
FORCE_DFNONE();
}
if(dyn->insts[ninst].f_exit==status_unk)
go_fetch = 1;
break;
case status_none_pending:
if(dyn->insts[ninst].f_exit!=status_none)
go_fetch = 1;
break;
case status_none:
if(dyn->insts[ninst].f_exit==status_none_pending) {
FORCE_DFNONE();
} else
go_fetch = 1;
break;
}
if(go) {
if(dyn->f.pending!=SF_PENDING) {
if(go_fetch) {
if(dyn->f==status_unk) {
LDRw_U12(x1, xEmu, offsetof(x64emu_t, df));
j64 = (GETMARKF2)-(dyn->native_size);
CBZw(x1, j64);
@@ -2544,6 +2341,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst)
MSR_nzcv(x6);
MARKF2;
}
MESSAGE(LOG_DUMP, "\t---- Flags fetch\n");
}
static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
@@ -2936,3 +2734,91 @@ int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k
printf_log(LOG_NONE, "BOX64 Dynarec: Error, unable to free a reg for YMM %d at inst=%d on pass %d\n", ymm, ninst, STEP);
return i;
}
// Get an XMM quad reg and preload it (or do nothing if not possible)
static int xmm_preload_reg(dynarec_arm_t* dyn, int ninst, int last, int xmm)
{
dyn->n.ssecache[xmm].reg = fpu_get_reg_xmm(dyn, NEON_CACHE_XMMR, xmm);
int ret = dyn->n.ssecache[xmm].reg;
dyn->n.ssecache[xmm].write = 0;
VLDR128_U12(ret, xEmu, offsetof(x64emu_t, xmm[xmm]));
return ret;
}
// Get an YMM quad reg and preload it (or do nothing if not possible)
static int ymm_preload_reg(dynarec_arm_t* dyn, int ninst, int last, int ymm)
{
int i = -1;
// search for when it will be loaded the first time
for(int ii=0; ii<32 && i==-1; ++ii)
if(dyn->insts[last].n.neoncache[ii].n==ymm && (dyn->insts[last].n.neoncache[ii].t==NEON_CACHE_YMMR || dyn->insts[last].n.neoncache[ii].t==NEON_CACHE_YMMW))
i = ii;
if(i!=-1) {
VLDR128_U12(i, xEmu, offsetof(x64emu_t, ymm[ymm]));
dyn->n.neoncache[i].t = NEON_CACHE_YMMR;
dyn->n.neoncache[i].n = ymm;
}
return i;
}
void doPreload(dynarec_arm_t* dyn, int ninst)
{
int n = ninst?(ninst-1):ninst;
uint32_t preload = dyn->insts[ninst].preload_xmmymm;
int from = dyn->insts[ninst].preload_from;
if(!preload) return;
// preload XMM
MESSAGE(LOG_INFO, "Preload XMM/YMM -------- %x\n", preload);
for(int i=0; i<16; ++i) {
if(preload&(1<<i)) {
xmm_preload_reg(dyn, n, from, i);
}
if(preload&(1<<(16+i))) {
ymm_preload_reg(dyn, n, from, i);
}
}
MESSAGE(LOG_INFO, "-------- Preload XMM/YMM\n");
}
void doEnterBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// get dynarec address. It is stored just before the start of the block
MESSAGE(LOG_INFO, "doEnter --------\n");
int delta = -(dyn->native_size + sizeof(void*));
LDRx_literal(s1, delta);
// now increment in_used
ADDx_U12(s1, s1, offsetof(dynablock_t, in_used));
if(cpuext.atomics) {
MOV32w(s3, 1);
STADDLw(s3, s1);
} else {
LDAXRw(s2, s1);
ADDw_U12(s2, s2, 1);
STLXRw(s3, s2, s1);
CBNZw(s3, -3*4);
}
// set tick
LDRx_U12(s2, xEmu, offsetof(x64emu_t, context));
LDRw_U12(s2, s2, offsetof(box64context_t, tick));
STRw_U12(s2, s1, offsetof(dynablock_t, tick)-offsetof(dynablock_t, in_used));
MESSAGE(LOG_INFO, "-------- doEnter\n");
}
void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
MESSAGE(LOG_INFO, "doLeave --------\n");
// get dynarec address
int delta = -(dyn->native_size + sizeof(void*));
LDRx_literal(s1, delta);
ADDx_U12(s1, s1, offsetof(dynablock_t, in_used));
// decrement in_used
if(cpuext.atomics) {
MOV32w(s3, -1);
STADDLw(s3, s1);
} else {
LDAXRw(s2, s1);
SUBw_U12(s2, s2, 1);
STLXRw(s3, s2, s1);
CBNZw(s3, -3*4);
}
MESSAGE(LOG_INFO, "-------- doLeave\n");
}
+62 -214
View File
@@ -39,6 +39,9 @@
#ifndef FEMIT
#define FEMIT(A) EMIT(A)
#endif
#ifndef ENDPREFIX
#define ENDPREFIX
#endif
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -74,7 +77,7 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff << (3 - rex.is32bits), rex.is32bits ? 3 : 7, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff << (3 - (rex.is32bits || rex.is67)), (rex.is32bits || rex.is67) ? 3 : 7, rex, NULL, 0, D); \
LDz(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -100,28 +103,6 @@
LDSW(x1, wback, fixedaddress); \
wb = ed = x1; \
}
#define GETED32(D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, NULL, 0, D); \
LDxw(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSED32w(D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff << 2, 3, rex, NULL, 0, D); \
LDSW(x1, wback, fixedaddress); \
wb = ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
#define GETEDH(hint, D) \
if (MODREG) { \
@@ -133,16 +114,6 @@
LDxw(hint, wback, fixedaddress); \
ed = hint; \
}
#define GETED32H(hint, D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint == x2) ? x1 : x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, NULL, 0, D); \
LDxw(hint, wback, fixedaddress); \
ed = hint; \
}
//GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
#define GETEDW(hint, ret, D) \
if (MODREG) { \
@@ -155,69 +126,12 @@
ed = ret; \
LDxw(ed, wback, fixedaddress); \
}
#define GETED32W(hint, ret, D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
MOVxw_REG(ret, ed); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, NULL, 0, D); \
ed = ret; \
LDxw(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STxw(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0)
#define WBACKx if(wback) {STx(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0)
#define WBACKw if(wback) {STW(ed, wback, fixedaddress); SMWRITE();}
//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 = TO_NAT((nextop & 7) + (rex.b << 3)); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRxw_REGz(x1, O, wback); \
ed = x1; \
}
#define WBACKO(O) if(wback) {STRxw_REGz(ed, O, wback); SMWRITE2();}
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDOx(O, D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRx_REGz(x1, O, wback); \
ed = x1; \
}
//GETEDOz can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDOz(O, D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRz_REGz(x1, O, wback); \
ed = x1; \
}
#define GETSEDOw(O, D) \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRSW_REGz(x1, O, wback); \
wb = ed = x1; \
}
//FAKEELike GETED, but doesn't get anything
#define FAKEED \
if (MODREG) { \
@@ -284,22 +198,6 @@
ed = i; \
wb1 = 1; \
}
//GETEWO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEWO(i, D) \
if (MODREG) { \
wback = TO_NAT((nextop & 7) + (rex.b << 3)); \
UXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff << 1, (1 << 1) - 1, rex, NULL, 0, D); \
ADDz_REG(x3, wback, i); \
if (wback != x3) wback = x3; \
LDH(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEW will use i for ed, and can use r3 for wback. This is the Signed version
#define GETSEW(i, D) \
if (MODREG) { \
@@ -351,29 +249,6 @@
wb1 = 1; \
ed = i; \
}
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEBO(i, D) \
if (MODREG) { \
if (rex.rex) { \
wback = TO_NAT((nextop & 7) + (rex.b << 3)); \
wb2 = 0; \
} else { \
wback = (nextop & 7); \
wb2 = (wback >> 2) * 8; \
wback = TO_NAT(wback & 3); \
} \
UBFXx(i, wback, wb2, 8); \
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, D); \
ADDz_REG(x3, wback, i); \
if (wback != x3) wback = x3; \
LDB(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i, D) \
if (MODREG) { \
@@ -735,9 +610,9 @@
// CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x87pc, ret, 0, 0)
// CALL_ will use x7 for the call address.
// All regs are saved, including scratch. This is use to call internal function that should not change state
#define CALL_I(F) call_i(dyn, ninst, F)
// CALL_D will use x7 for the call address. Use for function having 1 or 2 double args and returning 1 double
// All regs are saved, including xmm0-7, will move arg1/arg2 to D0, D1, return D0 to ret (unless any is -1)
#define CALL_D(F, ret, arg1, arg2, sav1, sav2) call_d(dyn, ninst, F, ret, arg1, arg2, sav1, sav2)
#define MARK dyn->insts[ninst].mark = dyn->native_size
#define GETMARK dyn->insts[ninst].mark
@@ -1126,70 +1001,48 @@
#endif
#define FORCE_DFNONE() STRw_U12(wZR, xEmu, offsetof(x64emu_t, df))
#define CHECK_DFNONE(N) do {if(dyn->f==status_none_pending) {FORCE_DFNONE(); if(N) dyn->f = status_none;}} while(0)
#define SET_DFNONE() \
do { \
if (!dyn->f.dfnone) { \
FORCE_DFNONE(); \
} \
if(!dyn->insts[ninst].x64.may_set) { \
dyn->f.dfnone = 1; \
} \
#define SET_DFNONE() \
do { \
if(!dyn->insts[ninst].x64.may_set && (dyn->f!=status_none)) { \
dyn->f = status_none_pending; \
} \
} while(0)
#define SET_DF(S, N) \
if ((N) != d_none) { \
MOVZw(S, (N)); \
STRw_U12(S, xEmu, offsetof(x64emu_t, df)); \
if (dyn->f.pending == SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after & X_PEND)) { \
TABLE64C(x6, const_updateflags_arm64); \
BLR(x6); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone = 0; \
dyn->f = status_set; \
} else \
SET_DFNONE()
#ifndef SET_NODF
#define SET_NODF() dyn->f.dfnone = 0
#endif
#define SET_DFOK() dyn->f.dfnone = 1
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
&& (dyn->f.pending!=SF_SET_PENDING)) { \
if(dyn->f.pending!=SF_PENDING) { \
LDRw_U12(x3, xEmu, offsetof(x64emu_t, df)); \
j64 = (GETMARKF)-(dyn->native_size); \
CBZw(x3, j64); \
} \
TABLE64C(x6, const_updateflags_arm64); \
BLR(x6); \
MARKF; \
dyn->f.pending = SF_SET; \
SET_DFOK(); \
if((A)!=X_PEND \
&& (dyn->f==status_unk)) { \
TABLE64C(x6, const_updateflags_arm64); \
BLR(x6); \
dyn->f = status_none; \
}
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->f.pending!=SF_SET \
&& ((B)&SF_SUB) \
#define SETFLAGS(A, B) do { \
if (((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)));\
{ 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: SET_DFNONE(); dyn->f.pending = SF_SET; break; \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_SET_DF: dyn->f.pending = SF_SET; dyn->f.dfnone = 1; break; \
case SF_SET_NODF: dyn->f.pending = SF_SET; dyn->f.dfnone = 0; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SET_DF: dyn->f = status_set; break; \
case SF_SET_NODF: break; \
case SF_SUBSET: \
case SF_SUBSET_PENDING: \
case SF_SET: \
case SF_PENDING: \
case SF_SET_PENDING: \
dyn->f.pending = (dyn->insts[ninst].x64.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
break; \
} else dyn->f.pending = SF_SET
SET_DFNONE(); break; \
} else if((B)!=SF_SET_NODF) SET_DFNONE();} while(0)
#endif
#ifndef JUMP
#define JUMP(A, C) SMEND()
@@ -1303,14 +1156,7 @@
#define dynarec64_00 STEPNAME(dynarec64_00)
#define dynarec64_0F STEPNAME(dynarec64_0F)
#define dynarec64_64 STEPNAME(dynarec64_64)
#define dynarec64_65 STEPNAME(dynarec64_65)
#define dynarec64_66 STEPNAME(dynarec64_66)
#define dynarec64_67 STEPNAME(dynarec64_67)
#define dynarec64_67_32 STEPNAME(dynarec64_67_32)
#define dynarec64_67_AVX STEPNAME(dynarec64_67_AVX)
#define dynarec64_6764 STEPNAME(dynarec64_6764)
#define dynarec64_6764_32 STEPNAME(dynarec64_6764_32)
#define dynarec64_D8 STEPNAME(dynarec64_D8)
#define dynarec64_D9 STEPNAME(dynarec64_D9)
#define dynarec64_DA STEPNAME(dynarec64_DA)
@@ -1323,7 +1169,6 @@
#define dynarec64_660F STEPNAME(dynarec64_660F)
#define dynarec64_66F20F STEPNAME(dynarec64_66F20F)
#define dynarec64_66F30F STEPNAME(dynarec64_66F30F)
#define dynarec64_6664 STEPNAME(dynarec64_6664)
#define dynarec64_66F0 STEPNAME(dynarec64_66F0)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
@@ -1340,7 +1185,6 @@
#define dynarec64_AVX_F3_0F38 STEPNAME(dynarec64_AVX_F3_0F38)
#define geted STEPNAME(geted)
#define geted32 STEPNAME(geted32)
#define geted16 STEPNAME(geted16)
#define jump_to_epilog STEPNAME(jump_to_epilog)
#define jump_to_next STEPNAME(jump_to_next)
@@ -1348,7 +1192,7 @@
#define retn_to_epilog STEPNAME(retn_to_epilog)
#define iret_to_epilog STEPNAME(iret_to_epilog)
#define call_c STEPNAME(call_c)
#define call_i STEPNAME(call_i)
#define call_d STEPNAME(call_d)
#define call_n STEPNAME(call_n)
#define grab_segdata STEPNAME(grab_segdata)
#define emit_cmp8 STEPNAME(emit_cmp8)
@@ -1444,6 +1288,8 @@
#define emit_rcr16c STEPNAME(emit_rcr16c)
#define emit_rcl32c STEPNAME(emit_rcl32c)
#define emit_rcr32c STEPNAME(emit_rcr32c)
#define emit_rcl32 STEPNAME(emit_rcl32)
#define emit_rcr32 STEPNAME(emit_rcr32)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
#define emit_shld32c STEPNAME(emit_shld32c)
@@ -1483,6 +1329,9 @@
#define ymm_get_reg_empty STEPNAME(ymm_get_reg_empty)
#define ymm_mark_zero STEPNAME(ymm_mark_zero)
#define fpu_get_reg_ymm STEPNAME(fpu_get_reg_ymm)
#define doPreload STEPNAME(doPreload)
#define doEnterBlock STEPNAME(doEnterBlock)
#define doLeaveBlock STEPNAME(doLeaveBlock)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
@@ -1506,10 +1355,7 @@
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* unscaled, 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* unscaled, 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* unscaled, int absmax, uint32_t mask, int s);
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* unscaled, int absmax, uint32_t mask, rex_t rex, int s);
// generic x64 helper
@@ -1519,7 +1365,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex);
void retn_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n);
void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits);
void call_c(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int reg, int ret, int saveflags, int save_reg);
void call_i(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc);
void call_d(dynarec_arm_t* dyn, int ninst, arm64_consts_t fnc, int ret, int arg1, int arg2, int sav1, int sav2);
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
@@ -1615,6 +1461,8 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_rcl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
void emit_rcr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
@@ -1671,8 +1519,10 @@ void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val);
#if STEP < 2
#define CHECK_CACHE() 0
#elif STEP == 2
#define CHECK_CACHE() (cacheupd = dyn->insts[ninst].cacheupd = CacheNeedsTransform(dyn, ninst))
#else
#define CHECK_CACHE() (cacheupd = CacheNeedsTransform(dyn, ninst))
#define CHECK_CACHE() (cacheupd = dyn->insts[ninst].cacheupd)
#endif
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
@@ -1726,7 +1576,7 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n);
// propagate stack state
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3, uint32_t unneeded);
// purge MMX cache
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
// purge x87 cache
@@ -1749,31 +1599,29 @@ int ymm_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a, int k1, int
void ymm_mark_zero(dynarec_arm_t* dyn, int ninst, int a);
// Get an YMM upper quad reg, while keeping up to 3 other YMM reg (-1 to no keep)
int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k2, int k3);
// Preload XMM/YMM regs
void doPreload(dynarec_arm_t* dyn, int ninst);
// Enter a block (atomic inrement of hot and in_used)
void doEnterBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Leave a block (atomic decrement of in_used)
void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
uintptr_t dynarec64_00(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_0F(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_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
//uintptr_t dynarec64_65(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_66(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_67(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_67_32(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_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_6764(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_D8(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_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
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_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog);
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog);
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog);
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog);
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, 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_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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);
uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
+5 -6
View File
@@ -7,18 +7,17 @@
#define MESSAGE(A, ...) do {} while (0)
#define READFLAGS(A) \
dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\
dyn->insts[ninst].x64.use_flags = A; if(dyn->f!=status_none_pending) dyn->f = status_none;\
if(!BOX64ENV(dynarec_df) && (A)&X_PEND) dyn->insts[ninst].x64.use_flags = X_ALL; \
dyn->f.pending=SF_SET
dyn->f = status_none
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0; \
if(!BOX64ENV(dynarec_df)) {dyn->f.dfnone=1; dyn->f.pending=0; if((A)==SF_PENDING){printf_log(LOG_INFO, "Warning, some opcode use SF_PENDING, forcing deferedflags ON\n"); SET_BOX64ENV(dynarec_df, 1); }}
dyn->f=((B)&SF_SET)?(((B)==SF_SET_NODF)?dyn->f:status_none_pending):(((B)&SF_SET_PENDING)?status_set:status_none_pending); \
if(!BOX64ENV(dynarec_df)) {dyn->f=status_none; if((A)==SF_PENDING){printf_log(LOG_INFO, "Warning, some opcode use SF_PENDING, forcing deferedflags ON\n"); SET_BOX64ENV(dynarec_df, 1); }}
#define EMIT(A) dyn->native_size+=4
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C; dyn->insts[ninst].x64.jmp_insts = 0
#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
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3, 0); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
#define NEW_INST \
++dyn->size; \
+3 -7
View File
@@ -2,16 +2,12 @@
#define FINI
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define SET_NODF() \
if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \
propagate_nodf(dyn, ninst); \
dyn->f.dfnone = 0
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0; \
if(!BOX64ENV(dynarec_df)) {dyn->f.dfnone=1; dyn->f.pending=0; }
dyn->f=((B)&SF_SET)?(((B)==SF_SET_NODF)?dyn->f:status_none_pending):(((B)&SF_SET_PENDING)?status_set:status_none_pending); \
if(!BOX64ENV(dynarec_df)) {dyn->f = status_none; }
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
+2 -1
View File
@@ -7,11 +7,12 @@
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
#define ENDPREFIX dyn->prefixsize = dyn->native_size; dyn->insts[ninst].address = dyn->native_size; dyn->insts[ninst].size = 0
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>(dyn->insts[ninst-1].size/4))?dyn->insts[ninst-1].x64.size:(dyn->insts[ninst-1].size/4))/15; \
dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \
dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
#define INST_NAME(name)
+1
View File
@@ -16,6 +16,7 @@
do { \
if (dyn->need_dump) dynarec_log(LOG_NONE, __VA_ARGS__); \
} while (0)
#define ENDPREFIX dyn->insts[ninst].size2 = 0
#define NEW_INST \
if(ninst) { \
if(dyn->insts[ninst].address!=(uintptr_t)dyn->block-(uintptr_t)dyn->native_start) dyn->abort = 1; \
+17 -3
View File
@@ -84,10 +84,16 @@ typedef struct neoncache_s {
uint64_t ymm_regs; // 4bits (0-15) position of 16 ymmXX regs removed
} neoncache_t;
typedef struct flagcache_s {
typedef enum flagcache_s {
status_unk = 0, // unknown deferred flags status
status_set, // deferred flags set to something (not 0)
status_none_pending, // deferred flags set to 0, but still pending the write to x64emu_t
status_none, // deferred flags set to 0, written to x64emu_t
} flagcache_t;
/*typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
uint8_t dfnone; // if deferred flags is already set to df_none
} flagcache_t;
} flagcache_t;*/
typedef struct instruction_arm64_s {
instruction_x64_t x64;
@@ -137,6 +143,9 @@ typedef struct instruction_arm64_s {
flagcache_t f_exit; // flags status at end of instruction
neoncache_t n; // neoncache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin
int cacheupd;
uint32_t preload_xmmymm;
int preload_from;
} instruction_arm64_t;
typedef struct dynarec_arm_s {
@@ -146,6 +155,7 @@ typedef struct dynarec_arm_s {
uintptr_t start; // start of the block
uintptr_t end; // maximum end of the block (only used in pass0)
uint32_t isize; // size in bytes of x64 instructions included
uint32_t prefixsize; // size in byte of the prefix of the block
void* block; // memory pointer where next instruction is emitted
uintptr_t native_start; // start of the arm code
size_t native_size; // size of emitted arm code
@@ -179,6 +189,11 @@ typedef struct dynarec_arm_s {
uint8_t doublepop;
uint8_t always_test;
uint8_t abort; // abort the creation of the block
uint8_t use_x87:1; // set if x87 regs are used
uint8_t use_mmx:1;
uint8_t use_xmm:1;
uint8_t use_ymm:1;
uint8_t have_purge:1; // set to 1 if block can be purged
void* gdbjit_block;
uint32_t need_x87check; // needs x87 precision control check if non-null, or 0 if not
uint32_t need_dump; // need to dump the block
@@ -194,7 +209,6 @@ void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int get_first_jump_addr(dynarec_arm_t *dyn, uintptr_t next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
int isTable64(dynarec_arm_t *dyn, uint64_t val); // return 1 if val already in Table64
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
+2 -3
View File
@@ -3,7 +3,6 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include "os.h"
#include "debug.h"
@@ -41,12 +40,12 @@ void* create_updateflags()
helper.insts = insts;
helper.need_dump = BOX64ENV(dynarec_dump);
helper.cap = 1;
helper.f.dfnone = 1;
helper.f.pending = SF_NODF;
helper.f = status_none;
helper.insts[0].x64.gen_flags = X_ALL;
// pass 0
updateflags_pass0(&helper, jmp_df);
// check if all flags are handled
helper.have_purge = 0; // force no purge
int ok = 1;
for(int i=d_none; i<d_unknown; ++i)
if(!jmp_df[i]) {
+44 -2
View File
@@ -221,6 +221,13 @@ void cancelFillBlock()
LongJmp(GET_JUMPBUFF(dynarec_jmpbuf), 1);
}
void dynablock_leave_runtime(dynablock_t* db)
{
if(!db) return;
if(!db->tick) return;
__atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL);
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
@@ -230,6 +237,8 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
if (hasAlternate((void*)filladdr))
return NULL;
const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ;
if(BOX64ENV(nodynarec_delay) && (addr>=BOX64ENV(nodynarec_start)) && (addr<BOX64ENV(nodynarec_end)))
return NULL;
dynablock_t* block = getDB(addr);
if(block || !create) {
if(block && getNeedTest(addr) && (getProtection(addr)&req_prot)!=req_prot)
@@ -344,6 +353,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
return db;
}
mutex_unlock(&my_context->mutex_dyndump);
dynarec_log(LOG_DEBUG, "Cannot run block (or previous) %p from %p:%p (hash:%X/%X, always_test:%d, previous=%p/hash=%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, db->always_test,db->previous, db->previous?db->previous->hash:0,(void*)addr);
return NULL; // will be handle when hotpage is over
}
db->done = 0; // invalidating the block
@@ -434,10 +444,15 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr,
uintptr_t getX64Address(dynablock_t* db, uintptr_t native_addr)
{
uintptr_t x64addr = (uintptr_t)db->x64_addr;
uintptr_t armaddr = (uintptr_t)db->block;
if ((native_addr < (uintptr_t)db->block) || (native_addr > (uintptr_t)db->actual_block + db->size))
return 0;
uintptr_t x64addr = (uintptr_t)db->x64_addr;
uintptr_t armaddr = (uintptr_t)db->block;
if (!db->isize) return x64addr;
if(native_addr<(uintptr_t)db->block+db->prefixsize)
// issue indide the prefix, return as the 1st opcode
return x64addr;
armaddr += db->prefixsize;
int i = 0;
do {
int x64sz = 0;
@@ -463,6 +478,7 @@ int getX64AddressInst(dynablock_t* db, uintptr_t x64pc)
int ret = 0;
if (x64pc < (uintptr_t)db->x64_addr || x64pc > (uintptr_t)db->x64_addr + db->x64_size)
return -1;
armaddr += db->prefixsize;
int i = 0;
do {
int x64sz = 0;
@@ -481,3 +497,29 @@ int getX64AddressInst(dynablock_t* db, uintptr_t x64pc)
} while (db->instsize[i].x64 || db->instsize[i].nat);
return ret;
}
uintptr_t getX64InstAddress(dynablock_t* db, int inst)
{
uintptr_t x64addr = (uintptr_t)db->x64_addr;
uintptr_t armaddr = (uintptr_t)db->block + db->prefixsize;
if (inst < 0 || inst > db->isize)
return (uintptr_t)-1LL;
int i = 0;
int ret = 0;
do {
if (inst == ret)
return x64addr;
int x64sz = 0;
int armsz = 0;
do {
x64sz += db->instsize[i].x64;
armsz += db->instsize[i].nat * 4;
++i;
} while ((db->instsize[i - 1].x64 == 15) || (db->instsize[i - 1].nat == 15));
// if the opcode is a NOP on ARM side (so armsz==0), it cannot be an address to find
armaddr += armsz;
x64addr += x64sz;
ret++;
} while (db->instsize[i].x64 || db->instsize[i].nat);
return (uintptr_t)-1LL;
}
+3
View File
@@ -15,9 +15,12 @@ typedef struct dynablock_s {
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
struct dynablock_s* previous; // a previous block that might need to be freed
uint32_t in_used;// will be 0 if not in_used, >0 if used be some code
uint32_t tick; // last "tick" when dynablock was run
void* x64_addr;
uintptr_t x64_size;
size_t native_size;
uint32_t prefixsize; // size in byte of the prefix of the block
int size;
uint32_t hash;
uint8_t done;
+10 -4
View File
@@ -118,7 +118,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
DynaRun(emu);
emu->flags.need_jmpbuf = 1;
EmuRun(emu, 1);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
@@ -142,7 +143,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
extern int running32bits;
void DynaRun(x64emu_t* emu)
void EmuRun(x64emu_t* emu, int use_dynarec)
{
// prepare setjump for signal handling
JUMPBUFF jmpbuf[1] = {0};
@@ -166,7 +167,7 @@ void DynaRun(x64emu_t* emu)
if ((skip = SigSetJmp(emu->jmpbuf, 1)))
#endif
{
dynarec_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x will %sskip dynarec next\n", emu->segs[_FS], (skip==3)?"not ":"");
dynarec_log(LOG_DEBUG, "Setjmp EmuRun, fs=0x%x will %sskip dynarec next\n", emu->segs[_FS], (skip==3)?"not ":"");
#ifdef DYNAREC
if(BOX64ENV(dynarec_test)) {
if(emu->test.clean)
@@ -182,7 +183,7 @@ void DynaRun(x64emu_t* emu)
emu->flags.need_jmpbuf = 0;
#ifdef DYNAREC
if(!BOX64ENV(dynarec))
if(!BOX64ENV(dynarec) || !use_dynarec)
#endif
Run(emu, 0);
#ifdef DYNAREC
@@ -242,3 +243,8 @@ void DynaRun(x64emu_t* emu)
emu->xSPSave = old_savesp;
#endif
}
void DynaRun(x64emu_t *emu)
{
EmuRun(emu, 1);
}
+3 -3
View File
@@ -58,7 +58,7 @@ extern void* create_updateflags();
#define MAXBLOCK_SIZE ((1 << 27) - 200)
#define RAZ_SPECIFIC(A, N)
#define UPDATE_SPECIFICS(A)
#define UPDATE_SPECIFICS(A) propagateFpuBarrier(A)
#define PREUPDATE_SPECIFICS(A) updateNativeFlags(A)
#define POSTUPDATE_SPECIFICS(A)
@@ -67,9 +67,9 @@ extern void* create_updateflags();
#define ARCH_ADJUST(A, B, C, D) {}
#define STOP_NATIVE_FLAGS(A, B) {}
#define ARCH_UNALIGNED(A, B) 0
extern uint32_t la64_crc(void* p, uint32_t len);
#define ARCH_CRC(A, B) return la64_crc(A, B)
// NYI
#define NATIVE_RESTORE_X87PC()
#elif defined(RV64)
#define instruction_native_t instruction_rv64_t
+1
View File
@@ -201,6 +201,7 @@
#endif
int is_addr_unaligned(uintptr_t addr);
int is_addr_autosmc(uintptr_t addr);
#ifdef ARM64
#include "arm64/dynarec_arm64_helper.h"
+22 -137
View File
@@ -147,131 +147,8 @@ int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
return is_nops(dyn, addr+8, n-8);
return 0;
}
// return size of next instruction, -1 is unknown
// not all instructions are setup
int next_instruction(dynarec_native_t *dyn, uintptr_t addr)
{
uint8_t opcode = PK(0);
uint8_t nextop;
switch (opcode) {
case 0x66:
opcode = PK(1);
switch(opcode) {
case 0x90:
return 2;
}
break;
case 0x81:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 4;
case 0x83:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 1;
case 0x84:
case 0x85:
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9B:
case 0x9C:
case 0x9D:
case 0x9E:
case 0x9F:
return 1;
case 0xA0:
case 0xA1:
case 0xA2:
case 0xA3:
return 5;
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
return 2;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
return 5;
case 0xF3:
nextop = PK(1);
switch(nextop) {
case 0x90:
return 2;
default: break;
}
break;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7) {
case 0: // INC Ed
case 1: //DEC Ed
case 2: // CALL Ed
case 4: // JMP Ed
case 6: // Push Ed
return fakeed(dyn, addr+2, 0, nextop)-addr;
}
break;
default:
break;
}
return -1;
}
#undef PK
int is_instructions(dynarec_native_t *dyn, uintptr_t addr, int n)
{
int i = 0;
while(i<n) {
int j=next_instruction(dyn, addr+i);
if(j<=0) return 0;
i+=j;
}
return (i==n)?1:0;
}
void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size)
{
// x64 instruction is <16 bytes
@@ -547,9 +424,10 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
*/
if(addr>=BOX64ENV(nodynarec_start) && addr<BOX64ENV(nodynarec_end)) {
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(addr, is32bits, is_new);
return BOX64ENV(nodynarec_delay)?NULL:CreateEmptyBlock(addr, is32bits, is_new);
}
if(checkInHotPage(addr)) {
int is_inhotpage = checkInHotPage(addr);
if(is_inhotpage && !BOX64ENV(dynarec_dirty)) {
dynarec_log(LOG_DEBUG, "Not creating dynablock at %p as in a HotPage\n", (void*)addr);
return NULL;
}
@@ -602,14 +480,15 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
CancelBlock64(0);
return CreateEmptyBlock(addr, is32bits, is_new);
}
if(!isprotectedDB(addr, 1)) {
if(!is_inhotpage && !isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
CancelBlock64(0);
return NULL;
}
// protect the block of it goes over the 1st page
if((addr&~(box64_pagesize-1))!=(end&~(box64_pagesize-1))) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
if(!is_inhotpage)
if((addr&~(box64_pagesize-1))!=(end&~(box64_pagesize-1))) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// calculate barriers
@@ -672,6 +551,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
helper.insts[i].x64.jmp_insts = k;
helper.insts[i].barrier_maybe = 0;
} else {
helper.insts[i].x64.need_after |= X_PEND;
if(helper.insts[i].barrier_maybe) {
helper.insts[i].x64.barrier|=BARRIER_FLOAT;
helper.insts[i].barrier_maybe = 0;
@@ -772,22 +652,24 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
size_t callret_size = helper.callret_size*sizeof(callret_t);
size_t reloc_size = helper.reloc_size*sizeof(uint32_t);
// ok, now allocate mapped memory, with executable flag on
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size + callret_size + sizeof(dynablock_t) + reloc_size;
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size + callret_size;
size_t dynablock_align = (sz&7)?(8 -(sz&7)):0; // align dynablock
sz += dynablock_align + sizeof(dynablock_t) + reloc_size;
// dynablock_t* block (arm insts) table64 jmpnext code instsize arch callrets dynablock relocs
void* actual_p = (void*)AllocDynarecMap(addr, sz, is_new);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", (void*)addr, sz);
CancelBlock64(0);
return NULL;
}
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
void* tablestart = p + native_size;
void* next = tablestart + helper.table64size*sizeof(uint64_t);
void* instsize = next + 4*sizeof(void*);
void* arch = instsize + insts_rsize;
void* callrets = arch + arch_size;
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", (void*)addr, sz);
CancelBlock64(0);
return NULL;
}
helper.block = p;
dynablock_t* block = (dynablock_t*)(callrets+callret_size);
dynablock_t* block = (dynablock_t*)(callrets+callret_size+dynablock_align);
memset(block, 0, sizeof(dynablock_t));
void* relocs = helper.need_reloc?(block+1):NULL;
// fill the block
@@ -805,13 +687,14 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
helper.table64cap = helper.table64size;
helper.table64 = (uint64_t*)helper.tablestart;
helper.callrets = (callret_t*)callrets;
block->prefixsize = helper.prefixsize;
block->table64 = helper.table64;
if(callret_size)
memcpy(helper.callrets, static_callrets, helper.callret_size*sizeof(callret_t));
helper.callret_size = 0;
// pass 3, emit (log emit native opcode)
if(dyn->need_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes (native=%zu, table64=%zu, instsize=%zu, arch=%zu, callrets=%zu)", (dyn->need_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64", native_size, helper.table64size*sizeof(uint64_t), insts_rsize, arch_size, callret_size);
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes (native=%zu, table64=%zu, instsize=%zu, arch=%zu, callrets=%zu, entry=%p)", (dyn->need_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64", native_size, helper.table64size*sizeof(uint64_t), insts_rsize, arch_size, callret_size, helper.block);
PrintFunctionAddr(helper.start, " => ");
dynarec_log_prefix(0, LOG_NONE, "%s\n", (dyn->need_dump>1)?"\e[m":"");
}
@@ -906,7 +789,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
}
if(!isprotectedDB(addr, end-addr)) {
if(!is_inhotpage && !isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_INFO, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
block->dirty = 1;
//protectDB(addr, end-addr);
@@ -914,6 +797,8 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
if(getProtection(addr)&PROT_NEVERCLEAN) {
block->always_test = 1;
}
else if(is_inhotpage)
block->always_test = 2;
if(block->always_test) {
dynarec_log(LOG_INFO, "Note: block marked as always dirty %p:%ld\n", block->x64_addr, block->x64_size);
#ifdef ARCH_NOP
+81 -41
View File
@@ -80,24 +80,12 @@ void native_fxtract(x64emu_t* emu)
}
void native_fprem(x64emu_t* emu)
{
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
int64_t ll = (int64_t)trunc(ST0.d / ST1.d);
ST0.d = ST0.d - (ST1.d * ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll & 1) ? 1 : 0;
emu->sw.f.F87_C3 = (ll & 2) ? 1 : 0;
emu->sw.f.F87_C0 = (ll & 4) ? 1 : 0;
}
void native_fyl2xp1(x64emu_t* emu)
{
@@ -135,6 +123,50 @@ void native_fcos(x64emu_t* emu)
emu->sw.f.F87_C2 = 0;
}
double direct_f2xm1(x64emu_t* emu, double a)
{
return expm1(LN2 * a);
}
double direct_fyl2x(x64emu_t* emu, double a, double b)
{
return log2(a)*b;
}
double direct_fyl2xp1(x64emu_t* emu, double a, double b)
{
return log1p(a)*b/LN2;
}
double direct_fpatan(x64emu_t* emu, double a, double b)
{
#pragma STDC FENV_ACCESS ON
return atan2(b, a);
}
double direct_fsin(x64emu_t* emu, double a)
{
#pragma STDC FENV_ACCESS ON
// seems that sin of glib doesn't follow the rounding direction mode
emu->sw.f.F87_C2 = 0;
return sin(a);
}
double direct_fcos(x64emu_t* emu, double a)
{
#pragma STDC FENV_ACCESS ON
// seems that cos of glib doesn't follow the rounding direction mode
emu->sw.f.F87_C2 = 0;
return cos(a);
}
double direct_ftan(x64emu_t* emu, double a)
{
#pragma STDC FENV_ACCESS ON
// seems that tan of glib doesn't follow the rounding direction mode
emu->sw.f.F87_C2 = 0;
return tan(a);
}
double direct_fscale(x64emu_t* emu, double a, double b)
{
#pragma STDC FENV_ACCESS ON
return a?ldexp(a, trunc(b)):a;
}
void native_fbld(x64emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
@@ -284,23 +316,12 @@ void native_frstor16(x64emu_t* emu, uint8_t* ed)
void native_fprem1(x64emu_t* emu)
{
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
int64_t ll = (int64_t)round(ST0.d / ST1.d);
ST0.d = ST0.d - (ST1.d * ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll & 1) ? 1 : 0;
emu->sw.f.F87_C3 = (ll & 2) ? 1 : 0;
emu->sw.f.F87_C0 = (ll & 4) ? 1 : 0;
}
const uint8_t ff_mult2[4][256] = {
@@ -695,15 +716,29 @@ void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8)
GY->u128 = result;
}
void native_clflush(x64emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return 0;
#ifdef ARM64
// df_none is now a defered information
if(dyn->insts[ninst].f_exit==dyn->insts[jmp].f_entry)
return 0;
if(dyn->insts[jmp].df_notneeded)
return 0;
if((dyn->insts[jmp].f_entry==status_none_pending) && (dyn->insts[ninst].f_exit!=status_none_pending))
return 1;
switch (dyn->insts[jmp].f_entry) {
case status_unk:
return (dyn->insts[ninst].f_exit==status_none_pending)?1:0;
case status_none:
return 1;
case status_set:
return (dyn->insts[ninst].f_exit==status_none)?0:1;
case status_none_pending:
return 1;
}
#else
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone && !dyn->insts[jmp].df_notneeded)
@@ -724,6 +759,7 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
return 0;
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
#endif
return 0;
}
@@ -793,7 +829,11 @@ void propagate_nodf(dynarec_native_t* dyn, int ninst)
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
return; // flags are use, so maybe it's needed
dyn->insts[ninst].df_notneeded = 1;
--ninst;
if(!dyn->insts[ninst].pred_sz)
return;
for(int i=1; i<dyn->insts[ninst].pred_sz; ++i)
propagate_nodf(dyn, dyn->insts[ninst].pred[i]);
ninst = dyn->insts[ninst].pred[0];
}
}
+9 -2
View File
@@ -35,6 +35,15 @@ void native_frstor(x64emu_t* emu, uint8_t* ed);
void native_frstor16(x64emu_t* emu, uint8_t* ed);
void native_fprem1(x64emu_t* emu);
double direct_f2xm1(x64emu_t* emu, double a);
double direct_fyl2x(x64emu_t* emu, double a, double b);
double direct_fyl2xp1(x64emu_t* emu, double a, double b);
double direct_fpatan(x64emu_t* emu, double a, double b);
double direct_fsin(x64emu_t* emu, double a);
double direct_fcos(x64emu_t* emu, double a);
double direct_ftan(x64emu_t* emu, double a);
double direct_fscale(x64emu_t* emu, double a, double b);
void native_aesd(x64emu_t* emu, int xmm);
void native_aesd_y(x64emu_t* emu, int ymm);
void native_aese(x64emu_t* emu, int xmm);
@@ -50,8 +59,6 @@ void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul_x(x64emu_t* emu, int gx, int vx, void* p, uint32_t u8);
void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8);
void native_clflush(x64emu_t* emu, void* p);
void native_ud(x64emu_t* emu);
void native_br(x64emu_t* emu);
void native_priv(x64emu_t* emu);
+93 -26
View File
@@ -44,15 +44,23 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
int rep = 0; // 0 none, 1=F2 prefix, 2=F3 prefix
int need_epilog = 1;
// Clean up (because there are multiple passes)
#ifdef ARM64
dyn->f = status_unk;
#else
dyn->f.pending = 0;
dyn->f.dfnone = 0;
#endif
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
dyn->ymm_zero = 0;
int dynarec_dirty = BOX64ENV(dynarec_dirty);
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));
#ifdef ARM64
dyn->have_purge = BOX64ENV(dynarec_purge);
#endif
#endif
fpu_reset(dyn);
ARCH_INIT();
@@ -88,14 +96,27 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(!ninst && dyn->need_x87check) {
NATIVE_RESTORE_X87PC();
}
fpu_propagate_stack(dyn, ninst);
ip = addr;
#ifdef ARM64
if(!ninst) {
if(dyn->have_purge)
doEnterBlock(dyn, 0, x1, x2, x3);
if(dyn->insts[0].preload_xmmymm)
doPreload(dyn, 0);
ENDPREFIX;
}
#endif
fpu_propagate_stack(dyn, ninst);
if (reset_n!=-1) {
dyn->last_ip = 0;
if(reset_n==-2) {
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
#ifdef ARM64
dyn->f = status_unk;
#else
dyn->f.dfnone = 0;
dyn->f.pending = 0;
#endif
fpu_reset(dyn);
ARCH_RESET();
} else {
@@ -107,8 +128,12 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
if(dyn->insts[ninst].x64.barrier&BARRIER_FLAGS) {
MESSAGE(LOG_DEBUG, "Apply Barrier Flags\n");
#ifdef ARM64
dyn->f = status_unk;
#else
dyn->f.dfnone = 0;
dyn->f.pending = 0;
#endif
}
}
reset_n = -1;
@@ -167,32 +192,47 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
#endif
rep = 0;
rex.is32bits = is32bits;
uint8_t pk = PK(0);
while((pk==0xF2) || (pk==0xF3) || (pk==0x3E) || (pk==0x26)
|| (is32bits && ((pk==0x2E) || (pk==0x36)))
) {
switch(pk) {
case 0xF2: rep = 1; break;
case 0xF3: rep = 2; break;
case 0x2E:
case 0x36:
case 0x3E:
case 0x26: /* ignored */ break;
rex.rex = 0;
rex.seg = 0;
rex.offset = 0;
rex.is32bits = is32bits;
rex.is66 = 0;
rex.is67 = 0;
rex.isf0 = 0;
rex.rep = 0;
while((pk==0xF2) || (pk==0xF3) || (pk==0xf0)
|| (pk==0x3E) || (pk==0x26) || (pk==0x2e) || (pk==0x36)
|| (pk==0x64) || (pk==0x65) || (pk==0x66) || (pk==0x67)
|| (!is32bits && (pk>=0x40 && pk<=0x4f))) {
switch (pk) {
case 0xF0: rex.isf0 = 1; rex.rex = 0; break;
case 0xF2: rex.rep = 1; rex.rex = 0; break;
case 0xF3: rex.rep = 2; rex.rex = 0; break;
case 0x26: /* ES: */
case 0x2E: /* CS: */
case 0x36: /* SS; */
case 0x3E: /* DS; */
rex.seg = 0; rex.rex = 0; break;
case 0x64: rex.seg = _FS; rex.rex = 0; break;
case 0x65: rex.seg = _GS; rex.rex = 0; break;
case 0x66: rex.is66 = 1; rex.rex = 0; break;
case 0x67: rex.is67 = 1; rex.rex = 0; break;
case 0x40 ... 0x4F: rex.rex = pk; break;
}
++addr;
pk = PK(0);
}
rex.rex = 0;
if(!rex.is32bits)
while(pk>=0x40 && pk<=0x4f) {
rex.rex = pk;
++addr;
pk = PK(0);
}
addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
if(rex.isf0) {
if(rex.is66 && !rex.w)
addr = dynarec64_66F0(dyn, addr, ip, ninst, rex, &ok, &need_epilog);
else
addr = dynarec64_F0(dyn, addr, ip, ninst, rex, &ok, &need_epilog);
} else if(rex.is66)
addr = dynarec64_66(dyn, addr, ip, ninst, rex, &ok, &need_epilog);
else
addr = dynarec64_00(dyn, addr, ip, ninst, rex, &ok, &need_epilog);
if(dyn->abort)
return ip;
INST_EPILOG;
@@ -201,6 +241,11 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if (is_opcode_volatile || dyn->insts[ninst].lock)
DMB_ISH();
#endif
#ifdef ARM64
if(dyn->insts[ninst].x64.has_next && dyn->insts[ninst+1].preload_xmmymm) {
doPreload(dyn, ninst+1);
}
#endif
fpu_reset_scratch(dyn);
int next = ninst+1;
@@ -213,12 +258,16 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
else { tmp1=x1; tmp2=x2; tmp3=x3; }
fpu_purgecache(dyn, ninst, 0, tmp1, tmp2, tmp3);
#else
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3, 0);
#endif
}
if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
#ifdef ARM64
dyn->f = status_unk;
#else
dyn->f.pending = 0;
dyn->f.dfnone = 0;
#endif
dyn->last_ip = 0;
}
}
@@ -226,14 +275,25 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#ifndef PROT_READ
#define PROT_READ 1
#endif
#if STEP == 0
if(dynarec_dirty && ok && is_addr_autosmc(ip)) {
// this is the last opcode, because it will write in current block if not stopped
ok = 0;
need_epilog = 1;
}
#endif
#if STEP != 0
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
if((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// reset fpu value...
#ifdef ARM64
dyn->f = status_unk;
#else
dyn->f.dfnone = 0;
dyn->f.pending = 0;
#endif
fpu_reset(dyn);
while((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// may need to skip opcodes to advance
@@ -259,7 +319,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
#else
// check if block need to be stopped, because it's a 00 00 opcode (unreadeable is already checked earlier)
if((ok>0) && !dyn->forward && (!(getProtection(addr)&PROT_READ) || !(*(uint32_t*)addr))) {
if((ok>0) && !dyn->forward && (!(getProtection(addr+3)&PROT_READ) || !(*(uint32_t*)addr))) {
if (dyn->need_dump) dynarec_log(LOG_NONE, "Stopping block at %p reason: %s\n", (void*)addr, "Next opcode is 00 00 00 00");
ok = 0;
need_epilog = 1;
@@ -294,8 +354,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
(((next-addr)<15) && is_nops(dyn, addr, next-addr))))
{
ok = 1;
if(dyn->insts[ninst].x64.has_callret && !dyn->insts[ninst].x64.has_next) {
@@ -383,14 +442,22 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#endif
++ninst;
NOTEST(x3);
#if defined (RV64) || defined(LA64)
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
#else
fpu_purgecache(dyn, ninst, 0, x1, x2, x3, 0);
#endif
jump_to_next(dyn, addr, 0, ninst, rex.is32bits);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
NOTEST(x3);
#if defined (RV64) || defined(LA64)
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
#else
fpu_purgecache(dyn, ninst, 0, x1, x2, x3, 0);
#endif
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknown instruction
}
FINI;
File diff suppressed because it is too large. Load diff
+213 -138
View File
@@ -8,6 +8,7 @@
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
@@ -22,6 +23,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "elfloader.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
@@ -88,7 +90,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMEND();
GETIP(addr, x7);
STORE_XEMU_CALL();
CALL_S(const_x64syscall, -1, 0);
if(!box64_wine || FindElfAddress(my_context, ip)) {
CALL_S(const_x64syscall_linux, -1, 0);
} else {
CALL_S(const_x64syscall, -1, 0);
}
LOAD_XEMU_CALL();
TABLE64(x3, addr); // expected return address
BNE_MARK(xRIP, x3);
@@ -116,12 +122,24 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x0D:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 1:
INST_NAME("PREFETCHW");
case 0:
INST_NAME("PREFETCH");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
PRELD(0, ed, 0);
break;
case 1:
INST_NAME("PREFETCHW");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
PRELD(8, ed, 0);
break;
case 2:
INST_NAME("PREFETCHWT1");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
PRELD(8, ed, 0);
break;
default: // NOP
FAKEED;
break;
default: //???
DEFAULT;
}
break;
case 0x10:
@@ -188,7 +206,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x14:
INST_NAME("UNPCKLPS Gx, Ex");
nextop = F8;
SMREAD();
GETEX(q0, 0, 0);
GETGX(v0, 1);
VILVL_W(v0, q0, v0);
@@ -196,7 +213,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x15:
INST_NAME("UNPCKHPS Gx, Ex");
nextop = F8;
SMREAD();
GETEX(q0, 0, 0);
GETGX(v0, 1);
VILVH_W(v0, q0, v0);
@@ -237,12 +253,23 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else
switch ((nextop >> 3) & 7) {
case 0:
case 1:
case 2:
case 3:
INST_NAME("PREFETCHh Ed");
INST_NAME("PREFETCHNTA Ed");
FAKEED;
break;
case 1:
INST_NAME("PREFETCHT0 Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
PRELD(0, ed, 0);
break;
case 2:
INST_NAME("PREFETCHT1 Ed");
FAKEED;
break;
case 3:
INST_NAME("PREFETCHT2 Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
PRELDX_LOAD_L3_1CACHELINE(ed, x4); // is this a good idea?
break;
default:
INST_NAME("NOP (multibyte)");
FAKEED;
@@ -682,6 +709,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
else
REVB_2W(x1, gd);
SDxw(x1, wback, fixedaddress);
SMWRITE2();
break;
default:
DEFAULT;
@@ -766,6 +794,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
B##NO(tmp1, 8); \
} \
LDxw(gd, ed, fixedaddress); \
if (!rex.w) ZEROUP(gd); \
}
GOCOND(0x40, "CMOV", "Gd, Ed");
@@ -1293,7 +1322,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
j64 = (uint32_t)(addr + i32_); \
else \
j64 = addr + i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(j64, 1); \
if (!dyn->insts[ninst].nat_flags_fusion) { \
if (cpuext.lbt) { \
@@ -1340,36 +1368,48 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
#undef GO
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS(F); \
tmp1 = x1; \
tmp3 = x3; \
if (cpuext.lbt) { \
X64_SETJ(x3, I); \
} else { \
GETFLAGS; \
S##YES(x3, x1); \
} \
nextop = F8; \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_NAT(ed & 3); \
} \
BSTRINS_D(eb1, x3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(x3, ed, fixedaddress); \
SMWRITE(); \
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS_FUSION(F, x1, x2, x3, x4, x5); \
nextop = F8; \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVESET(NATYES, tmp3); \
} else if (cpuext.lbt) { \
X64_SETJ(tmp3, I); \
} else { \
GETFLAGS; \
S##YES(tmp3, x1); \
} \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_NAT(ed & 3); \
} \
BSTRINS_D(eb1, tmp3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(tmp3, ed, fixedaddress); \
SMWRITE(); \
}
GOCOND(0x90, "SET", "Eb");
#undef GO
case 0xA0:
INST_NAME("PUSH FS");
LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_FS]));
PUSH1z(x2);
break;
case 0xA1:
INST_NAME("POP FS");
POP1z(x2);
ST_H(x2, xEmu, offsetof(x64emu_t, segs[_FS]));
BEQ_NEXT(x2, xZR);
ADDI_D(x1, xZR, _FS);
CALL(const_getsegmentbase, -1, x1, 0);
break;
case 0xA2:
INST_NAME("CPUID");
NOTEST(x1);
@@ -1393,11 +1433,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, gd, 6);
else
SRAI_W(x1, gd, 5);
ALSL_D(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ALSLy(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
}
if (X_CF) {
IFX (X_CF) {
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRLxw(x4, ed, x2);
if (cpuext.lbt)
@@ -1413,7 +1454,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
u8 = F8 & (rex.w ? 63 : 31);
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
@@ -1422,6 +1463,33 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
F8;
}
break;
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
GETGD;
GETED(0);
if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); }
ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f);
BEQ_NEXT(x3, xZR);
emit_shld32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
WBACK;
break;
case 0xA8:
INST_NAME("PUSH GS");
LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_GS]));
PUSH1z(x2);
break;
case 0xA9:
INST_NAME("POP GS");
POP1z(x2);
ST_H(x2, xEmu, offsetof(x64emu_t, segs[_GS]));
BEQ_NEXT(x2, xZR);
ADDI_D(x1, xZR, _GS);
CALL(const_getsegmentbase, -1, x1, 0);
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -1438,7 +1506,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, gd, 6);
else
SRAI_W(x1, gd, 5);
ALSL_D(x3, x1, wback, 2 + rex.w);
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ALSLy(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -1469,8 +1538,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
u8 = F8 & (rex.w ? 63 : 31);
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
@@ -1479,21 +1547,35 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
F8;
}
break;
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
GETGD;
GETED(0);
if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); }
ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f);
BEQ_NEXT(x3, xZR);
emit_shrd32(dyn, ninst, rex, ed, gd, x3, x5, x4, x6);
WBACK;
break;
case 0xAE:
nextop = F8;
if (MODREG)
switch (nextop) {
case 0xE8:
INST_NAME("LFENCE");
SMDMB();
DBAR(0);
break;
case 0xF0:
INST_NAME("MFENCE");
SMDMB();
DBAR(0);
break;
case 0xF8:
INST_NAME("SFENCE");
SMDMB();
DBAR(0);
break;
default:
DEFAULT;
@@ -1504,7 +1586,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("FXSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x1);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
BARRIER(BARRIER_FLOAT);
if (MODREG) {
DEFAULT;
} else {
@@ -1516,7 +1598,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("FXRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x1);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
BARRIER(BARRIER_FLOAT);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
CALL(rex.is32bits ? const_fpu_fxrstor32 : const_fpu_fxrstor64, -1, ed, 0);
break;
@@ -1571,7 +1653,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 4:
INST_NAME("XSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
BARRIER(BARRIER_FLOAT);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
MOV32w(x2, rex.w ? 0 : 1);
CALL(const_fpu_xsave, -1, ed, x2);
@@ -1579,16 +1661,16 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 5:
INST_NAME("XRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
BARRIER(BARRIER_FLOAT);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
MOV32w(x2, rex.w ? 0 : 1);
CALL(const_fpu_xrstor, -1, ed, x2);
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
CALL_(const_native_clflush, -1, 0, ed, 0);
FAKEED;
// Full flush... no fine-grained options available
DBAR(0);
break;
default:
DEFAULT;
@@ -1596,77 +1678,51 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
nextop = F8;
GETGD;
GETED(0);
if (BOX64ENV(dynarec_test)) {
// avoid noise during test
CLEAR_FLAGS(x3);
}
CLEAR_FLAGS(x3);
if (rex.w) {
// 64bits imul
UFLAG_IF {
if (cpuext.lbt) {
X64_MUL_D(gd, ed);
}
MULH_D(x3, gd, ed);
MUL_D(gd, gd, ed);
IFX (X_PEND) {
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
SET_DFNONE();
}
IFXA (X_CF | X_OF, !cpuext.lbt) {
SET_DFNONE();
IFX (X_CF | X_OF) {
SRAI_D(x4, gd, 63);
XOR(x3, x3, x4);
SNEZ(x3, x3);
IFX (X_CF) {
BSTRINS_D(xFlags, x3, F_CF, F_CF);
}
IFX (X_OF) {
BSTRINS_D(xFlags, x3, F_OF, F_OF);
}
IFX (X_CF) BSTRINS_D(xFlags, x3, F_CF, F_CF);
IFX (X_OF) BSTRINS_D(xFlags, x3, F_OF, F_OF);
}
} else {
MULxw(gd, gd, ed);
MUL_D(gd, gd, ed);
}
} else {
// 32bits imul
UFLAG_IF {
if (cpuext.lbt) {
X64_MUL_W(gd, ed);
}
SLLI_W(gd, gd, 0);
SLLI_W(x3, ed, 0);
MUL_D(gd, gd, x3);
SRLI_D(x3, gd, 32);
SLLI_W(gd, gd, 0);
IFX (X_PEND) {
UFLAG_RES(gd);
UFLAG_OP1(x3);
UFLAG_DF(x4, d_imul32);
} else IFX (X_CF | X_OF) {
SET_DFNONE();
}
IFXA (X_CF | X_OF, !cpuext.lbt) {
SRAI_W(x4, gd, 31);
SUB_D(x3, x3, x4);
MUL_D(x4, gd, x3);
SRLI_D(x3, x4, 32);
SLLI_W(gd, x4, 0);
SET_DFNONE();
IFX (X_CF | X_OF) {
XOR(x3, gd, x4);
SNEZ(x3, x3);
IFX (X_CF) {
BSTRINS_D(xFlags, x3, F_CF, F_CF);
}
IFX (X_OF) {
BSTRINS_D(xFlags, x3, F_OF, F_OF);
}
IFX (X_CF) BSTRINS_D(xFlags, x3, F_CF, F_CF);
IFX (X_OF) BSTRINS_D(xFlags, x3, F_OF, F_OF);
}
} else {
MULxw(gd, gd, ed);
MUL_W(gd, gd, ed);
}
ZEROUP(gd);
}
IFX (X_SF) {
SRLI_D(x3, gd, rex.w ? 63 : 31);
BSTRINS_D(xFlags, x3, F_SF, F_SF);
}
IFX (X_PF) emit_pf(dyn, ninst, gd, x3, x4);
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xB3:
INST_NAME("BTR Ed, Gd");
@@ -1684,7 +1740,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, gd, 6);
else
SRAI_W(x1, gd, 5);
ADDSL(x3, wback, x1, 2 + rex.w, x1);
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ALSLy(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -1711,6 +1768,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
GETGD;
SCRATCH_USAGE(0);
if (MODREG) {
if (rex.rex) {
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
@@ -1842,7 +1900,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, gd, 6);
else
SRAI_W(x1, gd, 5);
ADDSL(x3, wback, x1, 2 + rex.w, x1);
if (!rex.w && !rex.is32bits) { ADDI_W(x1, x1, 0); }
ALSLy(x3, x1, wback, 2 + rex.w); // (&ed) += r1*4;
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
@@ -1865,8 +1924,13 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xBC:
INST_NAME("BSF Gd, Ed");
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
CLEAR_FLAGS(x2);
nextop = F8;
GETED(0);
GETGD;
@@ -1875,29 +1939,25 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ed = x4;
}
BNE_MARK(ed, xZR);
if (cpuext.lbt) {
ADDI_D(x3, xZR, 1 << F_ZF);
X64_SET_EFLAGS(x3, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
B_NEXT_nocond;
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
B_MARK2_nocond;
MARK;
// gd is undefined if ed is all zeros, don't worry.
if (rex.w)
CTZ_D(gd, ed);
else
CTZ_W(gd, ed);
if (cpuext.lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
CTZxw(gd, ed);
MARK2;
IFX (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
SPILL_EFLAGS();
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
CLEAR_FLAGS(x2);
nextop = F8;
GETED(0);
GETGD;
@@ -1906,25 +1966,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ed = x4;
}
BNE_MARK(ed, xZR);
if (cpuext.lbt) {
ADDI_D(x3, xZR, 1 << F_ZF);
X64_SET_EFLAGS(x3, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
B_NEXT_nocond;
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
B_MARK2_nocond;
MARK;
if (cpuext.lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
}
if (rex.w)
CLZ_D(gd, ed);
else
CLZ_W(gd, ed);
CLZxw(gd, ed);
ADDI_D(x1, xZR, rex.w ? 63 : 31);
SUB_D(gd, x1, gd);
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
SPILL_EFLAGS();
break;
case 0xBE:
INST_NAME("MOVSX Gd, Eb");
@@ -1962,6 +2014,29 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
if (!rex.w) ZEROUP(gd);
break;
case 0xC0:
INST_NAME("XADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGB(x1);
GETEB(x2, 0);
gd = x2;
ed = x1;
emit_add8(dyn, ninst, ed, gd, x4, x5);
GBBACK();
EBBACK();
break;
case 0xC1:
INST_NAME("XADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGD;
GETED(0);
if (ed != gd) MV(x7, ed);
emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
if (ed != gd) MVxw(gd, x7);
WBACK;
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
nextop = F8;
-538
View File
@@ -1,538 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)rep;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t u8;
uint8_t gd, ed, eb1, eb2, gb1, gb2;
uint8_t gback, wback, wb1, wb2, wb;
int64_t i64, j64;
uint64_t u64;
int v0, v1;
int q0;
int d0;
int64_t fixedaddress, gdoffset;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(j64);
MAYUSE(d0);
MAYUSE(q0);
MAYUSE(v0);
MAYUSE(v1);
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
switch (opcode) {
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x0B:
INST_NAME("OR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0F:
opcode = F8;
switch (opcode) {
case 0x18:
case 0x19:
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
FAKEED;
break;
default:
DEFAULT;
}
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x64:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
break;
case 0x80:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0: // ADD
INST_NAME("ADD Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 2: // ADC
INST_NAME("ADC Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
if (u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg, (MODREG));
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0x81) {
INST_NAME("ADD Ed, Id");
} else {
INST_NAME("ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7);
WBACKO(x6);
break;
case 1:
if (opcode == 0x81) {
INST_NAME("OR Ed, Id");
} else {
INST_NAME("OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 2:
if (opcode == 0x81) {
INST_NAME("ADC Ed, Id");
} else {
INST_NAME("ADC Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
IFXA (X_ALL, !cpuext.lbt)
ST_D(x6, xEmu, offsetof(x64emu_t, scratch));
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x7);
IFXA (X_ALL, !cpuext.lbt) {
LD_D(x6, xEmu, offsetof(x64emu_t, scratch));
}
WBACKO(x6);
break;
case 3:
if (opcode == 0x81) {
INST_NAME("SBB Ed, Id");
} else {
INST_NAME("SBB Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x7);
WBACKO(x6);
break;
case 4:
if (opcode == 0x81) {
INST_NAME("AND Ed, Id");
} else {
INST_NAME("AND Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 5:
if (opcode == 0x81) {
INST_NAME("SUB Ed, Id");
} else {
INST_NAME("SUB Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7);
WBACKO(x6);
break;
case 6:
if (opcode == 0x81) {
INST_NAME("XOR Ed, Id");
} else {
INST_NAME("XOR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 7:
if (opcode == 0x81) {
INST_NAME("CMP Ed, Id");
} else {
INST_NAME("CMP Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64) {
MOV64x(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5);
break;
}
break;
case 0x88:
INST_NAME("MOV Seg:Eb, Gb");
nextop = F8;
gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
if (rex.rex) {
gb2 = 0;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd & 4) << 1);
gb1 = TO_NAT(gd & 3);
}
if (gb2) {
gd = x4;
BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
} else {
gd = gb1;
}
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) << 1); // L or H
}
BSTRINS_D(eb1, gd, eb2 + 7, eb2);
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
STX_B(gd, x4, wback);
}
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
if (rex.is32bits) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
SDxw(gd, x4, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
SDXxw(gd, ed, x4);
}
SMWRITE2();
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
if (MODREG) { // reg <= reg
MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
if (rex.is32bits) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
LDxw(gd, x4, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
LDXxw(gd, ed, x4);
}
}
break;
case 0x8E:
INST_NAME("MOV Seg, Ew");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
u8 = (nextop & 0x38) >> 3;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
ADDz(x4, wback, x4);
LD_HU(x1, x4, 0);
ed = x1;
}
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
ST_W(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if (rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
if (rex.is32bits) {
ADDz(x4, x1, x4);
LDxw(xRAX, x4, 0);
} else
LDXxw(xRAX, x4, x1);
break;
case 0xA3:
INST_NAME("MOV FS:Od, EAX");
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if (rex.is32bits)
u64 = F32;
else
u64 = F64;
if (u64 < 0x800) {
ADDIz(x1, x4, u64);
} else {
MOV64z(x1, u64);
ADDz(x1, x1, x4);
}
SDxw(xRAX, x1, 0);
SMWRITE2();
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
if (MODREG) { // reg <= u8
u8 = F8;
if (!rex.rex) {
ed = (nextop & 7);
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
} else {
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
}
MOV32w(x3, u8);
BSTRINS_D(eb1, x3, eb2 * 8 + 7, eb2 * 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1);
u8 = F8;
if (u8) {
ADDI_D(x3, xZR, u8);
ed = x3;
} else
ed = xZR;
if (rex.is32bits) {
ADDz(x4, wback, x4);
ST_B(ed, x4, 0);
} else {
STX_B(ed, wback, x4);
}
SMWRITE2();
}
break;
case 0xC7:
INST_NAME("MOV Seg:Ed, Id");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
if (MODREG) { // reg <= i32
i64 = F32S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 4);
i64 = F32S;
if (i64) {
MOV64x(x3, i64);
ed = x3;
} else
ed = xZR;
if (rex.is32bits) {
ADDz(x4, wback, x4);
SDxw(ed, x4, 0);
} else {
SDXxw(ed, wback, x4);
}
SMWRITE2();
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 6: // Push Ed
INST_NAME("PUSH Ed");
grab_segdata(dyn, addr, ninst, x6, seg, (MODREG));
GETEDOz(x6, 0, x3);
PUSH1z(ed);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+527 -141
View File
@@ -8,6 +8,7 @@
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
@@ -22,7 +23,7 @@
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
@@ -42,18 +43,8 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MAYUSE(j64);
MAYUSE(lock);
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;
}
GETREX();
if (rex.w && !(opcode == 0x0f || opcode == 0xf0 || opcode == 0x64 || opcode == 0x65)) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
if (rex.w && !(opcode == 0x0f)) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); // addr-1, to "put back" opcode
switch (opcode) {
case 0x01:
@@ -83,6 +74,16 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x06:
INST_NAME("PUSH ES");
LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
PUSH1_16(x1);
break;
case 0x07:
INST_NAME("POP ES");
POP1_16(x1);
ST_H(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
@@ -111,12 +112,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x0F:
switch (rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
switch (rex.rep) {
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
default:
DEFAULT;
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
default: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
}
break;
case 0x11:
@@ -179,6 +178,16 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0x1E:
INST_NAME("PUSH DS");
LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
PUSH1_16(x1);
break;
case 0x1F:
INST_NAME("POP DS");
POP1_16(x1);
ST_H(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
@@ -288,14 +297,103 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_cmp16_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
INST_NAME("INC Reg16 (32bits)");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
gd = TO_NAT(opcode & 7);
BSTRPICK_D(x1, gd, 15, 0);
emit_inc16(dyn, ninst, x1, x2, x3, x4);
BSTRINS_D(gd, x1, 15, 0);
break;
case 0x65:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg16 (32bits)");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
gd = TO_NAT(opcode & 7);
BSTRPICK_D(x1, gd, 15, 0);
emit_dec16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINS_D(gd, x1, 15, 0);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
INST_NAME("PUSH reg");
SCRATCH_USAGE(0);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
PUSH1_16(gd);
break;
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
INST_NAME("POP reg");
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
POP1_16(x1);
BSTRINS_D(gd, x1, 15, 0);
break;
case 0x60:
if (rex.is32bits) {
INST_NAME("PUSHA 16bits (32bits)");
MV(x1, xRSP);
PUSH1_16(xRAX);
PUSH1_16(xRCX);
PUSH1_16(xRDX);
PUSH1_16(xRBX);
PUSH1_16(x1);
PUSH1_16(xRBP);
PUSH1_16(xRSI);
PUSH1_16(xRDI);
} else
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
break;
case 0x61:
if (rex.is32bits) {
INST_NAME("POPA 16bits (32bits)");
POP1_16(x1);
BSTRINS_D(xRDI, x1, 15, 0);
POP1_16(x1);
BSTRINS_D(xRSI, x1, 15, 0);
POP1_16(x1);
BSTRINS_D(xRBP, x1, 15, 0);
POP1_16(x1); // RSP ignored
POP1_16(x1);
BSTRINS_D(xRBX, x1, 15, 0);
POP1_16(x1);
BSTRINS_D(xRDX, x1, 15, 0);
POP1_16(x1);
BSTRINS_D(xRCX, x1, 15, 0);
POP1_16(x1);
BSTRINS_D(xRAX, x1, 15, 0);
} else
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
break;
case 0x68:
INST_NAME("PUSH Iw");
u16 = F16;
MOV32w(x2, u16);
PUSH1_16(x2);
break;
case 0x69:
case 0x6B:
@@ -318,6 +416,33 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0x6A:
INST_NAME("PUSH Ib");
i16 = F8S;
MOV32w(x2, (uint16_t)i16);
PUSH1_16(x2);
break;
case 0x6C:
case 0x6E:
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
// just use regular conditional jump
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
case 0x81:
case 0x83:
nextop = F8;
@@ -466,15 +591,65 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGW(x2);
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);
MV(x1, gd);
BSTRINS_D(gd, ed, 15, 0);
BSTRINS_D(ed, x1, 15, 0);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x3, wback, 1);
BEQ_MARK(x3, xZR);
SMDMB();
LD_HU(x1, wback, 0);
ST_H(gd, wback, 0);
SMDMB();
BSTRINS_D(gd, x1, 15, 0);
B_NEXT_nocond;
MARK;
if (cpuext.lam_bh) {
AMSWAP_DB_H(x1, gd, wback);
} else if (cpuext.lamcas) {
LD_H(x1, wback, 0);
MARKLOCK;
MV(x6, x1);
AMCAS_DB_H(x1, gd, wback);
BNE_MARKLOCK(x1, x6);
} else {
MV(x6, wback);
BSTRINS_D(x6, xZR, 1, 0);
ANDI(x3, wback, 0b10);
BEQZ(x3, 4 + 4 * 6);
// hi16
LL_W(x5, x6, 0);
BSTRPICK_D(x1, x5, 31, 16);
BSTRINS_D(x5, gd, 31, 16);
SC_W(x5, x6, 0);
BEQZ(x5, -4 * 4);
B(4 + 4 * 5);
// lo16
LL_W(x5, x6, 0);
BSTRPICK_D(x1, x5, 15, 0);
BSTRINS_D(x5, gd, 15, 0);
SC_W(x5, x6, 0);
BEQZ(x5, -4 * 4);
}
BSTRINS_D(gd, x1, 15, 0);
}
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD;
SCRATCH_USAGE(0);
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINSz(ed, gd, 15, 0);
}
if (ed != gd) BSTRINSz(ed, gd, 15, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
ST_H(gd, ed, fixedaddress);
@@ -486,10 +661,9 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
SCRATCH_USAGE(0);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINSz(gd, ed, 15, 0);
}
if (ed != gd) BSTRINSz(gd, ed, 15, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
@@ -497,6 +671,30 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRINSz(gd, x1, 15, 0);
}
break;
case 0x8C:
INST_NAME("MOV Ew, Seg");
nextop = F8;
LD_HU(x3, xEmu, offsetof(x64emu_t, segs[(nextop & 0x38) >> 3]));
if (MODREG) {
BSTRINSz(TO_NAT((nextop & 7) + (rex.b << 3)), x3, 15, 0);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ST_H(x3, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
rex.seg = 0;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
BSTRINS_D(gd, ed, 15, 0);
}
break;
case 0x8E:
INST_NAME("MOV Seg, Ew");
nextop = F8;
@@ -510,7 +708,31 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ed = x1;
}
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
ST_H(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
if ((u8 == _FS) || (u8 == _GS)) {
// refresh offset if needed
CBZ_NEXT(ed);
MOV32w(x1, u8);
CALL(const_getsegmentbase, -1, x1, x2);
}
break;
case 0x8F:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("POP Ew");
POP1_16(x1);
if (MODREG) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BSTRINS_D(wback, x1, 15, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
ST_H(x1, wback, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x90:
case 0x91:
@@ -536,53 +758,79 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SRAI_D(x1, x1, 56);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0xA4:
if (rep) {
INST_NAME("REP MOVSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
// special optim for large RCX value on forward case only
OR(x1, xRSI, xRDI);
ANDI(x1, x1, 7);
BNEZ_MARK(x1);
ADDI_D(x6, xZR, 8);
MARK3;
BLT_MARK(xRCX, x6);
LD_D(x1, xRSI, 0);
ST_D(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 8);
ADDI_D(xRDI, xRDI, 8);
ADDI_D(xRCX, xRCX, -8);
BNEZ_MARK3(xRCX);
B_NEXT_nocond;
MARK; // Part with DF==0
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 1);
ADDI_D(xRDI, xRDI, 1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, -1);
ADDI_D(xRDI, xRDI, -1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, x1, 1);
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
case 0x99:
INST_NAME("CWD");
SLLI_D(x1, xRAX, 48);
SRAI_D(x1, x1, 48);
SRLI_D(x1, x1, 48);
BSTRINS_D(xRDX, x1, 15, 0);
break;
case 0x9C:
INST_NAME("PUSHF");
READFLAGS(X_ALL);
RESTORE_EFLAGS(x1);
PUSH1_16(xFlags);
SMWRITE();
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SMREAD();
POP1_16(x1);
MOV32w(x2, 0x7FD7);
AND(x1, x1, x2);
ORI(x1, x1, 0x202);
// no need to restore eflags here
BSTRINS_D(xFlags, x1, 15, 0);
SPILL_EFLAGS();
SET_DFNONE();
if (box64_wine) { // should this be done all the time?
ANDI(x1, xFlags, 1 << F_TF);
CBZ_NEXT(x1);
// go to epilog, TF should trigger at end of next opcode, so using Interpreter only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
case 0xA1:
INST_NAME("MOV EAX, Od");
if (rex.is32bits && rex.is67)
u64 = F16S;
else if (rex.is32bits || rex.is67)
u64 = F32S;
else
u64 = F64;
MOV64y(x1, u64);
if (rex.seg) {
grab_segdata(dyn, addr, ninst, x3, rex.seg, 0);
ADDxREGy(x1, x3, x1, x1);
}
lock = (rex.seg) ? 0 : isLockAddress(u64);
SMREADLOCK(lock);
LD_HU(x2, x1, 0);
BSTRINSz(xRAX, x2, 15, 0);
break;
case 0xA3:
INST_NAME("MOV Od, EAX");
if (rex.is32bits && rex.is67)
u64 = F16S;
else if (rex.is32bits || rex.is67)
u64 = F32S;
else
u64 = F64;
MOV64y(x1, u64);
if (rex.seg) {
grab_segdata(dyn, addr, ninst, x3, rex.seg, 0);
ADDxREGy(x1, x3, x1, x1);
}
lock = (rex.seg) ? 0 : isLockAddress(u64);
ST_H(xRAX, x1, 0);
SMWRITELOCK(lock);
break;
case 0xA4:
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
break;
case 0xA5:
if (rep) {
if (rex.rep) {
INST_NAME("REP MOVSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
@@ -611,12 +859,13 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xA7:
switch (rep) {
switch (rex.rep) {
case 1:
case 2:
if (rep == 1) {
if (rex.rep == 1) {
INST_NAME("REPNZ CMPSW");
} else {
INST_NAME("REPZ CMPSW");
@@ -632,7 +881,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADDI_D(xRSI, xRSI, 2);
ADDI_D(xRDI, xRDI, 2);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
if (rex.rep == 1) {
BEQ_MARK3(x1, x2); // REPNZ
} else {
BNE_MARK3(x1, x2); // REPZ
@@ -645,7 +894,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADDI_D(xRSI, xRSI, -2);
ADDI_D(xRDI, xRDI, -2);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
if (rex.rep == 1) {
BEQ_MARK3(x1, x2); // REPNZ
} else {
BNE_MARK3(x1, x2); // REPZ
@@ -675,7 +924,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xAB:
if (rep) {
if (rex.rep) {
INST_NAME("REP STOSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
@@ -698,12 +947,24 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ST_H(xRAX, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xAD:
if (rex.rep) {
DEFAULT;
} else {
INST_NAME("LODSW");
GETDIR(x1, x2, 2);
LD_HU(x2, xRSI, 0);
ADD_D(xRSI, xRSI, x1);
BSTRINSz(xRAX, x2, 15, 0);
}
break;
case 0xAF:
switch (rep) {
switch (rex.rep) {
case 1:
case 2:
if (rep == 1) {
if (rex.rep == 1) {
INST_NAME("REPNZ SCASW");
} else {
INST_NAME("REPZ SCASW");
@@ -717,7 +978,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LD_D(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
if (rex.rep == 1) {
BEQ_MARK3(xRAX, x2);
} else {
BNE_MARK3(xRAX, x2);
@@ -731,7 +992,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LD_HU(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
if (rex.rep == 1) {
BEQ_MARK3(x1, x2);
} else {
BNE_MARK3(x1, x2);
@@ -777,23 +1038,57 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(const_rol16, x1, x3, x1, x2);
EWBACK;
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8) & 0x1f;
emit_rol16c(dyn, ninst, x1, u8, x4, x5, x6);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(const_ror16, x1, x3, x1, x2);
EWBACK;
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8) & 0x1f;
emit_ror16c(dyn, ninst, x1, u8, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 2:
INST_NAME("RCL Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8) & 0x1f;
emit_rcl16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 3:
INST_NAME("RCR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8) & 0x1f;
emit_rcr16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 4:
case 6:
@@ -835,8 +1130,6 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
F8;
}
break;
default:
DEFAULT;
}
break;
case 0xC7:
@@ -856,18 +1149,69 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0xD1:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Ew, 1");
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 0);
emit_rol16c(dyn, ninst, x1, 1, x5, x4, x6);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 1);
emit_ror16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 2:
INST_NAME("RCL Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 0);
emit_rcl16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); // removed PENDING on purpose
GETEW(x1, 0);
emit_rcr16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 5:
INST_NAME("SHR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETEW(x1, 0);
emit_shr16c(dyn, ninst, x1, 1, x5, x4, x6);
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETEW(x1, 0);
emit_shl16c(dyn, ninst, x1, 1, x5, x4, x6);
EWBACK;
break;
case 7:
INST_NAME("SAR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETSEW(x1, 0);
emit_sar16c(dyn, ninst, x1, 1, x5, x4, x6);
EWBACK;
break;
}
break;
case 0xD3:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0xD1) {
INST_NAME("ROL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
INST_NAME("ROL Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
@@ -875,15 +1219,42 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
CALL_(const_rol16, x1, x3, x1, x2);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 1);
CALL_(const_ror16, x1, x3, x1, x2);
EWBACK;
break;
case 2:
INST_NAME("RCL Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 1);
CALL_(const_rcl16, x1, x3, x1, x2);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 1);
CALL_(const_rcr16, x1, x3, x1, x2);
EWBACK;
break;
case 5:
if (opcode == 0xD1) {
INST_NAME("SHR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
INST_NAME("SHR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 0);
@@ -892,44 +1263,38 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 4:
case 6:
if (opcode == 0xD1) {
INST_NAME("SHL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
INST_NAME("SHL Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
case 7:
if (opcode == 0xD1) {
INST_NAME("SAR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
INST_NAME("SAR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
default:
DEFAULT;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0xE4: /* IN AL, Ib */
case 0xE5: /* IN AX, Ib */
case 0xE6: /* OUT Ib, AL */
case 0xE7: /* OUT Ib, AX */
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
case 0xEC: /* IN AL, DX */
case 0xED: /* IN AX, DX */
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, AX */
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
case 0xF7:
nextop = F8;
@@ -957,6 +1322,19 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
case 4:
INST_NAME("MUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
GETEW(x1, 0);
BSTRPICK_D(x2, xRAX, 15, 0);
MUL_W(x1, x2, x1);
ZEROUP(x1);
UFLAG_RES(x1);
BSTRINSz(xRAX, x1, 15, 0);
SRLI_D(x1, x1, 16);
BSTRINS_D(xRDX, x1, 15, 0);
UFLAG_DF(x1, d_mul16);
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
@@ -966,7 +1344,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SLLI_D(x7, xRDX, 48);
SRLI_D(x7, x7, 32);
OR(x2, x2, x7);
if(BOX64ENV(dynarec_div0)) {
if (BOX64ENV(dynarec_div0)) {
BNE_MARK3(ed, xZR);
GETIP_(ip, x6);
STORE_XEMU_CALL();
@@ -980,6 +1358,11 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MOD_WU(x4, x2, ed);
BSTRINSz(xRAX, x7, 15, 0);
BSTRINSz(xRDX, x4, 15, 0);
SET_DFNONE();
CLEAR_FLAGS(x5);
ADDI_D(x5, xZR, ((1 << F_ZF) | (1 << F_PF)));
OR(xFlags, xFlags, x5);
SPILL_EFLAGS();
break;
case 7:
INST_NAME("IDIV Ew");
@@ -1009,6 +1392,9 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0xF8:
case 0xF9:
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog);
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
+412 -13
View File
@@ -8,6 +8,7 @@
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
@@ -886,6 +887,46 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, 0);
REVB_2H(x1, gd);
ST_H(x1, wback, fixedaddress);
SMWRITE();
break;
case 0xF6:
INST_NAME("ADCX Gd, Ed");
nextop = F8;
READFLAGS(X_CF);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETED(0);
GETGD;
if(cpuext.lbt) {
X64_GET_EFLAGS(x3, X_CF); // CF pos is 0, no need SLLI
} else {
BSTRPICK_D(x3, xFlags, F_CF, F_CF);
}
IFX(X_CF) {
if(rex.w) {
ADD_D(x4, gd, ed);
SLTU(x5, x4, gd);
ADD_D(gd, x4, x3);
SLTU(x6, gd, x4);
} else {
ADD_W(x4, gd, ed);
ZEROUP(x4);
ZEROUP(gd);
SLTU(x5, x4, gd);
ADD_W(gd, x4, x3);
ZEROUP(gd);
SLTU(x6, gd, x4);
}
OR(x5, x5, x6);
if(cpuext.lbt) {
X64_SET_EFLAGS(x5, X_CF);
} else {
BSTRINS_D(xFlags, x5, F_CF, F_CF);
}
} else {
ADDxw(x5, gd, ed);
ADDxw(gd, x5, x3);
if (!rex.w) ZEROUP(gd);
}
break;
default:
DEFAULT;
@@ -1079,6 +1120,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = (F8) & 15;
VPICKVE2GR_BU(x1, q0, u8);
ST_B(x1, wback, fixedaddress);
SMWRITE2();
}
break;
case 0x15:
@@ -1095,6 +1137,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = (F8) & 7;
VPICKVE2GR_HU(x1, q0, u8);
ST_H(x1, wback, fixedaddress);
SMWRITE2();
}
break;
case 0x16:
@@ -2047,17 +2090,158 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0xA3:
INST_NAME("BT Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
EXT_W_H(x1, gd);
SRAI_D(x1, x1, 4);
ALSL_D(x3, x1, wback, 1);
LD_H(x1, x3, fixedaddress);
ed = x1;
}
IFX (X_CF) {
ANDI(x2, gd, 0xf);
SRL_D(x4, ed, x2);
if (cpuext.lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
break;
case 0xA4:
INST_NAME("SHLD Ew, Gw, Ib");
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f;
if (u8) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 1);
GETGW(x2);
u8 = F8;
emit_shld16c(dyn, ninst, rex, ed, gd, u8, x6, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETGW(x2);
ANDI(gd, gd, 15);
SRL_D(x4, ed, gd);
if (cpuext.lbt)
X64_SET_EFLAGS(x4, X_CF);
GETEW(x1, 0);
ANDI(x4, xRCX, 0x1f);
UFLAG_IF { BEQ_NEXT(x4, xZR); }
emit_shld16(dyn, ninst, ed, gd, x4, x5, x6, x7);
EWBACK;
break;
case 0xAB:
INST_NAME("BTS Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
EXT_W_H(x1, gd);
SRAI_D(x1, x1, 4);
ALSL_D(x3, x1, wback, 1);
LD_H(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, 0xf);
IFX (X_CF) {
SRL_D(x4, ed, x2);
if (cpuext.lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
ADDI_D(x4, xZR, 1);
SLL_D(x4, x4, x2);
OR(ed, ed, x4);
if (wback) {
ST_H(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ew, Gw, Ib");
u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f;
if (u8) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 1);
GETGW(x2);
u8 = F8;
emit_shrd16c(dyn, ninst, rex, ed, gd, u8, x6, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETGW(x2);
GETEW(x1, 0);
ANDI(x4, xRCX, 0x1f);
UFLAG_IF { BEQ_NEXT(x4, xZR); }
emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6, x7);
EWBACK;
break;
case 0xAE:
nextop = F8;
if (MODREG)
switch (nextop) {
default: DEFAULT;
}
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
switch ((nextop >> 3) & 7) {
case 6:
INST_NAME("CLWB Ed");
FAKEED;
// Full flush... no fine-grained options available
DBAR(0);
break;
case 7:
INST_NAME("CLFLUSHOPT Ed");
FAKEED;
// Full flush... no fine-grained options available
DBAR(0);
break;
default:
DEFAULT;
}
break;
case 0xAF:
INST_NAME("IMUL Gw,Ew");
@@ -2071,6 +2255,46 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0xB3:
INST_NAME("BTR Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
EXT_W_H(x1, gd);
SRAI_D(x1, x1, 4);
ALSL_D(x3, x1, wback, 1);
LD_H(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, 0xf);
IFX (X_CF) {
SRL_D(x4, ed, x2);
if (cpuext.lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
ADDI_D(x4, xZR, 1);
SLL_D(x4, x4, x2);
NOR(x4, x4, xZR);
AND(ed, ed, x4);
if (wback) {
ST_H(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xB6:
INST_NAME("MOVZX Gw, Eb");
nextop = F8;
@@ -2097,11 +2321,15 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("BT Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
GETED(1);
u8 = F8;
u8 &= rex.w ? 0x3f : 15;
u8 &= (rex.w ? 0x3f : 0x0f);
IFX (X_CF) {
BSTRPICK_D(x3, ed, u8, u8);
if (cpuext.lbt) {
@@ -2111,10 +2339,171 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
}
break;
case 5:
INST_NAME("BTS Ew, Ib");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
GETEW(x1, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x0f);
if (cpuext.lbt) {
SRLI_D(x3, ed, u8);
X64_SET_EFLAGS(x3, X_CF);
} else {
BSTRINS_D(xFlags, ed, u8, u8);
}
if (u8 <= 11) {
ORI(ed, ed, (1LL << u8));
} else {
ADDI_D(x3, xZR, -1);
BSTRINS_D(ed, x3, u8, u8);
}
EWBACK;
break;
case 6:
INST_NAME("BTR Ew, Ib");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
GETEW(x1, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x0f);
if (cpuext.lbt) {
SRLI_D(x3, ed, u8);
X64_SET_EFLAGS(x3, X_CF);
} else {
BSTRINS_D(xFlags, ed, u8, u8);
}
BSTRINS_D(ed, xZR, u8, u8);
EWBACK;
break;
case 7:
INST_NAME("BTC Ew, Ib");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
GETEW(x1, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x0f);
if (cpuext.lbt) {
SRLI_D(x3, ed, u8);
X64_SET_EFLAGS(x3, X_CF);
} else {
BSTRINS_D(xFlags, ed, u8, u8);
}
if (u8 <= 11) {
XORI(ed, ed, (1LL << u8));
} else {
MOV64xw(x6, (1LL << u8));
XOR(ed, ed, x6);
}
EWBACK;
break;
default:
DEFAULT;
}
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL & ~X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
EXT_W_H(x1, gd);
SRAI_D(x1, x1, 4);
ALSL_D(x3, x1, wback, 1);
LD_H(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, 0xf);
IFX (X_CF) {
SRL_D(x4, ed, x2);
if (cpuext.lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
ADDI_D(x4, xZR, 1);
SLL_D(x4, x4, x2);
XOR(ed, ed, x4);
if (wback) {
ST_H(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xBC:
INST_NAME("BSF Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
IFX (X_ALL) CLEAR_FLAGS(x3);
} else
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETEW(x5, 0);
GETGW(x4);
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
B_MARK2_nocond;
MARK;
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
CTZ_D(gd, ed);
GWBACK;
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
}
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBD:
INST_NAME("BSR Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
IFX (X_ALL) CLEAR_FLAGS(x3);
} else
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETEW(x5, 0);
GETGW(x4);
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
B_MARK2_nocond;
MARK;
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
CLZ_D(gd, ed);
ADDI_D(x1, xZR, 63);
SUB_D(gd, x1, gd);
GWBACK;
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
}
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBE:
INST_NAME("MOVSX Gw, Eb");
nextop = F8;
@@ -2142,6 +2531,16 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
BSTRINS_D(gd, x1, 15, 0);
break;
case 0xC1:
INST_NAME("XADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
BSTRINS_D(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), ed, 15, 0);
emit_add16(dyn, ninst, ed, gd, x4, x5, x6);
EWBACK;
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex, Ib");
nextop = F8;
@@ -2152,11 +2551,11 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0: VFCMP_D(v0, v0, v1, cEQ); break; // Equal => cEQ True if EQ
case 1: VFCMP_D(v0, v0, v1, cLT); break; // Less than => cLT True if EQ LT
case 2: VFCMP_D(v0, v0, v1, cLE); break; // Less or equal => CLE True if LT EQ
case 3: VFCMP_D(v0, v0, v0, cUN); break; // unordered => CUN True if UN
case 3: VFCMP_D(v0, v0, v1, cUN); break; // unordered => CUN True if UN
case 4: VFCMP_D(v0, v0, v1, cUNE); break; // Not Equal or unordered True if UN LT GT
case 5: VFCMP_D(v0, v1, v0, cULE); break; // grether or equal or un True if UN EQ GT, use cULE UN LT, swap v0 v1
case 6: VFCMP_D(v0, v1, v0, cULT); break; // Greater or unordered True if UN GT, use cULE UN EQ LT, swap v0 v1
case 7: VFCMP_D(v0, v0, v0, cOR); break; // not NaN(ordered) True if LT EQ GT
case 7: VFCMP_D(v0, v0, v1, cOR); break; // not NaN(ordered) True if LT EQ GT
}
break;
case 0xC4:
@@ -2212,8 +2611,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if(rex.w){
REVB_D(gd, gd);
} else {
REVB_2H(x2, gd);
BSTRINS_D(gd, x2, 15, 0);
// undefined behaviour
BSTRINS_D(gd, xZR, 15, 0);
}
break;
case 0xD0:
-69
View File
@@ -1,69 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int64_t j64;
int v0, v1;
int64_t fixedaddress;
int unscaled;
MAYUSE(j64);
GETREX();
switch (opcode) {
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if (rex.w) {
MV(gd, ed);
} else {
if (ed != gd) BSTRINS_D(gd, ed, 15, 0);
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
if (rex.w) {
LD_D(gd, x4, fixedaddress);
} else {
LD_HU(x1, x4, fixedaddress);
BSTRINS_D(gd, x1, 15, 0);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+460 -28
View File
@@ -8,6 +8,7 @@
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
@@ -21,10 +22,9 @@
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_66F0(dynarec_la64_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_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)rep;
(void)need_epilog;
uint8_t opcode = F8;
@@ -42,36 +42,371 @@ uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MAYUSE(wb2);
MAYUSE(j64);
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
switch (opcode) {
case 0x01:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
AMADD_DB_H(x1, x5, wback);
} else {
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
ADD_D(x4, x1, x5);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
ADD_D(x4, x1, x5);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
}
// final
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
}
}
break;
case 0x09:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
OR(x4, x1, x5);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
OR(x4, x1, x5);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
// final
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x6, x1, 15, 0);
emit_or16(dyn, ninst, x6, x5, x3, x4);
}
}
break;
case 0x0F:
nextop = F8;
switch (nextop) {
case 0xAB:
if (MODREG) {
INST_NAME("Invalid LOCK BTS");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK BTS Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (rex.w) {
SRAI_D(x1, gd, 3);
} else {
EXT_W_H(x4, gd);
SRAI_W(x1, x4, 3);
}
ANDI(x2, gd, 7);
ADD_D(x6, wback, x1);
ANDI(x4, x6, 0b11);
ALSL_D(x2, x4, x2, 3);
BSTRINS_D(x6, xZR, 1, 0);
ADDI_D(x5, xZR, 1);
SLL_D(x5, x5, x2);
AMOR_DB_W(x4, x5, x6);
IFX (X_CF) {
SRL_D(x4, x4, x2);
if (cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
}
break;
case 0xB1:
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK CMPXCHG Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
nextop = F8;
GETGD;
BSTRPICK_D(x6, xRAX, 15, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
// Aligned
if (cpuext.lamcas) {
MV(x1, x6);
AMCAS_DB_H(x1, gd, wback);
BSTRPICK_D(x1, x1, 15, 0);
BEQ_MARK(x1, x6); // equal = cas success.
} else {
MV(x7, wback);
BSTRINS_D(x7, xZR, 1, 0);
ANDI(x3, wback, 0b10);
BEQZ(x3, 4 + 4 * 7);
// hi16
LL_W(x5, x7, 0);
BSTRPICK_D(x1, x5, 31, 16);
BNE_MARK2(x1, x6);
BSTRINS_D(x5, gd, 31, 16);
SC_W(x5, x7, 0);
BEQZ(x5, -4 * 5);
B_MARK_nocond;
// lo16
LL_W(x5, x7, 0);
BSTRPICK_D(x1, x5, 15, 0);
BNE_MARK2(x1, x6);
BSTRINS_D(x5, gd, 15, 0);
SC_W(x5, x7, 0);
BEQZ(x5, -4 * 5);
B_MARK_nocond;
}
MARK2;
BSTRINS_D(xRAX, x1, 15, 0);
MARK;
UFLAG_IF { emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5, x7); }
}
break;
case 0xB3:
if (MODREG) {
INST_NAME("Invalid LOCK BTR");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK BTR Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (rex.w) {
SRAI_D(x1, gd, 3);
} else {
EXT_W_H(x4, gd);
SRAI_W(x1, x4, 3);
}
ANDI(x2, gd, 7);
ADD_D(x6, wback, x1);
ANDI(x4, x6, 0b11);
ALSL_D(x2, x4, x2, 3);
BSTRINS_D(x6, xZR, 1, 0);
ADDI_D(x5, xZR, 1);
SLL_D(x5, x5, x2);
NOR(x5, x5, xZR);
AMAND_DB_W(x4, x5, x6);
IFX (X_CF) {
SRL_D(x4, x4, x2);
if (cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
}
break;
case 0xBA:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
break;
case 5:
if (MODREG) {
INST_NAME("Invalid LOCK BTS");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK BTS Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 0, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0xf);
ADDI_D(x6, wback, u8 >> 3);
MOV64x(x2, u8 & 7);
ANDI(x4, x6, 0b11);
ALSL_D(x2, x4, x2, 3);
BSTRINS_D(x6, xZR, 1, 0); // aligned_dword_addr = byte_addr & ~3
ADDI_D(x5, xZR, 1);
SLL_D(x5, x5, x2); // mask = 1 << total_bit_offset
AMOR_DB_W(x4, x5, x6);
IFX (X_CF) {
SRL_D(x4, x4, x2);
if (cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
}
break;
case 6:
if (MODREG) {
INST_NAME("Invalid LOCK BTR");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK BTR Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 0, 1);
u8 = F8;
u8 &= (rex.w ? 0x3f : 0xf);
ADDI_D(x6, wback, u8 >> 3);
MOV64x(x2, u8 & 7);
ANDI(x4, x6, 0b11);
ALSL_D(x2, x4, x2, 3);
BSTRINS_D(x6, xZR, 1, 0); // aligned_dword_addr = byte_addr & ~3
ADDI_D(x5, xZR, 1);
SLL_D(x5, x5, x2); // mask = 1 << total_bit_offset
NOR(x5, x5, xZR);
AMAND_DB_W(x4, x5, x6);
IFX (X_CF) {
SRL_D(x4, x4, x2);
if (cpuext.lbt) {
X64_SET_EFLAGS(x4, X_CF);
} else {
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
}
}
break;
default:
DEFAULT;
}
break;
case 0xC1:
nextop = F8;
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETGD;
BSTRPICK_D(x5, gd, 15, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
AMADD_DB_H(x1, x5, wback);
} else {
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
ADD_D(x4, x1, x5);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
ADD_D(x4, x1, x5);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
}
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, gd, x3, x4, x5);
}
BSTRINS_D(gd, x1, 15, 0);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
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, NAT_FLAGS_FUSION);
if (MODREG) {
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64x(x5, u64);
BSTRPICK_D(x6, ed, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x2);
BSTRINS_D(ed, x6, 15, 0);
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
if (opcode == 0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -92,9 +427,6 @@ uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x1, x1, 15, 0);
}
B_MARK3_nocond;
MARK;
// upper 16 bits
@@ -111,7 +443,107 @@ uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
// final
IFXORNAT (X_ALL | X_PEND) {
emit_add16(dyn, ninst, x1, x5, x3, x4, x6);
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
}
}
break;
default:
DEFAULT;
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
ADDI_D(x5, xZR, 1);
AMADD_DB_H(x1, x5, wback);
} else {
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
ADDI_D(x4, x1, 1);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
ADDI_D(x4, x1, 1);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
}
// final
IFXORNAT (X_ALL | X_PEND) {
if (!cpuext.lam_bh) ADDI_D(x5, xZR, 1);
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
}
}
break;
case 1:
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
ADDI_D(x5, xZR, -1);
AMADD_DB_H(x1, x5, wback);
} else {
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
ADDI_D(x4, x1, -1);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
ADDI_D(x4, x1, -1);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
}
// final
IFXORNAT (X_ALL | X_PEND) {
if (!cpuext.lam_bh) ADDI_D(x5, xZR, -1);
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
}
}
break;
-377
View File
@@ -1,377 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x0F:
opcode = F8;
switch (opcode) {
case 0xB6:
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
GETGD;
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) << 1); // L or H
}
BSTRPICK_D(gd, eb1, eb2 + 7, eb2);
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LD_BU(gd, ed, fixedaddress);
}
break;
case 0xB7:
INST_NAME("MOVZX Gd, Ew");
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BSTRPICK_D(gd, ed, 15, 0);
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(gd, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x1A:
INST_NAME("SBB Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5);
GBBACK();
break;
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
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, NAT_FLAGS_FUSION);
GETED32((opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
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, NAT_FLAGS_FUSION);
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, NAT_FLAGS_FUSION);
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, x5, x6);
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, NAT_FLAGS_FUSION);
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, x5);
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, NAT_FLAGS_FUSION);
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, NAT_FLAGS_FUSION);
GETED32((opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
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, NAT_FLAGS_FUSION);
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, NAT_FLAGS_FUSION);
GETED32((opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64) {
MOV64x(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5);
break;
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
if (rex.rex) {
gb2 = 0;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd & 4) << 1);
gb1 = TO_NAT(gd & 3);
}
if (gb2) {
gd = x4;
BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
} else {
gd = gb1; // no need to extract
}
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) >> 2); // L or H
}
BSTRINS_D(eb1, gd, eb2 * 8 + 7, eb2 * 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
ST_B(gb1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SDxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8B:
INST_NAME("MOV Gd, Ed");
nextop = F8;
GETGD;
if (MODREG) {
MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LDxw(gd, ed, fixedaddress);
}
break;
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, x1, &fixedaddress, rex, NULL, 0, 0);
ZEROUP2(gd, ed);
}
break;
case 0xE8:
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
GETED32(0);
if (rex.w) {
if (ed == xRDX)
gd = x3;
else
gd = xRDX;
MULH_DU(gd, xRAX, ed);
MUL_D(xRAX, xRAX, ed);
if (gd != xRDX) MV(xRDX, gd);
} else {
MUL_D(xRDX, xRAX, ed); // 64 <- 32x32
ZEROUP2(xRAX, xRDX);
SRLI_W(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w ? d_mul64 : d_mul32);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
-1
View File
@@ -396,7 +396,6 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
u8 = sse_setround(dyn, ninst, x6, x4);
}
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if(vex.l) {
XVFCVTH_D_S(d0, v1);
XVFCVTL_D_S(v0, v1);
+1 -1
View File
@@ -357,7 +357,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
INST_NAME("VCVTPD2PS Gx, Ex");
nextop = F8;
GETEYxy(v1, 0, 0);
GETGYx_empty(v0);
+70 -52
View File
@@ -258,14 +258,20 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0x13:
INST_NAME("VCVTPH2PS Gx, Ex");
nextop = F8;
GETEYSD(v1, 0, 0);
GETGYxy_empty(v0);
d0 = fpu_get_scratch(dyn);
if (vex.l) {
XVFCVTH_S_H(d0, v1);
XVFCVTL_S_H(v0, v1);
XVPERMI_Q(v0, d0, XVPERMI_IMM_4_0(0, 2));
GETEYx(v1, 0, 0);
GETGYy_empty(v0);
d0 = fpu_get_scratch(dyn);
/*
xvffintl.s.h convert [h0..h3,h4..h7,h8..h11,h12..h15] to [h0..h3,h8..h11]
xvffinth.s.h convert [h0..h3,h4..h7,h8..h11,h12..h15] to [h4..h7,h12..h15]
so user xvpermi.d to reorder input [h0..h3,h4..h7,h8..h11,h12..h15] to [h0..h3,h8..h11,h4..h7,h12..h15]
*/
XVPERMI_D(d0, v1, 0b11011000);
XVFCVTL_S_H(v0, d0);
} else {
GETEYSD(v1, 0, 0);
GETGYx_empty(v0);
VFCVTL_S_H(v0, v1);
}
break;
@@ -910,7 +916,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
d1 = fpu_get_scratch(dyn);
if (vex.l) {
v1 = avx_get_reg(dyn, ninst, x6, eb2, 0, LSX_AVX_WIDTH_256);
v1 = avx_get_reg(dyn, ninst, x6, eb2, 0, rex.w ? LSX_AVX_WIDTH_128 : LSX_AVX_WIDTH_256);
if (rex.w) {
XVSRLI_D(d1, v2, 63);
} else {
@@ -919,7 +925,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
for (int i = 0; i < (rex.w ? 4 : 8); i++) {
XVPICKVE2GRxw(x4, d1, i);
BEQZ(x4, 4 + 4 * 4);
XVPICKVE2GR_WU(x4, v1, i);
XVPICKVE2GR_W(x4, v1, i);
SLLI_D(x4, x4, wb1);
LDXxw(x6, ed, x4);
XVINSGR2VRxw(v0, x6, i);
@@ -935,7 +941,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
for (int i = 0; i < (rex.w ? 2 : 4); i++) {
VPICKVE2GRxw(x4, d1, i);
BEQZ(x4, 4 + 4 * 4);
VPICKVE2GR_WU(x4, v1, i);
VPICKVE2GR_W(x4, v1, i);
SLLI_D(x4, x4, wb1);
LDXxw(x6, ed, x4);
VINSGR2VRxw(v0, x6, i);
@@ -980,8 +986,13 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
}
// ed is base
wb1 = u8 >> 6; // scale
GETVYxy(v2, 1);
GETGYxy(v0, 1);
if (rex.w) {
GETVYxy(v2, 1);
GETGYxy(v0, 1);
} else {
GETVYx(v2, 1);
GETGYx(v0, 1);
}
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
@@ -1017,6 +1028,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
VINSGR2VRxw(v0, x6, i);
}
VXOR_V(v2, v2, v2);
if (!rex.w) VINSGR2VR_D(v0, xZR, 1); // for set DEST[127:64] to zero, cause 128bit op only gather 2 32bits float.
}
break;
case 0x96:
@@ -1274,97 +1286,103 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
case 0xDB:
INST_NAME("VAESIMC Gx, Ex");
nextop = F8;
GETGY_empty_EY_xy(q0, q1, 0);
GETEYx(q1, 0, 0);
GETGYx_empty(q0);
if (q0 != q1) {
VOR_V(q0, q1, q1);
}
avx_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(const_native_aesimc, -1, x1, 0);
if (!vex.l) {
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]));
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8);
}
GETGYx(q0, 1); // reget writable for mark zeroup hi-128bits.
break;
case 0xDC:
INST_NAME("VAESENC Gx, Ex");
INST_NAME("VAESENC Gx, Vx, Ex");
nextop = F8;
GETG;
GETEYx(q1, 0, 0);
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
VOR_V(d0, q1, q1);
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
if (gd != vex.v) {
VOR_Vxy(q0, q1, q1);
}
avx_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(const_native_aese, -1, x1, 0);
GETGYx(q0, 1);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
if (!vex.l) {
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]));
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8);
if (vex.l) {
MOV32w(x1, gd);
CALL(const_native_aese_y, -1, x1, 0);
}
GETGYxy(q0, 1);
VXOR_Vxy(q0, q0, (d0 != -1) ? d0 : q2);
break;
case 0xDD:
INST_NAME("VAESENCLAST Gx, Ex");
INST_NAME("VAESENCLAST Gx, Vx, Ex");
nextop = F8;
GETG;
GETEYx(q1, 0, 0);
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
VOR_V(d0, q1, q1);
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
if (gd != vex.v) {
VOR_Vxy(q0, q1, q1);
}
avx_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(const_native_aeselast, -1, x1, 0);
GETGYx(q0, 1);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
if (!vex.l) {
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]));
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8);
if (vex.l) {
MOV32w(x1, gd);
CALL(const_native_aeselast_y, -1, x1, 0);
}
GETGYxy(q0, 1);
VXOR_Vxy(q0, q0, (d0 != -1) ? d0 : q2);
break;
case 0xDE:
INST_NAME("VAESDEC Gx, Ex"); // AES-NI
INST_NAME("VAESDEC Gx, Vx, Ex"); // AES-NI
nextop = F8;
GETG;
GETEYx(q1, 0, 0);
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
VOR_V(d0, q1, q1);
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
if (gd != vex.v) {
VOR_Vxy(q0, q1, q1);
}
avx_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(const_native_aesd, -1, x1, 0);
GETGYx(q0, 1);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
if (!vex.l) {
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]));
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8);
if (vex.l) {
MOV32w(x1, gd);
CALL(const_native_aesd_y, -1, x1, 0);
}
GETGYxy(q0, 1);
VXOR_Vxy(q0, q0, (d0 != -1) ? d0 : q2);
break;
case 0xDF:
INST_NAME("VAESDECLAST Gx, Ex"); // AES-NI
INST_NAME("VAESDECLAST Gx, Vx, Ex"); // AES-NI
nextop = F8;
GETG;
GETEYx(q1, 0, 0);
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
VOR_V(d0, q1, q1);
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
if (gd != vex.v) {
VOR_Vxy(q0, q1, q1);
}
avx_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(const_native_aesdlast, -1, x1, 0);
GETGYx(q0, 1);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
if (!vex.l) {
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]));
ST_D(xZR, xEmu, offsetof(x64emu_t, ymm[gd]) + 8);
if (vex.l) {
MOV32w(x1, gd);
CALL(const_native_aesdlast_y, -1, x1, 0);
}
GETGYxy(q0, 1);
VXOR_Vxy(q0, q0, (d0 != -1) ? d0 : q2);
break;
case 0xF7:
INST_NAME("SHLX Gd, Ed, Vd");
@@ -387,6 +387,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 0, 1);
u8 = (F8) & 15;
VSTELM_B(q0, wback, 0, u8);
SMWRITE2();
}
break;
case 0x15:
@@ -402,6 +403,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x4, &fixedaddress, rex, NULL, 0, 1);
u8 = (F8) & 7;
VSTELM_H(q0, wback, 0, u8);
SMWRITE2();
}
break;
case 0x16:
@@ -126,7 +126,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
d1 = fpu_get_scratch(dyn);
if (rex.w) {
MOVGR2FR_D(d1, ed);
FFINT_D_L(d1, d1);
+8 -4
View File
@@ -482,15 +482,19 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
YMM_UNMARK_UPPER_ZERO(v0);
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
INST_NAME("VCVTDQ2PD Gx, Ex");
nextop = F8;
d0 = fpu_get_scratch(dyn);
if(vex.l){
GETEYx(v1, 0, 0);
GETGYy_empty(v0);
XVFFINTL_D_W(v0, v1);
XVFFINTH_D_W(d0, v1);
XVPERMI_Q(v0, d0, XVPERMI_IMM_4_0(0, 2));
/*
xvffintl.d.w convert [v0,v1,v2,v3,v4,v5,v6,v7] to [v0,v1,v4,v5]
xvffinth.d.w convert [v0,v1,v2,v3,v4,v5,v6,v7] to [v2,v3,v6,v7]
so user xvpermi.d to reorder input [v0v1,v2v3,v4v5,v6v7] to [v0v1,v4v5,v2v3,v6v7]
*/
XVPERMI_D(d0, v1, 0b11011000);
XVFFINTL_D_W(v0, d0);
}else{
GETEYSD(v1, 0, 0);
GETGYx_empty(v0);
+1 -1
View File
@@ -45,7 +45,6 @@ uintptr_t getConst(la64_consts_t which)
case const_native_int3: return (uintptr_t)native_int3;
case const_native_int: return (uintptr_t)native_int;
case const_native_div0: return (uintptr_t)native_div0;
case const_native_clflush: return (uintptr_t)native_clflush;
case const_native_fprem: return (uintptr_t)native_fprem;
case const_native_fprem1: return (uintptr_t)native_fprem1;
case const_native_frstor16: return (uintptr_t)native_frstor16;
@@ -81,6 +80,7 @@ uintptr_t getConst(la64_consts_t which)
case const_int3: return (uintptr_t)EmuInt3;
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
case const_x64syscall_linux: return (uintptr_t)EmuX64Syscall_linux;
case const_rcl8: return (uintptr_t)rcl8;
case const_rcl16: return (uintptr_t)rcl16;
case const_rcl32: return (uintptr_t)rcl32;
+1 -1
View File
@@ -16,7 +16,6 @@ typedef enum la64_consts_s {
const_native_int3,
const_native_int,
const_native_div0,
const_native_clflush,
const_native_fprem,
const_native_fprem1,
const_native_frstor16,
@@ -52,6 +51,7 @@ typedef enum la64_consts_s {
const_int3,
const_x86syscall,
const_x64syscall,
const_x64syscall_linux,
const_rcl8,
const_rcl16,
const_rcl32,
+275
View File
@@ -0,0 +1,275 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_D8(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int i1, i2, i3;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
if (MODREG)
switch (nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FADD 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FADD_S(v1, v1, v2);
} else {
FADD_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xC8 ... 0xCF:
INST_NAME("FMUL 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FMUL_S(v1, v1, v2);
} else {
FMUL_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xD0 ... 0xD7:
INST_NAME("FCOM 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)) {
FCOMS(v1, v2, x1, x2, x3);
} else {
FCOMD(v1, v2, x1, x2, x3);
}
break;
case 0xD8 ... 0xDF:
INST_NAME("FCOMP 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)) {
FCOMS(v1, v2, x1, x2, x3);
} else {
FCOMD(v1, v2, x1, x2, x3);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0 ... 0xE7:
INST_NAME("FSUB 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FSUB_S(v1, v1, v2);
} else {
FSUB_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xE8 ... 0xEF:
INST_NAME("FSUBR 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FSUB_S(v1, v2, v1);
} else {
FSUB_D(v1, v2, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xF0 ... 0xF7:
INST_NAME("FDIV 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FDIV_S(v1, v1, v2);
} else {
FDIV_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xF8 ... 0xFF:
INST_NAME("FDIVR 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FDIV_S(v1, v2, v1);
} else {
FDIV_D(v1, v2, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
break;
}
else
switch ((nextop >> 3) & 7) {
case 0:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FADD_S(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FADD_D(v1, v1, s0);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 1:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FMUL_S(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FMUL_D(v1, v1, s0);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 2:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FCOMS(v1, s0, x1, x6, x3);
} else {
FCVT_D_S(s0, s0);
FCOMD(v1, s0, x1, x6, x3);
}
break;
case 3:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FCOMS(v1, s0, x1, x6, x3);
} else {
FCVT_D_S(s0, s0);
FCOMD(v1, s0, x1, x6, x3);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FSUB_S(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FSUB_D(v1, v1, s0);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 5:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FSUB_S(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FSUB_D(v1, s0, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 6:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FDIV_S(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FDIV_D(v1, v1, s0);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 7:
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, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(s0, ed, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
if (ST_IS_F(0)) {
FDIV_S(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FDIV_D(v1, s0, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
}
+515
View File
@@ -0,0 +1,515 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_D9(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v0, v1, v2;
int s0;
int i1, i2, i3;
int64_t j64;
MAYUSE(s0);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(j64);
if (MODREG)
switch (nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FLD STx");
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, X87_ST(nextop & 7));
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop & 7) + 1, X87_COMBINE(0, (nextop & 7) + 1));
if (ST_IS_F(0)) {
FMOV_S(v2, v1);
} else {
FMOV_D(v2, v1);
}
break;
case 0xC8:
INST_NAME("FXCH ST0");
break;
case 0xC9 ... 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;
case 0xD0:
INST_NAME("FNOP");
break;
case 0xD8:
INST_NAME("FSTPNCE ST0, ST0");
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9 ... 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_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if (ST_IS_F(0)) {
FNEG_S(v1, v1);
} else {
FNEG_D(v1, v1);
}
break;
case 0xE1:
INST_NAME("FABS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if (ST_IS_F(0)) {
FABS_S(v1, v1);
} else {
FABS_D(v1, v1);
}
break;
case 0xE4:
INST_NAME("FTST");
DEFAULT;
break;
case 0xE5:
INST_NAME("FXAM");
#if 1
i1 = x87_get_current_cache(dyn, ninst, 0, LSX_CACHE_ST_D);
// value put in x4
if (i1 == -1) {
if (fpu_is_st_freed(dyn, ninst, 0)) {
MOV32w(x4, 0b100000100000000);
B_MARK3_nocond;
} else {
// not in cache, so check Empty status and load it
i2 = -dyn->lsx.x87stack;
LD_WU(x3, xEmu, offsetof(x64emu_t, fpu_stack));
if (i2) {
ADDI_D(x3, x3, -i2);
}
MOV32w(x4, 0b100000100000000); // empty: C3,C2,C0 = 101
BGE_MARK3(xZR, x3);
// x5 will be the actual top
LD_WU(x5, xEmu, offsetof(x64emu_t, top));
if (i2) {
ADDI_D(x5, x5, i2);
ANDI(x5, x5, 7); // (emu->top + i)&7
}
// load x2 with ST0 anyway, for sign extraction
SLLI_D(x5, x5, 3);
ADD_D(x1, xEmu, x5);
LD_D(x2, x1, offsetof(x64emu_t, x87));
// load tag
if (i2 >= 0) {
LD_HU(x3, xEmu, offsetof(x64emu_t, fpu_tags));
if (i2 > 0) {
BSTRINS_D(x3, xZR, 15, 0);
SRLI_D(x3, x3, i2 * 2);
}
ANDI(x3, x3, 0b11);
BNEZ_MARK3(x3); // empty: C3,C2,C0 = 101
}
}
} else {
// simply move from cache reg to x2
v1 = dyn->lsx.x87reg[i1];
MOVFR2GR_D(x2, v1);
}
// get exponant in x1
SRLI_D(x1, x2, 20 + 32);
ANDI(x1, x1, 0x7ff); // 0x7ff
BNEZ_MARK(x1); // not zero or denormal
MOV64x(x3, 0x7fffffffffffffff);
AND(x1, x2, x3);
MOV32w(x4, 0b100000000000000); // Zero: C3,C2,C0 = 100
BEQZ_MARK3(x1);
MOV32w(x4, 0b100010000000000); // Denormal: C3,C2,C0 = 110
B_MARK3_nocond;
MARK;
ADDI_D(x3, xZR, 0x7ff); // infinite/NaN?
MOV32w(x4, 0b000010000000000); // normal: C3,C2,C0 = 010
BNE_MARK3(x1, x3);
SLLI_D(x3, x2, 12);
SRLI_D(x3, x3, 12); // and 0x000fffffffffffff
MOV32w(x4, 0b000010100000000); // infinity: C3,C2,C0 = 011
BEQZ_MARK3(x3);
MOV32w(x4, 0b000000100000000); // NaN: C3,C2,C0 = 001
MARK3;
// Extract sign & Update SW
SRLI_D(x1, x2, 63);
SLLI_D(x1, x1, 9);
OR(x4, x4, x1); // C1
LD_HU(x1, xEmu, offsetof(x64emu_t, sw));
MOV32w(x2, ~0b0100011100000000);
AND(x1, x1, x2);
OR(x4, x4, x1);
ST_H(x4, xEmu, offsetof(x64emu_t, sw));
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_refresh(dyn, ninst, x1, x2, 0);
s0 = x87_stackcount(dyn, ninst, x1);
CALL(fpu_fxam, -1, 0, 0); // should be possible inline, but is it worth it?
x87_unstackcount(dyn, ninst, x1, s0);
#endif
break;
case 0xE8:
INST_NAME("FLD1");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_F);
if (ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
MOVGR2FR_W(v1, x1);
} else {
MOV64x(x1, 0x3FF0000000000000);
MOVGR2FR_D(v1, x1);
}
break;
case 0xE9:
INST_NAME("FLDL2T");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FTABLE64(v1, L2T);
break;
case 0xEA:
INST_NAME("FLDL2E");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FTABLE64(v1, L2E);
break;
case 0xEB:
INST_NAME("FLDPI");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FTABLE64(v1, PI);
break;
case 0xEC:
INST_NAME("FLDLG2");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FTABLE64(v1, LG2);
break;
case 0xED:
INST_NAME("FLDLN2");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FTABLE64(v1, LN2);
break;
case 0xEE:
INST_NAME("FLDZ");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_F);
if (ST_IS_F(0))
MOVGR2FR_W(v1, xZR);
else
MOVGR2FR_D(v1, xZR);
break;
case 0xF0:
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_f2xm1, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xF1:
INST_NAME("FYL2X");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_fyl2x, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_ftan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_F);
if (ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
MOVGR2FR_W(v1, x1);
} else {
MOV64x(x1, 0x3FF0000000000000);
MOVGR2FR_D(v1, x1);
}
break;
case 0xF3:
INST_NAME("FPATAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_fpatan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF4:
INST_NAME("FXTRACT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_fxtract, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xF5:
INST_NAME("FPREM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_fprem1, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xF6:
INST_NAME("FDECSTP");
BARRIER(BARRIER_FLOAT);
LD_W(x2, xEmu, offsetof(x64emu_t, top));
ADDI_D(x2, x2, -1);
ANDI(x2, x2, 7);
ST_W(x2, xEmu, offsetof(x64emu_t, top));
break;
case 0xF7:
INST_NAME("FINCSTP");
BARRIER(BARRIER_FLOAT);
LD_W(x2, xEmu, offsetof(x64emu_t, top));
ADDI_D(x2, x2, 1);
ANDI(x2, x2, 7);
ST_W(x2, xEmu, offsetof(x64emu_t, top));
break;
case 0xF8:
INST_NAME("FPREM");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_fprem, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xF9:
INST_NAME("FYL2XP1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(const_native_fyl2xp1, -1, 0, 0);
x87_unstackcount(dyn, ninst, x3, s0);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FSQRT_S(v1, v1);
} else {
FSQRT_D(v1, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xFB:
INST_NAME("FSINCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_fsincos, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xFC:
INST_NAME("FRNDINT");
v0 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
v1 = fpu_get_scratch(dyn);
v2 = fpu_get_scratch(dyn);
u8 = x87_setround(dyn, ninst, x1, x2);
if (ST_IS_F(0)) {
FCMP_S(fcc0, v0, v0, cEQ);
BCNEZ_MARK(fcc0);
B_NEXT_nocond;
MARK; // v0 is not nan
FABS_S(v1, v0);
MOV64x(x3, 1ULL << __FLT_MANT_DIG__);
MOVGR2FR_W(v2, x3);
FFINT_S_L(v2, v2);
FCMP_S(fcc1, v1, v2, cLT);
BCNEZ_MARK2(fcc1);
B_NEXT_nocond;
MARK2;
FTINT_L_S(v1, v0);
FFINT_S_L(v1, v1);
FCOPYSIGN_S(v0, v1, v0);
} else {
FCMP_D(fcc0, v0, v0, cEQ);
BCNEZ_MARK(fcc0);
B_NEXT_nocond;
MARK; // v0 is not nan
FABS_D(v1, v0);
MOV64x(x3, 1ULL << __DBL_MANT_DIG__);
MOVGR2FR_D(v2, x3);
FFINT_D_L(v2, v2);
FCMP_D(fcc1, v1, v2, cLT);
BCNEZ_MARK2(fcc1);
B_NEXT_nocond;
MARK2;
FTINT_L_D(v1, v0);
FFINT_D_L(v1, v1);
FCOPYSIGN_D(v0, v1, v0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xFD:
INST_NAME("FSCALE");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_fscale, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_fsin, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
s0 = x87_stackcount(dyn, ninst, x3);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
CALL_(const_native_fcos, -1, BOX64ENV(dynarec_fastround) ? 0 : u8, 0, 0);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x3, s0);
break;
default:
DEFAULT;
break;
}
else
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, (BOX64ENV(dynarec_x87double) == 1) ? LSX_CACHE_ST_D : LSX_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v1, ed, fixedaddress);
if (!ST_IS_F(0)) {
FCVT_D_S(v1, v1);
}
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_F);
if (ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch(dyn);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x2);
FCVT_S_D(s0, v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FST_S(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if (!ST_IS_F(0)) {
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x3);
FCVT_S_D(v1, v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
}
FST_S(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
MOV32w(x2, 0);
CALL(const_fpu_loadenv, -1, ed, x2);
NATIVE_RESTORE_X87PC();
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
ST_H(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
if (dyn->need_x87check) {
SRLI_D(x87pc, x1, 8);
ANDI(x87pc, x87pc, 0b11);
}
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
BARRIER(BARRIER_FLOAT); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
MOV32w(x2, 0);
CALL(const_fpu_savenv, -1, ed, x2);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 0, 0);
ed = x1;
wb1 = 1;
LD_H(x1, xEmu, offsetof(x64emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
return addr;
}
+210
View File
@@ -0,0 +1,210 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_DA(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int64_t j64;
uint8_t ed;
uint8_t u8;
uint8_t wback;
int v1, v2;
int d0;
int s0;
int64_t fixedaddress;
int unscaled;
MAYUSE(s0);
MAYUSE(d0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(j64);
if (MODREG)
switch (nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FCMOVB ST0, STx");
READFLAGS(X_CF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, 1 << F_CF);
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMOV_S(v1, v2);
else
FMOV_D(v1, v2);
break;
case 0xC8 ... 0xCF:
INST_NAME("FCMOVE ST0, STx");
READFLAGS(X_ZF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, 1 << F_ZF);
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMOV_S(v1, v2);
else
FMOV_D(v1, v2);
break;
case 0xD0 ... 0xD7:
INST_NAME("FCMOVBE ST0, STx");
READFLAGS(X_CF | X_ZF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF));
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMOV_S(v1, v2);
else
FMOV_D(v1, v2);
break;
case 0xD8 ... 0xDF:
INST_NAME("FCMOVU ST0, STx");
READFLAGS(X_PF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, (1 << F_PF));
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMOV_S(v1, v2);
else
FMOV_D(v1, v2);
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3);
} else {
FCOMD(v1, v2, x1, x2, x3);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
break;
}
else
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FADD_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FMUL_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
FCOMD(v1, v2, x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
FCOMD(v1, v2, x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v1, v2);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v2, ed, fixedaddress);
FFINT_D_W(v2, v2); // i32 -> double
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
}
+273
View File
@@ -0,0 +1,273 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "la64_emitter.h"
#include "la64_mapping.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_DB(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int64_t j64;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j64);
if (MODREG)
switch (nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FCMOVNB ST0, STx");
READFLAGS(X_CF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, 1 << F_CF);
CBNZ_NEXT(x1);
if (ST_IS_F(0)) {
FMOV_S(v1, v2);
} else {
FMOV_D(v1, v2); // F_CF==0
}
break;
case 0xC8 ... 0xCF:
INST_NAME("FCMOVNE ST0, STx");
READFLAGS(X_ZF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, 1 << F_ZF);
CBNZ_NEXT(x1);
if (ST_IS_F(0)) {
FMOV_S(v1, v2);
} else {
FMOV_D(v1, v2); // F_ZF==0
}
break;
case 0xD0 ... 0xD7:
INST_NAME("FCMOVNBE ST0, STx");
READFLAGS(X_CF | X_ZF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF));
CBNZ_NEXT(x1);
if (ST_IS_F(0)) {
FMOV_S(v1, v2);
} else {
FMOV_D(v1, v2); // F_CF==0 & F_ZF==0
}
break;
case 0xD8 ... 0xDF:
INST_NAME("FCMOVNU ST0, STx");
READFLAGS(X_PF);
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));
RESTORE_EFLAGS(x5);
ANDI(x1, xFlags, 1 << F_PF);
CBNZ_NEXT(x1);
if (ST_IS_F(0)) {
FMOV_S(v1, v2);
} else {
FMOV_D(v1, v2); // F_PF==0
}
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
break;
case 0xE2:
INST_NAME("FNCLEX");
LD_H(x2, xEmu, offsetof(x64emu_t, sw));
BSTRINS_D(x2, x2, 7, 0); // IE .. PE, SF, ES
BSTRINS_D(x2, x2, 15, 15); // B
ST_H(x2, xEmu, offsetof(x64emu_t, sw));
break;
case 0xE3:
INST_NAME("FNINIT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
CALL(const_reset_fpu, -1, 0, 0);
NATIVE_RESTORE_X87PC();
break;
case 0xE8 ... 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
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)) {
FCOMIS(v1, v2, x1, x2);
} else {
FCOMID(v1, v2, x1, x2);
}
break;
case 0xF0 ... 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
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)) {
FCOMIS(v1, v2, x1, x2);
} else {
FCOMID(v1, v2, x1, x2);
}
break;
default:
DEFAULT;
break;
}
else
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("FILD ST0, Ed");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_S(v1, ed, fixedaddress);
FFINT_D_W(v1, v1); // i32 -> double
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
FTINTRZ_W_D(v2, v1);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
BSTRPICK_D(x5, x5, FR_V, FR_V);
BEQZ_MARK(x5);
MOV32w(x4, 0x80000000);
MOVGR2FR_W(v2, x4);
MARK;
}
FST_S(v2, wback, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v2 = fpu_get_scratch(dyn);
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
FTINT_W_D(v2, v1);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
BSTRPICK_D(x5, x5, FR_V, FR_V);
BEQZ_MARK(x5);
MOV32w(x4, 0x80000000);
MOVGR2FR_W(v2, x4);
MARK;
}
FST_S(v2, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
break;
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v2 = fpu_get_scratch(dyn);
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
FTINT_W_D(v2, v1);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
BSTRPICK_D(x5, x5, FR_V, FR_V);
BEQZ_MARK(x5);
MOV32w(x4, 0x80000000);
MOVGR2FR_W(v2, x4);
MARK;
}
FST_S(v2, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
if ((PK(0) == 0xDB && ((PK(1) >> 3) & 7) == 7) || (!rex.is32bits && PK(0) >= 0x40 && PK(0) <= 0x4f && PK(1) == 0xDB && ((PK(2) >> 3) & 7) == 7)) {
NOTEST(x5);
// the FLD is immediatly followed by an FSTP
LD_D(x5, ed, fixedaddress + 0);
LD_H(x6, ed, fixedaddress + 8);
// no persistant scratch register, so unrool both instruction here...
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; // 0xDB or rex
if (!rex.is32bits && nextop >= 0x40 && nextop <= 0x4f) {
rex.rex = nextop;
nextop = F8; // 0xDB
} else
rex.rex = 0;
nextop = F8; // modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
ST_D(x5, ed, fixedaddress + 0);
ST_H(x6, ed, fixedaddress + 8);
} else {
if (BOX64ENV(x87_no80bits)) {
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, LSX_CACHE_ST_D);
FLD_D(v1, ed, fixedaddress);
} else {
ADDI_D(x1, ed, fixedaddress);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
x87_reflectcount(dyn, ninst, x3, x4);
CALL(const_native_fld, -1, x1, 0);
x87_unreflectcount(dyn, ninst, x3, x4);
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if (BOX64ENV(x87_no80bits)) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FST_D(v1, wback, fixedaddress);
} else {
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
x87_reflectcount(dyn, ninst, x3, x4);
CALL(const_native_fstp, -1, ed, 0);
x87_unreflectcount(dyn, ninst, x3, x4);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
}
return addr;
}
+226
View File
@@ -0,0 +1,226 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_DC(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
if (MODREG)
switch (nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FADD 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FADD_S(v1, v1, v2);
} else {
FADD_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xC8 ... 0xCF:
INST_NAME("FMUL 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FMUL_S(v1, v1, v2);
} else {
FMUL_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xD0 ... 0xD7:
INST_NAME("FCOM 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)) {
FCOMS(v1, v2, x1, x2, x3);
} else {
FCOMD(v1, v2, x1, x2, x3);
}
break;
case 0xD8 ... 0xDF:
INST_NAME("FCOMP 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)) {
FCOMS(v1, v2, x1, x2, x3);
} else {
FCOMD(v1, v2, x1, x2, x3);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0 ... 0xE7:
INST_NAME("FSUBR 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FSUB_S(v1, v2, v1);
} else {
FSUB_D(v1, v2, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xE8 ... 0xEF:
INST_NAME("FSUB 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FSUB_S(v1, v1, v2);
} else {
FSUB_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xF0 ... 0xF7:
INST_NAME("FDIVR 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FDIV_S(v1, v2, v1);
} else {
FDIV_D(v1, v2, v1);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 0xF8 ... 0xFF:
INST_NAME("FDIV 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 (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
if (ST_IS_F(0)) {
FDIV_S(v1, v1, v2);
} else {
FDIV_D(v1, v1, v2);
}
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
break;
}
else
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FADD_D(v1, v1, v2);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FMUL_D(v1, v1, v2);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
FCOMD(v1, v2, x1, x6, x3);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
FCOMD(v1, v2, x1, x6, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v1, v2);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FSUB_D(v1, v2, v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v1, v2);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, LSX_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD_D(v2, wback, fixedaddress);
if (!BOX64ENV(dynarec_fastround)) u8 = x87_setround(dyn, ninst, x1, x5);
FDIV_D(v1, v2, v1);
X87_CHECK_PRECISION(v1);
if (!BOX64ENV(dynarec_fastround)) x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
}
Loaded 100 of 437 files, more files were not shown because too many files have changed in this diff. Show more